16
16
using Microsoft . WindowsAzure . Commands . Utilities . Common ;
17
17
using System . Management . Automation ;
18
18
using System . Linq ;
19
+ using Microsoft . Rest . Azure ;
20
+ using System . Threading . Tasks ;
19
21
20
22
namespace Microsoft . Azure . Commands . ResourceManager . Cmdlets . SdkClient
21
23
{
@@ -25,6 +27,8 @@ public class DeploymentStacksSdkClient
25
27
26
28
private IAzureContext azureContext ;
27
29
30
+ public Action < string > VerboseLogger { get ; set ; }
31
+
28
32
public DeploymentStacksSdkClient ( IDeploymentStacksClient deploymentStacksClient )
29
33
{
30
34
this . DeploymentStacksClient = deploymentStacksClient ;
@@ -350,7 +354,14 @@ string updateBehavior
350
354
351
355
352
356
var deploymentStack = DeploymentStacksClient . DeploymentStacks . BeginCreateOrUpdateAtResourceGroup ( resourceGroupName , deploymentStackName , deploymentStackModel ) ;
353
- return new PSDeploymentStack ( deploymentStack ) ;
357
+ var getStackFunc = this . GetStackAction ( deploymentStackName , "resourceGroup" , resourceGroupName ) ;
358
+
359
+ var finalStack = this . waitStackCompletion (
360
+ getStackFunc ,
361
+ "succeeded" ,
362
+ "failed"
363
+ ) ;
364
+ return new PSDeploymentStack ( finalStack ) ;
354
365
}
355
366
356
367
internal void DeleteResourceGroupDeploymentStackSnapshot ( string resourceGroupName , string name , string snapshotName )
@@ -474,7 +485,70 @@ string updateBehavior
474
485
}
475
486
476
487
var deploymentStack = DeploymentStacksClient . DeploymentStacks . BeginCreateOrUpdateAtSubscription ( deploymentStackName , deploymentStackModel ) ;
477
- return new PSDeploymentStack ( deploymentStack ) ;
488
+ var getStackFunc = this . GetStackAction ( deploymentStackName , "subscription" ) ;
489
+
490
+ var finalStack = this . waitStackCompletion (
491
+ getStackFunc ,
492
+ "succeeded" ,
493
+ "failed"
494
+ ) ;
495
+
496
+ return new PSDeploymentStack ( finalStack ) ;
497
+ }
498
+
499
+ private DeploymentStack waitStackCompletion ( Func < Task < AzureOperationResponse < DeploymentStack > > > getStack , params string [ ] status )
500
+ {
501
+ //Poll stack deployment based on RetryAfter. If no RetyrAfter is present, polling status in two phases.
502
+ //Phase one: poll every 5 seconds for 400 seconds. If not completed in this duration, move to phase two
503
+ //Phase two: poll every 60 seconds
504
+ DeploymentStack stack ;
505
+
506
+ const int counterUnit = 1000 ;
507
+ int step = 5 ;
508
+ int phaseOne = 400 ;
509
+ do
510
+ {
511
+ WriteVerbose ( string . Format ( "Checking stack deployment status" , step ) ) ;
512
+ TestMockSupport . Delay ( step * counterUnit ) ;
513
+
514
+ if ( phaseOne > 0 )
515
+ phaseOne -= step ;
516
+
517
+ var getStackTask = getStack ( ) ;
518
+
519
+ using ( var getResult = getStackTask . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) )
520
+ {
521
+ stack = getResult . Body ;
522
+ var response = getResult . Response ;
523
+
524
+ if ( response != null && response . Headers . RetryAfter != null && response . Headers . RetryAfter . Delta . HasValue )
525
+ {
526
+ step = response . Headers . RetryAfter . Delta . Value . Seconds ;
527
+ }
528
+ else
529
+ {
530
+ step = phaseOne > 0 ? 5 : 60 ;
531
+ }
532
+ }
533
+
534
+ } while ( ! status . Any ( s => s . Equals ( stack . ProvisioningState , StringComparison . OrdinalIgnoreCase ) ) ) ;
535
+
536
+ return stack ;
537
+ }
538
+
539
+ Func < Task < AzureOperationResponse < DeploymentStack > > > GetStackAction ( string stackName , string scope , string rgName = null )
540
+ {
541
+ switch ( scope )
542
+ {
543
+ case "subscription" :
544
+ return ( ) => DeploymentStacksClient . DeploymentStacks . GetAtSubscriptionWithHttpMessagesAsync ( stackName ) ;
545
+
546
+ case "resourceGroup" :
547
+ return ( ) => DeploymentStacksClient . DeploymentStacks . GetAtResourceGroupWithHttpMessagesAsync ( rgName , stackName ) ;
548
+
549
+ default :
550
+ throw new NotImplementedException ( ) ;
551
+ }
478
552
}
479
553
480
554
public PSDeploymentStack UpdateResourceGroupDeploymentStack (
@@ -529,5 +603,13 @@ string description
529
603
var deploymentStack = DeploymentStacksClient . DeploymentStacks . BeginCreateOrUpdateAtResourceGroup ( resourceGroupName , deploymentStackName , deploymentStackModel ) ;
530
604
return new PSDeploymentStack ( deploymentStack ) ;
531
605
}
606
+
607
+ private void WriteVerbose ( string progress )
608
+ {
609
+ if ( VerboseLogger != null )
610
+ {
611
+ VerboseLogger ( progress ) ;
612
+ }
613
+ }
532
614
}
533
615
}
0 commit comments