Skip to content

Commit 0670b24

Browse files
authored
Merge pull request Azure#5722 from sergey-shandar/sergey-strategy-upgrade
Improved strategy cmdlets for VM and VMSS.
2 parents e9f109a + 6151994 commit 0670b24

14 files changed

+417
-322
lines changed

src/ResourceManager/Common/Commands.Common.Strategies/ResourceConfigExtensions.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ namespace Microsoft.Azure.Commands.Common.Strategies
2424
{
2525
public static class ResourceConfigExtensions
2626
{
27+
public static ResourceConfig<TModel> CreateResourceConfig<TModel>(
28+
this ResourceStrategy<TModel> strategy,
29+
IResourceConfig resourceGroup,
30+
string name,
31+
Func<IEngine, TModel> createModel,
32+
IEnumerable<IEntityConfig> dependencies)
33+
where TModel : class
34+
=> new ResourceConfig<TModel>(
35+
strategy,
36+
resourceGroup,
37+
name,
38+
createModel,
39+
new[] { resourceGroup }
40+
.Concat(dependencies)
41+
.Where(v => v != null));
42+
2743
public static ResourceConfig<TModel> CreateResourceConfig<TModel>(
2844
this ResourceStrategy<TModel> strategy,
2945
IResourceConfig resourceGroup,
@@ -36,16 +52,13 @@ public static ResourceConfig<TModel> CreateResourceConfig<TModel>(
3652
var engine = new DependencyEngine();
3753
createModel(engine);
3854
//
39-
return new ResourceConfig<TModel>(
40-
strategy,
55+
return strategy.CreateResourceConfig(
4156
resourceGroup,
4257
name,
4358
createModel,
4459
engine
4560
.Dependencies
46-
.Values
47-
.Concat(new[] { resourceGroup })
48-
.Where(v => v != null));
61+
.Values);
4962
}
5063

5164
public static async Task<TModel> GetAsync<TModel>(

src/ResourceManager/Compute/Commands.Compute/Commands.Compute.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@
282282
<Compile Include="Strategies\ComputeRp\VirtualMachineStrategy.cs" />
283283
<Compile Include="Strategies\ComputeRp\WindowsConfigurationStrategy.cs" />
284284
<Compile Include="Strategies\IAsyncCmdlet.cs" />
285+
<Compile Include="Strategies\IParameters.cs" />
285286
<Compile Include="Strategies\Location.cs" />
286287
<Compile Include="Strategies\Network\BackendAddressPoolStrategy.cs" />
287288
<Compile Include="Strategies\Network\FrontendIPConfigurationStrategy.cs" />
@@ -297,6 +298,7 @@
297298
<Compile Include="Strategies\Network\VirtualNetworkStrategy.cs" />
298299
<Compile Include="Strategies\ResourceManager\ResourceGroupStrategy.cs" />
299300
<Compile Include="Strategies\ShouldProcess.cs" />
301+
<Compile Include="Strategies\StrategyCmdlet.cs" />
300302
<Compile Include="Usage\GetAzureVMUsageCommand.cs" />
301303
<Compile Include="Usage\VirtualMachineUsageBaseCmdlet.cs" />
302304
<Compile Include="VirtualMachineSizes\GetAzureVMSizeCommand.cs" />

src/ResourceManager/Compute/Commands.Compute/Manual/VirtualMachineScaleSetCreateOrUpdateMethod.cs

Lines changed: 113 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
using Microsoft.Azure.Management.Compute.Models;
2424
using Microsoft.Azure.Management.Internal.Network.Version2017_10_01.Models;
2525
using System.Collections.Generic;
26+
using System.Linq;
2627
using System.Management.Automation;
2728
using System.Net;
2829
using System.Threading;
2930
using System.Threading.Tasks;
31+
using System;
3032

3133
namespace Microsoft.Azure.Commands.Compute.Automation
3234
{
@@ -112,141 +114,149 @@ public partial class NewAzureRmVmss : ComputeAutomationBaseCmdlet
112114
[Parameter(ParameterSetName = SimpleParameterSet, Mandatory = false)]
113115
public int[] NatBackendPort { get; set; }
114116

115-
async Task SimpleParameterSetExecuteCmdlet(IAsyncCmdlet asyncCmdlet)
117+
const int FirstPortRangeStart = 50000;
118+
119+
sealed class Parameters : IParameters<VirtualMachineScaleSet>
116120
{
117-
ResourceGroupName = ResourceGroupName ?? VMScaleSetName;
118-
VirtualNetworkName = VirtualNetworkName ?? VMScaleSetName;
119-
SubnetName = SubnetName ?? VMScaleSetName;
120-
PublicIpAddressName = PublicIpAddressName ?? VMScaleSetName;
121-
SecurityGroupName = SecurityGroupName ?? VMScaleSetName;
122-
LoadBalancerName = LoadBalancerName ?? VMScaleSetName;
123-
FrontendPoolName = FrontendPoolName ?? VMScaleSetName;
124-
BackendPoolName = BackendPoolName ?? VMScaleSetName;
121+
NewAzureRmVmss _cmdlet { get; }
125122

126-
var imageAndOsType = new ImageAndOsType(OperatingSystemTypes.Windows, null);
123+
Client _client { get; }
127124

128-
var resourceGroup = ResourceGroupStrategy.CreateResourceGroupConfig(ResourceGroupName);
125+
public Parameters(NewAzureRmVmss cmdlet, Client client)
126+
{
127+
_cmdlet = cmdlet;
128+
_client = client;
129+
}
129130

130-
var publicIpAddress = resourceGroup.CreatePublicIPAddressConfig(
131-
name: PublicIpAddressName,
132-
getDomainNameLabel: () => DomainNameLabel,
133-
allocationMethod: AllocationMethod);
131+
public string Location
132+
{
133+
get { return _cmdlet.Location; }
134+
set { _cmdlet.Location = value; }
135+
}
134136

135-
var virtualNetwork = resourceGroup.CreateVirtualNetworkConfig(
136-
name: VirtualNetworkName, addressPrefix: VnetAddressPrefix);
137+
public ImageAndOsType ImageAndOsType { get; set; }
137138

138-
var subnet = virtualNetwork.CreateSubnet(SubnetName, SubnetAddressPrefix);
139+
public async Task<ResourceConfig<VirtualMachineScaleSet>> CreateConfigAsync()
140+
{
141+
ImageAndOsType = await _client.UpdateImageAndOsTypeAsync(
142+
ImageAndOsType, _cmdlet.ImageName, Location);
139143

140-
var loadBalancer = resourceGroup.CreateLoadBalancerConfig(
141-
name: LoadBalancerName);
144+
// generate a domain name label if it's not specified.
145+
_cmdlet.DomainNameLabel = await PublicIPAddressStrategy.UpdateDomainNameLabelAsync(
146+
domainNameLabel: _cmdlet.DomainNameLabel,
147+
name: _cmdlet.VMScaleSetName,
148+
location: Location,
149+
client: _client);
142150

143-
var frontendIpConfiguration = loadBalancer.CreateFrontendIPConfiguration(
144-
name: FrontendPoolName,
145-
zones: Zone,
146-
publicIpAddress: publicIpAddress);
151+
var resourceGroup = ResourceGroupStrategy.CreateResourceGroupConfig(_cmdlet.ResourceGroupName);
147152

148-
var backendAddressPool = loadBalancer.CreateBackendAddressPool(
149-
name: BackendPoolName);
153+
var publicIpAddress = resourceGroup.CreatePublicIPAddressConfig(
154+
name: _cmdlet.PublicIpAddressName,
155+
domainNameLabel: _cmdlet.DomainNameLabel,
156+
allocationMethod: _cmdlet.AllocationMethod);
150157

151-
if (BackendPort != null)
152-
{
153-
var LoadBalancingRuleName = LoadBalancerName;
154-
foreach (var backendPort in BackendPort)
155-
{
156-
loadBalancer.CreateLoadBalancingRule(
157-
name: LoadBalancingRuleName + backendPort.ToString(),
158-
fronendIpConfiguration: frontendIpConfiguration,
159-
backendAddressPool: backendAddressPool,
160-
frontendPort: backendPort,
161-
backendPort: backendPort);
162-
}
163-
}
158+
var virtualNetwork = resourceGroup.CreateVirtualNetworkConfig(
159+
name: _cmdlet.VirtualNetworkName,
160+
addressPrefix: _cmdlet.VnetAddressPrefix);
164161

165-
var inboundNatPools = new List<NestedResourceConfig<InboundNatPool, LoadBalancer>>();
166-
167-
var virtualMachineScaleSet = resourceGroup.CreateVirtualMachineScaleSetConfig(
168-
name: VMScaleSetName,
169-
subnet: subnet,
170-
frontendIpConfigurations: new[] { frontendIpConfiguration },
171-
backendAdressPool: backendAddressPool,
172-
inboundNatPools: inboundNatPools,
173-
getImageAndOsType: () => imageAndOsType,
174-
adminUsername: Credential.UserName,
175-
adminPassword: new NetworkCredential(string.Empty, Credential.Password).Password,
176-
vmSize: VmSize,
177-
instanceCount: InstanceCount,
178-
upgradeMode: MyInvocation.BoundParameters.ContainsKey(nameof(UpgradePolicyMode))
179-
? UpgradePolicyMode
180-
: (UpgradeMode?)null);
162+
var subnet = virtualNetwork.CreateSubnet(
163+
_cmdlet.SubnetName, _cmdlet.SubnetAddressPrefix);
181164

182-
var client = new Client(DefaultProfile.DefaultContext);
165+
var loadBalancer = resourceGroup.CreateLoadBalancerConfig(
166+
name: _cmdlet.LoadBalancerName);
183167

184-
// get current Azure state
185-
var current = await virtualMachineScaleSet.GetStateAsync(client, new CancellationToken());
186-
187-
Location = current.UpdateLocation(Location, virtualMachineScaleSet);
188-
189-
imageAndOsType = await client.UpdateImageAndOsTypeAsync(ImageName, Location);
190-
191-
NatBackendPort = imageAndOsType.OsType.UpdatePorts(NatBackendPort);
192-
193-
var inboundNatPoolName = VMScaleSetName;
194-
const int FirstPortRangeStart = 50000;
195-
var portRangeStart = FirstPortRangeStart;
196-
var PortRangeSize = InstanceCount * 2;
197-
foreach (var natBackendPort in NatBackendPort)
198-
{
199-
inboundNatPools.Add(
200-
loadBalancer.CreateInboundNatPool(
201-
name: inboundNatPoolName + natBackendPort.ToString(),
202-
frontendIpConfiguration: frontendIpConfiguration,
203-
frontendPortRangeStart: portRangeStart,
204-
frontendPortRangeEnd: portRangeStart + PortRangeSize,
205-
backendPort: natBackendPort));
206-
portRangeStart += 2000;
207-
}
168+
var frontendIpConfiguration = loadBalancer.CreateFrontendIPConfiguration(
169+
name: _cmdlet.FrontendPoolName,
170+
zones: _cmdlet.Zone,
171+
publicIpAddress: publicIpAddress);
208172

209-
// generate a domain name label if it's not specified.
210-
DomainNameLabel = await PublicIPAddressStrategy.UpdateDomainNameLabelAsync(
211-
domainNameLabel: DomainNameLabel,
212-
name: VMScaleSetName,
213-
location: Location,
214-
client: client);
173+
var backendAddressPool = loadBalancer.CreateBackendAddressPool(
174+
name: _cmdlet.BackendPoolName);
215175

216-
var fqdn = PublicIPAddressStrategy.Fqdn(DomainNameLabel, Location);
176+
if (_cmdlet.BackendPort != null)
177+
{
178+
var loadBalancingRuleName = _cmdlet.LoadBalancerName;
179+
foreach (var backendPort in _cmdlet.BackendPort)
180+
{
181+
loadBalancer.CreateLoadBalancingRule(
182+
name: loadBalancingRuleName + backendPort.ToString(),
183+
fronendIpConfiguration: frontendIpConfiguration,
184+
backendAddressPool: backendAddressPool,
185+
frontendPort: backendPort,
186+
backendPort: backendPort);
187+
}
188+
}
189+
190+
_cmdlet.NatBackendPort = ImageAndOsType.UpdatePorts(_cmdlet.NatBackendPort);
191+
192+
var inboundNatPoolName = _cmdlet.VMScaleSetName;
193+
var PortRangeSize = _cmdlet.InstanceCount * 2;
194+
195+
var inboundNatPools = _cmdlet.NatBackendPort
196+
?.Select((port, i) =>
197+
{
198+
var portRangeStart = FirstPortRangeStart + i * 2000;
199+
return loadBalancer.CreateInboundNatPool(
200+
name: inboundNatPoolName + port.ToString(),
201+
frontendIpConfiguration: frontendIpConfiguration,
202+
frontendPortRangeStart: portRangeStart,
203+
frontendPortRangeEnd: portRangeStart + PortRangeSize,
204+
backendPort: port);
205+
})
206+
.ToList();
207+
208+
return resourceGroup.CreateVirtualMachineScaleSetConfig(
209+
name: _cmdlet.VMScaleSetName,
210+
subnet: subnet,
211+
frontendIpConfigurations: new[] { frontendIpConfiguration },
212+
backendAdressPool: backendAddressPool,
213+
inboundNatPools: inboundNatPools,
214+
imageAndOsType: ImageAndOsType,
215+
adminUsername: _cmdlet.Credential.UserName,
216+
adminPassword: new NetworkCredential(string.Empty, _cmdlet.Credential.Password).Password,
217+
vmSize: _cmdlet.VmSize,
218+
instanceCount: _cmdlet.InstanceCount,
219+
upgradeMode: _cmdlet.MyInvocation.BoundParameters.ContainsKey(nameof(UpgradePolicyMode))
220+
? _cmdlet.UpgradePolicyMode
221+
: (UpgradeMode?)null);
222+
}
223+
}
224+
225+
async Task SimpleParameterSetExecuteCmdlet(IAsyncCmdlet asyncCmdlet)
226+
{
227+
ResourceGroupName = ResourceGroupName ?? VMScaleSetName;
228+
VirtualNetworkName = VirtualNetworkName ?? VMScaleSetName;
229+
SubnetName = SubnetName ?? VMScaleSetName;
230+
PublicIpAddressName = PublicIpAddressName ?? VMScaleSetName;
231+
SecurityGroupName = SecurityGroupName ?? VMScaleSetName;
232+
LoadBalancerName = LoadBalancerName ?? VMScaleSetName;
233+
FrontendPoolName = FrontendPoolName ?? VMScaleSetName;
234+
BackendPoolName = BackendPoolName ?? VMScaleSetName;
217235

218-
var engine = new SdkEngine(client.SubscriptionId);
219-
var target = virtualMachineScaleSet.GetTargetState(current, engine, Location);
236+
var client = new Client(DefaultProfile.DefaultContext);
220237

221-
var newState = await virtualMachineScaleSet
222-
.UpdateStateAsync(
223-
client,
224-
target,
225-
new CancellationToken(),
226-
new ShouldProcess(asyncCmdlet),
227-
asyncCmdlet.ReportTaskProgress);
238+
var parameters = new Parameters(this, client);
228239

229-
var result = newState.Get(virtualMachineScaleSet);
230-
if (result == null)
231-
{
232-
result = current.Get(virtualMachineScaleSet);
233-
}
240+
var result = await StrategyCmdlet.RunAsync(
241+
client, parameters, asyncCmdlet, new CancellationToken());
234242

235243
if (result != null)
236244
{
245+
var fqdn = PublicIPAddressStrategy.Fqdn(DomainNameLabel, Location);
246+
237247
var psObject = new PSVirtualMachineScaleSet();
238248
ComputeAutomationAutoMapperProfile.Mapper.Map(result, psObject);
239249
psObject.FullyQualifiedDomainName = fqdn;
240250

241251
var port = "<port>";
242-
var connectionString = imageAndOsType.GetConnectionString(
252+
var connectionString = parameters.ImageAndOsType.GetConnectionString(
243253
fqdn,
244254
Credential.UserName,
245255
port);
246256
var range =
247257
FirstPortRangeStart.ToString() +
248258
".." +
249-
(FirstPortRangeStart + PortRangeSize).ToString();
259+
(FirstPortRangeStart + InstanceCount * 2).ToString();
250260

251261
asyncCmdlet.WriteVerbose(
252262
Resources.VmssUseConnectionString,

src/ResourceManager/Compute/Commands.Compute/Strategies/ComputeRp/AvailabilitySetStrategy.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
using Microsoft.Azure.Management.Compute;
1717
using Microsoft.Azure.Management.Compute.Models;
1818
using Microsoft.Azure.Management.Internal.Resources.Models;
19+
using System;
20+
using System.Linq;
1921

2022
namespace Microsoft.Azure.Commands.Compute.Strategies.ComputeRp
2123
{
@@ -36,11 +38,10 @@ public static ResourceConfig<AvailabilitySet> CreateAvailabilitySetConfig(
3638
=> Strategy.CreateResourceConfig(
3739
resourceGroup: resourceGroup,
3840
name: name,
39-
createModel: subscription => new AvailabilitySet
41+
createModel: _ =>
4042
{
41-
Sku = new Azure.Management.Compute.Models.Sku { Name = "Aligned" },
42-
PlatformFaultDomainCount = 2,
43-
PlatformUpdateDomainCount = 2,
44-
});
43+
throw new InvalidOperationException("Availability set doesn't exist.");
44+
},
45+
dependencies: Enumerable.Empty<IEntityConfig>());
4546
}
4647
}

src/ResourceManager/Compute/Commands.Compute/Strategies/ComputeRp/ImageEx.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,32 @@ namespace Microsoft.Azure.Commands.Compute.Strategies.ComputeRp
2525
{
2626
static class ImageEx
2727
{
28-
public static int[] UpdatePorts(this OperatingSystemTypes osType, int[] ports)
29-
=> ports ?? (osType == OperatingSystemTypes.Windows ? new[] { 3389, 5985 } : new[] { 22 });
28+
public static int[] UpdatePorts(this ImageAndOsType imageAndOsType, int[] ports)
29+
=> ports ?? imageAndOsType?.OsType.CreatePorts();
30+
31+
private static int[] CreatePorts(this OperatingSystemTypes osType)
32+
=> osType == OperatingSystemTypes.Windows ? new[] { 3389, 5985 }
33+
: osType == OperatingSystemTypes.Linux ? new[] { 22 }
34+
: null;
3035

3136
public static async Task<ImageAndOsType> UpdateImageAndOsTypeAsync(
32-
this IClient client, string imageName, string location)
37+
this IClient client,
38+
ImageAndOsType imageAndOsType,
39+
string imageName,
40+
string location)
3341
{
42+
if (imageAndOsType != null)
43+
{
44+
return imageAndOsType;
45+
}
46+
3447
if (imageName.Contains(':'))
3548
{
49+
if (location == null)
50+
{
51+
return null;
52+
}
53+
3654
var imageArray = imageName.Split(':');
3755
if (imageArray.Length != 4)
3856
{

src/ResourceManager/Compute/Commands.Compute/Strategies/ComputeRp/LinuxConfigurationStrategy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Microsoft.Azure.Commands.Compute.Strategies.ComputeRp
1919
static class LinuxConfigurationStrategy
2020
{
2121
public static LinuxConfiguration CreateLinuxConfiguration(this ImageAndOsType imageAndOsType)
22-
=> imageAndOsType.OsType == OperatingSystemTypes.Linux
22+
=> imageAndOsType?.OsType == OperatingSystemTypes.Linux
2323
? new LinuxConfiguration()
2424
: null;
2525
}

0 commit comments

Comments
 (0)