Public/Export-PCOciSnapshot.ps1

function Export-PCOciSnapshot {
    <#
    .SYNOPSIS
        Reads the tenancy's compartments, instances, volumes, backups and backup policies into one snapshot file.

    .DESCRIPTION
        Every family in scope, or the ones named with -Include, from every subscribed region or the ones named
        with -Region, below the tenancy root or the compartment named with -CompartmentId. Records are joined by
        id. A family that cannot be read in a compartment is recorded in the run report and the run continues;
        the snapshot is then marked complete: false and a warning is written. No field exists for instance
        metadata. The run report is written beside the snapshot.

    .PARAMETER Path
        The snapshot file. Default: .\snapshot.json.

    .PARAMETER Include
        Families to read: Compartments, Instances, Volumes, Backups, BackupPolicies. Default: all.

    .PARAMETER Deterministic
        Omit the generation time, so two reads of the same state are byte-identical.

    .PARAMETER PassThru
        Return the snapshot object instead of the summary.

    .EXAMPLE
        Connect-PCOci -ProfileName READONLY; Export-PCOciSnapshot -Path .\data\snapshot.json -Deterministic
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([pscustomobject], [PowerCraft.OCI.Core.Snapshot.TenancySnapshot])]
    param(
        [PowerCraft.OCI.Core.Identity.OciContext]$Context,
        [string]$Path = (Join-Path (Get-Location).Path 'snapshot.json'),
        [string[]]$Region,
        [string]$CompartmentId,
        [ValidateSet('Compartments', 'Instances', 'Volumes', 'Backups', 'BackupPolicies')][string[]]$Include,
        [switch]$IncludeDeleted,
        [switch]$Deterministic,
        [string]$ReportPath,
        [switch]$PassThru,
        [switch]$Force
    )

    $ctx = Get-PCOciContextOrThrow -Context $Context
    if ((Test-Path -LiteralPath $Path) -and -not $Force) { throw "A file already exists at '$Path'. Use -Force to overwrite it." }
    if (-not $ReportPath) { $ReportPath = [IO.Path]::ChangeExtension($Path, '.report.json') }
    if (-not $PSCmdlet.ShouldProcess($Path, "Read tenancy '$($ctx.TenancyName)' into a snapshot")) { return }

    $options = [PowerCraft.OCI.Core.Snapshot.SnapshotOptions]::new()
    if ($Region) { $options.Regions.AddRange([string[]]$Region) }
    if ($CompartmentId) { $options.RootCompartmentId = $CompartmentId }
    $options.IncludeDeleted = [bool]$IncludeDeleted
    $options.Families = [PowerCraft.OCI.Core.Snapshot.SnapshotOptions]::ParseFamilies([string[]]$Include)

    $report = [PowerCraft.OCI.Core.Report.RunReport]::new()
    $report.Verb = 'Export-PCOciSnapshot'
    $started = [DateTimeOffset]::UtcNow
    $report.StartedAt = $started
    Write-Verbose "Reading $($options.Families) from $(if ($Region) { $Region -join ', ' } else { 'every subscribed region' })"
    $snapshot = [PowerCraft.OCI.Core.Gateways.OciSession]::ExportSnapshot($ctx, $options, $report)
    $duration = [long]([DateTimeOffset]::UtcNow - $started).TotalMilliseconds
    $report.DurationMs = $duration

    [PowerCraft.OCI.Core.Snapshot.SnapshotWriter]::Write($snapshot, $Path, [bool]$Deterministic)
    $report.Write($ReportPath, [bool]$Deterministic)
    foreach ($w in $report.Warnings) { Write-Warning $w }
    if (-not $snapshot.Complete) {
        Write-Warning ("The snapshot is incomplete: {0} failure(s). See the report at '{1}'." -f $report.Failures.Count, $ReportPath)
    }

    if ($PassThru) { return $snapshot }
    [pscustomobject]@{
        SnapshotPath   = (Resolve-Path -LiteralPath $Path).Path
        ReportPath     = (Resolve-Path -LiteralPath $ReportPath).Path
        Complete       = $snapshot.Complete
        Regions        = @($snapshot.Regions)
        Compartments   = $snapshot.Compartments.Count
        Instances      = $snapshot.Instances.Count
        Volumes        = $snapshot.Volumes.Count
        Backups        = $snapshot.Backups.Count
        BackupPolicies = $snapshot.BackupPolicies.Count
        Failures       = $report.Failures.Count
        DurationMs     = $duration
    }
}