Public/Update-GuacConnection.ps1

function Update-GuacConnection {
    <#
    .SYNOPSIS
        Updates an existing Guacamole connection.
 
    .DESCRIPTION
        Two mutation modes, exactly one of which must be supplied:
 
        - -Patch (the canonical form): a JSON Patch operations array applied
          via the collection PATCH endpoint (DirectoryResource.patchObjects).
          A single operation or an array of operations is accepted. Supported
          operations: add (create), replace (full or partial object update,
          path "/{id}"), and remove (path "/{id}").
 
        - -Replace: a full replacement of the connection via
          DirectoryObjectResource.updateObject (PUT /connections/{id}). The
          body should contain the complete APIConnection (name, protocol,
          parameters, parentIdentifier, attributes).
 
        WARNING: both modes are full replacements, not merges. The server
        translator (ConnectionObjectTranslator.applyExternalChanges) applies
        every field of the supplied object unconditionally, so any field that
        is missing from the body (or missing from the "value" of a "replace"
        patch operation) is set to null on the server. To change a single
        field, read the full object first (Get-GuacConnection -Id), modify
        the property, and submit the complete object.
 
        The target connection is addressed by -Id, or by piping a connection
        object (as returned by Get-GuacConnection) into the cmdlet (bound to
        -InputObject); the piped object's Identifier is used when -Id is not
        given. -Id takes precedence over the piped identifier.
 
        Reference (Apache Guacamole 1.6.0):
        - guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
          (patchObjects: @PATCH with List<APIPatch<ExternalType>>)
        - guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java
          (updateObject: @PUT)
        - guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java
          (applyExternalChanges: protocol, parameters, parentIdentifier, name,
           attributes)
        - guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnection.java
 
    .EXAMPLE
        # Read-modify-write: submit the complete object, not just the changed field.
        $conn = Get-GuacConnection -Id $id
        $conn.Name = 'renamed'
        Update-GuacConnection -Id $conn.Identifier -Patch (
            @{ op = 'replace'; path = ('/{0}' -f $conn.Identifier); value = $conn }
        )
 
    .EXAMPLE
        # A batch of atomic operations on the same collection: replace one
        # connection and remove another, all-or-nothing.
        Update-GuacConnection -Id $id -Patch @(
            @{ op = 'replace'; path = ('/{0}' -f $id); value = $fullConn }
            @{ op = 'remove'; path = ('/{0}' -f $obsoleteConn.Identifier) }
        )
 
    .EXAMPLE
        Update-GuacConnection -Id $conn.Identifier -Replace @{
            name = 'db-server'
            protocol = 'ssh'
            parameters = @{ hostname = 'db2.example.com' }
            parentIdentifier = 'ROOT'
        }
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([PSCustomObject])]
    param (
        [Parameter(Mandatory = $false)]
        [AllowNull()]
        [N2C_GuacAdmin_GuacSession] $Session,

        [Parameter(Mandatory = $false)]
        [AllowEmptyString()]
        [string] $Server = [string]::Empty,

        [Parameter(Mandatory = $false)]
        [AllowEmptyString()]
        [string] $DataSource = [string]::Empty,

        [Parameter(Mandatory = $false, Position = 0)]
        [AllowEmptyString()]
        [string] $Id = [string]::Empty,

        [Parameter(Mandatory = $false)]
        [AllowNull()]
        [object] $Patch,

        [Parameter(Mandatory = $false)]
        [AllowNull()]
        [object] $Replace,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [AllowNull()]
        [object] $InputObject
    )

    begin {
        $pendingId = [string]::Empty
    }

    process {
            if ($null -ne $InputObject) {
                $pendingId = Get-GuacIdentifier -Object $InputObject
                # DataSource resolution priority: explicit param > piped object > session default
                if ([string]::IsNullOrWhiteSpace($DataSource)) {
                    $pipedDs = Get-GuacDataSourceFromObject -Object $InputObject
                    if (-not [string]::IsNullOrWhiteSpace($pipedDs)) {
                        $DataSource = $pipedDs
                    }
                }
            }
        }

    end {
        $hasPatch = ($null -ne $Patch)
        $hasReplace = ($null -ne $Replace)
        if ($hasPatch -and $hasReplace) {
            throw ($script:GuacRestExceptionType::new(
                'Update-GuacConnection: supply exactly one of -Patch or -Replace, not both.'
            ))
        }
        if (-not $hasPatch -and -not $hasReplace) {
            throw ($script:GuacRestExceptionType::new(
                'Update-GuacConnection: supply -Patch (a JSON Patch operations array) or -Replace (a full connection object), or pipe a connection object with one of them.'
            ))
        }

        $targetId = $Id
        if ([string]::IsNullOrWhiteSpace($targetId)) { $targetId = $pendingId }
        if ($hasReplace -and [string]::IsNullOrWhiteSpace($targetId)) {
            throw ($script:GuacRestExceptionType::new(
                'Update-GuacConnection -Replace requires the connection identifier: supply -Id or pipe a connection object carrying an Identifier.'
            ))
        }

        $ctx = Resolve-GuacSessionContext -Session $Session -Server $Server -DataSource $DataSource -CmdletName 'Update-GuacConnection'

        if ($hasPatch) {
            if (-not [string]::IsNullOrWhiteSpace($targetId)) {
                $whatIfTarget = ('connection {0}' -f $targetId)
            }
            else {
                $whatIfTarget = 'connection (patch)'
            }
            if (-not ($PSCmdlet.ShouldProcess($whatIfTarget, 'Update Guacamole connection (PATCH connections)'))) {
                return
            }
            Invoke-GuacEntityPatch -Context $ctx -Collection 'connections' `
                -TargetLabel ('connection {0}' -f $targetId) -Patch $Patch | Out-Null
            return
        }

        # Full replacement via PUT.
        $body = ConvertTo-GuacEntityBody -Object $Replace -ExcludeProperty @('identifier', 'Identifier', 'activeConnections', 'lastActive', 'sharingProfiles')
        if (-not ($PSCmdlet.ShouldProcess(('connection {0}' -f $targetId), 'Replace Guacamole connection (PUT connections/{id})'))) {
            return
        }
        return (Invoke-GuacDirectory -Context $ctx -Collection 'connections' -Action 'Update' -Id $targetId -Body $body)
    }
}