Private/Start-CustomVMUpdate.ps1

# Will be called in VM
function Global:Start-CustomVMUpdate {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        ...
    .DESCRIPTION
        ...
    #>

    param(
        [Parameter(Mandatory = $true, Position = 1)]
        [string]
        $ObjectName,
        [Parameter(Mandatory = $false, Position = 2)]
        [switch]
        $IsScaleSet,
        [Parameter(Mandatory = $true, Position = 3)]
        [string]
        $ResourceGroupName,
        [Parameter(Mandatory = $true, Position = 4)]
        [string]
        $StorageAccountName,
        [Parameter(Mandatory = $true, Position = 5)]
        [string]
        $KeyVaultName,
        [Parameter(Mandatory = $true, Position = 6)]
        [string]
        $StorageTableNameSetup,
        [Parameter(Mandatory = $true, Position = 7)]
        [string]
        $StorageTableNameEnvironments,
        [Parameter(Mandatory = $true, Position = 8)]
        [string]
        $StorageTableNameEnvironmentDefaults
    )
    process {
        # TODO: add StorageAccount TableName for Environments and for EnvironmentDefaults

        Write-Host "Starting auto update..."

        # Uses managed identity to connect to Azure Account
        Connect-FromMachineToAzAccount
        
        Write-Host "Loading pending commands..."
        $storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
        $storageAccountContext = $storageAccount.Context
        # TODO: Switch from hardcoded-value to new entry in "Properties.ps1"
        #$storageAccountTable = Get-AzStorageTable -Name 'Setup' -Context $storageAccountContext.Context
        $storageAccountTable = Get-AzStorageTable -Name $StorageTableNameSetup -Context $storageAccountContext.Context
        $cloudTable = $storageAccountTable.CloudTable
        $rows = Get-AzTableRow -Table $cloudTable | Where-Object { ($_.ExecutedBy -notlike "*$env:computername*") -and (($_.ObjectName -eq 'NULL') -or ($_.ObjectName -eq $ObjectName)) }
        foreach ($row in $rows) {
            Write-Host "Handling Command: $($row.Command)"
            switch ($row.Command) {
                'JoinDomain' {
                    if ((Get-WmiObject win32_computersystem).partofdomain -eq $false) { 
                        Write-Host "Loading credentials..."
                        # Load Admin Credentials from KeyVault
                        $adminUserName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminUsername').SecretValueText
                        $adminUserPass = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminPassword').SecretValueText
                        $domainName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainName').SecretValueText                    
                        $adminUserName = "$domainName\$adminUserName"
                        $domainAdminCredentials = New-Object System.Management.Automation.PSCredential ($adminUserName, (ConvertTo-SecureString -String $adminUserPass -AsPlainText -Force))
                        if ($row.RestartNecessary -eq $true) {
                            # Update Command Table, because machine will be restartet in a moment
                            Set-StorageCommandExecuted -CommandRow $row -ExecutedByName $env:computername
                        }
                        Add-Computer -DomainName $domainName -Credential $domainAdminCredentials -Restart -Force | Out-Null
                    } else {
                        Write-Host "Machine is already part of domain."
                    }
                }
                'CreateInstances' {
                    Write-Host "Importing Cloud.Ready.Software.NAV..."
                    Import-Module Cloud.Ready.Software.NAV -Force
                    Write-Host "Importing NAV Modules..."
                    Import-NAVModules

                    #$environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableName 'Environments'
                    $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableName $StorageTableNameEnvironments -TypeFilter $row.Parameter1 -ConfigType Application
                    foreach ($environment in $environments) {
                        if (-not (Get-NavServerInstance -ServerInstance $environment.ServerInstance)) {
                            Write-Host "Creating instance: $($environment.ServerInstance)"
                            New-NAVEnvironment -ServerInstance $environment.ServerInstance `
                                -DatabaseServer $environment.DatabaseServer  `
                                -DatabaseInstance $environment.DatabaseInstance  `
                                -Databasename $environment.Databasename `
                                -EnablePortSharing:$false `
                                -ClientServicesPort $environment.ClientServicesPort   `
                                -ManagementServicesPort $environment.ManagementServicesPort `
                                -CreateWebServerInstance:$false `
                                -StartWindowsClient:$false
                            Write-Host "Changing port-configuration..."
                            Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName DeveloperServicesPort -KeyValue $environment.DeveloperServicesPort
                            Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName ODataServicesPort -KeyValue $environment.OdataServicesPort
                            Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName SOAPServicesPort -KeyValue $environment.SoapServicesPort
                            Write-Host "Updating authentication-method..."
                            Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName ClientServicesCredentialType -KeyValue $environment.Authentication
                            foreach ($setting in $environment.Settings) {
                                if (-not([string]::IsNullOrEmpty($setting.Key))) {
                                    Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName $setting.Key -KeyValue $setting.Value
                                }
                            }                            
                            Write-Host "Restarting service"
                            # TODO: Activate
                            # Restart-NAVServerInstance -ServerInstance $environment.ServerInstance
                        }                        
                    }
                    <#
                    # Get default values (like database server)
                    $storageAccountTableDefaultValues = Get-AzStorageTable -Name 'EnvironmentDefaultValues' -Context $storageAccountContext.Context
                    $cloudTableDefaultValues = $storageAccountTableDefaultValues.CloudTable
                    $rowsDefaultValues = Get-AzTableRow -Table $cloudTableDefaultValues | Where-Object { ($_.ServiceName -eq $null) -or ($_.ServiceName -eq "") }
                     
                    $storageAccountTableInstances = Get-AzStorageTable -Name 'Environments' -Context $storageAccountContext.Context
                    $cloudTableInstances = $storageAccountTableInstances.CloudTable
                    $rowsInstance = Get-AzTableRow -Table $cloudTableInstances
                     
                    foreach ($instanceRow in $rowsInstance) {
                        if (-not (Get-NavServerInstance -ServerInstance $instanceRow.ServiceName)) {
                             
                            $storageAccountTableDefaultValuesService = Get-AzStorageTable -Name 'EnvironmentDefaultValues' -Context $storageAccountContext.Context
                            $cloudTableDefaultValuesService = $storageAccountTableDefaultValuesService.CloudTable
                            $rowsDefaultValuesService = Get-AzTableRow -Table $cloudTableDefaultValuesService | Where-Object { ($_.ServiceName -eq $instanceRow.ServiceName) }
                             
                            Write-Host "Creating instance: " $instanceRow.ServiceName
                            New-NAVEnvironment -ServerInstance $instanceRow.ServiceName `
                                -DatabaseServer $rowsDefaultValues.DatabaseServer `
                                -DatabaseInstance $instanceRow.DatabaseInstance `
                                -Databasename $instanceRow.DatabaseName `
                                -EnablePortSharing:$false `
                                -ClientServicesPort $instanceRow.ClientServicePort `
                                -ManagementServicesPort $instanceRow.ManagementServicePort `
                                -CreateWebServerInstance:$false `
                                -StartWindowsClient:$false
                            Write-Host "Changing port-configuration..."
                            Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName DeveloperServicesPort -KeyValue $instanceRow.DeveloperServicePort
                            Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName ODataServicesPort -KeyValue $instanceRow.ODataServicePort
                            Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName SOAPServicesPort -KeyValue $instanceRow.SoapServicePort
                            Write-Host "Updating authentication-method..."
                            Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName ClientServicesCredentialType -KeyValue $instanceRow.AuthType
                            # Apply Defaults (all services)
                            foreach ($rowDefaultValue in $rowsDefaultValues) {
                                if (-not([string]::IsNullOrEmpty($rowDefaultValue.KeyValue))) {
                                    Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName $rowDefaultValue.KeyName -KeyValue $rowDefaultValue.KeyValue
                                }
                            }
                            # Apply Defaults (for specific service)
                            foreach ($rowDefaultValue in $rowsDefaultValuesService) {
                                if (-not([string]::IsNullOrEmpty($rowDefaultValue.KeyValue))) {
                                    Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName $rowDefaultValue.KeyName -KeyValue $rowDefaultValue.KeyValue
                                }
                            }
                        }
                    }
                    #>

                }
                'UpdateInstanceConfiguration' {
                    Write-Host "Importing Cloud.Ready.Software.NAV..."
                    Import-Module Cloud.Ready.Software.NAV -Force
                    Write-Host "Importing NAV Modules..."
                    Import-NAVModules

                    $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableName $StorageTableNameEnvironments -ConfigType Application
                    foreach ($environment in $environments) {                        
                        if (Get-NavServerInstance -ServerInstance $environment.ServerInstance) {
                            $config = Get-NAVServerConfiguration -ServerInstance $environment.ServerInstance

                            # Convert Result to HashTable
                            $currentConf = @{ }
                            $config | ForEach-Object { $currentConf[$_.key] = $_.value }
                            $currentConf["TraceLevel"]
                            #
                            $updated = $false
                            $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName DeveloperServicesPort -KeyValue $environment.DeveloperServicesPort -Verbose)
                            $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName ODataServicesPort -KeyValue $environment.OdataServicesPort -Verbose)
                            $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName SOAPServicesPort -KeyValue $environment.SoapServicesPort -Verbose)
                            $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName ClientServicesCredentialType -KeyValue $environment.Authentication -Verbose)
                            #Write-Host "Changing port-configuration..."
                            #Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName DeveloperServicesPort -KeyValue $environment.DeveloperServicesPort
                            #Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName ODataServicesPort -KeyValue $environment.OdataServicesPort
                            #Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName SOAPServicesPort -KeyValue $environment.SoapServicesPort
                            #Write-Host "Updating authentication-method..."
                            #Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName ClientServicesCredentialType -KeyValue $environment.Authentication
                            foreach ($setting in $environment.Settings) {
                                if (-not([string]::IsNullOrEmpty($setting.Key))) {
                                    #Set-NAVServerConfiguration -ServerInstance $environment.ServerInstance -KeyName $setting.Key -KeyValue $setting.Value
                                    $updated = $updated -or (Set-NAVConfigurationIfDifferent -ServerInstance $environment.ServerInstance -KeyName $setting.Key -KeyValue $setting.Value -Verbose)
                                }
                            }
                            if ($updated -and ($row.Parameter2 -eq "RestartService")) {
                                Write-Host "Restarting service"
                                # TODO: Activate
                                # Restart-NAVServerInstance -ServerInstance $environment.ServerInstance
                            }
                        }
                    }
                    <#
                    # Get default values (like database server)
                    $storageAccountTableDefaultValues = Get-AzStorageTable -Name 'EnvironmentDefaultValues' -Context $storageAccountContext.Context
                    $cloudTableDefaultValues = $storageAccountTableDefaultValues.CloudTable
                    $rowsDefaultValues = Get-AzTableRow -Table $cloudTableDefaultValues | Where-Object { ($_.ServiceName -eq $null) -or ($_.ServiceName -eq "") }
                     
                    $storageAccountTableInstances = Get-AzStorageTable -Name 'Environments' -Context $storageAccountContext.Context
                    $cloudTableInstances = $storageAccountTableInstances.CloudTable
                    $rowsInstance = Get-AzTableRow -Table $cloudTableInstances
                    foreach ($instanceRow in $rowsInstance) {
                        if (Get-NavServerInstance -ServerInstance $instanceRow.ServiceName) {
                            $storageAccountTableDefaultValuesService = Get-AzStorageTable -Name 'EnvironmentDefaultValues' -Context $storageAccountContext.Context
                            $cloudTableDefaultValuesService = $storageAccountTableDefaultValuesService.CloudTable
                            $rowsDefaultValuesService = Get-AzTableRow -Table $cloudTableDefaultValuesService | Where-Object { ($_.ServiceName -eq $instanceRow.ServiceName) }
                                                 
                            # Apply Defaults (all services)
                            foreach ($rowDefaultValue in $rowsDefaultValues) {
                                if (-not([string]::IsNullOrEmpty($rowDefaultValue.KeyValue))) {
                                    Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName $rowDefaultValue.KeyName -KeyValue $rowDefaultValue.KeyValue
                                }
                            }
                            # Apply Defaults (for specific service)
                            foreach ($rowDefaultValue in $rowsDefaultValuesService) {
                                if (-not([string]::IsNullOrEmpty($rowDefaultValue.KeyValue))) {
                                    Set-NAVServerConfiguration -ServerInstance $instanceRow.ServiceName -KeyName $rowDefaultValue.KeyName -KeyValue $rowDefaultValue.KeyValue
                                }
                            }
                        }
                    }
                    #>

                }
                'UpdateLicense' {
                    Write-Hoste "Loading Instance-data..."
                    Import-Module Cloud.Ready.Software.NAV -Force
                    Import-NAVModules

                    # Download License
                    $targetFilename = 'C:\Install\ScriptDownload\license.flf'
                    Download-CustomFile -URI $row.Parameter1 -DestinationFile $targetFilename

                    # Get default values (like database server)
                    $storageAccountTableInstances = Get-AzStorageTable -Name $StorageTableNameEnvironments -Context $storageAccountContext.Context
                    $cloudTableInstances = $storageAccountTableInstances.CloudTable
                    $rowsInstance = Get-AzTableRow -Table $cloudTableInstances
                    foreach ($instanceRow in $rowsInstance) {
                        if (Get-NavServerInstance -ServerInstance $instanceRow.ServiceName) {
                            Import-NAVServerLicense -ServerInstance $instanceRow.ServiceName -LicenseFile $targetFilename
                            Restart-NAVServerInstance -ServerInstance $instanceRow.ServiceName | Out-Null
                        }
                    }
                }
                # Add "CreateWebInstances"
                # Add "UpdateWebInstanceConfiguration"
                # Add "UpdateCertificate"
                # Add "UpdateWebCertificate"
                # Add "CreateDelegation"
                # Add "CreateSPN"
                default {
                    Write-Host "Not implemented yet."
                }                
            }
            if ($row.RestartNecessary -eq $false) {
                # Update Command Table, because machine will be restartet in a moment
                Set-StorageCommandExecuted -CommandRow $row -ExecutedByName $env:computername
            }
            if ($row.RestartNecessary -eq $true) {
                break       
            }
        }
    }
}