Private/Import-InfraPulseChangePolicy.ps1
|
function Import-InfraPulseChangePolicy { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Path ) $resolvedPath = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath if ([System.IO.Path]::GetExtension($resolvedPath) -ne '.psd1') { throw "Policy files must use the .psd1 extension: '$resolvedPath'." } $policyData = Import-PowerShellDataFile -Path $resolvedPath $errors = New-Object System.Collections.Generic.List[string] $validStatuses = @('Healthy', 'Warning', 'Critical', 'Unknown', 'Skipped') $validIgnoreKeys = @('ComputerName', 'CheckName', 'Category', 'Target', 'Status') if (-not $policyData.Contains('SchemaVersion')) { [void]$errors.Add('SchemaVersion is required.') } elseif ([string]$policyData.SchemaVersion -ne '1.0') { [void]$errors.Add("Unsupported policy SchemaVersion '$($policyData.SchemaVersion)'. Supported version: 1.0.") } $failOn = @('Critical', 'Unknown') if ($policyData.Contains('FailOn')) { $failOn = @($policyData.FailOn | ForEach-Object { [string]$_ } | Select-Object -Unique) if ($failOn.Count -eq 0) { [void]$errors.Add('FailOn cannot be empty when specified.') } foreach ($status in $failOn) { if ($status -notin $validStatuses) { [void]$errors.Add("FailOn contains invalid status '$status'.") } } } $maximumWarnings = 0 if ($policyData.Contains('MaximumWarnings')) { if (-not (Test-InfraPulseNumber -Value $policyData.MaximumWarnings -Minimum 0)) { [void]$errors.Add('MaximumWarnings must be zero or greater.') } else { $maximumWarnings = [int]$policyData.MaximumWarnings } } $ignoreRules = @() if ($policyData.Contains('Ignore')) { $index = 0 foreach ($rule in @($policyData.Ignore)) { if (-not ($rule -is [System.Collections.IDictionary])) { [void]$errors.Add("Ignore[$index] must be a hashtable.") } else { $populatedKeys = 0 foreach ($key in $rule.Keys) { if ([string]$key -notin $validIgnoreKeys) { [void]$errors.Add("Ignore[$index] contains unsupported key '$key'. Supported keys: $($validIgnoreKeys -join ', ').") } elseif (-not [string]::IsNullOrWhiteSpace([string]$rule[$key])) { $populatedKeys++ } } if ($populatedKeys -eq 0) { [void]$errors.Add("Ignore[$index] must populate at least one field.") } else { $ignoreRules += , $rule } } $index++ } } if ($errors.Count -gt 0) { $message = "Policy file '$resolvedPath' is invalid:" + [Environment]::NewLine + (($errors | ForEach-Object { " - $_" }) -join [Environment]::NewLine) throw $message } [pscustomobject]@{ FailOn = $failOn MaximumWarnings = $maximumWarnings Ignore = @($ignoreRules) } } function Test-InfraPulseIgnoreRuleMatch { [CmdletBinding()] param( [Parameter(Mandatory)] [psobject]$Result, [AllowEmptyCollection()] [object[]]$Rules = @() ) foreach ($rule in @($Rules)) { $allFieldsMatch = $true $hasPopulatedField = $false foreach ($fieldName in @('ComputerName', 'CheckName', 'Category', 'Target', 'Status')) { if (-not $rule.Contains($fieldName) -or [string]::IsNullOrWhiteSpace([string]$rule[$fieldName])) { continue } $hasPopulatedField = $true if ([string]$Result.$fieldName -notlike [string]$rule[$fieldName]) { $allFieldsMatch = $false break } } if ($hasPopulatedField -and $allFieldsMatch) { return $true } } return $false } |