Public/resource-detail.ps1

# Resource details (metadata): the arbitrary key/value pairs attached to resources
# such as instances, templates, and volumes, separate from taggable resource tags.

function Get-CSResourceDetail {
    <#
    .SYNOPSIS
        Lists the details (metadata) on a resource.

    .DESCRIPTION
        Wraps listResourceDetails. -ResourceType is the kind of resource (for example
        UserVm, Template, Volume, Network); filter to one resource with -ResourceId
        and to one key with -Key. Accepts objects with an id on the pipeline.

    .PARAMETER ResourceType
        The resource type (for example UserVm, Template, Volume, Network)

    .PARAMETER ResourceId
        List details for this resource. Binds from a piped object's id.

    .PARAMETER Key
        Only the detail with this key

    .PARAMETER ForDisplay
        Only details marked for display

    .PARAMETER Keyword
        Filter by keyword

    .PARAMETER Page
        Page number of results to return

    .PARAMETER PageSize
        Number of results per page

    .EXAMPLE
        Get-CSResourceDetail -ResourceType UserVm -ResourceId $vmId
        Lists all details on an instance.

    .EXAMPLE
        Get-CSVM -Name 'db-01' | Get-CSResourceDetail -ResourceType UserVm -Key 'maintenance.window'
        Reads one detail of an instance piped in by object.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ResourceType,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$ResourceId,

        [string]$Key,

        [Nullable[bool]]$ForDisplay,

        [string]$Keyword,

        [int]$Page,

        [int]$PageSize
    )

    process {
        $apiParams = @{ resourcetype = $ResourceType }
        Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{
            ResourceId = 'resourceid'; Key = 'key'; Keyword = 'keyword'; Page = 'page'; PageSize = 'pagesize'
        })
        if ($PSBoundParameters.ContainsKey('ForDisplay')) { $apiParams['fordisplay'] = ([bool]$ForDisplay).ToString().ToLowerInvariant() }
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listResourceDetails' -Parameters $apiParams) -Command 'listResourceDetails'
    }
}

function Add-CSResourceDetail {
    <#
    .SYNOPSIS
        Adds detail (metadata) key/value pairs to a resource.

    .DESCRIPTION
        Wraps addResourceDetail, attaching one or more key/value details to a
        resource. Existing details with the same keys are overwritten. Accepts objects
        with an id on the pipeline.

    .PARAMETER ResourceType
        The resource type (for example UserVm, Template, Volume, Network)

    .PARAMETER ResourceId
        The resource to add details to. Binds from a piped object's id.

    .PARAMETER Details
        The details to add, as a hashtable of key = value pairs

    .PARAMETER ForDisplay
        Whether the details are shown to end users

    .EXAMPLE
        Add-CSResourceDetail -ResourceType UserVm -ResourceId $vmId -Details @{ 'maintenance.window' = 'Sun 02:00'; owner = 'dba-team' }
        Adds two details to an instance.

    .EXAMPLE
        Get-CSVM -Name 'db-01' | Add-CSResourceDetail -ResourceType UserVm -Details @{ tier = 'gold' }
        Adds a detail to an instance piped in by object.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ResourceType,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$ResourceId,

        [Parameter(Mandatory = $true)]
        [hashtable]$Details,

        [Nullable[bool]]$ForDisplay
    )

    process {
        if ($Details.Count -eq 0) { throw '-Details must contain at least one key/value pair.' }
        $apiParams = @{ resourcetype = $ResourceType; resourceid = $ResourceId }
        if ($PSBoundParameters.ContainsKey('ForDisplay')) { $apiParams['fordisplay'] = ([bool]$ForDisplay).ToString().ToLowerInvariant() }
        Add-CSMapParameter -ApiParameters $apiParams -Name 'details' -Map $Details
        if ($PSCmdlet.ShouldProcess("$ResourceType $ResourceId", "Add $($Details.Count) detail(s)")) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'addResourceDetail' -Parameters $apiParams) -Command 'addResourceDetail'
        }
    }
}

function Remove-CSResourceDetail {
    <#
    .SYNOPSIS
        Removes detail (metadata) from a resource.

    .DESCRIPTION
        Wraps removeResourceDetail. With -Key only that detail is removed; without it,
        all details on the resource are removed. Accepts objects with an id on the
        pipeline.

    .PARAMETER ResourceType
        The resource type (for example UserVm, Template, Volume, Network)

    .PARAMETER ResourceId
        The resource to remove details from. Binds from a piped object's id.

    .PARAMETER Key
        Remove only the detail with this key. Omit to remove all details.

    .EXAMPLE
        Remove-CSResourceDetail -ResourceType UserVm -ResourceId $vmId -Key 'maintenance.window'
        Removes one detail from an instance.

    .EXAMPLE
        Get-CSVM -Name 'db-01' | Remove-CSResourceDetail -ResourceType UserVm
        Removes all details from an instance piped in by object.
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ResourceType,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$ResourceId,

        [string]$Key
    )

    process {
        $apiParams = @{ resourcetype = $ResourceType; resourceid = $ResourceId }
        if ($PSBoundParameters.ContainsKey('Key')) { $apiParams['key'] = $Key }
        $target = if ($Key) { "detail '$Key' on $ResourceType $ResourceId" } else { "all details on $ResourceType $ResourceId" }
        if ($PSCmdlet.ShouldProcess($target, 'Remove')) {
            ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'removeResourceDetail' -Parameters $apiParams) -Command 'removeResourceDetail'
        }
    }
}

function Get-CSResourceDetailOption {
    <#
    .SYNOPSIS
        Lists the possible detail keys and values for a resource type.

    .DESCRIPTION
        Wraps listDetailOptions, returning the recognized detail keys (and their
        allowed values, where fixed) for a resource type such as UserVm or Template.

    .PARAMETER ResourceType
        The resource type to list detail options for (for example UserVm, Template)

    .PARAMETER ResourceId
        Scope the options to a specific resource

    .EXAMPLE
        Get-CSResourceDetailOption -ResourceType UserVm
        Lists the detail keys and options an instance supports.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$ResourceType,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [Alias('Id')]
        [string]$ResourceId
    )

    process {
        $apiParams = @{ resourcetype = $ResourceType }
        if ($PSBoundParameters.ContainsKey('ResourceId')) { $apiParams['resourceid'] = $ResourceId }
        ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listDetailOptions' -Parameters $apiParams) -Command 'listDetailOptions'
    }
}