Install-ALOpsExternalDeployer.ps1

function Install-ALOpsExternalDeployer(){
    [CmdletBinding()]
    param
    (
        [string] $ServerInstance = "BC",
        [string] $ListenHost = "localhost",
        [int] $ListenPort = 7000,
        [string] $CustomScriptPath
    )
    
    $ErrorActionPreference = "Stop"        

    #*** Check Prerequisites ***
    Write-Host "*** Check dotnet IntallUtil" -ForegroundColor Green
    $InstallUtilPath = Get-DotnetInstallUtil

    #*** Stop Existing Service ***
    Remove-ALOpsExternalDeployer -ServiceName "ALOpsExternalDeployer" -InstallUtilPath $InstallUtilPath

    #*** Check Certificate ***
    Install-ALOpsCertificate

    #*** Settings ***
    $DisplayName = "ALOps External Deployer - $($ServerInstance)"
    $ServiceName = "ALOpsExternalDeployer`$$($ServerInstance)"

    Write-Host "*** Deploy [$($DisplayName)]" -ForegroundColor Green
    
    #*** Remove Previous Installed Service
    Remove-ALOpsExternalDeployer -ServiceName $ServiceName -InstallUtilPath $InstallUtilPath

    #*** Install Service ***
    Write-Host "*** Install Agent" -ForegroundColor Green
    $alopsService = get-service -Name $ServiceName -ErrorAction SilentlyContinue
    if ($null -eq $alopsService) {
        $ServicePath = Join-Path -Path ((get-Module ALOps.ExternalDeployer).ModuleBase) -ChildPath "bin\*"
    
        $ProgramFilesRoot = Join-Path -Path $env:ProgramFiles -ChildPath "ALOps\ExternalDeployer\$($ServerInstance)"
        if (-not (Test-Path -Path $ProgramFilesRoot)){
            New-Item -Path $ProgramFilesRoot -ItemType Directory -Confirm:$false -Force:$true | Out-Null
        }

        Copy-Item -Path  $ServicePath -Destination $ProgramFilesRoot -Recurse -Confirm:$false -Force:$true

        ### Configure Service
        $ExternalDeployerConfig = Join-Path -Path $ProgramFilesRoot -ChildPath "ALOpsExternalDeployer.exe.config"

        $ConfigXml = [xml](Get-Content -Path $ExternalDeployerConfig -Encoding UTF8 -Raw)
        $ALOpsExternalDeployerSettings = $ConfigXml.configuration.applicationSettings.'ALOpsExternalDeployer.Properties.Settings'.setting

        $P_ServerInstance = ($ALOpsExternalDeployerSettings | where-object { $_.name -eq "ServerInstance"})
        $P_ServerInstance.value = "$($ServerInstance)"

        $P_ListenHost = ($ALOpsExternalDeployerSettings | where-object { $_.name -eq "listen_host"})
        $P_ListenHost.value = "$($ListenHost)"

        $P_ListenPort = ($ALOpsExternalDeployerSettings | where-object { $_.name -eq "listen_port"})
        $P_ListenPort.value = "$($ListenPort)"

        $P_ServiceName = ($ALOpsExternalDeployerSettings | where-object { $_.name -eq "ServiceName"})
        $P_ServiceName.value = "$($ServiceName)"

        $ConfigXml.Save($ExternalDeployerConfig)

        ### Register Service
        $ExternalDeployerEXE = Join-Path -Path $ProgramFilesRoot -ChildPath "ALOpsExternalDeployer.exe"
        & "sc.exe" create "$($ServiceName)" displayname= "$($DisplayName)" binpath= "$($ExternalDeployerEXE)" start= auto | Out-Null
    }

    #*** Start Service ***
    Write-Host "*** Start Service [$($ServiceName)]" -ForegroundColor Green
    Start-Service -Name $ServiceName
    
    #*** Setup ServiceTier
    $ALOpsExternalDeployerEndpoint = "http://$($ListenHost):$($ListenPort)/"

    Import-ALOpsNavManagementDlls -ServerInstance $ServerInstance
    
    $ModuleVersion = (Get-Module -Name "Microsoft.Dynamics.Nav.Management").Version

    Write-Host "*** Linking ServerInstance [$($ServerInstance)] to ALOps External Deployer [$($ALOpsExternalDeployerEndpoint)]"

    $ConfigExists = $null
    $ConfigExists = Get-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName "ReverseProxyBaseUrl" -ErrorAction SilentlyContinue

    if ($null -ne $ConfigExists){
        Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName "ReverseProxyBaseUrl" -KeyValue $ALOpsExternalDeployerEndpoint
    } else {        
        Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName "ExternalNavAppDeploymentEndpoint" -KeyValue $ALOpsExternalDeployerEndpoint
    }

    if ($ModuleVersion -ge [Version]::new(21,0,0,0)){
        Write-Host "*** BC Version >= v21. Using Certificate Authentication"

        $AzureTenantID = "0d9730f5-6cb6-475e-a9c9-88e78a3d8ab1"
        $AzureClientID = "f0b08e80-18c1-419d-8cfb-952f6e56f14c"
        $AccessToken   = "AppId=$($AzureClientID);CertificateSubjectName=ALOps-External-Deployer;TenantId=$($AzureTenantID);CertificateStoreLocation=LocalMachine"

        Set-NAVServerConfiguration -ServerInstance $ServerInstance `
                                   -KeyName AccessTokenConnectionString `
                                   -KeyValue "$($AccessToken)"

        Set-NAVServerConfiguration -ServerInstance $ServerInstance `
                                   -KeyName ExtensionProxyServiceClientId `
                                   -KeyValue "$($AzureClientID)"

        if ($null -ne $ConfigExists){
            Set-NAVServerConfiguration -ServerInstance $ServerInstance `
                                       -KeyName DeltaServiceClientId `
                                       -KeyValue "$($AzureClientID)"
        }
    } else {
        Write-Host "*** BC Version =< v20. Using API-Key Authentication"

        $AppDeployDetails = @{ 
            "AzureTenantID" = "0d9730f5-6cb6-475e-a9c9-88e78a3d8ab1"; 
            "AzureClientID" = "f0b08e80-18c1-419d-8cfb-952f6e56f14c"; 
        }

        Set-NAVServerConfiguration -ServerInstance $ServerInstance -KeyName LocalServiceApiKey -KeyValue ( $AppDeployDetails | ConvertTo-Json -Depth 100)
    }

    if ((Get-NAVServerInstance -ServerInstance $ServerInstance).state -ilike "Running"){
        Restart-NAVServerInstance -ServerInstance $ServerInstance
    }
}