Skip to content

Commit 9bdf159

Browse files
authored
Merge pull request #2468 from TianoMS/release-1.5.1
Check deployment exists before getting operations.
2 parents 9814af2 + facaa7a commit 9bdf159

File tree

14 files changed

+4866
-3848
lines changed

14 files changed

+4866
-3848
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
##2016.06.17 version 1.5.1
2+
* Azure Resource Manager
3+
- Fix a bug in New-AzureRmResourceGroupDeployment. In some deployments the cmdlet throws an exception with "Deployment 'deploymentName' could not be found." and causes the cmdlet to fail. The fix makes sure the deployment is created before getting operations.
14
##2016.06.01 version 1.5.0
25
* Azure Resource Manager
36
- (Get/Set/New/Remove)-AzureRmResourceGroup cmdlets will now use the new autorest generated ARM assembly

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);

0 commit comments

Comments
 (0)