Private/Snapshot.Diagnostics.ps1
|
function Get-UTCMSnapshotDiagnostic { [CmdletBinding()] param([Parameter(Mandatory)] $Snapshot) $status = [string](Get-UTCMObjectField $Snapshot @('status')) $errors = @(Get-UTCMObjectField $Snapshot @('errorDetails') | Where-Object { $null -ne $_ }) $summary = ($errors | ForEach-Object { if ($_ -is [string]) { $_ } else { ConvertTo-Json -InputObject $_ -Depth 99 -Compress } }) -join '; ' if ($status -ne 'succeeded' -and [string]::IsNullOrWhiteSpace($summary)) { $summary = 'The service returned no usable errorDetails; extraction failure reasons are unavailable.' } [pscustomobject]@{ id = [string](Get-UTCMObjectField $Snapshot @('id')) status = $status resources = @(Get-UTCMObjectField $Snapshot @('resources') | Where-Object { $null -ne $_ }) errorDetails = $errors errorSummary = $summary } } function Assert-UTCMComparableSnapshot { [CmdletBinding()] param( [Parameter(Mandatory)] $Snapshot, [Parameter(Mandatory)][string] $Role, [switch] $AllowPartialComparison ) $diagnostic = Get-UTCMSnapshotDiagnostic -Snapshot $Snapshot if ($diagnostic.status -eq 'succeeded' -or ($diagnostic.status -eq 'partiallySuccessful' -and $AllowPartialComparison)) { return } $message = ("{0} snapshot '{1}' has status '{2}'; comparison requires succeeded snapshots. " + "Only partiallySuccessful snapshots can be included with -AllowPartialComparison for investigation; " + "their differences cannot establish reliable drift or absence of drift. {3}") -f $Role, $diagnostic.id, $diagnostic.status, $diagnostic.errorSummary $record = [System.Management.Automation.ErrorRecord]::new( [System.InvalidOperationException]::new($message), 'UTCM.IncompleteSnapshotComparison', [System.Management.Automation.ErrorCategory]::InvalidData, $Snapshot ) $PSCmdlet.ThrowTerminatingError($record) } function Get-UTCMComparisonResource { [CmdletBinding()] param([Parameter(Mandatory)] $Snapshot) $diagnostic = Get-UTCMSnapshotDiagnostic -Snapshot $Snapshot if ($diagnostic.resources.Count -eq 0) { throw (("Snapshot '{0}' does not expose its original requested resources. Refusing to infer a reduced " + "comparison scope from populated configurationItems. Use Get-UTCMTenantDriftReport with " + "-CompareResources or -ComparePreset to choose an explicit scope.") -f $diagnostic.id) } foreach ($resource in $diagnostic.resources) { if ($resource -isnot [string] -or [string]::IsNullOrWhiteSpace($resource)) { throw "Snapshot '$($diagnostic.id)' contains an invalid original requested resource identifier." } } $diagnostic.resources | Select-Object -Unique } function Export-UTCMSnapshotDiagnostic { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)][AllowEmptyCollection()][object[]] $Diagnostic, [Parameter(Mandatory)][string] $Path, [switch] $Overwrite ) if ((Test-Path -LiteralPath $Path) -and -not $Overwrite) { throw "Diagnostics file '$Path' already exists. Use -Overwrite to replace it." } $payload = [ordered]@{ generatedUtc = [datetime]::UtcNow.ToString('o') snapshots = @($Diagnostic) } $fullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) [System.IO.File]::WriteAllText($fullPath, (ConvertTo-Json -InputObject $payload -Depth 99), [System.Text.UTF8Encoding]::new($false)) return $Path } |