Public/Get-TcReadiness.ps1
|
function Get-TcReadiness { <# .SYNOPSIS Returns the readiness score of each tenant, and the state of each of its workloads. .DESCRIPTION The most severe finding of a workload sets its state: Blocking for Critical, To address for High, Secondary for Medium, Passed otherwise. Their weights are 0, 0.35, 0.7 and 1. A workload with nothing against it reads Not collected, not Passed, when none of its collectors worked or none ran. Score is the one to report. It counts every workload the tenant has, and a workload earns its weight only if the rules read everything they needed for it, in this tenant and in the target, and none of them stopped. Whatever was not read could hide a blocker, so it counts as one, and losing a service can never raise Score. A workload whose service the tenant does not have (License or service missing, on every collector) leaves the count: there was nothing to read. CollectedScore averages the workloads that were read, with no penalty for the others. It says how the collected part looks, and it does go up when a bad workload is not collected. Compare it with Score to see how much of the picture is missing. Findings on all tenants together count for no tenant. A comparison finding counts for its source. .PARAMETER Snapshot The snapshot, as read from snapshot.json. .PARAMETER RuleSet The result of Invoke-TcRuleSet on this snapshot. Without it, the rules run first. .EXAMPLE Get-TcReadiness -Snapshot $snapshot | Format-Table Role, Tenant, Score, CollectedScore Shows the score of each tenant. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory)][System.Collections.IDictionary]$Snapshot, [System.Collections.IDictionary]$RuleSet ) if (-not $RuleSet) { $RuleSet = Invoke-TcRuleSet -Snapshot $Snapshot } $states = [ordered]@{ 'Blocking' = 0.0; 'To address' = 0.35; 'Secondary' = 0.7; 'Passed' = 1.0; 'Not collected' = $null } $severities = 'Critical', 'High', 'Medium', 'Low', 'Info' $tenants = Get-TcProperty $Snapshot 'tenants' $coverage = @(Get-TcProperty $Snapshot 'coverage' @()) $findings = @(Get-TcProperty $RuleSet 'findings' @()) $unread = @(Get-TcProperty $RuleSet 'unread' @()) $errors = @(Get-TcProperty $RuleSet 'errors' @()) foreach ($role in @('Target', 'S1', 'S2', 'S3' | Where-Object { $tenants.Contains($_) })) { $counts = [ordered]@{} foreach ($state in $states.Keys) { $counts[$state] = 0 } [double]$credit = 0 [double]$collected = 0 $applicable = 0 $read = 0 $lines = foreach ($workload in $script:TcWorkloads) { $rows = @($findings | Where-Object { $_['code'] -eq $role -and $_['workload'] -eq $workload }) $worst = if ($rows.Count) { (@($rows | ForEach-Object { $severities.IndexOf($_['severity']) }) | Measure-Object -Minimum).Minimum } else { 9 } $collectors = @($coverage | Where-Object { (Get-TcProperty $_ 'role') -eq $role -and (Get-TcProperty $_ 'workload') -eq $workload }) $failed = @($collectors | Where-Object { (Get-TcProperty $_ 'status') -notin 'OK', 'Partial' }) $absent = @($collectors | Where-Object { (Get-TcProperty $_ 'status') -eq 'License or service missing' }) $reading = if (-not $collectors.Count) { 'None' } elseif ($failed.Count -eq $collectors.Count) { 'Failed' } elseif ($failed.Count -or @($collectors | Where-Object { (Get-TcProperty $_ 'status') -eq 'Partial' }).Count) { 'Partial' } else { 'OK' } $state = switch ($worst) { 0 { 'Blocking' } 1 { 'To address' } 2 { 'Secondary' } default { 'Passed' } } if ($state -eq 'Passed' -and $reading -in 'Failed', 'None') { $state = 'Not collected' } $missing = @($unread | Where-Object { $_['role'] -eq $role -and $_['workload'] -eq $workload } | ForEach-Object { if ($_['tenantRole'] -eq $role) { $_['table'] } else { "$($_['tenantRole']).$($_['table'])" } }) $stopped = @($errors | Where-Object { (Get-TcProperty $_ 'role') -in $role, 'All' -and (Get-TcProperty $_ 'workload') -eq $workload }).Count $weight = $states[$state] $isApplicable = -not ($collectors.Count -and $absent.Count -eq $collectors.Count) $complete = $state -ne 'Not collected' -and -not $missing.Count -and -not $stopped $earned = if ($complete) { $weight } else { 0.0 } $counts[$state]++ if ($isApplicable) { $applicable++; $credit += $earned } if ($state -ne 'Not collected') { $read++; $collected += $weight } [pscustomobject][ordered]@{ Workload = $workload; State = $state; Weight = $weight; Credit = $earned; Complete = $complete; Applicable = $isApplicable Coverage = $reading; Findings = $rows.Count; Open = @($rows | Where-Object { $_['severity'] -ne 'Info' }).Count; Unread = $missing; RulesStopped = $stopped } } [pscustomobject][ordered]@{ Role = $role Tenant = [string](Get-TcProperty $tenants[$role] 'displayName' $role) Score = ConvertTo-TcReadinessScore -Sum $credit -Count $applicable CollectedScore = ConvertTo-TcReadinessScore -Sum $collected -Count $read States = $counts Workloads = @($lines) } } } |