CoreOps/VolumeGroupSnapshot/Get-SDPVolumeGroupSnapshot.ps1

<#
    SDPVolumeGroupSnapshot — typed wrapper for a regular SDP snapshot
    record (source = /volume_groups/X). View-snapshots from the
    -asViewSnapshot path also wear this type since the API record shape
    is identical.

    `source`, `volume_group`, `retention_policy`, and `replication_session`
    are ref-shaped; Update-SDPRefObjects attaches `*_name`
    NoteProperties at runtime. `creationTime` is a computed [datetime]
    derived from the raw `creation_time` int.
#>


class SDPVolumeGroupSnapshot {

    # --- Identity / properties shown in the default table view ---
    [string]   $name
    [string]   $id
    [string]   $short_name

    # --- Lifecycle ---
    [datetime] $creationTime
    [int]      $creation_time
    [int]      $data_creation_time
    [int]      $last_exposed_time
    [int]      $num_of_clones
    [string]   $triggered_by

    # --- Identity (additional) ---
    [string]   $description
    [string]   $iscsi_tgt_converted_name
    [string]   $wwn
    [int]      $generation_number

    # --- Sizing ---
    [long]     $volsnaps_provisioned_capacity

    # --- Flags ---
    [bool]     $is_application_consistent
    [bool]     $is_auto_deleteable
    [bool]     $is_deleted
    [bool]     $is_exist_on_peer
    [bool]     $is_exposable
    [bool]     $is_external
    [bool]     $is_locked_by_replication
    [bool]     $is_originating_from_peer

    # --- Refs (kept nested for Update-SDPRefObjects). ---
    [psobject] $source
    [psobject] $volume_group
    [psobject] $retention_policy
    [psobject] $replication_session

    # Hidden context
    hidden [string] $context

    SDPVolumeGroupSnapshot() {}

    SDPVolumeGroupSnapshot([psobject] $apiHit, [string] $context) {
        $this.id                            = $apiHit.id
        $this.name                          = $apiHit.name
        $this.short_name                    = $apiHit.short_name
        $this.description                   = $apiHit.description
        $this.iscsi_tgt_converted_name      = $apiHit.iscsi_tgt_converted_name
        $this.wwn                           = $apiHit.wwn
        $this.generation_number             = $apiHit.generation_number
        $this.creation_time                 = $apiHit.creation_time
        $this.data_creation_time            = $apiHit.data_creation_time
        $this.last_exposed_time             = $apiHit.last_exposed_time
        $this.num_of_clones                 = $apiHit.num_of_clones
        $this.triggered_by                  = $apiHit.triggered_by
        $this.volsnaps_provisioned_capacity = $apiHit.volsnaps_provisioned_capacity
        $this.is_application_consistent     = [bool] $apiHit.is_application_consistent
        $this.is_auto_deleteable            = [bool] $apiHit.is_auto_deleteable
        $this.is_deleted                    = [bool] $apiHit.is_deleted
        $this.is_exist_on_peer              = [bool] $apiHit.is_exist_on_peer
        $this.is_exposable                  = [bool] $apiHit.is_exposable
        $this.is_external                   = [bool] $apiHit.is_external
        $this.is_locked_by_replication      = [bool] $apiHit.is_locked_by_replication
        $this.is_originating_from_peer      = [bool] $apiHit.is_originating_from_peer
        $this.context                     = $context

        if ($apiHit.creation_time) {
            $this.creationTime = Convert-SDPTimeStampFrom -timestamp ([int] $apiHit.creation_time)
        }

        if ($apiHit.source)              { $this.source              = $apiHit.source }
        if ($apiHit.volume_group)        { $this.volume_group        = $apiHit.volume_group }
        if ($apiHit.retention_policy)    { $this.retention_policy    = $apiHit.retention_policy }
        if ($apiHit.replication_session) { $this.replication_session = $apiHit.replication_session }
    }

    # ---- Operational methods --------------------------------------------

    [SDPVolumeGroupSnapshot] Refresh() {
        return [SDPVolumeGroupSnapshot]::new(
            (Get-SDPVolumeGroupSnapshot -id $this.id -context $this.context -doNotResolve),
            $this.context)
    }

    [void] Delete() {
        Remove-SDPVolumeGroupSnapshot -id $this.id -context $this.context | Out-Null
    }

    [string] ToString() {
        return $this.name
    }
}

Update-TypeData -TypeName 'SDPVolumeGroupSnapshot' `
                -DefaultDisplayPropertySet 'name','id','source_name','retention_policy_name','creationTime','is_exposable' `
                -Force


<#
    .SYNOPSIS
    Retrieves volume group snapshots (and view-snapshots) from the SDP.

    .DESCRIPTION
    All snapshots live at the /snapshots endpoint. They differ by what
    `source` points at:

      * Regular snapshot — source = /volume_groups/X (default behavior)
      * View-snapshot — source = /snapshots/X where X is itself a view

    The `-asViewSnapshot` switch flips the post-fetch filter to return
    view-snapshots instead of regular snapshots. Without the switch, the
    function only returns snapshots whose source is a volume group.

    Use Get-SDPVolumeGroupView for views themselves (snapshot records
    where `is_exposable=true` and source is a regular snapshot).

    .PARAMETER name
    Filter by full snapshot name (the `vg:short_name` form).

    .PARAMETER short_name
    Filter by short name only (the user-supplied portion).

    .PARAMETER id
    The unique identifier of the snapshot.

    .PARAMETER volumeGroupName
    Filter by volume group name. Accepts piped input from
    Get-SDPVolumeGroup. Only meaningful for regular snapshots.

    .PARAMETER asViewSnapshot
    Return view-snapshots instead of regular snapshots.

    .PARAMETER doNotResolve
    Skip the auto-pipe through Update-SDPRefObjects. Returns raw API
    objects.

    .PARAMETER context
    K2 context name. Defaults to 'sdpconnection'.

    .EXAMPLE
    Get-SDPVolumeGroupSnapshot

    .EXAMPLE
    Get-SDPVolumeGroupSnapshot -name "test-vg:test-snap"

    .EXAMPLE
    Get-SDPVolumeGroup -name "test-vg" | Get-SDPVolumeGroupSnapshot

    .EXAMPLE
    Get-SDPVolumeGroupSnapshot -asViewSnapshot

    .NOTES
    Authored by J.R. Phillips (GitHub: JayAreP)

    .LINK
    https://github.com/silk-us/silk-sdp-powershell-sdk
#>


function Get-SDPVolumeGroupSnapshot {
    [CmdletBinding()]
    [OutputType([SDPVolumeGroupSnapshot])]
    param(
        # Typed as [object] to dodge module load-order coupling on the
        # SDPVolumeGroup class. Validated to [SDPVolumeGroup] at the top of process.
        [parameter(ValueFromPipeline)]
        [object] $InputObject,
        [parameter(ValueFromPipelineByPropertyName)]
        [Alias("pipeName")]
        [string] $volumeGroupName,
        [parameter()]
        [string] $description,
        [parameter()]
        [Alias("GenerationNumber")]
        [int] $generation_number,
        [parameter()]
        [int] $id,
        [parameter()]
        [Alias("IscsiTgtConvertedName")]
        [string] $iscsi_tgt_converted_name,
        [parameter()]
        [Alias("IsApplicationConsistent")]
        [bool] $is_application_consistent,
        [parameter()]
        [Alias("IsAutoDeleteable")]
        [bool] $is_auto_deleteable,
        [parameter()]
        [Alias("IsDeleted")]
        [bool] $is_deleted,
        [parameter()]
        [Alias("IsExistOnPeer")]
        [bool] $is_exist_on_peer,
        [parameter()]
        [Alias("IsExposable")]
        [bool] $is_exposable,
        [parameter()]
        [Alias("IsExternal")]
        [bool] $is_external,
        [parameter()]
        [Alias("IsOriginatingFromPeer")]
        [bool] $is_originating_from_peer,
        [parameter()]
        [Alias("LastExposedTime")]
        [string] $last_exposed_time,
        [parameter()]
        [ValidateLength(0, 42)]
        [string] $name,
        [parameter()]
        [Alias("ReplicationSession")]
        [string] $replication_session,
        [parameter()]
        [Alias("RetentionPolicy")]
        [string] $retention_policy,
        [parameter()]
        [Alias("ShortName")]
        [string] $short_name,
        [parameter()]
        [Alias("TriggeredBy")]
        [string] $triggered_by,
        [parameter()]
        [Alias("VolsnapsProvisionedCapacity")]
        [int] $volsnaps_provisioned_capacity,
        [parameter()]
        [Alias("VolumeGroup")]
        [string] $volume_group,
        [parameter()]
        [string] $wwn,
        [parameter()]
        [switch] $asViewSnapshot,
        [parameter()]
        [switch] $doNotResolve,
        [parameter()]
        [string] $context = 'sdpconnection'
    )

    begin {
        $endpoint = "snapshots"
    }

    process {

        if ($InputObject -and $InputObject -isnot [SDPVolumeGroup]) {
            throw "Get-SDPVolumeGroupSnapshot accepts pipeline input only from SDPVolumeGroup; got [$($InputObject.GetType().FullName)]."
        }
        # When piped an SDPVolumeGroup, write the volume_group ref directly
        # (skip the name → id lookup) and inherit context.
        if ($InputObject) {
            $PSBoundParameters.volume_group = ConvertTo-SDPObjectPrefix -ObjectID $InputObject.id -ObjectPath 'volume_groups' -nestedObject
            if (-not $PSBoundParameters.ContainsKey('context')) {
                $context = $InputObject.context
            }
        }
        $PSBoundParameters.Remove('InputObject') | Out-Null

        # Special Ops — translate volumeGroupName to a volume_group ref.

        if ($volumeGroupName) {
            $vg = Get-SDPVolumeGroup -name $volumeGroupName -context $context -doNotResolve
            $volumeGroupPath = ConvertTo-SDPObjectPrefix -ObjectID $vg.id -ObjectPath 'volume_groups' -nestedObject
            $PSBoundParameters.remove('volumeGroupName') | Out-Null
            $PSBoundParameters.volume_group = $volumeGroupPath
        }

        # Strip internal-only switches before passing to Invoke-SDPRestCall.
        $PSBoundParameters.Remove('asViewSnapshot') | Out-Null
        $PSBoundParameters.Remove('doNotResolve')  | Out-Null

        $results = Invoke-SDPRestCall -endpoint $endpoint -method GET -parameterList $PSBoundParameters -context $context -strictURI

        # Source-shape filter.

        if ($asViewSnapshot) {
            # View-snapshots: source is /snapshots/X AND X itself has source /snapshots/.
            $snapSourced = foreach ($r in $results) {
                $ref = ConvertFrom-SDPObjectPrefix -Object $r.source
                if ($ref.ObjectPath -eq 'snapshots') { $r }
            }
            $newResults = foreach ($r in $snapSourced) {
                $ref = ConvertFrom-SDPObjectPrefix -Object $r.source
                if ($snapSourced.id -contains $ref.ObjectId) { $r }
            }
        } else {
            # Default: regular snapshots — source = /volume_groups/.
            $newResults = foreach ($r in $results) {
                $ref = ConvertFrom-SDPObjectPrefix -Object $r.source
                if ($ref.ObjectPath -eq 'volume_groups') { $r }
            }
        }

        $instances = foreach ($hit in $newResults) {
            [SDPVolumeGroupSnapshot]::new($hit, $context)
        }

        if ($doNotResolve) {
            $instances
        } else {
            $instances | Update-SDPRefObjects -context $context
        }
    }
}