Export/New-DemoSqlServer.ps1

function Global:New-DemoSqlServer {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        ...
    .DESCRIPTION
        ...
    #>

    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceGroupName,        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceLocation,
        [Parameter(Mandatory = $true)]
        [string]
        $Name,
        [Alias("VirtualNetworkName")]
        [Parameter(Mandatory = $true)]
        [string]
        $VNetName,
        [Parameter(Mandatory = $true)]
        [string]
        $VMName,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImagePublisher,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImageOffer,
        [Parameter(Mandatory = $true)]
        [string]
        $VMImageSku,
        [Parameter(Mandatory = $true)]
        [string]
        $VMSize,
        [Parameter(Mandatory = $true)]
        [PSCredential]
        $VMCredentials,
        [Parameter(Mandatory = $true)]
        [int]
        $VMDiskSizeInGb,
        [Parameter(Mandatory = $true)]
        [string]
        $VMStorageAccountType,
        [Parameter(Mandatory = $true)]
        [string]
        $VMDataDiskName,
        [Alias("NetworkInterfaceName")]
        [Parameter(Mandatory = $true)]
        [string]
        $NicName,
        [Alias("NetworkInterfacePrivateIP")]
        [Parameter(Mandatory = $false)]
        [string]
        $NicPrivateIP,
        [Parameter(Mandatory = $false)]
        [string]
        $SubnetName,
        [Alias("PublicIPName")]
        [Parameter(Mandatory = $false)]
        [string]
        $PipName,
        [Alias("PublicIPDomainNameLabel")]
        [Parameter(Mandatory = $false)]
        [string]
        $PipDnsLabel,
        [Parameter(Mandatory = $false)]
        [string]
        $KeyVaultName,
        [Parameter(Mandatory = $true)]
        [string]
        $SqlUser,
        [Parameter(Mandatory = $true)]
        [string]
        $SqlPass,
        [Alias("Version")]
        [Parameter(Mandatory = $true)]
        [string]
        $BCVersion,
        [Alias("CumulativeUpdate")]
        [Parameter(Mandatory = $true)]
        [string]
        $BCCumulativeUpdate,
        [Alias("Language")]
        [Parameter(Mandatory = $true)]
        [string]
        $BCLanguage,
        [Parameter(Mandatory = $false)]
        [switch]
        $AsJob,
        [HashTable]
        $Tags
    )
    process {
        # TODO: Either disable Firewall or add rule for Sql Connections
        # TODO: Restore Demo Database after creation?
        Write-CustomHost -Message "Creating Demo SQL Server..."
        $scriptBlock = {
            # Create Variables in Scope of ScriptBlock for all variables passed in ArgumentList
            $args[0].GetEnumerator() | ForEach-Object {
                if ($_.Key -ne "AsJob") {
                    New-Variable -Name $_.Key -Value $_.Value
                }
            }

            $allParams = @{ }
            foreach ($param in ($args[0].GetEnumerator())) {
                if (($param.Name -notlike 'Sql*') -and ($param.Name -notlike 'AsJob') -and ($param.Name -notlike 'BC*')) {
                    $allParams.Add($param.Key, $param.Value)            
                }
            }
            # Create VM
            $sqlVM = New-CustomAzVm @allParams

            # Set SQL Extension
            $vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName
            if (-not($vm.Tags.ContainsKey("SqlExtension"))) {
                Write-CustomHost -Message "Adding SQL extension to VM... "
                Set-AzVMSqlServerExtension -ResourceGroupName $ResourceGroupName -VMName $VMName -name "SQLIaasExtension" -version "1.2" -Location $ResourceLocation | Out-Null
                Set-TagOnVM -VMName $VMName -TagName "SqlExtension" -TagValue "Executed"
            }

            # Configure Server before joining to domain
            $scriptExecutionParams = @{
                ResourceGroupName = $ResourceGroupName
                ResourceLocation  = $ResourceLocation
                VMName            = $VMName
            }
            $sqlParams = @{
                SqlUser = $SqlUser
                SqlPass = $SqlPass
            }
            Submit-ScriptToVmAndExecute @scriptExecutionParams -ScriptBlockName ConfigureSqlServer -RunParameter $sqlParams -MsgBeforeExecuting "Configuring SQL Server..."

            # Join in Domain
            $vm = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName
            if (-not($vm.Tags.ContainsKey("DomainJoined"))) {
                Write-CustomHost -Message "Joining Server to Domain... "
                $domainJoinSettings = Get-DomainJoinExtensionSettings -KeyVaultName $keyVaultName
                $domainJoinExtension = Set-AzVMExtension -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -VMName $VMName `
                    -Publisher $domainJoinSettings.Publisher -Type $domainJoinSettings.Type  -TypeHandlerVersion $domainJoinSettings.TypeHandlerVersion `
                    -Name $domainJoinSettings.Name -Settings $domainJoinSettings.Settings -ProtectedSettings $domainJoinSettings.ProtectedSetting
                Set-TagOnVM -VMName $VMName -TagName "DomainJoined" -TagValue "Executed"
            }

            # Configure Server
            $domainJoinSettings = Get-DomainJoinExtensionSettings -KeyVaultName $keyVaultName
            $DomainName = $domainJoinSettings.Settings.Name.Replace(".local", "").ToUpper()
            $sqlParams = @{
                SqlUser    = $SqlUser
                SqlPass    = $SqlPass
                DomainName = $DomainName
            }
            Submit-ScriptToVmAndExecute @scriptExecutionParams -ScriptBlockName ConfigureSqlServerDomain -RunParameter $sqlParams -MsgBeforeExecuting "Configuring SQL Server..."
            Submit-ScriptToVmAndExecute @scriptExecutionParams -ScriptBlockName InstallD365Module -MsgBeforeExecuting "Attempting to Install module on VM..."
            $bcVersionArgs = @{ }
            foreach ($param in $PsBoundParameters.GetEnumerator() | Where-Object { $_.Key -like "BC*" }) {
                $bcVersionArgs.Add($param.Key.Remove(0, 2), $param.Value)
            }
            Submit-ScriptToVmAndExecute @scriptExecutionParams -ScriptBlockName DownloadBC -RunParameter $bcVersionArgs -MsgBeforeExecuting "Attempting to download BC to VM..."
            Submit-ScriptToVmAndExecute @scriptExecutionParams -ScriptBlockName RestoreDemoDatabase -RunParameter $sqlParams -MsgBeforeExecuting "restoring demo database..."
        }
        # Get all parameters from within this function call and pass to actual ScriptBlock
        $params = Get-FunctionParameters $MyInvocation
        if ($AsJob) {            
            Start-Job -ScriptBlock $scriptBlock -InitializationScript { Import-Module SetupD365Environment -Force } -ArgumentList $params
        }
        else {
            Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $params
        }
    }
}