Public/Assets.ps1

function Set-TMAsset {
    <#
    .SYNOPSIS
        Update a single field on a TM asset using the TM `bulkChange` API.
 
    .DESCRIPTION
        Resolves a field label or field short-name for the specified asset type and
        submits a bulk change request to replace the field value on the provided
        TM asset. This function is suitable for single-field updates where the
        target field is supported by the TM `bulkChange` endpoint.
 
    .PARAMETER TMAssetId
        The identifier of the TM asset to update. If omitted, the function uses
        the current global asset id when available: `$TM?.Asset?.Id`.
 
    .PARAMETER TMAssetType
        The asset type. Valid values are: `DEVICE`, `APPLICATION`, `STORAGE`, `DATABASE`.
        Defaults to `DEVICE`.
 
    .PARAMETER FieldName
        The field to update. Can be provided as a field label (human-friendly)
        or as the field short name. The function will attempt to resolve labels
        to the internal field name using `Get-TMFieldSpecs` for the chosen
        `TMAssetType`.
 
    .PARAMETER NewValue
        The new value for the field. The parameter accepts a string and the
        value will be sent in the JSON payload as provided. Use numeric values
        without quotes if the API expects numbers; use quoted strings for text.
 
    .PARAMETER TMSession
        A TMSession object or session identifier used for authentication to the
        TM API. When a string is provided, the function calls `Get-TMSession`
        to resolve it. Defaults to `'Default'`.
 
    .EXAMPLE
        Set-TMAsset -TMAssetId '123456' -TMAssetType 'DEVICE' -FieldName 'status' -NewValue 2
 
    Updates the `status` field on asset `A123` to the numeric value `2`.
 
    .EXAMPLE
        $sess = Get-TMSession -Name 'Prod'
        Set-TMAsset -TMAssetId 'A123' -FieldName 'ShortNameOfField' -NewValue 'enabled' -TMSession $sess
 
    Uses an explicit session object and sets the field to the string value `enabled`.
 
    .NOTES
        - This function depends on `Get-TMSession` and `Get-TMFieldSpecs` being
          available in the current session.
        - Not all fields can be updated with this function. If the server
          rejects the change, the function throws an error including the
          server response.
        - The request is sent to: `https://<TMServer>/tdstm/ws/bulkChange`
          using the resolved session's `TMWebSession` cookie container.
 
    #>


    [CmdletBinding()]
    [Alias('Update-TMAsset')]
    param(
        [Parameter()][string]$TMAssetId = $TM?.Asset?.Id,
        [Parameter()][ValidateSet('DEVICE', 'APPLICATION', 'STORAGE', 'DATABASE')]
        [string]$TMAssetType = 'DEVICE',

        [Parameter(Mandatory)][string]$FieldName,
        [Parameter(Mandatory)][string]$NewValue,

        [Parameter()][psobject]$TMSession = 'Default'
    )

    begin {
        $TMSession = Get-TMSession $TMSession
        $fieldSpecs = Get-TMFieldSpecs

        # Deal with TM's case-sensitivity (shortName vs ShortName)
        # And with this endpoint supporting only field names (and not labels)
        if ($FieldName -in $fieldSpecs.$TMAssetType.fields.label) {
            $FieldName = $fieldSpecs.$TMAssetType.fields | Where-Object label -EQ $FieldName | Select-Object -ExpandProperty field
        } elseif ($FieldName -in $fieldSpecs.$TMAssetType.fields.field) {
            $FieldName = $fieldSpecs.$TMAssetType.fields | Where-Object field -EQ $FieldName | Select-Object -ExpandProperty field
        } else {
            throw "Field '$FieldName' was not found. Please review and retry."
        }
    }

    process {
        $uri = '{0}{1}/{2}' -f 'https://', $TMSession.TMServer, 'tdstm/ws/bulkChange'

        $body = @{
            'ids'   = @($TMAssetId)
            'type'  = $TMAssetType
            'edits' = @(
                @{
                    'fieldName' = $FieldName
                    'action'    = 'replace'
                    'value'     = $NewValue
                }
            )
        }

        $updateSplat = @{
            Uri        = $uri
            Method     = [Microsoft.PowerShell.Commands.WebRequestMethod]::Put
            WebSession = $TMSession.TMWebSession
            Body       = $body | ConvertTo-Json
        }

        $result = Invoke-WebRequest @updateSplat
        try {
            if ($result.StatusCode -eq 200) {
                if (($result.Content | ConvertFrom-Json).Status -eq 'success') {
                    Write-Verbose "Asset '$TMAssetId' update successfully"
                } else {
                    throw $result
                }
            } else {
                throw $result.Content
            }
        } catch {
            throw "Not all fields can be updated using this function. Custom fields can. Choose another field and try again. Server error: $_"
        }
    }
}