Public/New-DuneDeployment.ps1

<#
.SYNOPSIS
Create a new Dune deployment.

.DESCRIPTION
Creates a new deployment in Dune using the specified name, environment, collection, owners, default resource provider and optional template and parameters. Supports `ShouldProcess` semantics.

.PARAMETER Name
The unique name for the deployment. Mandatory.

.PARAMETER Environment
The target environment for the deployment (value from the `Environments` enum). Mandatory.

.PARAMETER CollectionId
GUID of the parent collection. Mandatory.

.PARAMETER Owner
One or more `DuneUser` objects that will be owners of the deployment. Mandatory.

.PARAMETER DefaultResourceProviderId
GUID of the default resource provider. Mandatory.

.PARAMETER DeploymentTemplate
A `DuneDeploymentTemplate` object used to populate template parameters (may be supplied via pipeline).

.PARAMETER DisplayName
Optional display name for the deployment.

.PARAMETER Description
Optional description.

.PARAMETER Parameters
Hashtable of template parameters to set; template parameters may also be prompted interactively.

.PARAMETER Stage
If set, stages the deployment after creation.

.PARAMETER ValidUntil
Optional expiration datetime for the deployment.

.PARAMETER IsNeverExpiring
If set, the deployment will not expire.

.PARAMETER Variables
Array of hashtables for deployment variables.

.PARAMETER Tags
Array of hashtables used as tags for the deployment.

.EXAMPLE
PS> New-DuneDeployment -Name "my-app" -Environment Prod -CollectionId 3d8f6b5a-... -Owner (Get-DuneUser -Name admin) -DefaultResourceProviderId 4a7f...
Creates a new production deployment named `my-app`.

.EXAMPLE
PS> Get-DuneDeploymentTemplate -Name "webapp" | New-DuneDeployment -Name "my-app" -Environment Dev -CollectionId 3d8f6b5a-... -Owner (Get-DuneUser -Name admin) -DefaultResourceProviderId 4a7f...
Creates a deployment using a deployment template provided via the pipeline.
#>

function New-DuneDeployment {
    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'None'
    )]
    param (
        [Parameter(Mandatory)]
        [string]$Name,

        [Parameter(Mandatory)]
        [Environments]$Environment,

        [Parameter(Mandatory)]
        [guid]$CollectionId,

        [Parameter(Mandatory)]
        [DuneUser[]]$Owner,

        [Parameter(Mandatory)]
        [Guid]$DefaultResourceProviderId,

        [Parameter(ValueFromPipeline)]
        [DuneDeploymentTemplate]$DeploymentTemplate,

        [Parameter()]
        [string]$DisplayName,

        [Parameter()]
        [string]$Description,

        [Parameter()]
        [hashtable]$Parameters,

        [Parameter()]
        [switch]$Stage,

        [Parameter()]
        [datetime]$ValidUntil,

        [Parameter()]
        [bool]$IsNeverExpiring = $false,

        [Parameter()]
        [hashtable[]]$Variables,

        [Parameter()]
        [hashtable[]]$Tags = @()
    )

    begin {}

    process {
        Write-Debug "$($MyInvocation.MyCommand)|process"
        $Body = @{
            Environment               = $Environment.ToString()
            IsNeverExpiring           = $IsNeverExpiring
            ParentId                  = $CollectionId
            DisplayName               = $DisplayName
            DefaultResourceProviderId = $DefaultResourceProviderId
            Description               = $Description
            Name                      = $Name
            OwnerUserIds              = $Owner.Id
            Parameters                = @()
            Tags                      = $Tags
        }
        if ($PSBoundParameters.ContainsKey('ValidUntil')) {
            $Body.ValidUntil = $ValidUntil.ToUniversalTime()
        }
        if ($PSBoundParameters.ContainsKey('DeploymentTemplate')) {
            $Body.TemplateId = $DeploymentTemplate.Id
        }
        foreach ($TemplateParameter in $DeploymentTemplate.Parameters) {
            $Parameter = @{
                Name        = $TemplateParameter.Name
                Description = $TemplateParameter.Description
                Type        = $TemplateParameter.Type
            }
            $Value = $Null
            while (-not $Value) {
                $Value = if ($Parameters.($TemplateParameter.Name)) {
                    $Parameters.($TemplateParameter.Name)
                }
                else {
                    $ReadHost = @{
                        Prompt = if ($TemplateParameter.Default) {
                            "{0} (Description: {1}, Type: {2}, Default: {3})" -f $TemplateParameter.Name, $TemplateParameter.Description, $TemplateParameter.Type, $TemplateParameter.Default
                        }
                        else {
                            "{0} (Description: {1}, Type: {2})" -f $TemplateParameter.Name, $TemplateParameter.Description, $TemplateParameter.Type
                        }
                    }
                    if ($TemplateParameter.Type -eq 'securestring') {
                        $Readhost.MaskInput = $True
                    }
                    $ReadHostValue = Read-Host @ReadHost
                    if (-not $ReadHostValue -and $TemplateParameter.Default) {
                        $TemplateParameter.Default | ConvertFrom-Json
                    }
                    else {
                        $ReadHostValue
                    }
                }
            }
            $Parameter.Value = if ($TemplateParameter.Type -eq 'Number') {
                $Value
            }
            else {
                ConvertTo-Json -InputObject $Value
            }
            $Body.Parameters += $Parameter
        }
        if ($PSBoundParameters.ContainsKey('Variables')) {
            $Variables | ForEach-Object {
                $_.Value = ConvertTo-Json -InputObject $Variables
            }
            $Body.Variables = $Variables
        }
        if ($PSCmdlet.ShouldProcess($($Body | ConvertTo-Json -Depth 16 -Compress))) {
            $Return = Invoke-DuneApiRequest -Uri "deployments" -Method POST -Body $Body -ErrorAction Stop
            $ReturnObject = if ($Return.Content) { $Return.Content | ConvertFrom-Json | ConvertTo-DuneClassObject -Class DuneDeployment }
            if ($Stage -and $ReturnObject) {
                $Null = $ReturnObject | Invoke-DuneDeploymentStage
            }
            return $ReturnObject
        }
    }

    end {}
}