Providers/FreeIPA/Private/Get-FreeIPAMemberFailure.ps1
|
function Get-FreeIPAMemberFailure { <# .SYNOPSIS Reads the failures out of a membership call's result, one line each .DESCRIPTION FreeIPA's add-member and remove-member calls never fail as a whole. They answer with a count of completed changes and a 'failed' tree - member, then the kind (user, group, host), then a list of [name, reason] pairs - and a caller that reads only the count misses a member that was silently not added. This flattens that tree into 'kind name: reason' lines, so each step can decide which reasons matter: 'already a member' is the normal answer on a re-run, and anything else is an error. .PARAMETER Outcome The envelope an add-member or remove-member call returned. .OUTPUTS System.String[]. One line per failure, or an empty array. .EXAMPLE PS> Get-FreeIPAMemberFailure -Outcome $outcome DESCRIPTION: Lists what a group_add_member call could not do OUTPUT: 'user jnino: This entry is already a member' USE CASE: Every step that assigns membership .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ #> [CmdletBinding()] [OutputType([string[]])] param( [Parameter()] [AllowNull()] [object]$Outcome ) $lines = [System.Collections.Generic.List[string]]::new() if (-not $Outcome -or -not $Outcome.PSObject.Properties['failed'] -or -not $Outcome.failed) { return $lines.ToArray() } foreach ($relation in $Outcome.failed.PSObject.Properties) { if (-not $relation.Value) { continue } foreach ($kind in $relation.Value.PSObject.Properties) { foreach ($pair in @($kind.Value)) { $items = @($pair) # Built into a variable first: inside a method call's argument list the commas # of the format operator would be read as argument separators. $line = $null if ($items.Count -ge 2) { $line = '{0} {1}: {2}' -f $kind.Name, $items[0], $items[1] } elseif ($items.Count -eq 1) { $line = '{0} {1}' -f $kind.Name, $items[0] } if ($line) { $lines.Add($line) } } } } return $lines.ToArray() } |