Export/Public/New-ScaleSet.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
function New-ScaleSet {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        Creates a new Scale Set, based on a previously generated image
    .DESCRIPTION
        ...
    #>

    param(
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceGroupName,        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceLocation,
        [Parameter(Mandatory = $true)]
        [string]
        $ImageName,
        [Parameter(Mandatory = $true)]
        [string]
        $ScaleSetName,
        [Parameter(Mandatory = $false)]
        [string]
        $VirtualNetworkResourceGroup,
        [Parameter(Mandatory = $true)]
        [string]
        $VirtualNetworkName,
        [Parameter(Mandatory = $true)]
        [string]
        $SubnetName,
        $PrivateIpAddress,
        [Parameter(Mandatory = $true)]
        [string]
        $KeyVaultName,
        [Parameter(Mandatory = $true)]
        [string]
        $VmAdminUserName,
        [Parameter(Mandatory = $true)]
        [string]
        $VmAdminPassword,
        [Parameter(Mandatory = $false)]
        [string]
        $VmSize,
        [int]
        [Parameter(Mandatory = $false)]
        $InstanceCount = 2,
        [Parameter(Mandatory = $false)]
        [object]
        $ResourceTags,
        [Parameter(Mandatory = $false)]
        [string]
        $TemplateFile,
        [Parameter(Mandatory = $false)]
        [string]
        $TemplateUri = "https://raw.githubusercontent.com/SimonOfHH/ARM-Templates/master/Templates/D365BCOnAzure/VMSS-Default.json",
        [switch]
        $AsJob
    )
    $scriptBlock = {
        $oldErrorActionPreference = $ErrorActionPreference
        $ErrorActionPreference = "Stop"

        $oldVerbosePreference = $VerbosePreference        
        $VerbosePreference = 'SilentlyContinue'
        Import-Module Az.Compute, Az.Resources, Az.KeyVault, Az.Storage
        $VerbosePreference = 'Continue'
        
        # Needed if started as Job
        $args[0].GetEnumerator() | ForEach-Object {
            New-Variable -Name $_.Key -Value $_.Value
        }
        try {
            Write-Verbose "Validating that Scale Set does not exist yet"
            if (Get-AzVmss -ResourceGroupName $ResourceGroupName -VMScaleSetName $ScaleSetName -ErrorAction SilentlyContinue) {
                Write-Verbose "Scale Set already exists. Exiting here."
                return
            }
            Write-Verbose "Validating that desired base image exists"
            $image = Get-AzImage -ResourceGroupName $resourceGroupName -ImageName $ImageName -ErrorAction SilentlyContinue
            if (-not($image)) {
                throw "Image $ImageName does not exist"
                return
            }

            Write-Verbose "Retrieving Domain-Join values from KeyVault"
            $domainAdminUserName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminUsername').SecretValueText
            $domainAdminUserPass = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminPassword').SecretValueText
            $domainName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainName').SecretValueText

            $vmssSettings = @{
                VmSsName            = $ScaleSetName
                VmSize              = $VmSize
                InstanceCount       = "$InstanceCount"
                VmAdminUserName     = $VmAdminUserName
                VmAdminPassword     = $VmAdminPassword
                BaseImageId         = $image.Id
                VirtualNetworkName  = $VirtualNetworkName
                SubnetName          = $SubnetName
                DomainName          = $domainName
                DomainAdminUsername = "$domainName\$domainAdminUserName"
                DomainAdminPassword = $domainAdminUserPass
            }
            $deployParams = @{
                Name                    = "$ScaleSetName-deploy"
                ResourceGroupName       = $ResourceGroupName
                TemplateParameterObject = $vmssSettings
            }
            if ($TemplateFile) {
                $deployParams.Add("TemplateFile", $TemplateFile)
            }
            else {
                if ($TemplateUri) {
                    $deployParams.Add("TemplateUri", $TemplateUri)
                }
            }
            New-AzResourceGroupDeployment @deployParams | Out-Null
        }
        catch {

        }
        Write-Verbose "Assigning access roles to managed identity of VM Scale Set..."
        $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -VMScaleSetName $ScaleSetName
        Wait-ForNewlyCreatedIdentity -ResourceGroupName $ResourceGroupName -ObjectId $VMSS.Identity.PrincipalId -Verbose:$Verbose
                
        Write-Verbose "Assigning role 'Reader' on Resource Group-level..."
        New-AzRoleAssignment -ObjectId $VMSS.Identity.PrincipalId -RoleDefinitionName "Reader" -ResourceGroupName $ResourceGroupName | Out-Null        
        Write-Verbose "Assigning role 'Contributor' on Storage Account-level..."
        New-AzRoleAssignment -ObjectId $VMSS.Identity.PrincipalId -RoleDefinitionName "Contributor" -ResourceGroupName $ResourceGroupName -ResourceName (Get-AzStorageAccount -ResourceGroupName $resourceGroupName | Select-Object -First 1).StorageAccountName -ResourceType "Microsoft.Storage/storageAccounts" | Out-Null
        Set-KeyVaultPermissionsForScaleSet -ResourceGroupName $ResourceGroupName -KeyVaultName $KeyVaultName -ScaleSetName $ScaleSetName -Verbose
        $VerbosePreference = $oldVerbosePreference
        $ErrorActionPreference = $oldErrorActionPreference
    }

    $params = Get-FunctionParameters $MyInvocation
    
    if ($AsJob) {            
        Start-Job -ScriptBlock $scriptBlock -InitializationScript { Import-Module D365BCOnAzureDeployment -Force } -ArgumentList $params
        #Start-Job -ScriptBlock $scriptBlock -ArgumentList $params
    }
    else {
        Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $params
    }
}