Public/Test-InfraPulseComparison.ps1
|
function Test-InfraPulseComparison { <# .SYNOPSIS Evaluates InfraPulse comparisons against a change policy. .DESCRIPTION Applies blocking change types to one or more InfraPulse.Comparison objects produced by Compare-InfraPulseReport and returns an InfraPulse.ComparisonEvaluation object describing the outcome. By default NewFinding and Regressed changes block, which turns a pre-change/post-change comparison into a deterministic release gate. The command never exits the PowerShell host process. It throws only when ThrowOnFailure is explicitly requested and the evaluation fails. .PARAMETER InputObject One or more InfraPulse.Comparison objects. .PARAMETER FailOn Change types that block the evaluation. Defaults to NewFinding and Regressed. .PARAMETER Quiet Returns only a Boolean evaluation result. .PARAMETER ThrowOnFailure Throws a terminating error with the evaluation message when blocking changes are present. .EXAMPLE Compare-InfraPulseReport $before $after | Test-InfraPulseComparison .EXAMPLE $comparison | Test-InfraPulseComparison -FailOn NewFinding, Regressed, NotComparable -ThrowOnFailure #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [object]$InputObject, [ValidateSet('NewFinding', 'Regressed', 'Resolved', 'Improved', 'Changed', 'NotComparable', 'Added', 'Unchanged')] [string[]]$FailOn = @('NewFinding', 'Regressed'), [switch]$Quiet, [switch]$ThrowOnFailure ) begin { $comparisons = New-Object System.Collections.Generic.List[object] } process { if ($null -eq $InputObject.PSObject.Properties['Changes'] -or $null -eq $InputObject.PSObject.Properties['HasRegressions']) { throw 'InputObject is not an InfraPulse comparison.' } [void]$comparisons.Add($InputObject) } end { if ($comparisons.Count -eq 0) { throw 'No InfraPulse comparisons were supplied.' } $comparisonArray = @($comparisons.ToArray()) $failOnTypes = @($FailOn | Select-Object -Unique) $allChanges = @($comparisonArray | ForEach-Object { @($_.Changes) }) $violations = @($allChanges | Where-Object { [string]$_.ChangeType -in $failOnTypes }) $passed = $violations.Count -eq 0 $message = if ($passed) { "$($allChanges.Count) classified change(s) contain no blocking change types ($($failOnTypes -join ', '))." } else { $violationTypes = @($violations | ForEach-Object { [string]$_.ChangeType } | Select-Object -Unique | Sort-Object) -join ', ' "Comparison evaluation failed: $($violations.Count) blocking change(s) of type $violationTypes." } $evaluation = [pscustomobject][ordered]@{ Passed = $passed Message = $message FailOn = $failOnTypes TotalChanges = $allChanges.Count ViolationCount = $violations.Count Violations = @( foreach ($violation in $violations) { [pscustomobject][ordered]@{ ComputerName = [string]$violation.ComputerName ChangeType = [string]$violation.ChangeType CheckName = [string]$violation.CheckName Target = [string]$violation.Target ReferenceStatus = [string]$violation.ReferenceStatus DifferenceStatus = [string]$violation.DifferenceStatus } } ) ComputerNames = @($comparisonArray | ForEach-Object { [string]$_.ComputerName } | Select-Object -Unique) GeneratedAtUtc = [DateTime]::UtcNow } $evaluation.PSObject.TypeNames.Insert(0, 'InfraPulse.ComparisonEvaluation') if (-not $passed -and $ThrowOnFailure) { throw $message } if ($Quiet) { return $passed } return $evaluation } } |