Public/Build-FMTTestVM.ps1

function Build-FMTTestVM {
    param(
        [parameter(Mandatory)]
        [ValidateSet('Windows','RHEL','SQL','SQLDev','Debian','Ubuntu','OEL8')]
        [string] $image,
        [parameter()]
        [string] $rg,
        [parameter()]
        [string] $vnetRG = $rg,
        [parameter(Mandatory)]
        [string] $vmName,
        [parameter()]
        [string] $vnet,
        [parameter()]
        [string] $subNet,
        [parameter()]
        [string] $dataSubnet,
        [parameter()]
        [switch] $publicIP,
        [parameter()]
        [string] $subscriptionName,
        [parameter(Mandatory)]
        [System.Management.Automation.PSCredential] $adminCreds,
        [parameter()]
        # [ValidateSet('Standard_D16s_v5','Standard_D32s_v5','Standard_D64s_v5')]
        [string] $size = 'Standard_D32s_v5',
        [parameter()]
        [int] $zone,
        [parameter()]
        [ValidateSet(1,2)]
        [int] $generation = 1,
        [parameter()]
        [switch] $trustedLaunch,
        [parameter()]
        [switch] $secureBoot,
        [parameter()]
        [string] $availabilitySetName,
        [parameter()]
        [string] $proximityPlacementGroupName
    )

    if ($proximityPlacementGroupName) {
        if (!$availabilitySetName) {
            $errorMsg = "if you specify -proximityPlacementGroupName you must also specify -availabilitySetName"
            return $errorMsg | Write-Error
        }
    }

    if ($availabilitySetName) {
        if (!$proximityPlacementGroupName) {
            $errorMsg = "if you specify -proximityPlacementGroupName you must also specify -availabilitySetName"
            return $errorMsg | Write-Error
        }
    }

    # Check AZ context

    $session = New-FMTSession
    if (!$session) {
        $message = '-- stopping --'
        return $message
    }

    if ($subscriptionName) {
        try {
            Get-AzSubscription -SubscriptionName $subscriptionName | Set-AzContext
        } catch {
            $error[0]
            exit
        }
    }
    
    # Fill in the gaps in parameter list

    if (!$rg) {
        $rgArray = Get-AzResourceGroup | Select-Object resourcegroupname,location | Sort-Object resourcegroupname
        $rg = Build-MenuFromArray -array $rgArray -property resourcegroupname -message "Select the desired resource group"
    }    
    
    if (!$vnetRG) {
        $vnetRG = $rg
        $rg = Build-MenuFromArray -array $rgArray -property resourcegroupname -message "Select the desired resource group"
    }

    if (!$vnet) {
        $vnetArray = Get-AzVirtualNetwork -ResourceGroupName $vnetRG | Select-Object name,location | Sort-Object name
        $vnetArray = Get-AzVirtualNetwork | Select-Object name,location | Sort-Object name
        $vnet = Build-MenuFromArray -array $vnetArray -property name -message "Select the desired Virtualnetwork"
    }

    if (!$subNet) {
        $subnetArray = Get-AzVirtualNetwork -Name $vnet -ResourceGroupName $vnetRG  | Get-AzVirtualNetworkSubnetConfig | Select-Object name
        $subnet = Build-MenuFromArray -array $subnetArray -property name -message "Select the desired management subnet"
    }

    if (!$dataSubnet) {
        $dataSubnetArray = Get-AzVirtualNetwork -Name $vnet -ResourceGroupName $vnetRG | Get-AzVirtualNetworkSubnetConfig | Select-Object name
        $dataSubnet = Build-MenuFromArray -array $dataSubnetArray -property name -message "Select the desired data subnet. Leave blank for no data interface."
    }

    # Get location data
    $rgData = Get-AzResourceGroup -ResourceGroupName $rg

    # create a PIP
    if ($publicIP) {
        $pipName = $vmName + '-pip'
        $pip = Get-AzPublicIpAddress -ResourceGroupName $rg -Name $pipName -ErrorAction SilentlyContinue
        if (!$pip) {
            Write-Host -ForegroundColor yellow "-- Public IP not found, setting one up for use..."
            if ($zone) {
                $pip = New-AzPublicIpAddress -Name $pipName -ResourceGroupName $rg -Location $rgData.Location -Sku Standard -AllocationMethod Static -Zone $zone
            } else {
                $pip = New-AzPublicIpAddress -Name $pipName -ResourceGroupName $rg -Location $rgData.Location -Sku Standard -AllocationMethod Static 
            }
        }    
    }

    # Create Data interface(s)
    $nic1Name = $vmName + '-mgmt'
    $nic1subnet = Get-AzVirtualNetwork -ResourceGroupName $vnetRG -Name $vnet | Get-AzVirtualNetworkSubnetConfig | where-object {$_.name -eq $subNet}
    if ($publicIP) {
        $mgmtNic = New-AzNetworkInterface -Subnet $nic1subnet -Name $nic1Name -ResourceGroupName $rg -Location $rgData.Location -EnableAcceleratedNetworking -PublicIpAddress $pip
    } else {
        $mgmtNic = New-AzNetworkInterface -Subnet $nic1subnet -Name $nic1Name -ResourceGroupName $rg -Location $rgData.Location -EnableAcceleratedNetworking 
    }

    if ($dataSubnet) {
        Write-Host '-- Adding Data interface --'
        $nic2Name = $vmName + '-data'
        $nic2subnet = Get-AzVirtualNetwork -ResourceGroupName $vnetRG -Name $vnet | Get-AzVirtualNetworkSubnetConfig | where-object {$_.name -eq $dataSubnet}
        $dataNic = New-AzNetworkInterface -Subnet $nic2subnet -Name $nic2Name -ResourceGroupName $rg -Location $rgData.Location -EnableAcceleratedNetworking
    }

    # Create the user credential
    $cred = $adminCreds

    # create the VM config
    if ($proximityPlacementGroupName) {
        $ppg = Get-AzProximityPlacementGroup -Name $proximityPlacementGroupName -ResourceGroupName $rg
    }
    if ($zone) {
        if ($proximityPlacementGroupName) {
            $aset = Get-AzAvailabilitySet -Name $availabilitySetName -ResourceGroupName $rg
            $vmConfig = New-AzVMConfig -VMName $vmName -VMSize $size -Zone $zone -ProximityPlacementGroupId $ppg.id
        } else {
            $vmConfig = New-AzVMConfig -VMName $vmName -VMSize $size -Zone $zone
        } 
    } else {
        if ($proximityPlacementGroupName) {
            $aset = Get-AzAvailabilitySet -Name $availabilitySetName -ResourceGroupName $rg
            $vmConfig = New-AzVMConfig -VMName $vmName -VMSize $size -ProximityPlacementGroupId $ppg.id -AvailabilitySetId $aset.id
        } else {
            $vmConfig = New-AzVMConfig -VMName $vmName -VMSize $size 
        } 
    }

    if ($trustedLaunch) {
        $vmConfig | Set-AzVmSecurityProfile -SecurityType "TrustedLaunch" 
    } else {
        $vmConfig | Set-AzVmSecurityProfile -SecurityType "Standard"
    }

    if ($secureBoot) {
        $vmConfig | Set-AzVmUefi -EnableVtpm $true -EnableSecureBoot $true
    }

    if ($image -eq 'Windows') {
        Write-Host '-- Setting OS for Windows --'
        $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred 
        if ($generation -eq 1) {
            $vmConfig | Set-AzVMSourceImage -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2022-datacenter" -Version "latest"
        } elseif ($generation -eq 2) {
            $vmConfig | Set-AzVMSourceImage -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2022-datacenter-g2" -Version "latest"
        }
    } elseif ($image -eq 'SQL') {
        Write-Host '-- Setting OS for Windows SQL --'
        $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred 
        $vmConfig | Set-AzVMSourceImage -PublisherName "microsoftsqlserver" -Offer "sql2022-ws2022" -Skus "enterprise-gen2" -Version "latest"
    } elseif ($image -eq 'SQLDev') {
        Write-Host '-- Setting OS for Windows SQL Dev --'
        $vmConfig | Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred 
        if ($generation -eq 1) {
            $vmConfig | Set-AzVMSourceImage -PublisherName "microsoftsqlserver" -Offer "sql2019-ws2019" -Skus "sqldev" -Version "latest"
        } elseif ($generation -eq 2) {
            $vmConfig | Set-AzVMSourceImage -PublisherName "microsoftsqlserver" -Offer "sql2019-ws2019" -Skus "sqldev-gen2" -Version "latest"
        }
    } elseif ($image -eq 'RHEL') {
        Write-Host '-- Setting OS for RHEL --'
        $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $vmName -Credential $cred 
        $vmConfig | Set-AzVMSourceImage -PublisherName "RedHat" -Offer "RHEL" -Skus "87-gen2" -Version "latest"
    } elseif ($image -eq 'Debian') {
        Write-Host '-- Setting OS for Debian --'
        $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $vmName -Credential $cred 
        $vmConfig | Set-AzVMSourceImage -PublisherName "debian" -Offer "debian-11" -Skus "11-gen2" -Version "latest"
    } elseif ($image -eq 'Ubuntu') {
        Write-Host '-- Setting OS for Debian --'
        $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $vmName -Credential $cred 
        $vmConfig | Set-AzVMSourceImage -PublisherName "canonical" -Offer "0001-com-ubuntu-server-focal" -Skus "20_04-lts-gen2" -Version "latest"
    } elseif ($image -eq 'OEL8') {
        Write-Host '-- Setting OS for OEL --'
        $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $vmName -Credential $cred 
        $vmConfig | Set-AzVMSourceImage -PublisherName "Oracle" -Offer "Oracle-Linux" -Skus "ol88-lvm-gen2" -Version "latest"
    } else {
        Write-Host '-- Setting OS for Linux --'
        $vmConfig | Set-AzVMOperatingSystem -Linux -ComputerName $vmName -Credential $cred
        $vmConfig | Set-AzVMSourceImage -PublisherName "Canonical" -Offer "0001-com-ubuntu-server-focal" -Skus "20_04-lts" -Version "latest"
    }
    $vmConfig | Add-AzVMNetworkInterface -Id $mgmtNic.Id

    if ($dataSubnet) {
        $vmConfig.NetworkProfile.NetworkInterfaces[0].Primary = $true
        $vmConfig | Add-AzVMNetworkInterface -Id $dataNic.Id
    }

    # Create a VM using the abov config

    $vmConfig | ConvertTo-Json -Depth 10 | write-verbose -Verbose

    if ($zone) {
        New-AzVm -ResourceGroupName $rg -Location $rgData.Location -Zone $zone -VM $vmConfig
    } else {
        New-AzVm -ResourceGroupName $rg -Location $rgData.Location -VM $vmConfig
    }
}