diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/Commands.ServiceManagement.Test.csproj b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/Commands.ServiceManagement.Test.csproj index cfeb5f86de9f..de9af6bad097 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/Commands.ServiceManagement.Test.csproj +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/Commands.ServiceManagement.Test.csproj @@ -423,64 +423,134 @@ - PreserveNewest + Always - PreserveNewest + Always - - + + Always + + + Always + Always Always - + + Always + - - - - - - - - - - - - - - - - - - - - - + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + - - - - - + + Always + + + Always + + + Always + + + Always + + + Always + - PreserveNewest + Always + + + Always - - - - - - + + Always + + + Always + + + Always + + + Always + + + Always + diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/FunctionalTest.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/FunctionalTest.cs index c70998bd8e6d..b1955c2ee152 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/FunctionalTest.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/FunctionalTest.cs @@ -539,9 +539,13 @@ public void AzureDeploymentTest() Assert.IsTrue(File.Exists(configPath3.FullName), "file not exist={0}", configPath3); string deploymentName = "deployment1"; + string deploymentName2 = "deployment2"; string deploymentLabel = "label1"; DeploymentInfoContext result; + PSCredential cred = new PSCredential(username, Utilities.convertToSecureString(password)); + ExtensionConfigurationInput rdpExtCfg = vmPowershellCmdlets.NewAzureServiceRemoteDesktopExtensionConfig(cred); + try { vmPowershellCmdlets.NewAzureService(serviceName, serviceName, locationName); @@ -549,13 +553,15 @@ public void AzureDeploymentTest() Utilities.RetryActionUntilSuccess(() => { - vmPowershellCmdlets.NewAzureDeployment(serviceName, packagePath1.FullName, configPath1.FullName, DeploymentSlotType.Staging, deploymentLabel, deploymentName, false, false); + vmPowershellCmdlets.NewAzureDeployment(serviceName, packagePath1.FullName, configPath1.FullName, DeploymentSlotType.Staging, deploymentLabel, deploymentName, false, false, rdpExtCfg); }, "Windows Azure is currently performing an operation on this hosted service that requires exclusive access.", 10, 30); result = vmPowershellCmdlets.GetAzureDeployment(serviceName, DeploymentSlotType.Staging); pass = Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName, deploymentLabel, DeploymentSlotType.Staging, null, 1); Console.WriteLine("successfully deployed the package"); + ExtensionContext extResult0 = vmPowershellCmdlets.GetAzureServiceExtension(serviceName, DeploymentSlotType.Staging)[0]; + Utilities.PrintContext(extResult0); // Move the deployment from 'Staging' to 'Production' Utilities.RetryActionUntilSuccess(() => @@ -564,9 +570,60 @@ public void AzureDeploymentTest() }, "The server encountered an internal error. Please retry the request.", 10, 30); result = vmPowershellCmdlets.GetAzureDeployment(serviceName, DeploymentSlotType.Production); pass &= Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName, deploymentLabel, DeploymentSlotType.Production, null, 1); - Console.WriteLine("successfully moved"); + Console.WriteLine("successfully moved."); + + ExtensionContext extResult1 = vmPowershellCmdlets.GetAzureServiceExtension(serviceName, DeploymentSlotType.Production)[0]; + Utilities.PrintContext(extResult1); + + Assert.IsTrue(string.Equals(extResult0.Id, extResult1.Id)); + + // Check until the deployment moving is done, and the staging slot is empty. + Utilities.RetryActionUntilSuccess(() => + { + try + { + result = vmPowershellCmdlets.GetAzureDeployment(serviceName, DeploymentSlotType.Staging); + Assert.IsNull(result); + } + catch (Exception e) + { + const string errorMessage = "No deployments were found."; + Assert.IsTrue(e.ToString().Contains(errorMessage) || (e.InnerException != null && e.InnerException.ToString().Contains(errorMessage))); + } + }, "Assert", 10, 60); + Console.WriteLine("successfully checked original deployment has been moved away."); + + // Re-create the Staging depoyment with the extension + Utilities.RetryActionUntilSuccess(() => + { + vmPowershellCmdlets.NewAzureDeployment(serviceName, packagePath2.FullName, configPath2.FullName, DeploymentSlotType.Staging, deploymentLabel, deploymentName2, false, false, rdpExtCfg); + }, "Windows Azure is currently performing an operation on this hosted service that requires exclusive access.", 10, 60); + + result = vmPowershellCmdlets.GetAzureDeployment(serviceName, DeploymentSlotType.Staging); + pass = Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName2, deploymentLabel, DeploymentSlotType.Staging, null, 2); + Console.WriteLine(string.Format("Successfully re-deployed the package #2 to the {0} slot.", DeploymentSlotType.Staging)); + + ExtensionContext extResult2 = vmPowershellCmdlets.GetAzureServiceExtension(serviceName, DeploymentSlotType.Staging)[0]; + Utilities.PrintContext(extResult2); + + // Update the deployment with the extension + Utilities.RetryActionUntilSuccess(() => + { + vmPowershellCmdlets.SetAzureDeploymentConfig(serviceName, DeploymentSlotType.Staging, configPath2.FullName, rdpExtCfg); + }, "The server encountered an internal error. Please retry the request.", 10, 30); + result = vmPowershellCmdlets.GetAzureDeployment(serviceName, DeploymentSlotType.Staging); + pass &= Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName2, deploymentLabel, DeploymentSlotType.Staging, null, 2); + Console.WriteLine("successfully updated the deployment #2"); + + ExtensionContext extResult3 = vmPowershellCmdlets.GetAzureServiceExtension(serviceName, DeploymentSlotType.Staging)[0]; + Utilities.PrintContext(extResult3); + + Assert.IsTrue(!string.Equals(extResult2.Id, extResult3.Id)); + + // Remove the deployment #2 + vmPowershellCmdlets.RemoveAzureDeployment(serviceName, DeploymentSlotType.Staging, true); - // Set the deployment status to 'Suspended' + // Set the deployment #1 status to 'Suspended' Utilities.RetryActionUntilSuccess(() => { vmPowershellCmdlets.SetAzureDeploymentStatus(serviceName, DeploymentSlotType.Production, DeploymentStatus.Suspended); @@ -575,7 +632,7 @@ public void AzureDeploymentTest() pass &= Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName, deploymentLabel, DeploymentSlotType.Production, DeploymentStatus.Suspended, 1); Console.WriteLine("successfully changed the status"); - // Update the deployment + // Update the deployment #1 Utilities.RetryActionUntilSuccess(() => { vmPowershellCmdlets.SetAzureDeploymentConfig(serviceName, DeploymentSlotType.Production, configPath2.FullName); @@ -584,7 +641,7 @@ public void AzureDeploymentTest() pass &= Utilities.PrintAndCompareDeployment(result, serviceName, deploymentName, deploymentLabel, DeploymentSlotType.Production, null, 2); Console.WriteLine("successfully updated the deployment"); - // Upgrade the deployment + // Upgrade the deployment #1 DateTime start = DateTime.Now; Utilities.RetryActionUntilSuccess(() => { diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/IaasCmdletInfo/SetAzureDeploymentCmdletInfo.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/IaasCmdletInfo/SetAzureDeploymentCmdletInfo.cs index 73e71a6fb535..b504f95c4f60 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/IaasCmdletInfo/SetAzureDeploymentCmdletInfo.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/IaasCmdletInfo/SetAzureDeploymentCmdletInfo.cs @@ -12,6 +12,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +using Microsoft.WindowsAzure.Commands.ServiceManagement.Extensions; using Microsoft.WindowsAzure.Commands.ServiceManagement.Test.FunctionalTests.PowershellCore; namespace Microsoft.WindowsAzure.Commands.ServiceManagement.Test.FunctionalTests.IaasCmdletInfo @@ -38,12 +39,13 @@ public static SetAzureDeploymentCmdletInfo SetAzureDeploymentStatusCmdletInfo(st } - public static SetAzureDeploymentCmdletInfo SetAzureDeploymentConfigCmdletInfo(string serviceName, string slot, string configPath) + public static SetAzureDeploymentCmdletInfo SetAzureDeploymentConfigCmdletInfo(string serviceName, string slot, string configPath, ExtensionConfigurationInput extConfig = null) { SetAzureDeploymentCmdletInfo result = new SetAzureDeploymentCmdletInfo(serviceName, slot); result.cmdletParams.Add(new CmdletParam("Config")); result.cmdletParams.Add(new CmdletParam("Configuration", configPath)); + result.cmdletParams.Add(new CmdletParam("ExtensionConfiguration", extConfig)); return result; } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/ServiceManagementCmdletTestHelper.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/ServiceManagementCmdletTestHelper.cs index 75537a22ab2d..67749028f22d 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/ServiceManagementCmdletTestHelper.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement.Test/FunctionalTests/ServiceManagementCmdletTestHelper.cs @@ -454,9 +454,9 @@ public ManagementOperationContext SetAzureDeploymentStatus(string serviceName, s return SetAzureDeployment(SetAzureDeploymentCmdletInfo.SetAzureDeploymentStatusCmdletInfo(serviceName, slot, newStatus)); } - public ManagementOperationContext SetAzureDeploymentConfig(string serviceName, string slot, string configPath) + public ManagementOperationContext SetAzureDeploymentConfig(string serviceName, string slot, string configPath, ExtensionConfigurationInput extConfig = null) { - return SetAzureDeployment(SetAzureDeploymentCmdletInfo.SetAzureDeploymentConfigCmdletInfo(serviceName, slot, configPath)); + return SetAzureDeployment(SetAzureDeploymentCmdletInfo.SetAzureDeploymentConfigCmdletInfo(serviceName, slot, configPath, extConfig)); } public ManagementOperationContext SetAzureDeploymentUpgrade(string serviceName, string slot, string mode, string packagePath, string configPath) diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/ADDomain/SetAzureServiceADDomainExtension.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/ADDomain/SetAzureServiceADDomainExtension.cs index 84e31ad1140b..9ab48953b43a 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/ADDomain/SetAzureServiceADDomainExtension.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/ADDomain/SetAzureServiceADDomainExtension.cs @@ -238,7 +238,7 @@ public void ExecuteCommand() Roles = new ExtensionRoleList(Role != null && Role.Any() ? Role.Select(r => new ExtensionRole(r)) : Enumerable.Repeat(new ExtensionRole(), 1)) }; - var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration); + var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration, PeerDeployment.ExtensionConfiguration); ChangeDeployment(extConfig); } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/BaseAzureServiceExtensionCmdlet.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/BaseAzureServiceExtensionCmdlet.cs index a24bfa9c41d6..8c5fa36ebeb3 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/BaseAzureServiceExtensionCmdlet.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/BaseAzureServiceExtensionCmdlet.cs @@ -50,6 +50,7 @@ public abstract class BaseAzureServiceExtensionCmdlet : ServiceManagementBaseCmd protected XDocument PublicConfigurationXml { get; set; } protected XDocument PrivateConfigurationXml { get; set; } protected DeploymentGetResponse Deployment { get; set; } + protected DeploymentGetResponse PeerDeployment { get; set; } public virtual string ServiceName { get; set; } public virtual string Slot { get; set; } @@ -109,6 +110,8 @@ protected void ValidateDeployment() } Deployment.ExtensionConfiguration = Deployment.ExtensionConfiguration ?? new Microsoft.WindowsAzure.Management.Compute.Models.ExtensionConfiguration(); } + + PeerDeployment = GetPeerDeployment(Slot); } protected void ValidateRoles() @@ -285,6 +288,15 @@ protected DeploymentGetResponse GetDeployment(string slot) return d; } + protected DeploymentGetResponse GetPeerDeployment(string currentSlot) + { + var currentSlotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), currentSlot, true); + var peerSlot = currentSlotType == DeploymentSlot.Production ? DeploymentSlot.Staging : DeploymentSlot.Production; + var peerSlotStr = peerSlot.ToString(); + + return GetDeployment(peerSlotStr); + } + protected SecureString GetSecurePassword(string password) { SecureString securePassword = new SecureString(); diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionManager.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionManager.cs index 2a4d98eff417..5301543f405a 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionManager.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionManager.cs @@ -147,7 +147,7 @@ private void GetThumbprintAndAlgorithm(IList new ExtensionRole(r)) : Enumerable.Repeat(new ExtensionRole(), 1)) }; - var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration); + var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration, PeerDeployment.ExtensionConfiguration); ChangeDeployment(extConfig); } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/RemoveAzureServiceAntimalwareExtension.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/RemoveAzureServiceAntimalwareExtension.cs index bfbf480dfdf7..6a6e60182b97 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/RemoveAzureServiceAntimalwareExtension.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/RemoveAzureServiceAntimalwareExtension.cs @@ -81,7 +81,7 @@ public void ExecuteCommand() // process any pending deployment changes if (extConfigInputs != null) { - ExtensionConfiguration newExtConfig = ExtensionManager.Add(Deployment, extConfigInputs, Slot); + ExtensionConfiguration newExtConfig = ExtensionManager.Add(Deployment, PeerDeployment, extConfigInputs, Slot); ChangeDeployment(newExtConfig); } } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/SetAzureServiceAntimalwareExtension.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/SetAzureServiceAntimalwareExtension.cs index 15c4c996695a..8f17331a15bd 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/SetAzureServiceAntimalwareExtension.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/MicrosoftAntimalware/SetAzureServiceAntimalwareExtension.cs @@ -444,7 +444,7 @@ public void ExecuteCommand() // process any pending deployment changes if (extConfigInputs != null) { - ExtensionConfiguration newExtConfig = ExtensionManager.Add(Deployment, extConfigInputs, Slot); + ExtensionConfiguration newExtConfig = ExtensionManager.Add(Deployment, PeerDeployment, extConfigInputs, Slot); ChangeDeployment(newExtConfig); } } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/RDP/SetAzureServiceRemoteDesktopExtension.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/RDP/SetAzureServiceRemoteDesktopExtension.cs index 36ac0f8a9e85..6e01f6e32ffe 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/RDP/SetAzureServiceRemoteDesktopExtension.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/RDP/SetAzureServiceRemoteDesktopExtension.cs @@ -132,7 +132,7 @@ public void ExecuteCommand() Version = Version, Roles = new ExtensionRoleList(Role != null && Role.Any() ? Role.Select(r => new ExtensionRole(r)) : Enumerable.Repeat(new ExtensionRole(), 1)) }; - var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration); + var extConfig = ExtensionManager.InstallExtension(context, Slot, Deployment.ExtensionConfiguration, PeerDeployment.ExtensionConfiguration); ChangeDeployment(extConfig); } diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/NewAzureDeployment.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/NewAzureDeployment.cs index 3d168eb176dd..8a3990f92697 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/NewAzureDeployment.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/NewAzureDeployment.cs @@ -159,14 +159,12 @@ public virtual void NewPaaSDeploymentProcess() } } - - var slotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true); - DeploymentGetResponse d = null; - InvokeInOperationContext(() => + Func func = t => { + DeploymentGetResponse d = null; try { - d = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, slotType); + d = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, t); } catch (CloudException ex) { @@ -175,10 +173,20 @@ public virtual void NewPaaSDeploymentProcess() this.WriteExceptionDetails(ex); } } - }); + + return d; + }; + + var slotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true); + DeploymentGetResponse currentDeployment = null; + InvokeInOperationContext(() => currentDeployment = func(slotType)); + + var peerSlottype = slotType == DeploymentSlot.Production ? DeploymentSlot.Staging : DeploymentSlot.Production; + DeploymentGetResponse peerDeployment = null; + InvokeInOperationContext(() => peerDeployment = func(peerSlottype)); ExtensionManager extensionMgr = new ExtensionManager(this, ServiceName); - extConfig = extensionMgr.Set(d, ExtensionConfiguration, this.Slot); + extConfig = extensionMgr.Set(currentDeployment, peerDeployment, ExtensionConfiguration, this.Slot); } var deploymentInput = new DeploymentCreateParameters diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/SetAzureDeployment.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/SetAzureDeployment.cs index 7d34c6d4dee8..54655bc57ea4 100644 --- a/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/SetAzureDeployment.cs +++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/HostedServices/SetAzureDeployment.cs @@ -164,13 +164,12 @@ public void ExecuteCommand() } } - var slotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true); - DeploymentGetResponse d = null; - InvokeInOperationContext(() => + Func func = t => { + DeploymentGetResponse d = null; try { - d = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, slotType); + d = this.ComputeClient.Deployments.GetBySlot(this.ServiceName, t); } catch (CloudException ex) { @@ -179,10 +178,20 @@ public void ExecuteCommand() this.WriteExceptionDetails(ex); } } - }); + + return d; + }; + + var slotType = (DeploymentSlot)Enum.Parse(typeof(DeploymentSlot), this.Slot, true); + DeploymentGetResponse currentDeployment = null; + InvokeInOperationContext(() => currentDeployment = func(slotType)); + + var peerSlottype = slotType == DeploymentSlot.Production ? DeploymentSlot.Staging : DeploymentSlot.Production; + DeploymentGetResponse peerDeployment = null; + InvokeInOperationContext(() => peerDeployment = func(peerSlottype)); ExtensionManager extensionMgr = new ExtensionManager(this, ServiceName); - extConfig = extensionMgr.Add(d, ExtensionConfiguration, this.Slot); + extConfig = extensionMgr.Add(currentDeployment, peerDeployment, ExtensionConfiguration, this.Slot); } // Upgrade Parameter Set