Private/Resolve-HDTDiskLayoutName.ps1
|
function Resolve-HDTDiskLayoutName { <# .SYNOPSIS Decides which named disk layout a machine gets. .DESCRIPTION The engine selects a layout by firmware unless the sequence pins one". Precedence, highest first: 1 the step's layout: property (-Layout) 2 the HDTDiskLayout variable 3 firmware - HDTIsUEFI true means uefi-standard A MACHINE WHOSE FIRMWARE WAS NEVER GATHERED IS NOT A UEFI MACHINE BY DEFAULT. An absent HDTIsUEFI resolves to bios-standard and WARNS, rather than assuming the modern answer: an MBR disk on UEFI hardware fails to boot loudly and immediately, while a GPT disk on a BIOS machine fails after the image has been applied, which costs the whole deployment instead of the first minute of it. HDTIsUEFI is read as a boolean OR as text, because the variable dictionary carries whatever the rules produced and a rules.yaml value arrives as a string. The pinned name is %Var%-expanded first, so a sequence may write layout: "%HDTDiskLayout%". A token that resolves to nothing leaves the name unusable, and the resolver falls through to the next source rather than failing on a value the author never meant to pin. A name no layout defines is a terminating HDTConfigurationError listing the names that exist - and the name it returns is the layout's own casing, so callers may compare it exactly. .PARAMETER Variable The resolved variable scope. Read for HDTDiskLayout and HDTIsUEFI, and used to expand a %Var% in -Layout. .PARAMETER Layout The name the step pinned, if any. May contain %Var% tokens. .PARAMETER Definition Extra layout definitions, passed straight through to Get-HDTDiskLayout so a workspace-supplied layout is a legal pin. .OUTPUTS System.String - a layout name Get-HDTDiskLayout accepts. .EXAMPLE Resolve-HDTDiskLayoutName -Variable $scope The unattended case: firmware decides. .EXAMPLE Resolve-HDTDiskLayoutName -Variable $scope -Layout '%HDTDiskLayout%' The authored case, as the sample sequence pins it. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNull()] [System.Collections.IDictionary] $Variable, [Parameter(Position = 1)] [AllowEmptyString()] [AllowNull()] [string] $Layout, [Parameter()] [AllowNull()] [System.Collections.IDictionary] $Definition ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $known = @(Get-HDTDiskLayout -Definition $Definition) $knownName = @($known | ForEach-Object { $_.Name }) # A hashtable literal is case-SENSITIVE on its keys, and a variable scope is # not, so every lookup goes through one case-insensitive walk. $lookup = { param($Name) foreach ($key in @($Variable.Keys)) { if ([string] $key -eq $Name) { return $Variable[$key] } } return $null } $requested = '' if (-not [string]::IsNullOrWhiteSpace($Layout)) { $scope = [System.Collections.Specialized.OrderedDictionary]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($key in @($Variable.Keys)) { $scope[[string] $key] = $Variable[$key] } $expanded = Expand-HDTVariableToken -Value $Layout -Scope $scope # A token that resolved to nothing is left literally, so an unexpanded # per cent means the author pinned something this machine does not have. if ($expanded -notmatch '%') { $requested = $expanded } } if ([string]::IsNullOrWhiteSpace($requested)) { $requested = [string] (& $lookup 'HDTDiskLayout') } if (-not [string]::IsNullOrWhiteSpace($requested)) { foreach ($name in $knownName) { if ($name -eq $requested) { return $name } } $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -TargetObject $requested ` -Message ("'{0}' is not a disk layout this engine knows. The layouts are {1}." -f $requested, ($knownName -join ', ')))) } $firmware = & $lookup 'HDTIsUEFI' if ($null -eq $firmware) { Write-Warning 'HDTIsUEFI was not gathered for this machine, so the bios-standard disk layout was assumed. Set HDTIsUEFI, or pin a layout on the step, rather than relying on this.' return 'bios-standard' } $isUefi = $false if ($firmware -is [bool]) { $isUefi = [bool] $firmware } else { # A rules.yaml value arrives as text, so 'True' and 'true' both count and # anything else - including 'False' and '0' - does not. $isUefi = ([string] $firmware).Trim() -eq 'True' } if ($isUefi) { return 'uefi-standard' } return 'bios-standard' } |