Skip to content

Commit b5cccce

Browse files
committed
Check deployment exists before getting operations.
1 parent 3f141e4 commit b5cccce

File tree

3 files changed

+221
-25
lines changed

3 files changed

+221
-25
lines changed

src/ResourceManager/Resources/Commands.ResourceManager/Cmdlets/SdkClient/ResourceManagerSdkClient.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -350,21 +350,27 @@ private List<DeploymentOperation> GetNewOperations(List<DeploymentOperation> old
350350
Enum.TryParse<HttpStatusCode>(operation.Properties.StatusCode, out statusCode);
351351
if (!statusCode.IsClientFailureRequest())
352352
{
353-
List<DeploymentOperation> newNestedOperations = new List<DeploymentOperation>();
353+
var resourceGroupName = ResourceIdUtility.GetResourceGroupName(operation.Properties.TargetResource.Id);
354+
var deploymentName = operation.Properties.TargetResource.ResourceName;
354355

355-
var result = ResourceManagementClient.DeploymentOperations.List(
356-
resourceGroupName: ResourceIdUtility.GetResourceGroupName(operation.Properties.TargetResource.Id),
357-
deploymentName: operation.Properties.TargetResource.ResourceName);
356+
if (ResourceManagementClient.Deployments.CheckExistence(resourceGroupName, deploymentName) == true)
357+
{
358+
List<DeploymentOperation> newNestedOperations = new List<DeploymentOperation>();
358359

359-
newNestedOperations = GetNewOperations(operations, result);
360+
var result = ResourceManagementClient.DeploymentOperations.List(
361+
resourceGroupName: resourceGroupName,
362+
deploymentName: deploymentName);
360363

361-
foreach (DeploymentOperation op in newNestedOperations)
362-
{
363-
DeploymentOperation nestedOperationWithSameIdAndProvisioningState = newOperations.Find(o => o.OperationId.Equals(op.OperationId) && o.Properties.ProvisioningState.Equals(op.Properties.ProvisioningState));
364+
newNestedOperations = GetNewOperations(operations, result);
364365

365-
if (nestedOperationWithSameIdAndProvisioningState == null)
366+
foreach (DeploymentOperation op in newNestedOperations)
366367
{
367-
newOperations.Add(op);
368+
DeploymentOperation nestedOperationWithSameIdAndProvisioningState = newOperations.Find(o => o.OperationId.Equals(op.OperationId) && o.Properties.ProvisioningState.Equals(op.Properties.ProvisioningState));
369+
370+
if (nestedOperationWithSameIdAndProvisioningState == null)
371+
{
372+
newOperations.Add(op);
373+
}
368374
}
369375
}
370376
}
@@ -798,7 +804,7 @@ public virtual PSResourceGroupDeployment ExecuteDeployment(PSCreateResourceGroup
798804
WriteVerbose(ProjectResources.TemplateValid);
799805
}
800806

801-
ResourceManagementClient.Deployments.CreateOrUpdateAsync(parameters.ResourceGroupName, parameters.DeploymentName, deployment);
807+
ResourceManagementClient.Deployments.BeginCreateOrUpdate(parameters.ResourceGroupName, parameters.DeploymentName, deployment);
802808
WriteVerbose(string.Format(ProjectResources.CreatedDeployment, parameters.DeploymentName));
803809
DeploymentExtended result = ProvisionDeploymentStatus(parameters.ResourceGroupName, parameters.DeploymentName, deployment);
804810

src/ResourceManager/Resources/Commands.Resources.Test/Models.ResourceGroups/ResourceClientTests.cs

Lines changed: 203 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using System;
16+
using System.Collections;
17+
using System.Collections.Concurrent;
18+
using System.Collections.Generic;
19+
using System.IO;
20+
using System.Linq;
21+
using System.Net;
22+
using System.Runtime.Serialization.Formatters;
23+
using System.Text.RegularExpressions;
24+
using System.Threading;
25+
using System.Threading.Tasks;
1526
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkClient;
1627
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels;
1728
using Microsoft.Azure.Commands.Resources.Models;
@@ -23,16 +34,6 @@
2334
using Microsoft.WindowsAzure.Commands.Test.Utilities.Common;
2435
using Moq;
2536
using Newtonsoft.Json;
26-
using System;
27-
using System.Collections;
28-
using System.Collections.Generic;
29-
using System.IO;
30-
using System.Linq;
31-
using System.Net;
32-
using System.Runtime.Serialization.Formatters;
33-
using System.Text.RegularExpressions;
34-
using System.Threading;
35-
using System.Threading.Tasks;
3637
using Xunit;
3738

3839
namespace Microsoft.Azure.Commands.Resources.Test.Models
@@ -392,7 +393,7 @@ public void NewResourceGroupUsesDeploymentNameForDeploymentName()
392393
}))
393394
.Callback((string rg, string dn, Deployment d, Dictionary<string, List<string>> customHeaders, CancellationToken c) => { deploymentFromValidate = d; });
394395

395-
deploymentsMock.Setup(f => f.CreateOrUpdateWithHttpMessagesAsync(
396+
deploymentsMock.Setup(f => f.BeginCreateOrUpdateWithHttpMessagesAsync(
396397
It.IsAny<string>(),
397398
It.IsAny<string>(),
398399
It.IsAny<Deployment>(),
@@ -408,6 +409,16 @@ public void NewResourceGroupUsesDeploymentNameForDeploymentName()
408409
.Callback((string name, string dName, Deployment bDeploy, Dictionary<string, List<string>> customHeaders, CancellationToken token) =>
409410
{ deploymentFromGet = bDeploy; deploymentName = dName; });
410411

412+
deploymentsMock.Setup(f => f.CheckExistenceWithHttpMessagesAsync(
413+
It.IsAny<string>(),
414+
It.IsAny<string>(),
415+
null,
416+
new CancellationToken()))
417+
.Returns(Task.Factory.StartNew(() => new AzureOperationResponse<bool?>()
418+
{
419+
Body = true
420+
}));
421+
411422
SetupListForResourceGroupAsync(parameters.ResourceGroupName, new List<GenericResource>
412423
{
413424
CreateGenericResource(null, null, "website")
@@ -537,6 +548,176 @@ public void NewResourceGroupUsesDeploymentNameForDeploymentName()
537548
Times.Once());
538549
}
539550

551+
[Fact]
552+
public void NewResourceGroupDeploymentWithDelay()
553+
{
554+
string deploymentName = "abc123";
555+
ConcurrentBag<string> deploymentNames = new ConcurrentBag<string>();
556+
557+
PSCreateResourceGroupParameters parameters = new PSCreateResourceGroupParameters()
558+
{
559+
ResourceGroupName = resourceGroupName,
560+
Location = resourceGroupLocation,
561+
DeploymentName = deploymentName,
562+
ConfirmAction = ConfirmAction,
563+
TemplateFile = "http://path/file.html"
564+
};
565+
566+
deploymentsMock.Setup(f => f.ValidateWithHttpMessagesAsync(
567+
parameters.ResourceGroupName,
568+
parameters.DeploymentName,
569+
It.IsAny<Deployment>(),
570+
null,
571+
new CancellationToken()))
572+
.Returns(Task.Factory.StartNew(() =>
573+
new AzureOperationResponse<DeploymentValidateResult>()
574+
{
575+
Body = new DeploymentValidateResult
576+
{
577+
}
578+
}));
579+
580+
deploymentsMock.Setup(f => f.GetWithHttpMessagesAsync(
581+
parameters.ResourceGroupName,
582+
parameters.DeploymentName,
583+
null,
584+
new CancellationToken()))
585+
.Returns<string, string, Dictionary<string, List<string>>, CancellationToken>(
586+
async (getResourceGroupName, getDeploymentName, customHeaders, cancellationToken) =>
587+
{
588+
await Task.Delay(100, cancellationToken);
589+
590+
if (deploymentNames.Contains(getDeploymentName))
591+
{
592+
return new AzureOperationResponse<DeploymentExtended>()
593+
{
594+
Body = new DeploymentExtended()
595+
{
596+
Name = getDeploymentName,
597+
Id = requestId,
598+
Properties = new DeploymentPropertiesExtended()
599+
{
600+
Mode = DeploymentMode.Incremental,
601+
CorrelationId = "123",
602+
ProvisioningState = "Succeeded"
603+
},
604+
}
605+
};
606+
}
607+
608+
throw new CloudException(String.Format("Deployment '{0}' could not be found.", getDeploymentName));
609+
});
610+
611+
deploymentsMock.Setup(f => f.BeginCreateOrUpdateWithHttpMessagesAsync(
612+
parameters.ResourceGroupName,
613+
parameters.DeploymentName,
614+
It.IsAny<Deployment>(),
615+
null,
616+
new CancellationToken()))
617+
.Returns<string, string, Deployment, Dictionary<string, List<string>>, CancellationToken>(
618+
async (craeteResourceGroupName, createDeploymentName, createDeployment, customHeaders, cancellationToken) =>
619+
{
620+
await Task.Delay(500, cancellationToken);
621+
622+
deploymentNames.Add(createDeploymentName);
623+
624+
return new AzureOperationResponse<DeploymentExtended>()
625+
{
626+
Body = new DeploymentExtended
627+
{
628+
Id = requestId
629+
}
630+
};
631+
});
632+
633+
deploymentsMock.Setup(f => f.CreateOrUpdateWithHttpMessagesAsync(
634+
parameters.ResourceGroupName,
635+
parameters.DeploymentName,
636+
It.IsAny<Deployment>(),
637+
null,
638+
new CancellationToken()))
639+
.Returns<string, string, Deployment, Dictionary<string, List<string>>, CancellationToken>(
640+
async (craeteResourceGroupName, createDeploymentName, createDeployment, customHeaders, cancellationToken) =>
641+
{
642+
await Task.Delay(10000, cancellationToken);
643+
644+
deploymentNames.Add(createDeploymentName);
645+
646+
return new AzureOperationResponse<DeploymentExtended>()
647+
{
648+
Body = new DeploymentExtended
649+
{
650+
Id = requestId
651+
}
652+
};
653+
});
654+
655+
deploymentsMock.Setup(f => f.CheckExistenceWithHttpMessagesAsync(
656+
parameters.ResourceGroupName,
657+
parameters.DeploymentName,
658+
null,
659+
new CancellationToken()))
660+
.Returns(Task.Factory.StartNew(() => new AzureOperationResponse<bool?>()
661+
{
662+
Body = true
663+
}));
664+
665+
SetupListForResourceGroupAsync(parameters.ResourceGroupName, new List<GenericResource>
666+
{
667+
CreateGenericResource(null, null, "website")
668+
});
669+
670+
var operationId = Guid.NewGuid().ToString();
671+
var operationQueue = new Queue<DeploymentOperation>();
672+
operationQueue.Enqueue(
673+
new DeploymentOperation()
674+
{
675+
OperationId = operationId,
676+
Properties = new DeploymentOperationProperties()
677+
{
678+
ProvisioningState = "Succeeded",
679+
TargetResource = new TargetResource()
680+
{
681+
ResourceType = "Microsoft.Website",
682+
ResourceName = resourceName
683+
}
684+
}
685+
}
686+
);
687+
deploymentOperationsMock.Setup(f => f.ListWithHttpMessagesAsync(
688+
parameters.ResourceGroupName,
689+
parameters.DeploymentName,
690+
null,
691+
null,
692+
new CancellationToken()))
693+
.Returns<string, string, int?, Dictionary<string, List<string>>, CancellationToken>(
694+
async (getResourceGroupName, getDeploymentName, top, customHeaders, cancellationToken) =>
695+
{
696+
await Task.Delay(100, cancellationToken);
697+
698+
if (deploymentNames.Contains(getDeploymentName))
699+
{
700+
return new AzureOperationResponse<IPage<DeploymentOperation>>()
701+
{
702+
Body = GetPagableType(
703+
new List<DeploymentOperation>()
704+
{
705+
operationQueue.Dequeue()
706+
})
707+
};
708+
}
709+
710+
throw new CloudException(String.Format("Deployment '{0}' could not be found.", getDeploymentName));
711+
});
712+
713+
Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroupDeployment result = resourcesClient.ExecuteDeployment(parameters);
714+
Assert.Equal(deploymentName, result.DeploymentName);
715+
Assert.Equal("Succeeded", result.ProvisioningState);
716+
progressLoggerMock.Verify(
717+
f => f(string.Format("Resource {0} '{1}' provisioning status is {2}", "Microsoft.Website", resourceName, "Succeeded".ToLower())),
718+
Times.Once());
719+
}
720+
540721
[Fact]
541722
[Trait(Category.AcceptanceType, Category.CheckIn)]
542723
public void NewResourceGroupWithDeploymentSucceeds()
@@ -573,7 +754,7 @@ public void NewResourceGroupWithDeploymentSucceeds()
573754
Body = new ResourceGroup() { Location = resourceGroupLocation }
574755
}));
575756

576-
deploymentsMock.Setup(f => f.CreateOrUpdateWithHttpMessagesAsync(resourceGroupName, deploymentName, It.IsAny<Deployment>(), null, new CancellationToken()))
757+
deploymentsMock.Setup(f => f.BeginCreateOrUpdateWithHttpMessagesAsync(resourceGroupName, deploymentName, It.IsAny<Deployment>(), null, new CancellationToken()))
577758
.Returns(Task.Factory.StartNew(() => new AzureOperationResponse<DeploymentExtended>()
578759
{
579760
Body = new DeploymentExtended
@@ -604,6 +785,15 @@ public void NewResourceGroupWithDeploymentSucceeds()
604785
{
605786
})))
606787
.Callback((string rg, string dn, Deployment d, Dictionary<string, List<string>> customHeaders, CancellationToken c) => { deploymentFromValidate = d; });
788+
deploymentsMock.Setup(f => f.CheckExistenceWithHttpMessagesAsync(
789+
It.IsAny<string>(),
790+
It.IsAny<string>(),
791+
null,
792+
new CancellationToken()))
793+
.Returns(Task.Factory.StartNew(() => new AzureOperationResponse<bool?>()
794+
{
795+
Body = true
796+
}));
607797

608798
SetupListForResourceGroupAsync(parameters.ResourceGroupName, new List<GenericResource>() { CreateGenericResource(null, null, "website") });
609799
deploymentOperationsMock.Setup(f => f.ListWithHttpMessagesAsync(resourceGroupName, deploymentName, null, null, new CancellationToken()))
@@ -626,7 +816,7 @@ public void NewResourceGroupWithDeploymentSucceeds()
626816

627817
PSResourceGroup result = resourcesClient.CreatePSResourceGroup(parameters);
628818
Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroupDeployment deploymentResult = resourcesClient.ExecuteDeployment(parameters);
629-
deploymentsMock.Verify((f => f.CreateOrUpdateWithHttpMessagesAsync(resourceGroupName, deploymentName, deploymentFromGet, null, new CancellationToken())), Times.Once());
819+
deploymentsMock.Verify((f => f.BeginCreateOrUpdateWithHttpMessagesAsync(resourceGroupName, deploymentName, deploymentFromGet, null, new CancellationToken())), Times.Once());
630820
Assert.Equal(parameters.ResourceGroupName, deploymentResult.ResourceGroupName);
631821

632822
Assert.Equal(DeploymentMode.Incremental, deploymentFromGet.Properties.Mode);

src/ResourceManager/Resources/Commands.Resources.Test/sampleNestedTemplateParams.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"contentVersion": "1.0.0.0",
44
"parameters": {
55
"StorageAccountName": {
6-
"value": "testvivek52f134"
6+
"value": "testvivek52f323kabcd8"
77
}
88
}
99
}

0 commit comments

Comments
 (0)