Containers/New-ContainerForNavxProduct.ps1

<#
 .Synopsis
  Creates a new NAV/BC container for a specific NAV-X Product
 .Description
  Creates a new NAV/BC container for a specific NAV-X Product
 .Parameter ContainerName
  Name of the container. Can be provided in the settings.json
 .Parameter Product
  The product that should be installed in the container
 .Parameter ProductVersion
  The version for the product that should be installed. If left empty, it will be the latest version
 .Parameter Version
  The NAV/BC version (NAV 2018 and higher). If it's BC, the version is defined in Major.Minor
 .Parameter cu
  The cumulative update to be used, only when it's NAV 2018. If any cumulative update other than 6 is used, an object merge might be required as the products are developed on this cumulative udpate
 .Parameter Type
  OnPrem or Sandbox. Default is OnPrem
 .Parameter LicenseFile
  Path to license file. It can be an Uri and then the license will be downloaded. If left blank, the standard NAV-X license will be used
 .Parameter Credential
  Credentials to be used for login to the container. If blank, a standard login will be setup
 .Parameter Country
  Country version of the container. If left blank, "us" will be used
 .Parameter SetupTestUsers
  Creates test users in the container after it is created
 .Parameter useHyperVIsolation
  Add this switch if you want to force Hyper V isolation when creating the container
 .Parameter useDevEndpoint
  Defines that the extensions are going to be installed via the developer endpoint to allow development on the apps
 .Example
  New-ContainerForNavxProduct -Product CommissionManagement -Version 18.0
#>

function New-ContainerForNavxProduct {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact="low")]
    Param(
        [Parameter(Mandatory = $false)]
        [string] $ContainerName,
        [Parameter(Mandatory = $true)]
        [ValidateSet('Allocations','CommissionManagement','CreditCard','CreditManagement','NationalAccounts','NationalAccountsUS', 'PayAssist','Search')]
        [string] $Product,
        [Parameter(Mandatory = $false)]
        [string] $productVersion = "*",
        [Parameter(Mandatory = $false)]
        [string] $Version = "latest",
        [Parameter(Mandatory = $false)]
        [string] $cu = "",
        [Parameter(Mandatory = $false)]
        [ValidateSet('OnPrem','Sandbox')]
        [string] $Type = "OnPrem",
        [Parameter(Mandatory = $false)]
        [string] $LicenseFile = "",
        [Parameter(Mandatory = $false)]
        [pscredential] $Credential,
        [Parameter(Mandatory = $false)]
        [string] $Country = "",
        [switch] $SetupTestUsers,
        [switch] $useHyperVIsolation,
        [switch] $useDevEndpoint
    )

    Write-Output @'

     ____ ____ _
    | _ \ _ __ ___ _ __ __ _ _ __ ___ | _ \ __ _ _ __ __ _ _ __ ___ ___| |_ ___ _ __ ___
    | |_) | '__/ _ \ '_ \ / _` | '__/ _ \ | |_) / _` | '__/ _` | '_ ` _ \ / _ \ __/ _ \ '__/ __|
    | __/| | | __/ |_) | (_| | | | __/ | __/ (_| | | | (_| | | | | | | __/ || __/ | \__ \
    |_| |_| \___| .__/ \__,_|_| \___| |_| \__,_|_| \__,_|_| |_| |_|\___|\__\___|_| |___/
                   |_|

'@


    switch ($Product) {
        "Allocations" {
            if ($ContainerName -eq "") {
                $ContainerName = "allocationsbc"
            }
            $devOpsArtifact = ""
        }
        "CommissionManagement" {
            if ($ContainerName -eq "") {
                $ContainerName = "commissionsbc"
            }
            $devOpsArtifact = "commission_management"
        }
        "CreditCard" {
            if ($ContainerName -eq "") {
                $ContainerName = "creditcardbc"
            }
            $devOpsArtifact = "credit_card"
        }
        "CreditManagement" {
            if ($ContainerName -eq "") {
                $ContainerName = "creditmgtbc"
            }
            $devOpsArtifact = "credit_management"
        }
        "NationalAccounts" {
            if ($ContainerName -eq "") {
                $ContainerName = "natacctbc"
            }
            $devOpsArtifact = "national_accounts"
        }
        "NationalAccountsUS" {
            if ($ContainerName -eq "") {
                $ContainerName = "natacctusbc"
            }
            $devOpsArtifact = "national_accounts_us"
        }
        "PayAssist" {
            if ($ContainerName -eq "") {
                $ContainerName = "payassistbc"
            }
            $devOpsArtifact = "payassist"
        }
        "Search" {
            if ($ContainerName -eq "") {
                $ContainerName = "searchbc"
            }
            $devOpsArtifact = "search"
        }
    }

    if ($null -eq $Credential) {
        $Credential = New-Object System.Management.Automation.PSCredential('admin', (ConvertTo-SecureString 'Cfbs!#00' -AsPlainText -Force))
    }

    $sqlCredential = New-Object System.Management.Automation.PSCredential('sa', (ConvertTo-SecureString ($Credential.GetNetworkCredential().Password) -AsPlainText -Force))
    $latestArtifactUrl = ""
    $artifactUrl = ""

    try {
        $versionInt = [decimal]$Version
    }
    catch {
        $versionInt = 0
    }

    if ($versionInt -eq 0) {
        if ($Version -ne "NextMinor" -and $Version -ne "NextMajor" -and $Version -ne "latest") {
            throw "Version $Version is not valid"
        }
    }

    if ($country -eq "") {
        if (($versionInt -ge 14 -and $versionInt -lt 15) -or ($versionInt -eq 2018)) {
            $Country = "na"
        }
        else {
            $Country = "us"
        }
    }
    if ($type -eq "") {
        if ($version -eq "NextMinor" -or $Version -eq "NextMajor" -or $Version -eq "latest") {
            $Type = "Sandbox"
        }
        else {
            $Type = "OnPrem"
        }
    }

    if ($Version -eq "NextMinor" -or $Version -eq "NextMajor") {
        try {
            $saasToken = Get-Secret -vaultName "NAV-X" -secretName "insiderToken"
            $artifactUrl = Get-BCArtifactUrl -country $Country -select $Version -sasToken "$saasToken"
        }
        catch {
            throw "Incorrect version $Version cu $cu country $Country"
        }

        if ($artifactUrl.StartsWith("https://bcinsider.azureedge.net/sandbox/")) {
            $tempVersion = [version]$artifactUrl.Substring($artifactUrl.IndexOf($type.ToLower()) + $type.Length + 1).Split('/')[0]
            $Version = ("{0}.{1}" -f $tempVersion.Major, $tempVersion.Minor)
            try {
                $versionInt = [decimal]$Version
            }
            catch {
                $versionInt = 0
            }
        }
    }
    else {
        if ($Version -eq "latest") {
            try {
                $artifactUrl = Get-BCArtifactUrl -country $Country -Type $Type -select Latest
                $latestArtifactUrl = $artifactUrl
            }
            catch {
                throw "Incorrect version $Version country $country"
            }
            $tempVersion = [version]$artifactUrl.Substring($artifactUrl.IndexOf($Type.ToLower()) + $Type.Length + 1).Split('/')[0]
            $Version = ("{0}.{1}" -f $tempVersion.Major, $tempVersion.Minor)
            try {
                $versionInt = [decimal]$Version
            }
            catch {
                $versionInt = 0
            }
        }
        if ($versionInt -eq 2018) {
            if ($cu -eq "") {
                $cu = "0"
            }

            try {
                if ($artifactUrl -eq "") {
                    $artifactUrl = Get-NavArtifactUrl -nav $Version -cu $cu -country $Country -select Latest
                }
            }
            catch {
                throw "Incorrect version $Version cu $cu country $Country"
            }
            $imagename = ("navx:{0}-cu{1}-{2}" -f $Version, $cu, $Country)

            if ($LicenseFile -eq "") {
                $LicenseFile = Get-LicenseFile -Publisher (Get-AppKeyValue -SourcePath $SourcePath -KeyName 'Publisher') -Version '2018'
            }
        }
        else {
            try {
                if ($artifactUrl -eq "") {
                    $artifactUrl = Get-BCArtifactUrl -type $Type -country $Country -version $Version -select Latest
                }
            }
            catch {
                throw "incorrect version $Version country $Country"
            }
        }
    }

    # Test, if requested BC version is the latest
    $isLatest = $false
    if ($latestArtifactUrl -eq "") {
        $latestArtifactUrl = Get-BCArtifactUrl -type $Type -country $Country -select Latest
    }
    $tempVersion = [version]$latestArtifactUrl.Substring($latestArtifactUrl.IndexOf($Type.ToLower()) + $Type.Length + 1).Split('/')[0]
    $tempVersion = ("{0}.{1}" -f $tempVersion.Major, $tempVersion.Minor)

    if ($versionInt -ge [decimal]$tempVersion -and $VersionInt -lt 2016) {
        $isLatest = $true
    }

    $devOpsToken = Get-Secret -vaultName "NAV-X" -secretName "personalDevOpsToken"

    $imagename = ("navx:{0}-{1}-{2}" -f $Version, $Country, $Type)

    if ($artifactUrl -eq "") {
        throw "Could not find the proper version to install"
    }

    if ($productVersion -eq "") {
        $productVersion = "*"
    }

    if ($LicenseFile -eq "") {
        switch ($Product) {
            'PayAssist' {
                $LicenseFile = Get-LicenseFile -Publisher "DTX" -Version $versionInt
            }
            default {
                $LicenseFile = Get-LicenseFile -Publisher "NAV-X" -Version $versionInt
            }
        }
    }

    Write-Output "Container: $ContainerName"
    Write-Output "Image: $imagename"
    Write-Output "Product: $Product"
    Write-Output "Product Version: $productVersion"
    Write-Output "Version: $Version"
    if ($versionInt -eq 2018) {
        Write-Output "Cumulative Update: $cu"
    }
    Write-Output "Country: $Country"
    if ($versionInt -ne 2018) {
        Write-Output "Type: $Type"
    }
    Write-Output "username: $($Credential.UserName)"
    Write-Output "password: $($Credential.GetNetworkCredential().Password)"

    $startParameters = @{}
    $startParameters.Add('imageName', $imagename)
    $startParameters.Add('artifactUrl', $artifactUrl)
    if ($LicenseFile -ne "") {
        $startParameters.Add('licenseFile', $LicenseFile)
    }
    if ($useHyperVIsolation.IsPresent) {
        $startParameters.Add('isolation', 'hyperv')
    }
    if ($versionInt -eq 14 -or $versionInt -eq 2018) {
        $startParameters.Add('shortcuts', 'DesktopFolder')
        $startParameters.Add('includeCSide', $true)
        $startParameters.Add('enableSymbolLoading', $true)
        $startParameters.Add('doNotExportObjectsToText', $true)
        $startParameters.Add('clickonce', $true)
    }
    else {
        $startParameters.Add('enableTaskScheduler', $true)
    }
    $startParameters.Add('updateHosts', $true)
    $startParameters.Add('alwaysPull', $true)
    $startParameters.Add('forceRebuild', $true)
    $startParameters.Add('useBestContainerOS', $true)
    $startParameters.Add('auth', 'NavUserPassword')
    $startParameters.Add('dns', '8.8.8.8')
    $startParameters.Add('accept_eula', $true)
    $startParameters.Add('accept_outdated', $true)
    $startParameters.Add('containerName', $ContainerName)
    $startParameters.Add('Credential', $Credential)


    # defines that it's a local container, so the memory will be set to a higher amount for performance reasons
    if ($PSCmdlet.ShouldProcess("Container", "This will create a new ")) {
        Write-Output @'

         ____ _ _ ____ _ _
        / ___|_ __ ___ __ _| |_(_)_ __ __ _ / ___|___ _ __ | |_ __ _(_)_ __ ___ _ __
       | | | '__/ _ \/ _` | __| | '_ \ / _` | | | / _ \| '_ \| __/ _` | | '_ \ / _ \ '__|
       | |___| | | __/ (_| | |_| | | | | (_| | | |__| (_) | | | | || (_| | | | | | __/ |
        \____|_| \___|\__,_|\__|_|_| |_|\__, | \____\___/|_| |_|\__\__,_|_|_| |_|\___|_|
                                         |___/
'@

        @($startParameters.Keys) | ForEach-Object {
            if ($_ -ne "Credential") {
                Write-Output "$($_): $($startParameters[$_])"
            }
        }

        New-BcContainer @startParameters
    }

    # waiting for container to be operational
    Wait-ForTenantReady -containerName $ContainerName -Tenant default

    if ($SetupTestUsers.IsPresent) {
        Setup-BcContainerTestUsers -containerName $ContainerName -tenant default -Password (ConvertTo-SecureString ($Credential.GetNetworkCredential().Password) -credential $Credential)
    }

    # download app and then download related apps
    $appsDirectory = New-TempDirectory

    # determine where to get product from
    $devOpsFeed = ""
    if (!$isLatest) {
        if ($versionInt -ge 2018) {
            $devOpsFeed = ("NAV-X_NAV{0}" -f $versionInt)
        }
        else {
            $devOpsFeed = ("NAV-X_BC{0}" -f $Version.Substring(0, 2))
        }

        $allFeeds = (Get-DevOpsFeedList -devOpsOrganization "NAV-X" -devOpsToken $devOpsToken)
        if (!$allFeeds.name.Contains($devOpsFeed)) {
            $devOpsFeed = ""
        }
    }
    if ($devOpsFeed -eq "") {
        if ($Type-eq "OnPrem") {
            $devOpsFeed = 'NAV-X_master_onprem'
        }
        else {
            $devOpsFeed = 'NAV-X_master'
        }
    }

    # if base objects exist, download and import
    $devOpsToken | az devops login --organization "https://dev.azure.com/NAV-X/"

    if ($versionInt -ge 2018 -or $versionInt -lt 15) {
        try {
            Get-DevOpsArtifactsFromFeed -devOpsOrganization "NAV-X" -devOpsFeed $devOpsFeed -devOpsArtifact "$($devOpsArtifact)_baseobjects" -destination $appsDirectory -version $productVersion
        }
        catch {
            [Console]::ForegroundColor = "Gray"
            Write-Output "Base Objects don't exist"
        }

        if (Test-Path (Join-Path $appsDirectory "*_baseobjects.fob")) {
            Get-Item (Join-Path $appsDirectory "*_baseobjects.fob") | ForEach-Object {
                if ((Get-Item $_.FullName).Length -gt 0) {
                    Import-ObjectsToNavContainer -containerName $ContainerName -objectsFile $_.FullName -sqlCredential $sqlCredential -ImportAction Overwrite -SynchronizeSchemaChanges Force
                }
            }
        }
    }

    $artifactName = "$($devOpsArtifact)_app"
    Get-AndInstallApp -devOpsOrganization "NAV-X" -devOpsFeed $devOpsFeed -devOpsArtifact "$artifactName" -Version $productVersion -useDevEndpoint:$useDevEndpoint -Credential $credential

    Remove-Item -Path $appsDirectory -Recurse -Force
}
Export-ModuleMember New-ContainerForNavxProduct