Private/PlanAccess.ps1
|
<# Accès sûrs aux structures de plan. Set-StrictMode -Version Latest fait échouer la lecture d'une clé absente d'une hashtable ou d'une propriété absente d'un objet. Ces helpers rendent l'accès tolérant tout en gardant le mode strict actif pour le reste du code (où il attrape de vraies fautes de frappe). #> function Get-SPMPlanValue { <# .SYNOPSIS Lit une clé d'une hashtable ou d'un objet, ou $null si absente. #> [CmdletBinding()] param( [Parameter(Position = 0)][AllowNull()]$Container, [Parameter(Mandatory, Position = 1)][string]$Key ) if ($null -eq $Container) { return $null } if ($Container -is [System.Collections.IDictionary]) { if ($Container.Contains($Key)) { return $Container[$Key] } # Comparaison insensible à la casse : YAML et JSON n'ont pas les mêmes usages foreach ($k in $Container.Keys) { if ("$k" -ieq $Key) { return $Container[$k] } } return $null } $property = $Container.PSObject.Properties[$Key] if ($property) { return $property.Value } return $null } function Merge-SPMPlanSection { <# .SYNOPSIS Fusionne une section fournie par l'utilisateur sur des valeurs par défaut. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory)][hashtable]$Defaults, [AllowNull()]$Provided ) $merged = @{} foreach ($k in $Defaults.Keys) { $merged[$k] = $Defaults[$k] } if ($null -ne $Provided) { if ($Provided -is [System.Collections.IDictionary]) { foreach ($k in $Provided.Keys) { $merged[$k] = $Provided[$k] } } else { foreach ($p in $Provided.PSObject.Properties) { $merged[$p.Name] = $p.Value } } } return $merged } function Resolve-SPMPlanVariable { <# .SYNOPSIS Remplace récursivement ${NOM} par la variable d'environnement correspondante. .DESCRIPTION Permet de versionner un plan sans y inscrire d'identifiant ni de secret. Une variable référencée mais absente est une erreur explicite, jamais une chaîne vide qui échouerait plus loin de façon obscure. #> [CmdletBinding()] param([Parameter(Position = 0)][AllowNull()]$Value) if ($Value -is [string]) { return [regex]::Replace($Value, '\$\{(?<name>[A-Za-z_][A-Za-z0-9_]*)\}', { param($m) $name = $m.Groups['name'].Value $envValue = [System.Environment]::GetEnvironmentVariable($name) if ([string]::IsNullOrEmpty($envValue)) { throw "Le plan référence `${$name} mais la variable d'environnement $name n'est pas définie." } $envValue }) } if ($Value -is [System.Collections.IDictionary]) { $copy = @{} foreach ($k in $Value.Keys) { $copy[$k] = Resolve-SPMPlanVariable -Value $Value[$k] } return $copy } if ($Value -is [System.Collections.IList] -and $Value -isnot [string]) { return @($Value | ForEach-Object { Resolve-SPMPlanVariable -Value $_ }) } return $Value } |