Public/Export-PCOciSnapshot.ps1

function Export-PCOciSnapshot {
    <#
    .SYNOPSIS
        Reads the tenancy's compartments, instances, volumes, backups, backup policies, networks and Cloud Guard problems 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. Cloud Guard is read once, from its reporting region, for every region at once: the active problems
        below the root and the tenancy's security and risk scores (0.2.0). Networks (0.3.0) are the VCNs, subnets,
        security lists and network security groups with their rules, route tables, gateways, dynamic routing
        gateways with their attachments, site-to-site VPN connections with their tunnels' state (never a shared
        secret) and the reserved public addresses, per region. 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, CloudGuard, Networks. 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', 'CloudGuard', 'Networks')][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
        Vcns           = $(if ($snapshot.Networks) { $snapshot.Networks.Vcns.Count } else { $null })
        Subnets        = $(if ($snapshot.Networks) { $snapshot.Networks.Subnets.Count } else { $null })
        CloudGuardProblems = $snapshot.CloudGuardProblems.Count
        SecurityScore  = $(if ($snapshot.CloudGuard) { $snapshot.CloudGuard.SecurityScore } else { $null })
        Failures       = $report.Failures.Count
        DurationMs     = $duration
    }
}