From 72b44bea662c7305c65ef0c296cf5da1e68f2916 Mon Sep 17 00:00:00 2001 From: Aaron Roney Date: Sun, 27 Aug 2017 18:43:14 -0700 Subject: [PATCH 01/33] Create VM rough draft. --- .../Compute.Experiments/Az.Compute.psm1 | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 tools/experiments/Compute.Experiments/Az.Compute.psm1 diff --git a/tools/experiments/Compute.Experiments/Az.Compute.psm1 b/tools/experiments/Compute.Experiments/Az.Compute.psm1 new file mode 100644 index 000000000000..6ee21b262cbb --- /dev/null +++ b/tools/experiments/Compute.Experiments/Az.Compute.psm1 @@ -0,0 +1,269 @@ +# Author: Aaron Roney. +# Modified: 20170827. +# Setup: Remove-Module Az.Compute; Import-Module .\Az.Compute.psm1; New-AzVm -Auto; + +# Resources: +# * [EXTERNAL] Azure PowerShell Docs: https://aka.ms/azpsdocs. +# * [EXTERNAL] Strategy Doc: https://aka.ms/azpsstrategy. +# * [EXTERNAL] Inspiration Sample: https://aka.ms/azpscreatevm. +# * [EXTERNAL] Community Standups: https://aka.ms/azpsnetstandup. +# * [EXTERNAL] Gallery Package: https://aka.ms/psazurerm. +# * [EXTERNAL] Docker: https://aka.ms/azpsdocker. +# * [EXTERNAL] Core Docker: https://aka.ms/azpscoredocker. +# * [INTERNAL] Research Evidence: https://aka.ms/azpsimprovementresearch. + +# TODO: +# * Implement `-Auto' parameter set (i.e., `Name` and `ResourceGroup` will become optional). +# * Implement new default formatter. +# * Lock down parameter list: should be good as is (if we add the option to set OS disk size). +# * Most of the parameters have "static" defaults: make these smart defaults, where applicable (e.g., location and open ports). +# * WinServer2016 is hardcoded: add parameters to allow people to use the full image provider, etc. +# * Import image providers, etc. from the "aliases.json". +# * Integrate into Nelson's build semantics. + +#Requires -Modules AzureRM.Compute + +function New-AzVm { + param ( + [Parameter(Mandatory = $true)] [string] $Name, + [Parameter(Mandatory = $true)] [string] $ResourceGroup, + + # Generate a random as a hash of the name so it will be idempotent (tack on resource group?). + [Parameter(DontShow)] + $Random = $(Get-Hash $Name), + + [string] $Location = "", + + [string] $Image = "WinServer2016", + [string] $Size = "Standard_DS1_v2", + + [string] $VnetName = "$($Name)Vnet", + [string] $SubnetAddressPrefix = "192.168.1.0/24", + [string] $VnetAddressPrefix = "192.168.0.0/16", + + [string] $PublicIpName = "$($Name)PublicIp", + [string] $PublicIpDnsLabel = "$Name-$Random".ToLower(), + [string] $PublicIpAllocationMethod = "Static", + [int] $PublicIpIdleTimeoutInMinutes = 4, + + [string] $NsgName = "$($Name)Nsg", + [int[]] $NsgOpenPorts = $null, + + [string] $NicName = "$($Name)Nic" + + # Storage - OS Disk Size. + # Compute: "this goes above and beyond the 80% scenario". + ) + + try { + + # Build credentials. + + $userName = $env:UserName; + $ptPassword = -join ((33..122) | Get-Random -Count 20 | ForEach-Object { [char]$_ }); + $password = ConvertTo-SecureString $ptPassword -AsPlainText -Force; + $creds = New-Object System.Management.Automation.PSCredential ($env:UserName, $password); + + # Set the smart defaults. + + if($Location -eq "") { + # TODO: Infer the location somehow? + $Location = "westus2"; + } + + if($NsgOpenPorts -eq $null) { + # TODO: Infer the ports to open from the image types. + $NsgOpenPorts = @(3389,5985); + } + + # Get image aliases. + + # TODO: Properly set images from below. Put this in its own "ensure" method? + $images = Invoke-WebRequest "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json" | ConvertFrom-Json; + + # Set variables. + + $fqdn = "$PublicIpDnsLabel.$Location.cloudapp.azure.com"; + + # Create! + + Write-Info "Ensuring resource group..."; + $rg = Use-ResourceGroup -ResourceGroup $ResourceGroup -Location $Location; + + Write-Info "Ensuring Vnet..."; + $vnet = Use-Vnet -Name $VnetName -ResourceGroup $ResourceGroup -Location $Location -SubnetAddressPrefix $SubnetAddressPrefix -VnetAddressPrefix $VnetAddressPrefix; + + Write-Info "Ensuring public IP..."; + $pip = Use-Pip -Name $PublicIpName -ResourceGroup $ResourceGroup -Location $Location -DnsLabel $PublicIpDnsLabel -AllocationMethod $PublicIpAllocationMethod -IdleTimeoutInMinutes $PublicIpIdleTimeoutInMinutes; + + Write-Info "Ensuring NSG..."; + $nsg = Use-Nsg -Name $PublicIpName -ResourceGroup $ResourceGroup -Location $Location -OpenPorts $NsgOpenPorts; + $Global:nsg = $nsg; + + Write-Info "Ensuring NIC..."; + $nic = Use-Nic -Name $NicName -ResourceGroup $ResourceGroup -Location $Location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id; + + # TODO: Add disk options (https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-vm-from-managed-os-disks?toc=%2fpowershell%2fmodule%2ftoc.json)? + # https://docs.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmosdisk?view=azurermps-4.2.0 + + # Create a virtual machine configuration + $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $Size | ` + Set-AzureRmVMOperatingSystem -Windows -ComputerName $Name -Credential $creds | ` + Set-AzureRmVMSourceImage -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2016-Datacenter -Version latest | ` + Add-AzureRmVMNetworkInterface -Id $nic.Id + + # Create a virtual machine + $vm = New-AzureRmVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig + + # Write info about VM. + + # TODO: Remove these and make this a formatter. + # Write-Info "$($tab)Resource group: $rgName."; + # Write-Info "$($tab)VM Name: MyVm$random."; + # Write-Info "$($tab)Location: $location."; + # Write-Info "$($tab)FQDN: $fqdn."; + Write-Info "$($tab)Username: $username."; + Write-Info "$($tab)Password: $ptPassword."; + + return $vm; + } catch { + Write-Error $_; + Write-Error "Something went wrong. Issue the command again: it is idempotent. :)"; + } +} + +Export-ModuleMember -Function New-AzVm + +# Helpers. + +function Use-ResourceGroup { + param ( + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location + ) + + $rg = Get-AzureRmResourceGroup | Where-Object { $_.ResourceGroupName -eq $ResourceGroup } | Select-Object -First 1 -Wait; + + if($rg -eq $null) { + return New-AzureRmResourceGroup -Name $ResourceGroup -Location $Location; + } else { + return $rg; + } +} + +function Use-Vnet { + param ( + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $SubnetAddressPrefix, + [Parameter(Mandatory=$true)] [string] $VnetAddressPrefix + ) + + $vnet = Get-AzureRmVirtualNetwork | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; + + if($vnet -eq $null) { + # Create a subnet configuration. + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name "$($Name)Subnet" -AddressPrefix $SubnetAddressPrefix; + + # Create a virtual network. + return New-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -AddressPrefix $VnetAddressPrefix -Subnet $subnetConfig + } else { + return $vnet; + } +} + +function Use-Pip { + param ( + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $DnsLabel, + [Parameter(Mandatory=$true)] [string] $AllocationMethod, + [Parameter(Mandatory=$true)] [int] $IdleTimeoutInMinutes + ) + + $pip = Get-AzureRmPublicIpAddress | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; + + if($pip -eq $null) { + # Create a public IP address and specify a DNS name. + return New-AzureRmPublicIpAddress -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -DomainNameLabel $DnsLabel -AllocationMethod $AllocationMethod -IdleTimeoutInMinutes $IdleTimeoutInMinutes; + } else { + return $pip; + } +} + +function Use-Nsg { + param ( + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [int[]] $OpenPorts + ) + + $nsg = Get-AzureRmNetworkSecurityGroup | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; + + if($nsg -eq $null) { + $rules = New-Object "System.Collections.Generic.List[Microsoft.Azure.Commands.Network.Models.PSSecurityRule]"; + $priority = 1000; + + foreach($port in $OpenPorts) + { + $nsgRule = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP -Protocol Tcp -Direction Inbound -Priority $priority -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $port -Access Allow; + $rules.Add($nsgRule); + + $priority--; + } + + # Create an NSG. + return New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -SecurityRules $rules; + } else { + return $nsg; + } +} + +function Use-Nic { + param ( + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $SubnetId, + [Parameter(Mandatory=$true)] [string] $PublicIpAddressId, + [Parameter(Mandatory=$true)] [psobject] $NetworkSecurityGroupId + ) + + $nic = Get-AzureRmNetworkInterface | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; + + if($nic -eq $null) { + # Create a virtual network card and associate with public IP address and NSG + return New-AzureRmNetworkInterface -Name $Name -ResourceGroupName $resourceGroup -Location $location -SubnetId $SubnetId -PublicIpAddressId $PublicIpAddressId -NetworkSecurityGroupId $NetworkSecurityGroupId.ToString(); + } else { + return $nic; + } +} + +function Write-Info { + param ( + [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [String] $Text + ) + + Write-Host $Text -ForegroundColor Cyan; +} + +function Get-Hash { + param ( + [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [String] $TextToHash, + [int] $Count = 10 + ) + + $hasher = new-object System.Security.Cryptography.SHA256Managed; + $toHash = [System.Text.Encoding]::UTF8.GetBytes($TextToHash); + $hashByteArray = $hasher.ComputeHash($toHash); + + foreach($byte in $hashByteArray) + { + $res += $byte.ToString(); + } + + return $res.substring(0, $Count); +} \ No newline at end of file From b8593899db5bdf576175f8d8f435aae2f214071c Mon Sep 17 00:00:00 2001 From: Aaron Roney Date: Sun, 27 Aug 2017 19:05:42 -0700 Subject: [PATCH 02/33] Move. --- .../Compute.Experiments/Az.Compute.psm1 | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {tools/experiments => experiments}/Compute.Experiments/Az.Compute.psm1 (100%) diff --git a/tools/experiments/Compute.Experiments/Az.Compute.psm1 b/experiments/Compute.Experiments/Az.Compute.psm1 similarity index 100% rename from tools/experiments/Compute.Experiments/Az.Compute.psm1 rename to experiments/Compute.Experiments/Az.Compute.psm1 From ee3ade0e10022de05734664a04410af1f8ca6b1d Mon Sep 17 00:00:00 2001 From: Aaron Roney Date: Sun, 27 Aug 2017 19:18:18 -0700 Subject: [PATCH 03/33] Update Az.Compute.psm1 --- experiments/Compute.Experiments/Az.Compute.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experiments/Compute.Experiments/Az.Compute.psm1 b/experiments/Compute.Experiments/Az.Compute.psm1 index 6ee21b262cbb..c78c820ffc96 100644 --- a/experiments/Compute.Experiments/Az.Compute.psm1 +++ b/experiments/Compute.Experiments/Az.Compute.psm1 @@ -20,6 +20,7 @@ # * WinServer2016 is hardcoded: add parameters to allow people to use the full image provider, etc. # * Import image providers, etc. from the "aliases.json". # * Integrate into Nelson's build semantics. +# * Integrate app insights instrumentation so we can get good telemetry. #Requires -Modules AzureRM.Compute @@ -266,4 +267,4 @@ function Get-Hash { } return $res.substring(0, $Count); -} \ No newline at end of file +} From 040b55294fe581e50e5b361a5b214634a748103b Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Fri, 1 Sep 2017 11:51:09 -0700 Subject: [PATCH 04/33] AzureRM.Compute.Experements --- .gitignore | 3 +- .../Compute.Experiments/Az.Compute.psm1 | 93 ++++++------ .../AzureRM.Compute.Experiments.Tests.ps1 | 16 +++ .../AzureRM.Compute.Experiments.psd1 | Bin 0 -> 7904 bytes .../AzureRM.Compute.Experiments.psm1 | 132 ++++++++++++++++++ experiments/Compute.Experiments/images.json | 84 +++++++++++ 6 files changed, 283 insertions(+), 45 deletions(-) create mode 100644 experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 create mode 100644 experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 create mode 100644 experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 create mode 100644 experiments/Compute.Experiments/images.json diff --git a/.gitignore b/.gitignore index 5159e91abbbc..f1fff314484b 100644 --- a/.gitignore +++ b/.gitignore @@ -207,4 +207,5 @@ FakesAssemblies/ /tools/*.dll *.GhostDoc.xml pingme.txt -groupMapping*.json \ No newline at end of file +groupMapping*.json +.vscode/ \ No newline at end of file diff --git a/experiments/Compute.Experiments/Az.Compute.psm1 b/experiments/Compute.Experiments/Az.Compute.psm1 index c78c820ffc96..0e1abef4fc02 100644 --- a/experiments/Compute.Experiments/Az.Compute.psm1 +++ b/experiments/Compute.Experiments/Az.Compute.psm1 @@ -26,36 +26,36 @@ function New-AzVm { param ( - [Parameter(Mandatory = $true)] [string] $Name, - [Parameter(Mandatory = $true)] [string] $ResourceGroup, + [Parameter(Mandatory = $true)] [string] $Name, + [Parameter(Mandatory = $true)] [string] $ResourceGroup, # Generate a random as a hash of the name so it will be idempotent (tack on resource group?). [Parameter(DontShow)] - $Random = $(Get-Hash $Name), + $Random = $(Get-Hash $Name), - [string] $Location = "", + [string] $Location = "", - [string] $Image = "WinServer2016", - [string] $Size = "Standard_DS1_v2", + [string] $Image = "WinServer2016", + [string] $Size = "Standard_DS1_v2", - [string] $VnetName = "$($Name)Vnet", - [string] $SubnetAddressPrefix = "192.168.1.0/24", - [string] $VnetAddressPrefix = "192.168.0.0/16", + [string] $VnetName = "$($Name)Vnet", + [string] $SubnetAddressPrefix = "192.168.1.0/24", + [string] $VnetAddressPrefix = "192.168.0.0/16", - [string] $PublicIpName = "$($Name)PublicIp", - [string] $PublicIpDnsLabel = "$Name-$Random".ToLower(), - [string] $PublicIpAllocationMethod = "Static", - [int] $PublicIpIdleTimeoutInMinutes = 4, + [string] $PublicIpName = "$($Name)PublicIp", + [string] $PublicIpDnsLabel = "$Name-$Random".ToLower(), + [string] $PublicIpAllocationMethod = "Static", + [int] $PublicIpIdleTimeoutInMinutes = 4, - [string] $NsgName = "$($Name)Nsg", - [int[]] $NsgOpenPorts = $null, + [string] $NsgName = "$($Name)Nsg", + [int[]] $NsgOpenPorts = $null, [string] $NicName = "$($Name)Nic" # Storage - OS Disk Size. # Compute: "this goes above and beyond the 80% scenario". ) - + try { # Build credentials. @@ -98,11 +98,16 @@ function New-AzVm { $pip = Use-Pip -Name $PublicIpName -ResourceGroup $ResourceGroup -Location $Location -DnsLabel $PublicIpDnsLabel -AllocationMethod $PublicIpAllocationMethod -IdleTimeoutInMinutes $PublicIpIdleTimeoutInMinutes; Write-Info "Ensuring NSG..."; - $nsg = Use-Nsg -Name $PublicIpName -ResourceGroup $ResourceGroup -Location $Location -OpenPorts $NsgOpenPorts; - $Global:nsg = $nsg; + $nsg = Use-Nsg -Name $NsgName -ResourceGroup $ResourceGroup -Location $Location -OpenPorts $NsgOpenPorts; Write-Info "Ensuring NIC..."; - $nic = Use-Nic -Name $NicName -ResourceGroup $ResourceGroup -Location $Location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id; + $nic = Use-Nic ` + -Name $NicName ` + -ResourceGroup $ResourceGroup ` + -Location $Location ` + -SubnetId $vnet.Subnets[0].Id ` + -PublicIpAddressId $pip.Id ` + -NetworkSecurityGroupId $nsg.Id; # TODO: Add disk options (https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-vm-from-managed-os-disks?toc=%2fpowershell%2fmodule%2ftoc.json)? # https://docs.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmosdisk?view=azurermps-4.2.0 @@ -139,12 +144,12 @@ Export-ModuleMember -Function New-AzVm function Use-ResourceGroup { param ( - [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, [Parameter(Mandatory=$true)] [string] $Location ) - + $rg = Get-AzureRmResourceGroup | Where-Object { $_.ResourceGroupName -eq $ResourceGroup } | Select-Object -First 1 -Wait; - + if($rg -eq $null) { return New-AzureRmResourceGroup -Name $ResourceGroup -Location $Location; } else { @@ -154,13 +159,13 @@ function Use-ResourceGroup { function Use-Vnet { param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $SubnetAddressPrefix, + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $SubnetAddressPrefix, [Parameter(Mandatory=$true)] [string] $VnetAddressPrefix ) - + $vnet = Get-AzureRmVirtualNetwork | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; if($vnet -eq $null) { @@ -176,14 +181,14 @@ function Use-Vnet { function Use-Pip { param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $DnsLabel, - [Parameter(Mandatory=$true)] [string] $AllocationMethod, + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $DnsLabel, + [Parameter(Mandatory=$true)] [string] $AllocationMethod, [Parameter(Mandatory=$true)] [int] $IdleTimeoutInMinutes ) - + $pip = Get-AzureRmPublicIpAddress | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; if($pip -eq $null) { @@ -196,12 +201,12 @@ function Use-Pip { function Use-Nsg { param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, [Parameter(Mandatory=$true)] [int[]] $OpenPorts ) - + $nsg = Get-AzureRmNetworkSecurityGroup | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; if($nsg -eq $null) { @@ -212,7 +217,7 @@ function Use-Nsg { { $nsgRule = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP -Protocol Tcp -Direction Inbound -Priority $priority -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $port -Access Allow; $rules.Add($nsgRule); - + $priority--; } @@ -225,14 +230,14 @@ function Use-Nsg { function Use-Nic { param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $SubnetId, - [Parameter(Mandatory=$true)] [string] $PublicIpAddressId, + [Parameter(Mandatory=$true)] [string] $Name, + [Parameter(Mandatory=$true)] [string] $ResourceGroup, + [Parameter(Mandatory=$true)] [string] $Location, + [Parameter(Mandatory=$true)] [string] $SubnetId, + [Parameter(Mandatory=$true)] [string] $PublicIpAddressId, [Parameter(Mandatory=$true)] [psobject] $NetworkSecurityGroupId ) - + $nic = Get-AzureRmNetworkInterface | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; if($nic -eq $null) { diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 new file mode 100644 index 000000000000..3e95933b3ffb --- /dev/null +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -0,0 +1,16 @@ +Import-Module .\..\..\src\Package\Debug\ResourceManager\AzureResourceManager\AzureRM.Profile\AzureRM.Profile.psd1 +Import-Module .\..\..\src\Package\Debug\ResourceManager\AzureResourceManager\AzureRM.Resources\AzureRM.Resources.psd1 +Import-Module .\..\..\src\Package\Debug\ResourceManager\AzureResourceManager\AzureRM.Network\AzureRM.Network.psd1 +Import-Module .\..\..\src\Package\Debug\ResourceManager\AzureResourceManager\AzureRM.Compute\AzureRM.Compute.psd1 +Import-Module .\..\..\experiments\Compute.Experiments\AzureRM.Compute.Experiments.psd1 + +# Login +$credentials = Get-Content -Path "C:\Users\sergey\Desktop\php-test.json" | ConvertFrom-Json +$clientSecret = ConvertTo-SecureString $credentials.clientSecret -AsPlainText -Force +$pscredentials = New-Object System.Management.Automation.PSCredential($credentials.applicationId, $clientSecret) +Login-AzureRmAccount -ServicePrincipal -Credential $pscredentials -TenantId $credentials.tenantId | Out-Null + +New-AzVm + +# clean-up +Remove-AzureRmResourceGroup -Name $resourceGroupName \ No newline at end of file diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 new file mode 100644 index 0000000000000000000000000000000000000000..2191f14717ec7f0215f97b99971af93c581f9fde GIT binary patch literal 7904 zcmeI1TW=Fr6ot=orTzztJOrvHG(ag-s)Usghy*E00_{Uz9N+4a*v57UwBoO~UEkT> zoH?GE#4+hbRTVkonK_rW_g?#U{KxNW;q&lWSPPBtJd8pooQ0Fn)!k`mg<%+kp6;e$ zrYAkUpTsxCaqFQOe$}jr#vN#l&9JR;r(vvTGdA;@R@C{XNuov9F^wT3=t8g(3>HuS8wfH-Nz&=yfH zt_9|G?YJrZo6UXKL+vuwA9{r;So}pe6kj?~Pljgt5vB7AeGY^UO;?R?1onIsZiZW# zlzU-E&(EX*+iRwsxrgO%bnR+IY&y{X#!}eNlcKef?8xyXybQLk$$1>Umc1W_dy@99 zJ{wxA7ar*8hMwKk_m;jf>Vb5!p(`WrYX+kp=L~{IL5Wg)eL)FUFu^^Wx@g&#s za>(%s%TCva`ssYlgzWFK!(S=QGPYQbTjf~NP;}o{+&&U}cEuX={B!AX5?)`KQJb1^ z^f5o;QSj9{3De0I#Az7)R=eSU@YE|5Vgns_qBu(+{GVlHO z>DnY&MyD?%D-{+on_7$7l)9`PxdTUt(N>u@R1NG$eRji_8uz2J?EUzyDIIq7{oV@N zbAFVOG;48G$C6Z4z-f3u-lICCUf~xpXod1f^EQtm zb)&rIuwEmtYMYT4UCB(XIEXu6q+7Js5*N&Ch&!L6pEb$9sH18`XsTST=ADRl7HIaS zA`^A|R%C4A3f#B+O-&0|`0uP}M?O$9PgGs94q5-YnUP{<5&u;2e57bx^w+v7{Ya6Q zZjoqi-Bd2~JK6JOE;;qP`9*HK^BDh42gzS9=QK9+{jY*~H~JABGoJO&;4Wgg3id_6 zEyn_)DmEC(D#Rl553-Z@#=Om|x8hsscq~dUjBaecv9qery`6QvW#)L)B|TmQ%72zFd zLv=X(?np0qZbz%2>7l+Y&LAe?xmNeMM_Z4|IRtxHUu!Gi+wk6c5>}@sv)m&Wg0RsFKZK9*=dh!(y|?vI#;*LNzp4I%R7K=J?YHl``;pq7HMCqofLC( zO|E8*SCNgJTGUv*hr&tfDdf?BRY3n#iO<{G#%7H`_>JFQzHnpU5? zrg-iMi&-S?R-H@I`y5R%`>&27jn zDC+FG^K;%)k_pK?SPQ#1WE(mWP+AQDTF!BI^u(~!{Y;g4xw9x#v>`Qmv14cDoCVyG zEg9)+rgL9@Rj582Ft5pVnoyYq((eTgt-@c9y>66`Uek;tq3TDgw8Yl2@OxD>iyEq~ zI$W=KB^le!?>NCo{Lbx)mhidJ{FKlt0P12p<3Rtc)E6FniJHLrB-4ar_G^y4%t#;S zSH?H>c`2`drfZUpU6Gm!X*ie1E2=u_@ls#euk3)2q;+0K8T`~aRT@6SuNPy3wZ=|P zOOJ)nPo2sr=@dud7mcHCs@I(LKR)i$a8f7I;h8U4tOkd11MdQTeFtBUa&NxoRq)a0 z!XC>=oU;&(h&rh&C|A*S_N-qG#;q4B1-In~J;$DpB{T8fcFp~=98=hzPu=WdWKB_^ zejN}zjhYziH=$wd5RChKA2C&P8x&Qu@f+qY%FS4QGvL=Gey=4znDxm%?{w!Zg&&+G zT3>-hik*&iVwZJ0#GUWw5d@vkjo{06#>!ni4x+9zaZfn>>}n(H@fzw4@D5f2zp=9{ Q<#r}baYk83AEIsl1ZKPsbN~PV literal 0 HcmV?d00001 diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 new file mode 100644 index 000000000000..bc7cdbd71afe --- /dev/null +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -0,0 +1,132 @@ +function New-AzVm { + # Images + Write-Host "Load images..." + $jsonImages = Get-Content -Path "images.json" | ConvertFrom-Json + Write-Host "done" + + # an array of @{ Type = ...; Name = ...; Image = ... } + $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { + # e.g. "Linux" + $type = $_.Name + $_.Value.psobject.Properties | ForEach-Object { + New-Object -TypeName psobject -Property @{ + # e.g. "Linux" + Type = $type; + # e.g. "CentOs" + Name = $_.Name; + # e.g. @{ publisher = "OpenLogic"; offer = "CentOS"; sku = "7.3"; version = "latest" } + Image = $_.Value + } + } + } + + # Find VM Image + $vmImageName = "Win2012R2Datacenter" + $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 + + Write-Host $vmImage + + # Location + Write-Host "Load locations..." + $location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location + $location = "eastus" + Write-Host "done" + + # Resource Group + $resourceGroupName = "resourceGroupTest" + New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + + # Virtual Network + $virtualNetworkName = "virtualNetworkTest" + $virtualNetworkAddressPrefix = "192.168.0.0/16" + $subnet = @{ Name = "subnetTest"; AddressPrefix = "192.168.1.0/24" } + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet.Name -AddressPrefix $subnet.AddressPrefix + $virtualNetwork = New-AzureRmVirtualNetwork ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $virtualNetworkName ` + -AddressPrefix $virtualNetworkAddressPrefix ` + -Subnet $subnetConfig + + # Piblic IP + $publicIpAddressName = "publicIpAddressTest" + $publicIpAddress = New-AzureRmPublicIpAddress ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -AllocationMethod Static ` + -Name $publicIpAddressName + + # Security Group (it may have several rules(ports)) + $securityGroupName = "securityGroupTest" + $securityRule = @{ + Name = "securityRuleTest"; + Protocol = "Tcp"; + Priority = 1000; + Access = "Allow"; + Direction = "Inbound"; + SourcePortRange = "*"; + SourceAddressPrefix = "*"; + DestinationPortRange = 3389; + DestinationAddressPrefix = "*"; + } + $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` + -Name $securityRule.Name ` + -Protocol $securityRule.Protocol ` + -Priority $securityRule.Priority ` + -Access $securityRule.Access ` + -Direction $securityRule.Direction ` + -SourcePortRange $securityRule.SourcePortRange ` + -SourceAddressPrefix $securityRule.SourceAddressPrefix ` + -DestinationPortRange $securityRule.DestinationPortRange ` + -DestinationAddressPrefix $securityRule.DestinationAddressPrefix + $securityGroup = New-AzureRmNetworkSecurityGroup ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $securityGroupName ` + -SecurityRules $securityRuleConfig + + # Network Interface + $networkInterfaceName = "networkInterfaceTest" + $networkInterface = New-AzureRmNetworkInterface ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $networkInterfaceName ` + -PublicIpAddressId $publicIpAddress.Id ` + -SubnetId $virtualNetwork.Subnets[0].Id ` + -NetworkSecurityGroupId $securityGroup.Id + + # VM + # $vmCredentials = Get-Credential + $vm = @{ Name = "vmTest"; Size = "Standard_DS2" } + $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size + $vmComputer = $vm.Name + $vmComputerPassword = "E5v7e9!@%f"; + $vmComputerUser = "special"; + switch ($vmImage.Type) { + "Windows" { + $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; + $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); + $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` + -Windows ` + -ComputerName $vmComputer ` + -Credential $cred + } + "Linux" { + + } + } + + $vmImageImage = $vmImage.Image + Write-Host $vmImageImage + $vmConfig = $vmConfig ` + | Set-AzureRmVMSourceImage ` + -PublisherName $vmImageImage.publisher ` + -Offer $vmImageImage.offer ` + -Skus $vmImageImage.sku ` + -Version $vmImageImage.version ` + | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id + + New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig +} + +Export-ModuleMember -Function New-AzVm \ No newline at end of file diff --git a/experiments/Compute.Experiments/images.json b/experiments/Compute.Experiments/images.json new file mode 100644 index 000000000000..df8a1577ffb3 --- /dev/null +++ b/experiments/Compute.Experiments/images.json @@ -0,0 +1,84 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [], + "outputs": { + "aliases": { + "type": "object", + "value": { + "Linux": { + "CentOS": { + "publisher": "OpenLogic", + "offer": "CentOS", + "sku": "7.3", + "version": "latest" + }, + "CoreOS": { + "publisher": "CoreOS", + "offer": "CoreOS", + "sku": "Stable", + "version": "latest" + }, + "Debian": { + "publisher": "credativ", + "offer": "Debian", + "sku": "8", + "version": "latest" + }, + "openSUSE-Leap": { + "publisher": "SUSE", + "offer": "openSUSE-Leap", + "sku": "42.2", + "version": "latest" + }, + "RHEL": { + "publisher": "RedHat", + "offer": "RHEL", + "sku": "7.3", + "version": "latest" + }, + "SLES": { + "publisher": "SUSE", + "offer": "SLES", + "sku": "12-SP2", + "version": "latest" + }, + "UbuntuLTS": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "16.04-LTS", + "version": "latest" + } + }, + "Windows": { + "Win2016Datacenter": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + }, + "Win2012R2Datacenter": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2012-R2-Datacenter", + "version": "latest" + }, + "Win2012Datacenter": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2012-Datacenter", + "version": "latest" + }, + "Win2008R2SP1": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2008-R2-SP1", + "version": "latest" + } + } + } + } + } +} \ No newline at end of file From 9eb80c707b634713ef195354866302954f024d17 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Fri, 1 Sep 2017 15:05:23 -0700 Subject: [PATCH 05/33] BOM ? --- .../AzureRM.Compute.Experiments.psd1 | Bin 7904 -> 3966 bytes .../AzureRM.Compute.Experiments.psm1 | 229 +++++++++--------- 2 files changed, 117 insertions(+), 112 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index 2191f14717ec7f0215f97b99971af93c581f9fde..f1a44ced5e6b6ca531878881c3c98fcb57a2d4e4 100644 GIT binary patch literal 3966 zcmc&%TTdf56n>AC|8PVe0#y=V7bvWRv=NtGBuG)Xv=4o8W;}_zGxn_QA!Mul@BQrY zOePT6qN;6PV0`(`ckaiXcB?~IDlSq^8IvO6#!{j*W#w9T_^r@xSzcH^ID5>w z78#e;baB^R|HLKN%<`Bfiw|@qBCU){?6X}ZKhV+k?)JN#-JkttyY=zUcFRHBL|Wvw z5(@DXA(>uO3yA1-ew-Zc_xIi>tUuX5-0ko0 z?Hn8>hlhLb4wFD?SlAg1xT;6H6_$ZjJ1AW6Y~_M*>4D35&E0Tf#4_&4JO{`ZT1;n_ zjD>q#Z1@l=9pvrUZk?#=&>DnOZhQbZKX~Gtl0rt#pez-3LAh2Bu#k(eRReXXc^A+@ zsVgBxR%Fnq^lm`?RY1YHp=&kg`ew${l(?J<$w~9Ch0tpxERQx~V84z5Z)lhcAt;n4yKg^1lexg2l( z>#QN#i#+)sH>rixNc!+6GeV^ ztF#J((GdZ@4{A`QU*SHtKj9Usysi!heAEtttR{{Q02cr$G(t-McVuO7>qMhEHpk;&__ezlZhGn9<9InH<6bNDD5UNg{ zQaOvhph?9D;d+z}lTtO0`)iGyX~LAn;8l=w)S{;l*IGPaLZg^j=9J1YQ@g(|SKgN0 zq1$IjC6*e6<|{2jJzyAxPaXPL8^wt zAp8fWh!t|^MsDo~m?(e(UP4r3L^JNOvD)reATMxoJ>D4A6^S%b7P;*kgL{RA&|Rvs za;&N8cUbKV#Tr+iMv5yv&FwN+SEH#cPoLq*3z;Zb|Kb^m4prN3x03B13JEJxG!xAe z@#wweMn-fF3PI`qv&G=B!0x2y$Y| KjhfN-cIz)<>Jg^^ literal 7904 zcmeI1TW=Fr6ot=orTzztJOrvHG(ag-s)Usghy*E00_{Uz9N+4a*v57UwBoO~UEkT> zoH?GE#4+hbRTVkonK_rW_g?#U{KxNW;q&lWSPPBtJd8pooQ0Fn)!k`mg<%+kp6;e$ zrYAkUpTsxCaqFQOe$}jr#vN#l&9JR;r(vvTGdA;@R@C{XNuov9F^wT3=t8g(3>HuS8wfH-Nz&=yfH zt_9|G?YJrZo6UXKL+vuwA9{r;So}pe6kj?~Pljgt5vB7AeGY^UO;?R?1onIsZiZW# zlzU-E&(EX*+iRwsxrgO%bnR+IY&y{X#!}eNlcKef?8xyXybQLk$$1>Umc1W_dy@99 zJ{wxA7ar*8hMwKk_m;jf>Vb5!p(`WrYX+kp=L~{IL5Wg)eL)FUFu^^Wx@g&#s za>(%s%TCva`ssYlgzWFK!(S=QGPYQbTjf~NP;}o{+&&U}cEuX={B!AX5?)`KQJb1^ z^f5o;QSj9{3De0I#Az7)R=eSU@YE|5Vgns_qBu(+{GVlHO z>DnY&MyD?%D-{+on_7$7l)9`PxdTUt(N>u@R1NG$eRji_8uz2J?EUzyDIIq7{oV@N zbAFVOG;48G$C6Z4z-f3u-lICCUf~xpXod1f^EQtm zb)&rIuwEmtYMYT4UCB(XIEXu6q+7Js5*N&Ch&!L6pEb$9sH18`XsTST=ADRl7HIaS zA`^A|R%C4A3f#B+O-&0|`0uP}M?O$9PgGs94q5-YnUP{<5&u;2e57bx^w+v7{Ya6Q zZjoqi-Bd2~JK6JOE;;qP`9*HK^BDh42gzS9=QK9+{jY*~H~JABGoJO&;4Wgg3id_6 zEyn_)DmEC(D#Rl553-Z@#=Om|x8hsscq~dUjBaecv9qery`6QvW#)L)B|TmQ%72zFd zLv=X(?np0qZbz%2>7l+Y&LAe?xmNeMM_Z4|IRtxHUu!Gi+wk6c5>}@sv)m&Wg0RsFKZK9*=dh!(y|?vI#;*LNzp4I%R7K=J?YHl``;pq7HMCqofLC( zO|E8*SCNgJTGUv*hr&tfDdf?BRY3n#iO<{G#%7H`_>JFQzHnpU5? zrg-iMi&-S?R-H@I`y5R%`>&27jn zDC+FG^K;%)k_pK?SPQ#1WE(mWP+AQDTF!BI^u(~!{Y;g4xw9x#v>`Qmv14cDoCVyG zEg9)+rgL9@Rj582Ft5pVnoyYq((eTgt-@c9y>66`Uek;tq3TDgw8Yl2@OxD>iyEq~ zI$W=KB^le!?>NCo{Lbx)mhidJ{FKlt0P12p<3Rtc)E6FniJHLrB-4ar_G^y4%t#;S zSH?H>c`2`drfZUpU6Gm!X*ie1E2=u_@ls#euk3)2q;+0K8T`~aRT@6SuNPy3wZ=|P zOOJ)nPo2sr=@dud7mcHCs@I(LKR)i$a8f7I;h8U4tOkd11MdQTeFtBUa&NxoRq)a0 z!XC>=oU;&(h&rh&C|A*S_N-qG#;q4B1-In~J;$DpB{T8fcFp~=98=hzPu=WdWKB_^ zejN}zjhYziH=$wd5RChKA2C&P8x&Qu@f+qY%FS4QGvL=Gey=4znDxm%?{w!Zg&&+G zT3>-hik*&iVwZJ0#GUWw5d@vkjo{06#>!ni4x+9zaZfn>>}n(H@fzw4@D5f2zp=9{ Q<#r}baYk83AEIsl1ZKPsbN~PV diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index bc7cdbd71afe..0e2dfe583511 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -1,132 +1,137 @@ function New-AzVm { - # Images - Write-Host "Load images..." - $jsonImages = Get-Content -Path "images.json" | ConvertFrom-Json - Write-Host "done" + [CmdletBinding()] + param () - # an array of @{ Type = ...; Name = ...; Image = ... } - $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { - # e.g. "Linux" - $type = $_.Name - $_.Value.psobject.Properties | ForEach-Object { - New-Object -TypeName psobject -Property @{ - # e.g. "Linux" - Type = $type; - # e.g. "CentOs" - Name = $_.Name; - # e.g. @{ publisher = "OpenLogic"; offer = "CentOS"; sku = "7.3"; version = "latest" } - Image = $_.Value + PROCESS { + # Images + Write-Host "Load images..." + $jsonImages = Get-Content -Path "images.json" | ConvertFrom-Json + Write-Host "done" + + # an array of @{ Type = ...; Name = ...; Image = ... } + $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { + # e.g. "Linux" + $type = $_.Name + $_.Value.psobject.Properties | ForEach-Object { + New-Object -TypeName psobject -Property @{ + # e.g. "Linux" + Type = $type; + # e.g. "CentOs" + Name = $_.Name; + # e.g. @{ publisher = "OpenLogic"; offer = "CentOS"; sku = "7.3"; version = "latest" } + Image = $_.Value + } } } - } - # Find VM Image - $vmImageName = "Win2012R2Datacenter" - $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 + # Find VM Image + $vmImageName = "Win2012R2Datacenter" + $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 - Write-Host $vmImage + Write-Host $vmImage - # Location - Write-Host "Load locations..." - $location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location - $location = "eastus" - Write-Host "done" + # Location + Write-Host "Load locations..." + $location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location + $location = "eastus" + Write-Host "done" - # Resource Group - $resourceGroupName = "resourceGroupTest" - New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + # Resource Group + $resourceGroupName = "resourceGroupTest" + New-AzureRmResourceGroup -Name $resourceGroupName -Location $location - # Virtual Network - $virtualNetworkName = "virtualNetworkTest" - $virtualNetworkAddressPrefix = "192.168.0.0/16" - $subnet = @{ Name = "subnetTest"; AddressPrefix = "192.168.1.0/24" } - $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet.Name -AddressPrefix $subnet.AddressPrefix - $virtualNetwork = New-AzureRmVirtualNetwork ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $virtualNetworkName ` - -AddressPrefix $virtualNetworkAddressPrefix ` - -Subnet $subnetConfig + # Virtual Network + $virtualNetworkName = "virtualNetworkTest" + $virtualNetworkAddressPrefix = "192.168.0.0/16" + $subnet = @{ Name = "subnetTest"; AddressPrefix = "192.168.1.0/24" } + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet.Name -AddressPrefix $subnet.AddressPrefix + $virtualNetwork = New-AzureRmVirtualNetwork ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $virtualNetworkName ` + -AddressPrefix $virtualNetworkAddressPrefix ` + -Subnet $subnetConfig - # Piblic IP - $publicIpAddressName = "publicIpAddressTest" - $publicIpAddress = New-AzureRmPublicIpAddress ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -AllocationMethod Static ` - -Name $publicIpAddressName + # Piblic IP + $publicIpAddressName = "publicIpAddressTest" + $publicIpAddress = New-AzureRmPublicIpAddress ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -AllocationMethod Static ` + -Name $publicIpAddressName - # Security Group (it may have several rules(ports)) - $securityGroupName = "securityGroupTest" - $securityRule = @{ - Name = "securityRuleTest"; - Protocol = "Tcp"; - Priority = 1000; - Access = "Allow"; - Direction = "Inbound"; - SourcePortRange = "*"; - SourceAddressPrefix = "*"; - DestinationPortRange = 3389; - DestinationAddressPrefix = "*"; - } - $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` - -Name $securityRule.Name ` - -Protocol $securityRule.Protocol ` - -Priority $securityRule.Priority ` - -Access $securityRule.Access ` - -Direction $securityRule.Direction ` - -SourcePortRange $securityRule.SourcePortRange ` - -SourceAddressPrefix $securityRule.SourceAddressPrefix ` - -DestinationPortRange $securityRule.DestinationPortRange ` - -DestinationAddressPrefix $securityRule.DestinationAddressPrefix - $securityGroup = New-AzureRmNetworkSecurityGroup ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $securityGroupName ` - -SecurityRules $securityRuleConfig + # Security Group (it may have several rules(ports)) + $securityGroupName = "securityGroupTest" + $securityRule = @{ + Name = "securityRuleTest"; + Protocol = "Tcp"; + Priority = 1000; + Access = "Allow"; + Direction = "Inbound"; + SourcePortRange = "*"; + SourceAddressPrefix = "*"; + DestinationPortRange = 3389; + DestinationAddressPrefix = "*"; + } + $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` + -Name $securityRule.Name ` + -Protocol $securityRule.Protocol ` + -Priority $securityRule.Priority ` + -Access $securityRule.Access ` + -Direction $securityRule.Direction ` + -SourcePortRange $securityRule.SourcePortRange ` + -SourceAddressPrefix $securityRule.SourceAddressPrefix ` + -DestinationPortRange $securityRule.DestinationPortRange ` + -DestinationAddressPrefix $securityRule.DestinationAddressPrefix + $securityGroup = New-AzureRmNetworkSecurityGroup ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $securityGroupName ` + -SecurityRules $securityRuleConfig - # Network Interface - $networkInterfaceName = "networkInterfaceTest" - $networkInterface = New-AzureRmNetworkInterface ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $networkInterfaceName ` - -PublicIpAddressId $publicIpAddress.Id ` - -SubnetId $virtualNetwork.Subnets[0].Id ` - -NetworkSecurityGroupId $securityGroup.Id + # Network Interface + $networkInterfaceName = "networkInterfaceTest" + $networkInterface = New-AzureRmNetworkInterface ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $networkInterfaceName ` + -PublicIpAddressId $publicIpAddress.Id ` + -SubnetId $virtualNetwork.Subnets[0].Id ` + -NetworkSecurityGroupId $securityGroup.Id - # VM - # $vmCredentials = Get-Credential - $vm = @{ Name = "vmTest"; Size = "Standard_DS2" } - $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size - $vmComputer = $vm.Name - $vmComputerPassword = "E5v7e9!@%f"; - $vmComputerUser = "special"; - switch ($vmImage.Type) { - "Windows" { - $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; - $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); - $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` - -Windows ` - -ComputerName $vmComputer ` - -Credential $cred - } - "Linux" { + # VM + # $vmCredentials = Get-Credential + $vm = @{ Name = "vmTest"; Size = "Standard_DS2" } + $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size + $vmComputer = $vm.Name + $vmComputerPassword = "E5v7e9!@%f"; + $vmComputerUser = "special"; + switch ($vmImage.Type) { + "Windows" { + $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; + $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); + $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` + -Windows ` + -ComputerName $vmComputer ` + -Credential $cred + } + "Linux" { + } } - } - $vmImageImage = $vmImage.Image - Write-Host $vmImageImage - $vmConfig = $vmConfig ` - | Set-AzureRmVMSourceImage ` - -PublisherName $vmImageImage.publisher ` - -Offer $vmImageImage.offer ` - -Skus $vmImageImage.sku ` - -Version $vmImageImage.version ` - | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id + $vmImageImage = $vmImage.Image + Write-Host $vmImageImage + $vmConfig = $vmConfig ` + | Set-AzureRmVMSourceImage ` + -PublisherName $vmImageImage.publisher ` + -Offer $vmImageImage.offer ` + -Skus $vmImageImage.sku ` + -Version $vmImageImage.version ` + | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id - New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig + New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig + } } Export-ModuleMember -Function New-AzVm \ No newline at end of file From 09a4dc27c9019e797ffb334f7a9117db8665642c Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Sat, 2 Sep 2017 01:30:00 -0700 Subject: [PATCH 06/33] hardcoded images --- .../AzureRM.Compute.Experiments.Tests.ps1 | 6 +- .../AzureRM.Compute.Experiments.psm1 | 102 ++++++++++++++++-- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index 3e95933b3ffb..a46272354504 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -10,7 +10,9 @@ $clientSecret = ConvertTo-SecureString $credentials.clientSecret -AsPlainText -F $pscredentials = New-Object System.Management.Automation.PSCredential($credentials.applicationId, $clientSecret) Login-AzureRmAccount -ServicePrincipal -Credential $pscredentials -TenantId $credentials.tenantId | Out-Null -New-AzVm +$vm = New-AzVm + +$vm # clean-up -Remove-AzureRmResourceGroup -Name $resourceGroupName \ No newline at end of file +Remove-AzureRmResourceGroup -ResourceId $vm.resourceId \ No newline at end of file diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 0e2dfe583511..18aa82f632aa 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -4,12 +4,15 @@ function New-AzVm { PROCESS { # Images + <# Write-Host "Load images..." $jsonImages = Get-Content -Path "images.json" | ConvertFrom-Json Write-Host "done" + #> # an array of @{ Type = ...; Name = ...; Image = ... } - $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { + # $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { + $images = $staticImages.psobject.Properties | ForEach-Object { # e.g. "Linux" $type = $_.Name $_.Value.psobject.Properties | ForEach-Object { @@ -25,7 +28,7 @@ function New-AzVm { } # Find VM Image - $vmImageName = "Win2012R2Datacenter" + $vmImageName = "openSUSE-Leap" # "Win2012R2Datacenter" $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 Write-Host $vmImage @@ -38,7 +41,7 @@ function New-AzVm { # Resource Group $resourceGroupName = "resourceGroupTest" - New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + $resource = New-AzureRmResourceGroup -Name $resourceGroupName -Location $location # Virtual Network $virtualNetworkName = "virtualNetworkTest" @@ -106,17 +109,20 @@ function New-AzVm { $vmComputer = $vm.Name $vmComputerPassword = "E5v7e9!@%f"; $vmComputerUser = "special"; + $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; + $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); switch ($vmImage.Type) { "Windows" { - $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; - $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Windows ` -ComputerName $vmComputer ` -Credential $cred } "Linux" { - + $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` + -Linux ` + -ComputerName $vmComputer ` + -Credential $cred } } @@ -130,8 +136,90 @@ function New-AzVm { -Version $vmImageImage.version ` | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id - New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig + New-PsObject @{ + ResourceId = $resource.ResourceId; + Response = New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig + } } } +function New-PsObject { + param([hashtable] $property) + + New-Object psobject -Property $property +} + +$staticImages = New-PsObject @{ + Linux = New-PsObject @{ + CentOS = New-PsObject @{ + publisher = "OpenLogic"; + offer = "CentOS"; + sku = "7.3"; + version = "latest"; + }; + CoreOS = New-PsObject @{ + publisher = "CoreOS"; + offer = "CoreOS"; + sku = "Stable"; + version = "latest"; + }; + Debian = New-PsObject @{ + publisher = "credativ"; + offer = "Debian"; + sku = "8"; + version = "latest"; + }; + "openSUSE-Leap" = New-PsObject @{ + publisher = "SUSE"; + offer = "openSUSE-Leap"; + sku = "42.2"; + version = "latest"; + }; + RHEL = New-PsObject @{ + publisher = "RedHat"; + offer = "RHEL"; + sku = "7.3"; + version = "latest"; + }; + SLES = New-PsObject @{ + publisher = "SUSE"; + offer = "SLES"; + sku = "12-SP2"; + version = "latest"; + }; + UbuntuLTS = New-PsObject @{ + publisher = "Canonical"; + offer = "UbuntuServer"; + sku = "16.04-LTS"; + version = "latest"; + }; + }; + Windows = New-PsObject @{ + Win2016Datacenter = New-PsObject @{ + publisher = "MicrosoftWindowsServer"; + offer = "WindowsServer"; + sku = "2016-Datacenter"; + version = "latest"; + }; + Win2012R2Datacenter = New-PsObject @{ + publisher = "MicrosoftWindowsServer"; + offer = "WindowsServer"; + sku = "2012-R2-Datacenter"; + version = "latest"; + }; + Win2012Datacenter = New-PsObject @{ + publisher = "MicrosoftWindowsServer"; + offer = "WindowsServer"; + sku = "2012-Datacenter"; + version = "latest"; + }; + Win2008R2SP1 = New-PsObject @{ + publisher = "MicrosoftWindowsServer"; + offer = "WindowsServer"; + sku = "2008-R2-SP1"; + version = "latest"; + }; + }; +} + Export-ModuleMember -Function New-AzVm \ No newline at end of file From 450720418577f6a741cf678c555860ff02b98fbc Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Sat, 2 Sep 2017 09:36:21 -0700 Subject: [PATCH 07/33] remove images.json --- experiments/Compute.Experiments/images.json | 84 --------------------- 1 file changed, 84 deletions(-) delete mode 100644 experiments/Compute.Experiments/images.json diff --git a/experiments/Compute.Experiments/images.json b/experiments/Compute.Experiments/images.json deleted file mode 100644 index df8a1577ffb3..000000000000 --- a/experiments/Compute.Experiments/images.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", - "contentVersion": "1.0.0.0", - "parameters": {}, - "variables": {}, - "resources": [], - "outputs": { - "aliases": { - "type": "object", - "value": { - "Linux": { - "CentOS": { - "publisher": "OpenLogic", - "offer": "CentOS", - "sku": "7.3", - "version": "latest" - }, - "CoreOS": { - "publisher": "CoreOS", - "offer": "CoreOS", - "sku": "Stable", - "version": "latest" - }, - "Debian": { - "publisher": "credativ", - "offer": "Debian", - "sku": "8", - "version": "latest" - }, - "openSUSE-Leap": { - "publisher": "SUSE", - "offer": "openSUSE-Leap", - "sku": "42.2", - "version": "latest" - }, - "RHEL": { - "publisher": "RedHat", - "offer": "RHEL", - "sku": "7.3", - "version": "latest" - }, - "SLES": { - "publisher": "SUSE", - "offer": "SLES", - "sku": "12-SP2", - "version": "latest" - }, - "UbuntuLTS": { - "publisher": "Canonical", - "offer": "UbuntuServer", - "sku": "16.04-LTS", - "version": "latest" - } - }, - "Windows": { - "Win2016Datacenter": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2016-Datacenter", - "version": "latest" - }, - "Win2012R2Datacenter": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2012-R2-Datacenter", - "version": "latest" - }, - "Win2012Datacenter": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2012-Datacenter", - "version": "latest" - }, - "Win2008R2SP1": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2008-R2-SP1", - "version": "latest" - } - } - } - } - } -} \ No newline at end of file From d63a3e920ceddd15382c30786fef95b002488282 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Sat, 2 Sep 2017 17:40:56 -0700 Subject: [PATCH 08/33] no password --- .../AzureRM.Compute.Experiments.Tests.ps1 | 8 ++- .../AzureRM.Compute.Experiments.psm1 | 57 +++++++++---------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index a46272354504..66632de7d23e 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -10,7 +10,13 @@ $clientSecret = ConvertTo-SecureString $credentials.clientSecret -AsPlainText -F $pscredentials = New-Object System.Management.Automation.PSCredential($credentials.applicationId, $clientSecret) Login-AzureRmAccount -ServicePrincipal -Credential $pscredentials -TenantId $credentials.tenantId | Out-Null -$vm = New-AzVm +$vmComputerPassword = $credentials.vmPassword; +$vmComputerUser = $credentials.vmUser; +$password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; +$vmCredential = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); + +# $vm = New-AzVm +$vm = New-AzVm -Credential $vmCredential $vm diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 18aa82f632aa..fb5a92017473 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -1,30 +1,13 @@ function New-AzVm { [CmdletBinding()] - param () + param ( + [PSCredential] $credential, + [string] $name = "vmTest" + ) PROCESS { - # Images - <# - Write-Host "Load images..." - $jsonImages = Get-Content -Path "images.json" | ConvertFrom-Json - Write-Host "done" - #> - - # an array of @{ Type = ...; Name = ...; Image = ... } - # $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { - $images = $staticImages.psobject.Properties | ForEach-Object { - # e.g. "Linux" - $type = $_.Name - $_.Value.psobject.Properties | ForEach-Object { - New-Object -TypeName psobject -Property @{ - # e.g. "Linux" - Type = $type; - # e.g. "CentOs" - Name = $_.Name; - # e.g. @{ publisher = "OpenLogic"; offer = "CentOS"; sku = "7.3"; version = "latest" } - Image = $_.Value - } - } + if (-not $credential) { + $credential = Get-Credential } # Find VM Image @@ -104,25 +87,21 @@ function New-AzVm { # VM # $vmCredentials = Get-Credential - $vm = @{ Name = "vmTest"; Size = "Standard_DS2" } + $vm = @{ Name = $name; Size = "Standard_DS2" } $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size $vmComputer = $vm.Name - $vmComputerPassword = "E5v7e9!@%f"; - $vmComputerUser = "special"; - $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; - $cred = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); switch ($vmImage.Type) { "Windows" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Windows ` -ComputerName $vmComputer ` - -Credential $cred + -Credential $credential } "Linux" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Linux ` -ComputerName $vmComputer ` - -Credential $cred + -Credential $credential } } @@ -222,4 +201,22 @@ $staticImages = New-PsObject @{ }; } +# Images +# an array of @{ Type = ...; Name = ...; Image = ... } +# $images = $jsonImages.outputs.aliases.value.psobject.Properties | ForEach-Object { +$images = $staticImages.psobject.Properties | ForEach-Object { + # e.g. "Linux" + $type = $_.Name + $_.Value.psobject.Properties | ForEach-Object { + New-Object -TypeName psobject -Property @{ + # e.g. "Linux" + Type = $type; + # e.g. "CentOs" + Name = $_.Name; + # e.g. @{ publisher = "OpenLogic"; offer = "CentOS"; sku = "7.3"; version = "latest" } + Image = $_.Value + } + } +} + Export-ModuleMember -Function New-AzVm \ No newline at end of file From 539bbe1445ceae2f99fd0657e8037a14c1f159bd Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Tue, 5 Sep 2017 11:16:54 -0700 Subject: [PATCH 09/33] parameter --- .../Compute.Experiments/AzureRM.Compute.Experiments.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index fb5a92017473..f44846819953 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -2,6 +2,7 @@ function New-AzVm { [CmdletBinding()] param ( [PSCredential] $credential, + [string] $imageName = "Win2012R2Datacenter", [string] $name = "vmTest" ) @@ -11,7 +12,7 @@ function New-AzVm { } # Find VM Image - $vmImageName = "openSUSE-Leap" # "Win2012R2Datacenter" + $vmImageName = $imageName $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 Write-Host $vmImage From 1d9486d58a2dd07af540c8b1ccc49a301f39c134 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Tue, 5 Sep 2017 18:08:14 -0700 Subject: [PATCH 10/33] Use specific version of modules --- .../AzureRM.Compute.Experiments.Tests.ps1 | 1 + .../AzureRM.Compute.Experiments.psd1 | 6 +- .../AzureRM.Compute.Experiments.psm1 | 76 ++++++++++--------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index 66632de7d23e..41c2ce8372f7 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -16,6 +16,7 @@ $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; $vmCredential = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); # $vm = New-AzVm +# $vm = New-AzVm -Credential $vmCredential $vm = New-AzVm -Credential $vmCredential $vm diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index f1a44ced5e6b..1fafb572ea35 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -51,7 +51,11 @@ PowerShellVersion = '5.0' # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module -RequiredModules = "AzureRM.Resources", "AzureRM.Network", "AzureRM.Compute" +RequiredModules = @( + @{ ModuleName = 'AzureRM.Resources'; ModuleVersion = '4.3.1'; }, + @{ ModuleName = 'AzureRM.Network'; ModuleVersion = '4.3.1'; }, + @{ ModuleName = 'AzureRM.Compute'; ModuleVersion = '3.3.1'; } +) # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index f44846819953..135d1377755a 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -1,56 +1,61 @@ function New-AzVm { [CmdletBinding()] param ( - [PSCredential] $credential, - [string] $imageName = "Win2012R2Datacenter", - [string] $name = "vmTest" + [Parameter()][PSCredential] $Credential, + [Parameter()][string] $Name = "VM", + [Parameter()][string] $ImageName = "Win2012R2Datacenter", + [Parameter()][string] $ResourceGroupName = $Name + "ResourceGroup", + [Parameter()][string] $Location = "eastus", + [Parameter()][string] $VirtualNetworkName = $Name + "VirtualNetwork", + [Parameter()][string] $PublicIpAddressName = $Name + "PublicIpAddress", + [Parameter()][string] $SecurityGroupName = $Name + "SecurityGroup", + [Parameter()][string] $NetworkInterfaceName = $Name + "NetworkInterface" ) PROCESS { - if (-not $credential) { - $credential = Get-Credential + if (-not $Credential) { + $Credential = Get-Credential } # Find VM Image - $vmImageName = $imageName - $vmImage = $images | Where-Object { $_.Name -eq $vmImageName } | Select-Object -First 1 + $vmImage = $images | Where-Object { $_.Name -eq $ImageName } | Select-Object -First 1 + if (-not $vmImage) { + throw "Unknown image: " + $ImageName + } Write-Host $vmImage # Location Write-Host "Load locations..." - $location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location - $location = "eastus" + # $Location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location Write-Host "done" # Resource Group - $resourceGroupName = "resourceGroupTest" - $resource = New-AzureRmResourceGroup -Name $resourceGroupName -Location $location + $resource = New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location # Virtual Network - $virtualNetworkName = "virtualNetworkTest" $virtualNetworkAddressPrefix = "192.168.0.0/16" - $subnet = @{ Name = "subnetTest"; AddressPrefix = "192.168.1.0/24" } - $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet.Name -AddressPrefix $subnet.AddressPrefix + $subnet = @{ Name = $Name + "Subnet"; AddressPrefix = "192.168.1.0/24" } + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` + -Name $subnet.Name ` + -AddressPrefix $subnet.AddressPrefix $virtualNetwork = New-AzureRmVirtualNetwork ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $virtualNetworkName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -Name $VirtualNetworkName ` -AddressPrefix $virtualNetworkAddressPrefix ` -Subnet $subnetConfig # Piblic IP - $publicIpAddressName = "publicIpAddressTest" $publicIpAddress = New-AzureRmPublicIpAddress ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` -AllocationMethod Static ` - -Name $publicIpAddressName + -Name $PublicIpAddressName # Security Group (it may have several rules(ports)) - $securityGroupName = "securityGroupTest" $securityRule = @{ - Name = "securityRuleTest"; + Name = $Name + "SecurityRule"; Protocol = "Tcp"; Priority = 1000; Access = "Allow"; @@ -71,24 +76,22 @@ function New-AzVm { -DestinationPortRange $securityRule.DestinationPortRange ` -DestinationAddressPrefix $securityRule.DestinationAddressPrefix $securityGroup = New-AzureRmNetworkSecurityGroup ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $securityGroupName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -Name $SecurityGroupName ` -SecurityRules $securityRuleConfig # Network Interface - $networkInterfaceName = "networkInterfaceTest" $networkInterface = New-AzureRmNetworkInterface ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $networkInterfaceName ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -Name $NetworkInterfaceName ` -PublicIpAddressId $publicIpAddress.Id ` -SubnetId $virtualNetwork.Subnets[0].Id ` -NetworkSecurityGroupId $securityGroup.Id # VM - # $vmCredentials = Get-Credential - $vm = @{ Name = $name; Size = "Standard_DS2" } + $vm = @{ Name = $Name; Size = "Standard_DS2" } $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size $vmComputer = $vm.Name switch ($vmImage.Type) { @@ -96,13 +99,13 @@ function New-AzVm { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Windows ` -ComputerName $vmComputer ` - -Credential $credential + -Credential $Credential } "Linux" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Linux ` -ComputerName $vmComputer ` - -Credential $credential + -Credential $Credential } } @@ -118,7 +121,10 @@ function New-AzVm { New-PsObject @{ ResourceId = $resource.ResourceId; - Response = New-AzureRmVm -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig + Response = New-AzureRmVm ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -VM $vmConfig } } } From 02692a720249dd89622c92eb71c229c428d905a7 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Wed, 6 Sep 2017 11:48:53 -0700 Subject: [PATCH 11/33] publishing. --- .../AzureRM.Compute.Experiments.psd1 | 10 +++++----- .../AzureRM.Compute.Experiments.psm1 | 5 ----- experiments/Compute.Experiments/publish-dev.ps1 | 13 +++++++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 experiments/Compute.Experiments/publish-dev.ps1 diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index 1fafb572ea35..e1dea5f5f6a6 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -12,7 +12,7 @@ RootModule = ".\AzureRM.Compute.Experiments.psm1" # Version number of this module. -ModuleVersion = '1.0' +ModuleVersion = '1.0.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -30,7 +30,7 @@ CompanyName = 'Microsoft' Copyright = 'Microsoft' # Description of the functionality provided by this module -# Description = '' +Description = 'Azure Compute' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '5.0' @@ -52,9 +52,9 @@ PowerShellVersion = '5.0' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @( - @{ ModuleName = 'AzureRM.Resources'; ModuleVersion = '4.3.1'; }, - @{ ModuleName = 'AzureRM.Network'; ModuleVersion = '4.3.1'; }, - @{ ModuleName = 'AzureRM.Compute'; ModuleVersion = '3.3.1'; } + @{ ModuleName = "AzureRM.Resources"; ModuleVersion = "4.3.1"; }, + @{ ModuleName = "AzureRM.Network"; ModuleVersion = "4.3.1"; }, + @{ ModuleName = "AzureRM.Compute"; ModuleVersion = "3.3.1"; } ) # Assemblies that must be loaded prior to importing this module diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 135d1377755a..1adc61c083ff 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -23,12 +23,8 @@ function New-AzVm { throw "Unknown image: " + $ImageName } - Write-Host $vmImage - # Location - Write-Host "Load locations..." # $Location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location - Write-Host "done" # Resource Group $resource = New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location @@ -110,7 +106,6 @@ function New-AzVm { } $vmImageImage = $vmImage.Image - Write-Host $vmImageImage $vmConfig = $vmConfig ` | Set-AzureRmVMSourceImage ` -PublisherName $vmImageImage.publisher ` diff --git a/experiments/Compute.Experiments/publish-dev.ps1 b/experiments/Compute.Experiments/publish-dev.ps1 new file mode 100644 index 000000000000..d3c462aa6eb2 --- /dev/null +++ b/experiments/Compute.Experiments/publish-dev.ps1 @@ -0,0 +1,13 @@ +$out = "..\build\AzureRM.Compute.Experiments\" +$repository = "sergey" +$dep = @("AzureRM.Resources", "AzureRM.Network", "AzureRM.Compute") +mkdir $out +copy .\AzureRM.Compute.Experiments.psd1 $out +copy .\AzureRM.Compute.Experiments.psm1 $out +foreach ($d in $dep) { + Install-Module $d -Repository $repository +} +Publish-Module -Path $out -Repository $repository -NuGetApiKey somekey +foreach ($d in $dep) { + Uninstall-Module $d +} From a321a65620d4bfa7fa9957c591af5c532979477a Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Wed, 6 Sep 2017 16:45:33 -0700 Subject: [PATCH 12/33] Set-ResourceGroup --- .../Compute.Experiments/Az.Compute.psm1 | 88 +++++++++++++++---- .../AzureRM.Compute.Experiments.psm1 | 43 ++++++--- .../Compute.Experiments/publish-dev.ps1 | 4 +- 3 files changed, 103 insertions(+), 32 deletions(-) diff --git a/experiments/Compute.Experiments/Az.Compute.psm1 b/experiments/Compute.Experiments/Az.Compute.psm1 index 0e1abef4fc02..e738c3fe6ad5 100644 --- a/experiments/Compute.Experiments/Az.Compute.psm1 +++ b/experiments/Compute.Experiments/Az.Compute.psm1 @@ -89,16 +89,33 @@ function New-AzVm { # Create! Write-Info "Ensuring resource group..."; - $rg = Use-ResourceGroup -ResourceGroup $ResourceGroup -Location $Location; + $rg = Use-ResourceGroup ` + -ResourceGroup $ResourceGroup ` + -Location $Location; Write-Info "Ensuring Vnet..."; - $vnet = Use-Vnet -Name $VnetName -ResourceGroup $ResourceGroup -Location $Location -SubnetAddressPrefix $SubnetAddressPrefix -VnetAddressPrefix $VnetAddressPrefix; + $vnet = Use-Vnet ` + -Name $VnetName ` + -ResourceGroup $ResourceGroup ` + -Location $Location ` + -SubnetAddressPrefix $SubnetAddressPrefix ` + -VnetAddressPrefix $VnetAddressPrefix; Write-Info "Ensuring public IP..."; - $pip = Use-Pip -Name $PublicIpName -ResourceGroup $ResourceGroup -Location $Location -DnsLabel $PublicIpDnsLabel -AllocationMethod $PublicIpAllocationMethod -IdleTimeoutInMinutes $PublicIpIdleTimeoutInMinutes; + $pip = Use-Pip ` + -Name $PublicIpName ` + -ResourceGroup $ResourceGroup ` + -Location $Location ` + -DnsLabel $PublicIpDnsLabel ` + -AllocationMethod $PublicIpAllocationMethod ` + -IdleTimeoutInMinutes $PublicIpIdleTimeoutInMinutes; Write-Info "Ensuring NSG..."; - $nsg = Use-Nsg -Name $NsgName -ResourceGroup $ResourceGroup -Location $Location -OpenPorts $NsgOpenPorts; + $nsg = Use-Nsg ` + -Name $NsgName ` + -ResourceGroup $ResourceGroup ` + -Location $Location ` + -OpenPorts $NsgOpenPorts; Write-Info "Ensuring NIC..."; $nic = Use-Nic ` @@ -113,10 +130,14 @@ function New-AzVm { # https://docs.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmosdisk?view=azurermps-4.2.0 # Create a virtual machine configuration - $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $Size | ` - Set-AzureRmVMOperatingSystem -Windows -ComputerName $Name -Credential $creds | ` - Set-AzureRmVMSourceImage -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2016-Datacenter -Version latest | ` - Add-AzureRmVMNetworkInterface -Id $nic.Id + $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $Size ` + | Set-AzureRmVMOperatingSystem -Windows -ComputerName $Name -Credential $creds ` + | Set-AzureRmVMSourceImage ` + -PublisherName MicrosoftWindowsServer ` + -Offer WindowsServer ` + -Skus 2016-Datacenter ` + -Version latest ` + | Add-AzureRmVMNetworkInterface -Id $nic.Id # Create a virtual machine $vm = New-AzureRmVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig @@ -148,7 +169,9 @@ function Use-ResourceGroup { [Parameter(Mandatory=$true)] [string] $Location ) - $rg = Get-AzureRmResourceGroup | Where-Object { $_.ResourceGroupName -eq $ResourceGroup } | Select-Object -First 1 -Wait; + $rg = Get-AzureRmResourceGroup ` + | Where-Object { $_.ResourceGroupName -eq $ResourceGroup } ` + | Select-Object -First 1 -Wait; if($rg -eq $null) { return New-AzureRmResourceGroup -Name $ResourceGroup -Location $Location; @@ -170,10 +193,17 @@ function Use-Vnet { if($vnet -eq $null) { # Create a subnet configuration. - $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name "$($Name)Subnet" -AddressPrefix $SubnetAddressPrefix; + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` + -Name "$($Name)Subnet" ` + -AddressPrefix $SubnetAddressPrefix; # Create a virtual network. - return New-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -AddressPrefix $VnetAddressPrefix -Subnet $subnetConfig + return New-AzureRmVirtualNetwork ` + -ResourceGroupName $ResourceGroup ` + -Location $Location ` + -Name $Name ` + -AddressPrefix $VnetAddressPrefix ` + -Subnet $subnetConfig } else { return $vnet; } @@ -193,7 +223,13 @@ function Use-Pip { if($pip -eq $null) { # Create a public IP address and specify a DNS name. - return New-AzureRmPublicIpAddress -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -DomainNameLabel $DnsLabel -AllocationMethod $AllocationMethod -IdleTimeoutInMinutes $IdleTimeoutInMinutes; + return New-AzureRmPublicIpAddress ` + -ResourceGroupName $ResourceGroup ` + -Location $Location ` + -Name $Name ` + -DomainNameLabel $DnsLabel ` + -AllocationMethod $AllocationMethod ` + -IdleTimeoutInMinutes $IdleTimeoutInMinutes; } else { return $pip; } @@ -210,19 +246,33 @@ function Use-Nsg { $nsg = Get-AzureRmNetworkSecurityGroup | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; if($nsg -eq $null) { - $rules = New-Object "System.Collections.Generic.List[Microsoft.Azure.Commands.Network.Models.PSSecurityRule]"; + $rules = New-Object ` + "System.Collections.Generic.List[Microsoft.Azure.Commands.Network.Models.PSSecurityRule]"; $priority = 1000; foreach($port in $OpenPorts) { - $nsgRule = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP -Protocol Tcp -Direction Inbound -Priority $priority -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $port -Access Allow; + $nsgRule = New-AzureRmNetworkSecurityRuleConfig ` + -Name myNetworkSecurityGroupRuleRDP ` + -Protocol Tcp ` + -Direction Inbound ` + -Priority $priority ` + -SourceAddressPrefix * ` + -SourcePortRange * ` + -DestinationAddressPrefix * ` + -DestinationPortRange $port ` + -Access Allow; $rules.Add($nsgRule); $priority--; } # Create an NSG. - return New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroup -Location $Location -Name $Name -SecurityRules $rules; + return New-AzureRmNetworkSecurityGroup ` + -ResourceGroupName $ResourceGroup ` + -Location $Location ` + -Name $Name ` + -SecurityRules $rules; } else { return $nsg; } @@ -242,7 +292,13 @@ function Use-Nic { if($nic -eq $null) { # Create a virtual network card and associate with public IP address and NSG - return New-AzureRmNetworkInterface -Name $Name -ResourceGroupName $resourceGroup -Location $location -SubnetId $SubnetId -PublicIpAddressId $PublicIpAddressId -NetworkSecurityGroupId $NetworkSecurityGroupId.ToString(); + return New-AzureRmNetworkInterface ` + -Name $Name ` + -ResourceGroupName $resourceGroup ` + -Location $location ` + -SubnetId $SubnetId ` + -PublicIpAddressId $PublicIpAddressId ` + -NetworkSecurityGroupId $NetworkSecurityGroupId.ToString(); } else { return $nic; } diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 1adc61c083ff..fa07d5317700 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -23,11 +23,8 @@ function New-AzVm { throw "Unknown image: " + $ImageName } - # Location - # $Location = (Get-AzureRmLocation | Select-Object -First 1 -Wait).Location - # Resource Group - $resource = New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location + $resourceGroup = Set-ResourceGroup -Name $ResourceGroupName -Location $Location # Virtual Network $virtualNetworkAddressPrefix = "192.168.0.0/16" @@ -87,20 +84,20 @@ function New-AzVm { -NetworkSecurityGroupId $securityGroup.Id # VM - $vm = @{ Name = $Name; Size = "Standard_DS2" } - $vmConfig = New-AzureRmVMConfig -VMName $vm.Name -VMSize $vm.Size - $vmComputer = $vm.Name + $vmSize = "Standard_DS2" + $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $vmSize + $vmComputerName = $Name + "Computer" switch ($vmImage.Type) { "Windows" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Windows ` - -ComputerName $vmComputer ` + -ComputerName $vmComputerName ` -Credential $Credential } "Linux" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Linux ` - -ComputerName $vmComputer ` + -ComputerName $vmComputerName ` -Credential $Credential } } @@ -114,16 +111,34 @@ function New-AzVm { -Version $vmImageImage.version ` | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id + $response = New-AzureRmVm ` + -ResourceGroupName $ResourceGroupName ` + -Location $Location ` + -VM $vmConfig + New-PsObject @{ - ResourceId = $resource.ResourceId; - Response = New-AzureRmVm ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -VM $vmConfig + ResourceId = $resourceGroup.ResourceId; + Response = $response } } } +function Set-ResourceGroup { + param( + [parameter(Mandatory = $true)][string]$Name, + [parameter(Mandatory = $true)][string]$Location + ) + + $resourceGroup = Get-AzureRmResourceGroup ` + | Where-Object { $_.ResourceGroupName -eq $Name } ` + | Select-Object -First 1 -Wait; + if ($resourceGroup) { + $resourceGroup; + } else { + New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location + } +} + function New-PsObject { param([hashtable] $property) diff --git a/experiments/Compute.Experiments/publish-dev.ps1 b/experiments/Compute.Experiments/publish-dev.ps1 index d3c462aa6eb2..b4369a72a831 100644 --- a/experiments/Compute.Experiments/publish-dev.ps1 +++ b/experiments/Compute.Experiments/publish-dev.ps1 @@ -2,8 +2,8 @@ $out = "..\build\AzureRM.Compute.Experiments\" $repository = "sergey" $dep = @("AzureRM.Resources", "AzureRM.Network", "AzureRM.Compute") mkdir $out -copy .\AzureRM.Compute.Experiments.psd1 $out -copy .\AzureRM.Compute.Experiments.psm1 $out +Copy-Item .\AzureRM.Compute.Experiments.psd1 $out +Copy-Item .\AzureRM.Compute.Experiments.psm1 $out foreach ($d in $dep) { Install-Module $d -Repository $repository } From 6571649a88d671475ac9e9cb83cbc7547ac8342f Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 7 Sep 2017 14:13:46 -0700 Subject: [PATCH 13/33] common --- .../AzureRM.Compute.Experiments.psd1 | 2 +- .../AzureRM.Compute.Experiments.psm1 | 80 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index e1dea5f5f6a6..baf69b571327 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -73,7 +73,7 @@ RequiredModules = @( # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'New-AzVm2','New-AzVm', 'New-AzVm3' +FunctionsToExport = 'New-AzVm' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. # CmdletsToExport = diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index fa07d5317700..15f01c8f6528 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -139,6 +139,86 @@ function Set-ResourceGroup { } } +class Common { + [string] $Location; + [string] $ResourceGroupName; + + [void] Update([string] $location, [string] $resourceGroupName) { + if (-not $this.Location) { + $this.Location = $location + } + if (-not $this.ResourceGroupName) { + $this.ResourceGroupName = $resourceGroupName + } + } +} + +class VirtualNetwork { + [string] $Name; + + [bool] UpdateCommon([Common] $common) { + if ($this.Name) { + $virtualNetwork = Get-AzureRMVirtualNetwork ` + | Where-Object { $_.Name -eq $Name } ` + | Select-Object -First 1 -Wait; + $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName) + return $true + } + return $false + } +} + +class PublicIpAddress { + [string] $Name; + + [bool] UpdateCommon([Common] $common) { + if ($this.Name) { + $virtualNetwork = Get-AzureRMPublicIpAddress ` + | Where-Object { $_.Name -eq $Name } ` + | Select-Object -First 1 -Wait; + $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName) + return $true + } + return $false + } +} + +class SecurityGroup { + [string] $Name; + + [bool] UpdateCommon([Common] $common) { + if ($this.Name) { + $virtualNetwork = Get-AzureRMSecurityGroup ` + | Where-Object { $_.Name -eq $Name } ` + | Select-Object -First 1 -Wait; + $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName); + return $true; + } + return $false; + } +} + +class NetworkInterface { + [string] $Name; + [VirtualNetwork] $VirtualNetwork; + [PublicIpAddress] $PublicIpAddress; + [SecurityGroup] $SecurityGroupName; + + [bool] UpdateCommon([Common] $common) { + if ($this.Name) { + $networkInterface = Get-AzureRMNetworkInterface ` + | Where-Object { $_.Name -eq $Name } ` + | Select-Object -First 1 -Wait; + $common.Update($networkInterface.Location, $networkInterface.ResourceGroupName); + return $true; + } else { + return $this.VirtualNetwork.UpdateCommon($common) ` + -or $this.PublicIpAddress.UpdateCommon($common) ` + -or $this.SecurityGroup.UpdateCommon($common); + } + } +} + function New-PsObject { param([hashtable] $property) From 96972d254dcb7121cd14540f1aa4ee40aeaa2ff8 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Fri, 8 Sep 2017 16:02:14 -0700 Subject: [PATCH 14/33] classes --- .../AzureRM.Compute.Experiments.psm1 | 213 ++++++++++++------ 1 file changed, 150 insertions(+), 63 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 15f01c8f6528..530dbb238fdf 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -4,18 +4,55 @@ function New-AzVm { [Parameter()][PSCredential] $Credential, [Parameter()][string] $Name = "VM", [Parameter()][string] $ImageName = "Win2012R2Datacenter", - [Parameter()][string] $ResourceGroupName = $Name + "ResourceGroup", + [Parameter()][string] $ResourceGroupName, [Parameter()][string] $Location = "eastus", - [Parameter()][string] $VirtualNetworkName = $Name + "VirtualNetwork", - [Parameter()][string] $PublicIpAddressName = $Name + "PublicIpAddress", - [Parameter()][string] $SecurityGroupName = $Name + "SecurityGroup", - [Parameter()][string] $NetworkInterfaceName = $Name + "NetworkInterface" + [Parameter()][string] $VirtualNetworkName, + [Parameter()][string] $PublicIpAddressName, + [Parameter()][string] $SecurityGroupName, + [Parameter()][string] $NetworkInterfaceName ) PROCESS { + $rgi = [ResourceGroup]::new($ResourceGroupName) + $nii = [NetworkInterface]::new( + $NetworkInterfaceName, + [VirtualNetwork]::new($VirtualNetworkName), + [PublicIpAddress]::new($PublicIpAddressName), + [SecurityGroup]::new($SecurityGroupName) + ); + $vmi = [VirtualMachine]::new($null, $nii, $rgi); + + $locationi = [Location]::new(); + if (-not $Location) { + $vmi.UpdateLocation($locationi); + if (-not $locationi.Value) { + $locationi.Value = "eastus"; + } + } else { + $locationi.Value = $Location; + } + + # Resource Group + $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value); + if (-not $Credential) { $Credential = Get-Credential } + if (-not $ResourceGroupName) { + $ResourceGroupName = $Name + "ResourceGroup"; + } + if (-not $VirtualNetworkName) { + $VirtualNetworkName = $Name + "VirtualNetwork"; + } + if (-not $PublicIpAddressName) { + $PublicIpAddressName = $Name + "PublicIpAddress"; + } + if (-not $SecurityGroupName) { + $SecurityGroupName = $Name + "SecurityGroup"; + } + if (-not $NetworkInterfaceName) { + $NetworkInterfaceName = $Name + "NetworkInterface" + } # Find VM Image $vmImage = $images | Where-Object { $_.Name -eq $ImageName } | Select-Object -First 1 @@ -24,7 +61,7 @@ function New-AzVm { } # Resource Group - $resourceGroup = Set-ResourceGroup -Name $ResourceGroupName -Location $Location + # $resourceGroup = Set-ResourceGroup -Name $ResourceGroupName -Location $Location # Virtual Network $virtualNetworkAddressPrefix = "192.168.0.0/16" @@ -139,83 +176,133 @@ function Set-ResourceGroup { } } -class Common { - [string] $Location; - [string] $ResourceGroupName; +class Location { + [int] $Priority; + [string] $Value; - [void] Update([string] $location, [string] $resourceGroupName) { - if (-not $this.Location) { - $this.Location = $location - } - if (-not $this.ResourceGroupName) { - $this.ResourceGroupName = $resourceGroupName - } + Location() { + $this.Priority = 0; + $this.Value = $null; } } -class VirtualNetwork { +class AzureObject { [string] $Name; + [AzureObject[]] $Children; + [int] $Priority; - [bool] UpdateCommon([Common] $common) { - if ($this.Name) { - $virtualNetwork = Get-AzureRMVirtualNetwork ` - | Where-Object { $_.Name -eq $Name } ` - | Select-Object -First 1 -Wait; - $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName) - return $true + AzureObject([string] $name, [AzureObject[]] $children) { + $this.Name = $name; + $this.Children = $children; + $this.Priority = 0; + foreach ($child in $this.Children) { + if ($this.Priority -lt $child.Priority) { + $this.Priority = $child.Priority; + } } - return $false + $this.Priority++; } -} -class PublicIpAddress { - [string] $Name; + # This function should be called only when $this.Name is not $null. + [object] GetInfo() { + return $null; + } - [bool] UpdateCommon([Common] $common) { + [object] Create([string] $name, [string] $location) { + return $null; + } + + [void] UpdateLocation([Location] $location) { + if ($this.Priority -gt $location.Priority) { + if ($this.Name) { + $location.Value = $this.GetInfo().Location; + $location.Priority = $this.Priority; + } else { + foreach ($child in $this.Children) { + $child.UpdateLocation($location); + } + } + } + } + + [object] GetOrCreate([string] $name, [string] $location) { if ($this.Name) { - $virtualNetwork = Get-AzureRMPublicIpAddress ` - | Where-Object { $_.Name -eq $Name } ` - | Select-Object -First 1 -Wait; - $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName) - return $true + return $this.GetInfo(); + } else { + $result = $this.Create($name, $location); + $this.Name = $name; + return $result; } - return $false } } -class SecurityGroup { - [string] $Name; +class ResourceGroup: AzureObject { + ResourceGroup([string] $name): base($name, @()) { + } - [bool] UpdateCommon([Common] $common) { - if ($this.Name) { - $virtualNetwork = Get-AzureRMSecurityGroup ` - | Where-Object { $_.Name -eq $Name } ` - | Select-Object -First 1 -Wait; - $common.Update($virtualNetwork.Location, $virtualNetwork.ResourceGroupName); - return $true; - } - return $false; + [object] GetInfo() { + return Get-AzureRmResourceGroup -Name $this.Name; + } + + [object] Create([string] $name, [string] $location) { + return New-AzureRmResourceGroup -Name $name -Location $location; } } -class NetworkInterface { - [string] $Name; - [VirtualNetwork] $VirtualNetwork; - [PublicIpAddress] $PublicIpAddress; - [SecurityGroup] $SecurityGroupName; +class Resource1: AzureObject { + Resource1([string] $name): base($name, @([ResourceGroup]::new($null))) { + } +} - [bool] UpdateCommon([Common] $common) { - if ($this.Name) { - $networkInterface = Get-AzureRMNetworkInterface ` - | Where-Object { $_.Name -eq $Name } ` - | Select-Object -First 1 -Wait; - $common.Update($networkInterface.Location, $networkInterface.ResourceGroupName); - return $true; - } else { - return $this.VirtualNetwork.UpdateCommon($common) ` - -or $this.PublicIpAddress.UpdateCommon($common) ` - -or $this.SecurityGroup.UpdateCommon($common); - } +class VirtualNetwork: Resource1 { + VirtualNetwork([string] $name): base($name) { + } + + [object] GetInfo() { + return Get-AzureRmVirtualNetwork -Name $this.Name; + } +} + +class PublicIpAddress: Resource1 { + PublicIpAddress([string] $name): base($name) { + } + + [object] GetInfo() { + return Get-AzureRMPublicIpAddress -Name $this.Name; + } +} + +class SecurityGroup: Resource1 { + SecurityGroup([string] $name): base($name) { + } + + [object] GetInfo() { + return Get-AzureRMSecurityGroup -Name $this.Name; + } +} + +class NetworkInterface: AzureObject { + NetworkInterface( + [string] $name, + [VirtualNetwork] $virtualNetwork, + [PublicIpAddress] $publicIpAddress, + [SecurityGroup] $securityGroup + ): base($name, @($virtualNetwork, $publicIpAddress, $securityGroup)) { + } + + [object] GetInfo() { + return Get-AzureRMNetworkInterface -Name $this.Name; + } +} + +class VirtualMachine: AzureObject { + VirtualMachine( + [string] $name, [NetworkInterface] $networkInterface, [ResourceGroup] $resourceGroup + ): base($name, @($networkInterface, $resourceGroup)) { + } + + [object] GetInfo() { + return Get-AzureRMVirtualMachine -Name $this.Name; } } From 255e154d5b9a5c616689eb779b544199008c03b5 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Fri, 8 Sep 2017 18:00:00 -0700 Subject: [PATCH 15/33] resource group name as a parameter --- .../AzureRM.Compute.Experiments.psm1 | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 530dbb238fdf..7a48f38b6d70 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -33,7 +33,7 @@ function New-AzVm { } # Resource Group - $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value); + $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); if (-not $Credential) { $Credential = Get-Credential @@ -208,7 +208,7 @@ class AzureObject { return $null; } - [object] Create([string] $name, [string] $location) { + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { return $null; } @@ -225,11 +225,11 @@ class AzureObject { } } - [object] GetOrCreate([string] $name, [string] $location) { + [object] GetOrCreate([string] $name, [string] $location, [string] $resourceGroupName) { if ($this.Name) { return $this.GetInfo(); } else { - $result = $this.Create($name, $location); + $result = $this.Create($name, $location, $resourceGroupName); $this.Name = $name; return $result; } @@ -244,7 +244,7 @@ class ResourceGroup: AzureObject { return Get-AzureRmResourceGroup -Name $this.Name; } - [object] Create([string] $name, [string] $location) { + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { return New-AzureRmResourceGroup -Name $name -Location $location; } } @@ -261,6 +261,18 @@ class VirtualNetwork: Resource1 { [object] GetInfo() { return Get-AzureRmVirtualNetwork -Name $this.Name; } + + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` + -Name "Subnet" ` + -AddressPrefix "192.168.1.0/24" + return New-AzureRmVirtualNetwork ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $name ` + -AddressPrefix "192.168.0.0/16" ` + -Subnet $subnetConfig + } } class PublicIpAddress: Resource1 { From 2384e268a1643737b3bc3cd59449c1f4521783cc Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Fri, 8 Sep 2017 18:28:01 -0700 Subject: [PATCH 16/33] Virtual Network as an object. --- .../AzureRM.Compute.Experiments.psm1 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 7a48f38b6d70..251ebe9002ff 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -13,10 +13,11 @@ function New-AzVm { ) PROCESS { - $rgi = [ResourceGroup]::new($ResourceGroupName) + $rgi = [ResourceGroup]::new($ResourceGroupName); + $vni = [VirtualNetwork]::new($VirtualNetworkName); $nii = [NetworkInterface]::new( $NetworkInterfaceName, - [VirtualNetwork]::new($VirtualNetworkName), + $vni, [PublicIpAddress]::new($PublicIpAddressName), [SecurityGroup]::new($SecurityGroupName) ); @@ -34,6 +35,10 @@ function New-AzVm { # Resource Group $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); + $virtualNetwork = $vni.GetOrCreate( + $Name + "VirtualNetwork", + $locationi.Value, + $resourceGroup.ResourceGroupName); if (-not $Credential) { $Credential = Get-Credential @@ -64,6 +69,7 @@ function New-AzVm { # $resourceGroup = Set-ResourceGroup -Name $ResourceGroupName -Location $Location # Virtual Network + <# $virtualNetworkAddressPrefix = "192.168.0.0/16" $subnet = @{ Name = $Name + "Subnet"; AddressPrefix = "192.168.1.0/24" } $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` @@ -75,6 +81,7 @@ function New-AzVm { -Name $VirtualNetworkName ` -AddressPrefix $virtualNetworkAddressPrefix ` -Subnet $subnetConfig + #> # Piblic IP $publicIpAddress = New-AzureRmPublicIpAddress ` From a434c6e0ece13f277e87dda6b048c9f579f98280 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 14:18:50 -0700 Subject: [PATCH 17/33] publicipaddress and securitygroup --- .../AzureRM.Compute.Experiments.psm1 | 113 +++++++++--------- 1 file changed, 54 insertions(+), 59 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 251ebe9002ff..b2ab5430addb 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -15,12 +15,13 @@ function New-AzVm { PROCESS { $rgi = [ResourceGroup]::new($ResourceGroupName); $vni = [VirtualNetwork]::new($VirtualNetworkName); + $piai = [PublicIpAddress]::new($PublicIpAddressName); + $sgi = [SecurityGroup]::new($SecurityGroupName); $nii = [NetworkInterface]::new( $NetworkInterfaceName, $vni, - [PublicIpAddress]::new($PublicIpAddressName), - [SecurityGroup]::new($SecurityGroupName) - ); + $piai, + $sgi); $vmi = [VirtualMachine]::new($null, $nii, $rgi); $locationi = [Location]::new(); @@ -33,12 +34,19 @@ function New-AzVm { $locationi.Value = $Location; } - # Resource Group $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); $virtualNetwork = $vni.GetOrCreate( $Name + "VirtualNetwork", $locationi.Value, $resourceGroup.ResourceGroupName); + $publicIpAddress = $piai.GetOrCreate( + $Name + "PublicIpAddress", + $locationi.Value, + $resourceGroup.ResourceGroupName); + $securityGroup = $sgi.GetOrCreate( + $Name + "SecurityGroup", + $locationi.Value, + $resourceGroup.ResourceGroupName) if (-not $Credential) { $Credential = Get-Credential @@ -65,59 +73,6 @@ function New-AzVm { throw "Unknown image: " + $ImageName } - # Resource Group - # $resourceGroup = Set-ResourceGroup -Name $ResourceGroupName -Location $Location - - # Virtual Network - <# - $virtualNetworkAddressPrefix = "192.168.0.0/16" - $subnet = @{ Name = $Name + "Subnet"; AddressPrefix = "192.168.1.0/24" } - $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` - -Name $subnet.Name ` - -AddressPrefix $subnet.AddressPrefix - $virtualNetwork = New-AzureRmVirtualNetwork ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -Name $VirtualNetworkName ` - -AddressPrefix $virtualNetworkAddressPrefix ` - -Subnet $subnetConfig - #> - - # Piblic IP - $publicIpAddress = New-AzureRmPublicIpAddress ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -AllocationMethod Static ` - -Name $PublicIpAddressName - - # Security Group (it may have several rules(ports)) - $securityRule = @{ - Name = $Name + "SecurityRule"; - Protocol = "Tcp"; - Priority = 1000; - Access = "Allow"; - Direction = "Inbound"; - SourcePortRange = "*"; - SourceAddressPrefix = "*"; - DestinationPortRange = 3389; - DestinationAddressPrefix = "*"; - } - $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` - -Name $securityRule.Name ` - -Protocol $securityRule.Protocol ` - -Priority $securityRule.Priority ` - -Access $securityRule.Access ` - -Direction $securityRule.Direction ` - -SourcePortRange $securityRule.SourcePortRange ` - -SourceAddressPrefix $securityRule.SourceAddressPrefix ` - -DestinationPortRange $securityRule.DestinationPortRange ` - -DestinationAddressPrefix $securityRule.DestinationAddressPrefix - $securityGroup = New-AzureRmNetworkSecurityGroup ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -Name $SecurityGroupName ` - -SecurityRules $securityRuleConfig - # Network Interface $networkInterface = New-AzureRmNetworkInterface ` -ResourceGroupName $ResourceGroupName ` @@ -289,6 +244,14 @@ class PublicIpAddress: Resource1 { [object] GetInfo() { return Get-AzureRMPublicIpAddress -Name $this.Name; } + + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + return New-AzureRmPublicIpAddress ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -AllocationMethod Static ` + -Name $name + } } class SecurityGroup: Resource1 { @@ -298,6 +261,37 @@ class SecurityGroup: Resource1 { [object] GetInfo() { return Get-AzureRMSecurityGroup -Name $this.Name; } + + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + $securityRule = @{ + Name = $name; + Protocol = "Tcp"; + Priority = 1000; + Access = "Allow"; + Direction = "Inbound"; + SourcePortRange = "*"; + SourceAddressPrefix = "*"; + DestinationPortRange = 3389; + DestinationAddressPrefix = "*"; + } + + $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` + -Name $name ` + -Protocol "Tcp" ` + -Priority 1000 ` + -Access "Allow" ` + -Direction "Inbound" ` + -SourcePortRange "*" ` + -SourceAddressPrefix "*" ` + -DestinationPortRange 3389 ` + -DestinationAddressPrefix "*" + + return New-AzureRmNetworkSecurityGroup ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $name ` + -SecurityRules $securityRuleConfig + } } class NetworkInterface: AzureObject { @@ -316,7 +310,9 @@ class NetworkInterface: AzureObject { class VirtualMachine: AzureObject { VirtualMachine( - [string] $name, [NetworkInterface] $networkInterface, [ResourceGroup] $resourceGroup + [string] $name, + [NetworkInterface] $networkInterface, + [ResourceGroup] $resourceGroup ): base($name, @($networkInterface, $resourceGroup)) { } @@ -324,7 +320,6 @@ class VirtualMachine: AzureObject { return Get-AzureRMVirtualMachine -Name $this.Name; } } - function New-PsObject { param([hashtable] $property) From 01cc466d1cb1d5463c33a4ae75e733bd1fdee3a3 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 15:12:48 -0700 Subject: [PATCH 18/33] NetworkInterface class implementation --- .../AzureRM.Compute.Experiments.psm1 | 54 ++++++++----------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index b2ab5430addb..b82059e13a25 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -35,18 +35,7 @@ function New-AzVm { } $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); - $virtualNetwork = $vni.GetOrCreate( - $Name + "VirtualNetwork", - $locationi.Value, - $resourceGroup.ResourceGroupName); - $publicIpAddress = $piai.GetOrCreate( - $Name + "PublicIpAddress", - $locationi.Value, - $resourceGroup.ResourceGroupName); - $securityGroup = $sgi.GetOrCreate( - $Name + "SecurityGroup", - $locationi.Value, - $resourceGroup.ResourceGroupName) + $networkInterface = $nii.GetOrCreate($Name, $locationi.Value, $resourceGroup.ResourceGroupName); if (-not $Credential) { $Credential = Get-Credential @@ -54,18 +43,6 @@ function New-AzVm { if (-not $ResourceGroupName) { $ResourceGroupName = $Name + "ResourceGroup"; } - if (-not $VirtualNetworkName) { - $VirtualNetworkName = $Name + "VirtualNetwork"; - } - if (-not $PublicIpAddressName) { - $PublicIpAddressName = $Name + "PublicIpAddress"; - } - if (-not $SecurityGroupName) { - $SecurityGroupName = $Name + "SecurityGroup"; - } - if (-not $NetworkInterfaceName) { - $NetworkInterfaceName = $Name + "NetworkInterface" - } # Find VM Image $vmImage = $images | Where-Object { $_.Name -eq $ImageName } | Select-Object -First 1 @@ -73,15 +50,6 @@ function New-AzVm { throw "Unknown image: " + $ImageName } - # Network Interface - $networkInterface = New-AzureRmNetworkInterface ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -Name $NetworkInterfaceName ` - -PublicIpAddressId $publicIpAddress.Id ` - -SubnetId $virtualNetwork.Subnets[0].Id ` - -NetworkSecurityGroupId $securityGroup.Id - # VM $vmSize = "Standard_DS2" $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $vmSize @@ -295,17 +263,37 @@ class SecurityGroup: Resource1 { } class NetworkInterface: AzureObject { + [VirtualNetwork] $VirtualNetwork; + [PublicIpAddress] $PublicIpAddress; + [SecurityGroup] $SecurityGroup; + NetworkInterface( [string] $name, [VirtualNetwork] $virtualNetwork, [PublicIpAddress] $publicIpAddress, [SecurityGroup] $securityGroup ): base($name, @($virtualNetwork, $publicIpAddress, $securityGroup)) { + $this.VirtualNetwork = $virtualNetwork; + $this.PublicIpAddress = $publicIpAddress; + $this.SecurityGroup = $securityGroup; } [object] GetInfo() { return Get-AzureRMNetworkInterface -Name $this.Name; } + + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + $xpublicIpAddress = $this.PublicIpAddress.GetOrCreate($name, $location, $resourceGroupName); + $xvirtualNetwork = $this.VirtualNetwork.GetOrCreate($name, $location, $resourceGroupName); + $xsecurityGroup = $this.SecurityGroup.GetOrCreate($name, $location, $resourceGroupName); + return New-AzureRmNetworkInterface ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -Name $name ` + -PublicIpAddressId $xpublicIpAddress.Id ` + -SubnetId $xvirtualNetwork.Subnets[0].Id ` + -NetworkSecurityGroupId $xsecurityGroup.Id + } } class VirtualMachine: AzureObject { From 144b3a6d0f9809576e6a69a330965e338276d000 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 15:21:35 -0700 Subject: [PATCH 19/33] unused object --- .../AzureRM.Compute.Experiments.psm1 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index b82059e13a25..cea118f4b688 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -231,18 +231,6 @@ class SecurityGroup: Resource1 { } [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { - $securityRule = @{ - Name = $name; - Protocol = "Tcp"; - Priority = 1000; - Access = "Allow"; - Direction = "Inbound"; - SourcePortRange = "*"; - SourceAddressPrefix = "*"; - DestinationPortRange = 3389; - DestinationAddressPrefix = "*"; - } - $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` -Name $name ` -Protocol "Tcp" ` From 3f782295110eab95510c52e686578c41fec0e656 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 16:02:00 -0700 Subject: [PATCH 20/33] VM creation using classes --- .../AzureRM.Compute.Experiments.psm1 | 115 ++++++++++-------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index cea118f4b688..27d062ce13ce 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -22,7 +22,7 @@ function New-AzVm { $vni, $piai, $sgi); - $vmi = [VirtualMachine]::new($null, $nii, $rgi); + $vmi = [VirtualMachine]::new($null, $nii, $rgi, $Credential, $ImageName, $images); $locationi = [Location]::new(); if (-not $Location) { @@ -35,57 +35,11 @@ function New-AzVm { } $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); - $networkInterface = $nii.GetOrCreate($Name, $locationi.Value, $resourceGroup.ResourceGroupName); - - if (-not $Credential) { - $Credential = Get-Credential - } - if (-not $ResourceGroupName) { - $ResourceGroupName = $Name + "ResourceGroup"; - } - - # Find VM Image - $vmImage = $images | Where-Object { $_.Name -eq $ImageName } | Select-Object -First 1 - if (-not $vmImage) { - throw "Unknown image: " + $ImageName - } - - # VM - $vmSize = "Standard_DS2" - $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $vmSize - $vmComputerName = $Name + "Computer" - switch ($vmImage.Type) { - "Windows" { - $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` - -Windows ` - -ComputerName $vmComputerName ` - -Credential $Credential - } - "Linux" { - $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` - -Linux ` - -ComputerName $vmComputerName ` - -Credential $Credential - } - } - - $vmImageImage = $vmImage.Image - $vmConfig = $vmConfig ` - | Set-AzureRmVMSourceImage ` - -PublisherName $vmImageImage.publisher ` - -Offer $vmImageImage.offer ` - -Skus $vmImageImage.sku ` - -Version $vmImageImage.version ` - | Add-AzureRmVMNetworkInterface -Id $networkInterface.Id - - $response = New-AzureRmVm ` - -ResourceGroupName $ResourceGroupName ` - -Location $Location ` - -VM $vmConfig + $vmResponse = $vmi.Create($Name, $locationi.Value, $resourceGroup.ResourceGroupName); New-PsObject @{ ResourceId = $resourceGroup.ResourceId; - Response = $response + Response = $vmResponse } } } @@ -285,16 +239,75 @@ class NetworkInterface: AzureObject { } class VirtualMachine: AzureObject { + [NetworkInterface] $NetworkInterface; + [pscredential] $Credential; + [string] $ImageName; + [object] $Images; + VirtualMachine( [string] $name, [NetworkInterface] $networkInterface, - [ResourceGroup] $resourceGroup - ): base($name, @($networkInterface, $resourceGroup)) { + [ResourceGroup] $resourceGroup, + [PSCredential] $credential, + [string] $imageName, + [object] $images): + base($name, @($networkInterface, $resourceGroup)) { + + $this.Credential = $credential; + $this.ImageName = $imageName; + $this.NetworkInterface = $networkInterface; + $this.Images = $images; } [object] GetInfo() { return Get-AzureRMVirtualMachine -Name $this.Name; } + + [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + $networkInterfaceInstance = $this.NetworkInterface.GetOrCreate( ` + $name, $location, $resourceGroupName); + + if (-not $this.Credential) { + $this.Credential = Get-Credential + } + + $vmImage = $this.Images | Where-Object { $_.Name -eq $this.ImageName } | Select-Object -First 1 + if (-not $vmImage) { + throw "Unknown image: " + $this.ImageName + } + + $vmSize = "Standard_DS2" + $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $vmSize + $vmComputerName = $Name + "Computer" + switch ($vmImage.Type) { + "Windows" { + $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` + -Windows ` + -ComputerName $vmComputerName ` + -Credential $this.Credential + } + "Linux" { + $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` + -Linux ` + -ComputerName $vmComputerName ` + -Credential $this.Credential + } + } + + $vmImageImage = $vmImage.Image + $vmConfig = $vmConfig ` + | Set-AzureRmVMSourceImage ` + -PublisherName $vmImageImage.publisher ` + -Offer $vmImageImage.offer ` + -Skus $vmImageImage.sku ` + -Version $vmImageImage.version ` + | Add-AzureRmVMNetworkInterface -Id $networkInterfaceInstance.Id + + return New-AzureRmVm ` + -ResourceGroupName $resourceGroupName ` + -Location $location ` + -VM $vmConfig + } } function New-PsObject { param([hashtable] $property) From 1ea0d9d465dd4c526ee81ddf5a3477fe93b36d79 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 16:12:49 -0700 Subject: [PATCH 21/33] remove Set-ResourceGroup --- .../AzureRM.Compute.Experiments.psm1 | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 27d062ce13ce..dd69156d77ed 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -44,22 +44,6 @@ function New-AzVm { } } -function Set-ResourceGroup { - param( - [parameter(Mandatory = $true)][string]$Name, - [parameter(Mandatory = $true)][string]$Location - ) - - $resourceGroup = Get-AzureRmResourceGroup ` - | Where-Object { $_.ResourceGroupName -eq $Name } ` - | Select-Object -First 1 -Wait; - if ($resourceGroup) { - $resourceGroup; - } else { - New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location - } -} - class Location { [int] $Priority; [string] $Value; From 90ab0facdf00ce64d541a6e13672b9e88b498863 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Mon, 11 Sep 2017 16:18:54 -0700 Subject: [PATCH 22/33] minor --- experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index dd69156d77ed..260c0d500b7c 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -293,6 +293,7 @@ class VirtualMachine: AzureObject { -VM $vmConfig } } + function New-PsObject { param([hashtable] $property) From 82731a3aba86de1cac5a03e65ce4e2157111b562 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 13:42:53 -0700 Subject: [PATCH 23/33] minor changes --- .../AzureRM.Compute.Experiments.Tests.ps1 | 2 +- .../AzureRM.Compute.Experiments.psm1 | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index 41c2ce8372f7..130e252a2e58 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -17,7 +17,7 @@ $vmCredential = New-Object System.Management.Automation.PSCredential ($vmCompute # $vm = New-AzVm # $vm = New-AzVm -Credential $vmCredential -$vm = New-AzVm -Credential $vmCredential +$vm = New-AzVm -Name MyVM -Credential $vmCredential $vm diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 260c0d500b7c..77dcebc0bb75 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -1,15 +1,15 @@ function New-AzVm { [CmdletBinding()] param ( + [Parameter(Mandatory=$true)][string] $Name = "VM", [Parameter()][PSCredential] $Credential, - [Parameter()][string] $Name = "VM", [Parameter()][string] $ImageName = "Win2012R2Datacenter", [Parameter()][string] $ResourceGroupName, - [Parameter()][string] $Location = "eastus", + [Parameter()][string] $Location, [Parameter()][string] $VirtualNetworkName, [Parameter()][string] $PublicIpAddressName, [Parameter()][string] $SecurityGroupName, - [Parameter()][string] $NetworkInterfaceName + # [Parameter()][string] $NetworkInterfaceName ) PROCESS { @@ -18,7 +18,7 @@ function New-AzVm { $piai = [PublicIpAddress]::new($PublicIpAddressName); $sgi = [SecurityGroup]::new($SecurityGroupName); $nii = [NetworkInterface]::new( - $NetworkInterfaceName, + $null, # $NetworkInterfaceName, $vni, $piai, $sgi); @@ -39,7 +39,7 @@ function New-AzVm { New-PsObject @{ ResourceId = $resourceGroup.ResourceId; - Response = $vmResponse + Response = $vmResponse; } } } From 35915ea5e2d7dcb91c1fb354760696da5c6c6567 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 14:33:48 -0700 Subject: [PATCH 24/33] Help template --- .../AzureRM.Compute.Experiments.psd1 | 2 +- .../AzureRM.Compute.Experiments.psm1 | 2 +- .../Compute.Experiments/docs/New-AzVm.md | 167 ++++++++++++++++++ 3 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 experiments/Compute.Experiments/docs/New-AzVm.md diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index baf69b571327..bbea7283a622 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -12,7 +12,7 @@ RootModule = ".\AzureRM.Compute.Experiments.psm1" # Version number of this module. -ModuleVersion = '1.0.1' +ModuleVersion = '1.0.2' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 77dcebc0bb75..b1b15856f024 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -8,7 +8,7 @@ function New-AzVm { [Parameter()][string] $Location, [Parameter()][string] $VirtualNetworkName, [Parameter()][string] $PublicIpAddressName, - [Parameter()][string] $SecurityGroupName, + [Parameter()][string] $SecurityGroupName # [Parameter()][string] $NetworkInterfaceName ) diff --git a/experiments/Compute.Experiments/docs/New-AzVm.md b/experiments/Compute.Experiments/docs/New-AzVm.md new file mode 100644 index 000000000000..cf1794664c36 --- /dev/null +++ b/experiments/Compute.Experiments/docs/New-AzVm.md @@ -0,0 +1,167 @@ +--- +external help file: AzureRM.Compute.Experiments-help.xml +Module Name: AzureRM.Compute.Experiments +online version: +schema: 2.0.0 +--- + +# New-AzVm + +## SYNOPSIS +{{Fill in the Synopsis}} + +## SYNTAX + +``` +New-AzVm [-Name] [[-Credential] ] [[-ImageName] ] + [[-ResourceGroupName] ] [[-Location] ] [[-VirtualNetworkName] ] + [[-PublicIpAddressName] ] [[-SecurityGroupName] ] +``` + +## DESCRIPTION +{{Fill in the Description}} + +## EXAMPLES + +### Example 1 +``` +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Credential +{{Fill Credential Description}} + +```yaml +Type: PSCredential +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImageName +{{Fill ImageName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Location +{{Fill Location Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +{{Fill Name Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PublicIpAddressName +{{Fill PublicIpAddressName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 6 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceGroupName +{{Fill ResourceGroupName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SecurityGroupName +{{Fill SecurityGroupName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 7 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -VirtualNetworkName +{{Fill VirtualNetworkName Description}} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 5 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## INPUTS + +### None + + +## OUTPUTS + +### System.Object + +## NOTES + +## RELATED LINKS + From e89a5485ca92fe9a67b4ce62bbbfd7de40b72a35 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 15:08:30 -0700 Subject: [PATCH 25/33] help --- .../Compute.Experiments/AzureRM.Compute.Experiments.psd1 | 2 +- .../Compute.Experiments/AzureRM.Compute.Experiments.psm1 | 3 +++ experiments/Compute.Experiments/publish-dev.ps1 | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index bbea7283a622..f6987ea25571 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -12,7 +12,7 @@ RootModule = ".\AzureRM.Compute.Experiments.psm1" # Version number of this module. -ModuleVersion = '1.0.2' +ModuleVersion = '1.0.4' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index b1b15856f024..9ddd792e316d 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -1,3 +1,6 @@ +<# +.ExternalHelp AzureRM.Compute.Experiments-help.xml +#> function New-AzVm { [CmdletBinding()] param ( diff --git a/experiments/Compute.Experiments/publish-dev.ps1 b/experiments/Compute.Experiments/publish-dev.ps1 index b4369a72a831..ac1402c1fe90 100644 --- a/experiments/Compute.Experiments/publish-dev.ps1 +++ b/experiments/Compute.Experiments/publish-dev.ps1 @@ -1,9 +1,11 @@ $out = "..\build\AzureRM.Compute.Experiments\" $repository = "sergey" $dep = @("AzureRM.Resources", "AzureRM.Network", "AzureRM.Compute") +Remove-Item $out -Recurse mkdir $out Copy-Item .\AzureRM.Compute.Experiments.psd1 $out Copy-Item .\AzureRM.Compute.Experiments.psm1 $out +New-ExternalHelp -Path .\docs\ -OutputPath $out foreach ($d in $dep) { Install-Module $d -Repository $repository } From 24c2a661966ecf60d4bf9136dd7fff56e69b95c4 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 15:59:02 -0700 Subject: [PATCH 26/33] docs --- .../AzureRM.Compute.Experiments.psm1 | 11 +++-- .../Compute.Experiments/docs/New-AzVm.md | 42 +++++++++---------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 9ddd792e316d..f255ebd300b4 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -4,7 +4,7 @@ function New-AzVm { [CmdletBinding()] param ( - [Parameter(Mandatory=$true)][string] $Name = "VM", + [Parameter(Mandatory=$true, Position=0)][string] $Name = "VM", [Parameter()][PSCredential] $Credential, [Parameter()][string] $ImageName = "Win2012R2Datacenter", [Parameter()][string] $ResourceGroupName, @@ -12,21 +12,26 @@ function New-AzVm { [Parameter()][string] $VirtualNetworkName, [Parameter()][string] $PublicIpAddressName, [Parameter()][string] $SecurityGroupName - # [Parameter()][string] $NetworkInterfaceName ) PROCESS { $rgi = [ResourceGroup]::new($ResourceGroupName); + $vni = [VirtualNetwork]::new($VirtualNetworkName); $piai = [PublicIpAddress]::new($PublicIpAddressName); $sgi = [SecurityGroup]::new($SecurityGroupName); + + # we don't allow to reuse NetworkInterface so $name is $null. $nii = [NetworkInterface]::new( - $null, # $NetworkInterfaceName, + $null, $vni, $piai, $sgi); + + # the purpouse of the New-AzVm cmdlet is to create (not get) a VM so $name is $null. $vmi = [VirtualMachine]::new($null, $nii, $rgi, $Credential, $ImageName, $images); + # infer a location $locationi = [Location]::new(); if (-not $Location) { $vmi.UpdateLocation($locationi); diff --git a/experiments/Compute.Experiments/docs/New-AzVm.md b/experiments/Compute.Experiments/docs/New-AzVm.md index cf1794664c36..8f75bd817378 100644 --- a/experiments/Compute.Experiments/docs/New-AzVm.md +++ b/experiments/Compute.Experiments/docs/New-AzVm.md @@ -1,14 +1,14 @@ --- external help file: AzureRM.Compute.Experiments-help.xml Module Name: AzureRM.Compute.Experiments -online version: +online version: schema: 2.0.0 --- # New-AzVm ## SYNOPSIS -{{Fill in the Synopsis}} +Creates a virtual machine and all required resources. ## SYNTAX @@ -19,26 +19,26 @@ New-AzVm [-Name] [[-Credential] ] [[-ImageName] ] ``` ## DESCRIPTION -{{Fill in the Description}} +The cmdlet creates a virtual machine and all required resources in Azure. ## EXAMPLES ### Example 1 ``` -PS C:\> {{ Add example code here }} +PS C:\> New-AzVm -Name MyCoolVM ``` -{{ Add example description here }} +Creates a virtual machine with name `MyCoolVM`. ## PARAMETERS ### -Credential -{{Fill Credential Description}} +Specifies the user name and password for the virtual machine as a PSCredential object. ```yaml Type: PSCredential Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 1 @@ -48,12 +48,12 @@ Accept wildcard characters: False ``` ### -ImageName -{{Fill ImageName Description}} +A name of virtual machine image. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 2 @@ -63,12 +63,12 @@ Accept wildcard characters: False ``` ### -Location -{{Fill Location Description}} +Specifies a location for the virtual machine. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 4 @@ -78,12 +78,12 @@ Accept wildcard characters: False ``` ### -Name -{{Fill Name Description}} +A name of a virtual machine. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: True Position: 0 @@ -93,12 +93,12 @@ Accept wildcard characters: False ``` ### -PublicIpAddressName -{{Fill PublicIpAddressName Description}} +Specifies a name of PublicIPAddress object to assign to a network interface. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 6 @@ -108,12 +108,12 @@ Accept wildcard characters: False ``` ### -ResourceGroupName -{{Fill ResourceGroupName Description}} +Specifies the name of a resource group. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 3 @@ -123,12 +123,12 @@ Accept wildcard characters: False ``` ### -SecurityGroupName -{{Fill SecurityGroupName Description}} +Specifies a Network Security Group name. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 7 @@ -138,12 +138,12 @@ Accept wildcard characters: False ``` ### -VirtualNetworkName -{{Fill VirtualNetworkName Description}} +Specifies a Virtual Network name. ```yaml Type: String Parameter Sets: (All) -Aliases: +Aliases: Required: False Position: 5 From 5d2629fa941de4b58e5f3557db5c32fedb853eb7 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 16:59:07 -0700 Subject: [PATCH 27/33] ShouldProcess --- .../AzureRM.Compute.Experiments.psd1 | 2 +- .../AzureRM.Compute.Experiments.psm1 | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index f6987ea25571..895311f327f5 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -12,7 +12,7 @@ RootModule = ".\AzureRM.Compute.Experiments.psm1" # Version number of this module. -ModuleVersion = '1.0.4' +ModuleVersion = '1.0.5' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index f255ebd300b4..82d8cafd3868 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -2,7 +2,7 @@ .ExternalHelp AzureRM.Compute.Experiments-help.xml #> function New-AzVm { - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory=$true, Position=0)][string] $Name = "VM", [Parameter()][PSCredential] $Credential, @@ -42,12 +42,14 @@ function New-AzVm { $locationi.Value = $Location; } - $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); - $vmResponse = $vmi.Create($Name, $locationi.Value, $resourceGroup.ResourceGroupName); + if ($PSCmdlet.ShouldProcess($Name, "Creating a virtual machine")) { + $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); + $vmResponse = $vmi.Create($Name, $locationi.Value, $resourceGroup.ResourceGroupName); - New-PsObject @{ - ResourceId = $resourceGroup.ResourceId; - Response = $vmResponse; + New-PsObject @{ + ResourceId = $resourceGroup.ResourceId; + Response = $vmResponse; + } } } } From b8950d45dc948d338bb5fc24c2cc6370044f5d16 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 17:09:07 -0700 Subject: [PATCH 28/33] -WhatIf test --- .../Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index 130e252a2e58..56e9047febc2 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -15,6 +15,8 @@ $vmComputerUser = $credentials.vmUser; $password = ConvertTo-SecureString $vmComputerPassword -AsPlainText -Force; $vmCredential = New-Object System.Management.Automation.PSCredential ($vmComputerUser, $password); +New-AzVm -Name MyVM -Credential $vmCredential -WhatIf + # $vm = New-AzVm # $vm = New-AzVm -Credential $vmCredential $vm = New-AzVm -Name MyVM -Credential $vmCredential From 63bf4b04fa4d3f5b8742faea88940fa331c4e39c Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 17:24:40 -0700 Subject: [PATCH 29/33] -Warning SilentlyContinue --- .../AzureRM.Compute.Experiments.psm1 | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 82d8cafd3868..2f418057d4ba 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -123,7 +123,10 @@ class ResourceGroup: AzureObject { } [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { - return New-AzureRmResourceGroup -Name $name -Location $location; + return New-AzureRmResourceGroup ` + -Name $name ` + -Location $location ` + -WarningAction SilentlyContinue; } } @@ -149,7 +152,8 @@ class VirtualNetwork: Resource1 { -Location $location ` -Name $name ` -AddressPrefix "192.168.0.0/16" ` - -Subnet $subnetConfig + -Subnet $subnetConfig ` + -WarningAction SilentlyContinue } } @@ -166,7 +170,8 @@ class PublicIpAddress: Resource1 { -ResourceGroupName $resourceGroupName ` -Location $location ` -AllocationMethod Static ` - -Name $name + -Name $name ` + -WarningAction SilentlyContinue } } @@ -194,7 +199,8 @@ class SecurityGroup: Resource1 { -ResourceGroupName $resourceGroupName ` -Location $location ` -Name $name ` - -SecurityRules $securityRuleConfig + -SecurityRules $securityRuleConfig ` + -WarningAction SilentlyContinue } } @@ -228,7 +234,8 @@ class NetworkInterface: AzureObject { -Name $name ` -PublicIpAddressId $xpublicIpAddress.Id ` -SubnetId $xvirtualNetwork.Subnets[0].Id ` - -NetworkSecurityGroupId $xsecurityGroup.Id + -NetworkSecurityGroupId $xsecurityGroup.Id ` + -WarningAction SilentlyContinue } } @@ -300,7 +307,8 @@ class VirtualMachine: AzureObject { return New-AzureRmVm ` -ResourceGroupName $resourceGroupName ` -Location $location ` - -VM $vmConfig + -VM $vmConfig ` + -WarningAction SilentlyContinue } } From 390bc2930b24b2dfb14346c406d713b502b9943f Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 17:44:52 -0700 Subject: [PATCH 30/33] 1.0.6 --- .../Compute.Experiments/AzureRM.Compute.Experiments.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 index 895311f327f5..b56584a2fd3a 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psd1 @@ -12,7 +12,7 @@ RootModule = ".\AzureRM.Compute.Experiments.psm1" # Version number of this module. -ModuleVersion = '1.0.5' +ModuleVersion = '1.0.6' # Supported PSEditions # CompatiblePSEditions = @() From 315747d87923598734c474ecf79fbfaef7a85ddf Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 18:15:52 -0700 Subject: [PATCH 31/33] CreateParams type --- .../AzureRM.Compute.Experiments.psm1 | 85 +++++++++++-------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 2f418057d4ba..971a58201edf 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -42,9 +42,11 @@ function New-AzVm { $locationi.Value = $Location; } + $createParams = [CreateParams]::new($Name, $locationi.Value, $Name); + if ($PSCmdlet.ShouldProcess($Name, "Creating a virtual machine")) { - $resourceGroup = $rgi.GetOrCreate($Name + "ResourceGroup", $locationi.Value, $null); - $vmResponse = $vmi.Create($Name, $locationi.Value, $resourceGroup.ResourceGroupName); + $resourceGroup = $rgi.GetOrCreate($createParams); + $vmResponse = $vmi.Create($createParams); New-PsObject @{ ResourceId = $resourceGroup.ResourceId; @@ -64,6 +66,18 @@ class Location { } } +class CreateParams { + [string] $Name; + [string] $Location; + [string] $ResourceGroupName; + + CreateParams([string] $name, [string] $location, [string] $resourceGroupName) { + $this.Name = $name; + $this.Location = $location; + $this.ResourceGroupName = $resourceGroupName; + } +} + class AzureObject { [string] $Name; [AzureObject[]] $Children; @@ -86,7 +100,7 @@ class AzureObject { return $null; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + [object] Create([CreateParams] $p) { return $null; } @@ -103,12 +117,12 @@ class AzureObject { } } - [object] GetOrCreate([string] $name, [string] $location, [string] $resourceGroupName) { + [object] GetOrCreate([CreateParams] $p) { if ($this.Name) { return $this.GetInfo(); } else { - $result = $this.Create($name, $location, $resourceGroupName); - $this.Name = $name; + $result = $this.Create($p); + $this.Name = $p.Name; return $result; } } @@ -122,10 +136,10 @@ class ResourceGroup: AzureObject { return Get-AzureRmResourceGroup -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + [object] Create([CreateParams] $p) { return New-AzureRmResourceGroup ` - -Name $name ` - -Location $location ` + -Name $p.Name ` + -Location $p.Location ` -WarningAction SilentlyContinue; } } @@ -143,14 +157,14 @@ class VirtualNetwork: Resource1 { return Get-AzureRmVirtualNetwork -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + [object] Create([CreateParams] $p) { $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` -Name "Subnet" ` -AddressPrefix "192.168.1.0/24" return New-AzureRmVirtualNetwork ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $name ` + -ResourceGroupName $p.ResourceGroupName ` + -Location $p.Location ` + -Name $p.Name ` -AddressPrefix "192.168.0.0/16" ` -Subnet $subnetConfig ` -WarningAction SilentlyContinue @@ -165,12 +179,12 @@ class PublicIpAddress: Resource1 { return Get-AzureRMPublicIpAddress -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + [object] Create([CreateParams] $p) { return New-AzureRmPublicIpAddress ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` + -ResourceGroupName $p.ResourceGroupName ` + -Location $p.Location ` + -Name $p.Name ` -AllocationMethod Static ` - -Name $name ` -WarningAction SilentlyContinue } } @@ -183,9 +197,9 @@ class SecurityGroup: Resource1 { return Get-AzureRMSecurityGroup -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { + [object] Create([CreateParams] $p) { $securityRuleConfig = New-AzureRmNetworkSecurityRuleConfig ` - -Name $name ` + -Name $p.Name ` -Protocol "Tcp" ` -Priority 1000 ` -Access "Allow" ` @@ -196,9 +210,9 @@ class SecurityGroup: Resource1 { -DestinationAddressPrefix "*" return New-AzureRmNetworkSecurityGroup ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $name ` + -ResourceGroupName $p.ResourceGroupName ` + -Location $p.Location ` + -Name $p.Name ` -SecurityRules $securityRuleConfig ` -WarningAction SilentlyContinue } @@ -224,14 +238,14 @@ class NetworkInterface: AzureObject { return Get-AzureRMNetworkInterface -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { - $xpublicIpAddress = $this.PublicIpAddress.GetOrCreate($name, $location, $resourceGroupName); - $xvirtualNetwork = $this.VirtualNetwork.GetOrCreate($name, $location, $resourceGroupName); - $xsecurityGroup = $this.SecurityGroup.GetOrCreate($name, $location, $resourceGroupName); + [object] Create([CreateParams] $p) { + $xpublicIpAddress = $this.PublicIpAddress.GetOrCreate($p); + $xvirtualNetwork = $this.VirtualNetwork.GetOrCreate($p); + $xsecurityGroup = $this.SecurityGroup.GetOrCreate($p); return New-AzureRmNetworkInterface ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` - -Name $name ` + -ResourceGroupName $p.ResourceGroupName ` + -Location $p.Location ` + -Name $p.Name ` -PublicIpAddressId $xpublicIpAddress.Id ` -SubnetId $xvirtualNetwork.Subnets[0].Id ` -NetworkSecurityGroupId $xsecurityGroup.Id ` @@ -264,9 +278,8 @@ class VirtualMachine: AzureObject { return Get-AzureRMVirtualMachine -Name $this.Name; } - [object] Create([string] $name, [string] $location, [string] $resourceGroupName) { - $networkInterfaceInstance = $this.NetworkInterface.GetOrCreate( ` - $name, $location, $resourceGroupName); + [object] Create([CreateParams] $p) { + $networkInterfaceInstance = $this.NetworkInterface.GetOrCreate($p); if (-not $this.Credential) { $this.Credential = Get-Credential @@ -278,8 +291,8 @@ class VirtualMachine: AzureObject { } $vmSize = "Standard_DS2" - $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $vmSize - $vmComputerName = $Name + "Computer" + $vmConfig = New-AzureRmVMConfig -VMName $p.Name -VMSize $vmSize + $vmComputerName = $p.Name + "Computer" switch ($vmImage.Type) { "Windows" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` @@ -305,8 +318,8 @@ class VirtualMachine: AzureObject { | Add-AzureRmVMNetworkInterface -Id $networkInterfaceInstance.Id return New-AzureRmVm ` - -ResourceGroupName $resourceGroupName ` - -Location $location ` + -ResourceGroupName $p.ResourceGroupName ` + -Location $p.Location ` -VM $vmConfig ` -WarningAction SilentlyContinue } From eac627773ecc282b7f697bbeb418985d8919ffc3 Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 18:55:14 -0700 Subject: [PATCH 32/33] OutputType --- .../AzureRM.Compute.Experiments.Tests.ps1 | 2 +- .../AzureRM.Compute.Experiments.psm1 | 57 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 index 56e9047febc2..2bc2c51f4506 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.Tests.ps1 @@ -24,4 +24,4 @@ $vm = New-AzVm -Name MyVM -Credential $vmCredential $vm # clean-up -Remove-AzureRmResourceGroup -ResourceId $vm.resourceId \ No newline at end of file +Remove-AzureRmResourceGroup -ResourceId $vm.ResourceGroupId \ No newline at end of file diff --git a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 index 971a58201edf..b373bf4f4eac 100644 --- a/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 +++ b/experiments/Compute.Experiments/AzureRM.Compute.Experiments.psm1 @@ -5,13 +5,17 @@ function New-AzVm { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory=$true, Position=0)][string] $Name = "VM", - [Parameter()][PSCredential] $Credential, - [Parameter()][string] $ImageName = "Win2012R2Datacenter", + [Parameter()][string] $ResourceGroupName, [Parameter()][string] $Location, + [Parameter()][string] $VirtualNetworkName, [Parameter()][string] $PublicIpAddressName, - [Parameter()][string] $SecurityGroupName + [Parameter()][string] $SecurityGroupName, + + [Parameter()][PSCredential] $Credential, + [Parameter()][string] $ImageName = "Win2012R2Datacenter", + [Parameter()][string] $Size = "Standard_DS1_v2" ) PROCESS { @@ -29,7 +33,14 @@ function New-AzVm { $sgi); # the purpouse of the New-AzVm cmdlet is to create (not get) a VM so $name is $null. - $vmi = [VirtualMachine]::new($null, $nii, $rgi, $Credential, $ImageName, $images); + $vmi = [VirtualMachine]::new( + $null, + $nii, + $rgi, + $Credential, + $ImageName, + $images, + $Size); # infer a location $locationi = [Location]::new(); @@ -48,14 +59,24 @@ function New-AzVm { $resourceGroup = $rgi.GetOrCreate($createParams); $vmResponse = $vmi.Create($createParams); - New-PsObject @{ - ResourceId = $resourceGroup.ResourceId; - Response = $vmResponse; - } + return [PSAzureVm]::new( + $resourceGroup.ResourceId, + $Name + ); } } } +class PSAzureVm { + [string] $ResourceGroupId; + [string] $Name; + + PSAzureVm([string] $resourceGroupId, [string] $name) { + $this.ResourceGroupId = $resourceGroupId; + $this.Name = $name; + } +} + class Location { [int] $Priority; [string] $Value; @@ -258,6 +279,7 @@ class VirtualMachine: AzureObject { [pscredential] $Credential; [string] $ImageName; [object] $Images; + [string] $Size; VirtualMachine( [string] $name, @@ -265,13 +287,15 @@ class VirtualMachine: AzureObject { [ResourceGroup] $resourceGroup, [PSCredential] $credential, [string] $imageName, - [object] $images): + [object] $images, + [string] $size): base($name, @($networkInterface, $resourceGroup)) { $this.Credential = $credential; $this.ImageName = $imageName; $this.NetworkInterface = $networkInterface; $this.Images = $images; + $this.Size = $size; } [object] GetInfo() { @@ -282,29 +306,28 @@ class VirtualMachine: AzureObject { $networkInterfaceInstance = $this.NetworkInterface.GetOrCreate($p); if (-not $this.Credential) { - $this.Credential = Get-Credential + $this.Credential = Get-Credential; } - $vmImage = $this.Images | Where-Object { $_.Name -eq $this.ImageName } | Select-Object -First 1 + $vmImage = $this.Images | Where-Object { $_.Name -eq $this.ImageName } | Select-Object -First 1; if (-not $vmImage) { - throw "Unknown image: " + $this.ImageName + throw "Unknown image: " + $this.ImageName; } - $vmSize = "Standard_DS2" - $vmConfig = New-AzureRmVMConfig -VMName $p.Name -VMSize $vmSize - $vmComputerName = $p.Name + "Computer" + $vmConfig = New-AzureRmVMConfig -VMName $p.Name -VMSize $this.Size; + $vmComputerName = $p.Name + "Computer"; switch ($vmImage.Type) { "Windows" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Windows ` -ComputerName $vmComputerName ` - -Credential $this.Credential + -Credential $this.Credential; } "Linux" { $vmConfig = $vmConfig | Set-AzureRmVMOperatingSystem ` -Linux ` -ComputerName $vmComputerName ` - -Credential $this.Credential + -Credential $this.Credential; } } From 01d6a9299c0a53486673d7a993a0bff0365423ab Mon Sep 17 00:00:00 2001 From: Sergey Shandar Date: Thu, 14 Sep 2017 18:58:49 -0700 Subject: [PATCH 33/33] remove old Az.Compute.psm1 --- .../Compute.Experiments/Az.Compute.psm1 | 331 ------------------ 1 file changed, 331 deletions(-) delete mode 100644 experiments/Compute.Experiments/Az.Compute.psm1 diff --git a/experiments/Compute.Experiments/Az.Compute.psm1 b/experiments/Compute.Experiments/Az.Compute.psm1 deleted file mode 100644 index e738c3fe6ad5..000000000000 --- a/experiments/Compute.Experiments/Az.Compute.psm1 +++ /dev/null @@ -1,331 +0,0 @@ -# Author: Aaron Roney. -# Modified: 20170827. -# Setup: Remove-Module Az.Compute; Import-Module .\Az.Compute.psm1; New-AzVm -Auto; - -# Resources: -# * [EXTERNAL] Azure PowerShell Docs: https://aka.ms/azpsdocs. -# * [EXTERNAL] Strategy Doc: https://aka.ms/azpsstrategy. -# * [EXTERNAL] Inspiration Sample: https://aka.ms/azpscreatevm. -# * [EXTERNAL] Community Standups: https://aka.ms/azpsnetstandup. -# * [EXTERNAL] Gallery Package: https://aka.ms/psazurerm. -# * [EXTERNAL] Docker: https://aka.ms/azpsdocker. -# * [EXTERNAL] Core Docker: https://aka.ms/azpscoredocker. -# * [INTERNAL] Research Evidence: https://aka.ms/azpsimprovementresearch. - -# TODO: -# * Implement `-Auto' parameter set (i.e., `Name` and `ResourceGroup` will become optional). -# * Implement new default formatter. -# * Lock down parameter list: should be good as is (if we add the option to set OS disk size). -# * Most of the parameters have "static" defaults: make these smart defaults, where applicable (e.g., location and open ports). -# * WinServer2016 is hardcoded: add parameters to allow people to use the full image provider, etc. -# * Import image providers, etc. from the "aliases.json". -# * Integrate into Nelson's build semantics. -# * Integrate app insights instrumentation so we can get good telemetry. - -#Requires -Modules AzureRM.Compute - -function New-AzVm { - param ( - [Parameter(Mandatory = $true)] [string] $Name, - [Parameter(Mandatory = $true)] [string] $ResourceGroup, - - # Generate a random as a hash of the name so it will be idempotent (tack on resource group?). - [Parameter(DontShow)] - $Random = $(Get-Hash $Name), - - [string] $Location = "", - - [string] $Image = "WinServer2016", - [string] $Size = "Standard_DS1_v2", - - [string] $VnetName = "$($Name)Vnet", - [string] $SubnetAddressPrefix = "192.168.1.0/24", - [string] $VnetAddressPrefix = "192.168.0.0/16", - - [string] $PublicIpName = "$($Name)PublicIp", - [string] $PublicIpDnsLabel = "$Name-$Random".ToLower(), - [string] $PublicIpAllocationMethod = "Static", - [int] $PublicIpIdleTimeoutInMinutes = 4, - - [string] $NsgName = "$($Name)Nsg", - [int[]] $NsgOpenPorts = $null, - - [string] $NicName = "$($Name)Nic" - - # Storage - OS Disk Size. - # Compute: "this goes above and beyond the 80% scenario". - ) - - try { - - # Build credentials. - - $userName = $env:UserName; - $ptPassword = -join ((33..122) | Get-Random -Count 20 | ForEach-Object { [char]$_ }); - $password = ConvertTo-SecureString $ptPassword -AsPlainText -Force; - $creds = New-Object System.Management.Automation.PSCredential ($env:UserName, $password); - - # Set the smart defaults. - - if($Location -eq "") { - # TODO: Infer the location somehow? - $Location = "westus2"; - } - - if($NsgOpenPorts -eq $null) { - # TODO: Infer the ports to open from the image types. - $NsgOpenPorts = @(3389,5985); - } - - # Get image aliases. - - # TODO: Properly set images from below. Put this in its own "ensure" method? - $images = Invoke-WebRequest "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json" | ConvertFrom-Json; - - # Set variables. - - $fqdn = "$PublicIpDnsLabel.$Location.cloudapp.azure.com"; - - # Create! - - Write-Info "Ensuring resource group..."; - $rg = Use-ResourceGroup ` - -ResourceGroup $ResourceGroup ` - -Location $Location; - - Write-Info "Ensuring Vnet..."; - $vnet = Use-Vnet ` - -Name $VnetName ` - -ResourceGroup $ResourceGroup ` - -Location $Location ` - -SubnetAddressPrefix $SubnetAddressPrefix ` - -VnetAddressPrefix $VnetAddressPrefix; - - Write-Info "Ensuring public IP..."; - $pip = Use-Pip ` - -Name $PublicIpName ` - -ResourceGroup $ResourceGroup ` - -Location $Location ` - -DnsLabel $PublicIpDnsLabel ` - -AllocationMethod $PublicIpAllocationMethod ` - -IdleTimeoutInMinutes $PublicIpIdleTimeoutInMinutes; - - Write-Info "Ensuring NSG..."; - $nsg = Use-Nsg ` - -Name $NsgName ` - -ResourceGroup $ResourceGroup ` - -Location $Location ` - -OpenPorts $NsgOpenPorts; - - Write-Info "Ensuring NIC..."; - $nic = Use-Nic ` - -Name $NicName ` - -ResourceGroup $ResourceGroup ` - -Location $Location ` - -SubnetId $vnet.Subnets[0].Id ` - -PublicIpAddressId $pip.Id ` - -NetworkSecurityGroupId $nsg.Id; - - # TODO: Add disk options (https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-vm-from-managed-os-disks?toc=%2fpowershell%2fmodule%2ftoc.json)? - # https://docs.microsoft.com/en-us/powershell/module/azurerm.compute/set-azurermvmosdisk?view=azurermps-4.2.0 - - # Create a virtual machine configuration - $vmConfig = New-AzureRmVMConfig -VMName $Name -VMSize $Size ` - | Set-AzureRmVMOperatingSystem -Windows -ComputerName $Name -Credential $creds ` - | Set-AzureRmVMSourceImage ` - -PublisherName MicrosoftWindowsServer ` - -Offer WindowsServer ` - -Skus 2016-Datacenter ` - -Version latest ` - | Add-AzureRmVMNetworkInterface -Id $nic.Id - - # Create a virtual machine - $vm = New-AzureRmVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig - - # Write info about VM. - - # TODO: Remove these and make this a formatter. - # Write-Info "$($tab)Resource group: $rgName."; - # Write-Info "$($tab)VM Name: MyVm$random."; - # Write-Info "$($tab)Location: $location."; - # Write-Info "$($tab)FQDN: $fqdn."; - Write-Info "$($tab)Username: $username."; - Write-Info "$($tab)Password: $ptPassword."; - - return $vm; - } catch { - Write-Error $_; - Write-Error "Something went wrong. Issue the command again: it is idempotent. :)"; - } -} - -Export-ModuleMember -Function New-AzVm - -# Helpers. - -function Use-ResourceGroup { - param ( - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location - ) - - $rg = Get-AzureRmResourceGroup ` - | Where-Object { $_.ResourceGroupName -eq $ResourceGroup } ` - | Select-Object -First 1 -Wait; - - if($rg -eq $null) { - return New-AzureRmResourceGroup -Name $ResourceGroup -Location $Location; - } else { - return $rg; - } -} - -function Use-Vnet { - param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $SubnetAddressPrefix, - [Parameter(Mandatory=$true)] [string] $VnetAddressPrefix - ) - - $vnet = Get-AzureRmVirtualNetwork | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; - - if($vnet -eq $null) { - # Create a subnet configuration. - $subnetConfig = New-AzureRmVirtualNetworkSubnetConfig ` - -Name "$($Name)Subnet" ` - -AddressPrefix $SubnetAddressPrefix; - - # Create a virtual network. - return New-AzureRmVirtualNetwork ` - -ResourceGroupName $ResourceGroup ` - -Location $Location ` - -Name $Name ` - -AddressPrefix $VnetAddressPrefix ` - -Subnet $subnetConfig - } else { - return $vnet; - } -} - -function Use-Pip { - param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $DnsLabel, - [Parameter(Mandatory=$true)] [string] $AllocationMethod, - [Parameter(Mandatory=$true)] [int] $IdleTimeoutInMinutes - ) - - $pip = Get-AzureRmPublicIpAddress | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; - - if($pip -eq $null) { - # Create a public IP address and specify a DNS name. - return New-AzureRmPublicIpAddress ` - -ResourceGroupName $ResourceGroup ` - -Location $Location ` - -Name $Name ` - -DomainNameLabel $DnsLabel ` - -AllocationMethod $AllocationMethod ` - -IdleTimeoutInMinutes $IdleTimeoutInMinutes; - } else { - return $pip; - } -} - -function Use-Nsg { - param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [int[]] $OpenPorts - ) - - $nsg = Get-AzureRmNetworkSecurityGroup | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; - - if($nsg -eq $null) { - $rules = New-Object ` - "System.Collections.Generic.List[Microsoft.Azure.Commands.Network.Models.PSSecurityRule]"; - $priority = 1000; - - foreach($port in $OpenPorts) - { - $nsgRule = New-AzureRmNetworkSecurityRuleConfig ` - -Name myNetworkSecurityGroupRuleRDP ` - -Protocol Tcp ` - -Direction Inbound ` - -Priority $priority ` - -SourceAddressPrefix * ` - -SourcePortRange * ` - -DestinationAddressPrefix * ` - -DestinationPortRange $port ` - -Access Allow; - $rules.Add($nsgRule); - - $priority--; - } - - # Create an NSG. - return New-AzureRmNetworkSecurityGroup ` - -ResourceGroupName $ResourceGroup ` - -Location $Location ` - -Name $Name ` - -SecurityRules $rules; - } else { - return $nsg; - } -} - -function Use-Nic { - param ( - [Parameter(Mandatory=$true)] [string] $Name, - [Parameter(Mandatory=$true)] [string] $ResourceGroup, - [Parameter(Mandatory=$true)] [string] $Location, - [Parameter(Mandatory=$true)] [string] $SubnetId, - [Parameter(Mandatory=$true)] [string] $PublicIpAddressId, - [Parameter(Mandatory=$true)] [psobject] $NetworkSecurityGroupId - ) - - $nic = Get-AzureRmNetworkInterface | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 -Wait; - - if($nic -eq $null) { - # Create a virtual network card and associate with public IP address and NSG - return New-AzureRmNetworkInterface ` - -Name $Name ` - -ResourceGroupName $resourceGroup ` - -Location $location ` - -SubnetId $SubnetId ` - -PublicIpAddressId $PublicIpAddressId ` - -NetworkSecurityGroupId $NetworkSecurityGroupId.ToString(); - } else { - return $nic; - } -} - -function Write-Info { - param ( - [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [String] $Text - ) - - Write-Host $Text -ForegroundColor Cyan; -} - -function Get-Hash { - param ( - [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [String] $TextToHash, - [int] $Count = 10 - ) - - $hasher = new-object System.Security.Cryptography.SHA256Managed; - $toHash = [System.Text.Encoding]::UTF8.GetBytes($TextToHash); - $hashByteArray = $hasher.ComputeHash($toHash); - - foreach($byte in $hashByteArray) - { - $res += $byte.ToString(); - } - - return $res.substring(0, $Count); -}