Public/Export-VMetricTemplate.ps1

function Export-VMetricTemplate {
    <#
    .SYNOPSIS
    Writes existing resources as a Bicep template.
 
    .DESCRIPTION
    Export-VMetricTemplate writes the resources you pipe in (or name with -Type and -Id) as one deployment
    template, ready to deploy to another tenant with New-VMetricDeployment. References to other resources
    become existing resources named by parameters defaulted to the current names, and secrets the server
    withholds become @secure() parameters whose empty default keeps the stored value. At most 100 resources.
 
    It writes the template text to the pipeline, or to a file with -Path.
 
    .PARAMETER InputObject
    Objects from the Get-VMetric cmdlets (Get-VMetricDevice, Get-VMetricTarget, ...) or deployment operations.
 
    .PARAMETER Type
    The resource type, such as VirtualMetric/devices.
 
    .PARAMETER Id
    The ids of the resources of that type.
 
    .PARAMETER Path
    Write the template to this file (UTF-8) instead of the pipeline.
 
    .PARAMETER NoClobber
    Do not overwrite an existing file.
 
    .PARAMETER PassThru
    With -Path, write the file (FileInfo) to the pipeline.
 
    .EXAMPLE
    Get-VMetricDevice -Name syslog-udp | Export-VMetricTemplate -Path ./syslog.bicep
 
    .EXAMPLE
    Export-VMetricTemplate -Type VirtualMetric/targets -Id 7318146275443761152
 
    .EXAMPLE
    (Get-VMetricDeployment -Id 7318146275443761152).Operations | Export-VMetricTemplate -Path ./rollout.bicep
 
    .OUTPUTS
    System.String, or System.IO.FileInfo with -Path -PassThru.
 
    .LINK
    New-VMetricDeployment
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low', DefaultParameterSetName = 'Object')]
    [OutputType([string], [System.IO.FileInfo])]
    param(
        [Parameter(Mandatory, ParameterSetName = 'Object', ValueFromPipeline)]
        [object[]] $InputObject,

        [Parameter(Mandatory, ParameterSetName = 'ByType')]
        [ValidatePattern('^VirtualMetric/')]
        [string] $Type,

        [Parameter(Mandatory, ParameterSetName = 'ByType', ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string[]] $Id,

        [ValidateNotNullOrEmpty()]
        [string] $Path,

        [switch] $NoClobber,

        [switch] $PassThru
    )

    begin {
        $resources = [System.Collections.Generic.List[object]]::new()
    }

    process {
        try {
            if ($PSCmdlet.ParameterSetName -eq 'ByType') {
                foreach ($item in $Id) {
                    $resources.Add([ordered]@{ type = $Type; id = $item })
                }
            }
            else {
                foreach ($item in $InputObject) {
                    $resources.Add((Resolve-VMetricExportReference -InputObject $item))
                }
            }
        }
        catch {
            if (Test-VMetricFlowControl -ErrorRecord $_) {
                throw
            }
            Write-VMetricCmdletError -Cmdlet $PSCmdlet -ErrorRecord $_ -Terminating
        }
    }

    end {
        try {
            if ($resources.Count -eq 0) {
                throw (New-VMetricException -Message 'Nothing to export: pipe resources in, or give -Type and -Id.' -Code 'NothingToExport' -Category InvalidArgument)
            }
            if ($resources.Count -gt 100) {
                throw (New-VMetricException -Message "A template holds at most 100 resources; $($resources.Count) were given." -Code 'TooManyResources' -Category LimitsExceeded)
            }
            $answer = Invoke-VMetricRequest -Method POST -Path '/deployments/export' -Body ([ordered]@{ resources = $resources.ToArray() })
            foreach ($warning in (ConvertTo-VMetricArray -InputObject (Get-VMetricMember -InputObject $answer -Name 'warnings'))) {
                Write-Warning (ConvertTo-VMetricSafeText -Text ([string]$warning))
            }
            $templateText = [string](Get-VMetricMember -InputObject $answer -Name 'template')
            if (-not $Path) {
                $templateText
                return
            }

            $target = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Path)
            if ($NoClobber -and (Test-Path -LiteralPath $target)) {
                throw (New-VMetricException -Message "'$Path' exists and -NoClobber was given." -Code 'FileExists' -Category ResourceExists)
            }
            if (-not $PSCmdlet.ShouldProcess($target, 'Write template')) {
                return
            }
            [System.IO.File]::WriteAllText($target, $templateText, [System.Text.UTF8Encoding]::new($false))
            if ($PassThru) {
                Get-Item -LiteralPath $target
            }
        }
        catch {
            if (Test-VMetricFlowControl -ErrorRecord $_) {
                throw
            }
            Write-VMetricCmdletError -Cmdlet $PSCmdlet -ErrorRecord $_ -Terminating
        }
    }
}