Public/Import-HDTRuleDocument.ps1
|
function Import-HDTRuleDocument { <# .SYNOPSIS Reads, parses, validates and normalises a rules.yaml. .DESCRIPTION The public front door to rules.yaml. It reads the file through an injected IFileSystem - never Get-Content - so the whole authoring path is provable under Pester with no share, no media and no disk. Four steps, and a failure at any of them is a terminating HDTConfigurationError naming the file: 1. read through IFileSystem; 2. parse with ConvertFrom-HDTYaml, which turns a parser exception into an error naming the file and the LINE; 3. validate with Assert-HDTRuleDocument, which names the file and the RULE; 4. normalise. Step 4 is load-bearing rather than cosmetic. Rule resolution applies set: in document order and looks names up case-insensitively, so every When and Set is re-materialised into an OrderedDictionary built with StringComparer::OrdinalIgnoreCase. The caller then never has to care what the YAML parser handed back, and a hand-written rules.yaml may spell HDTmodel however it likes. .PARAMETER Path The rules.yaml to read. Interpreted by the filesystem service, so it may be a share path, a media path or a fake's in-memory path. .PARAMETER FileSystem An IFileSystem - the real adapter in production, New-HDTFakeFileSystem in a test. .OUTPUTS System.Management.Automation.PSCustomObject: Path the path it was given SchemaVersion [int] Rule one [pscustomobject] per rule, in document order: Index (1-based), Name, When, Set, SetFrom When is an empty ordered dictionary for a rule with no conditions; Set is $null for a setFrom rule and SetFrom is $null for a set rule. .EXAMPLE $document = Import-HDTRuleDocument -Path 'X:\Deploy\rules.yaml' -FileSystem (New-HDTFileSystem) $document.Rule | Format-Table Index, Name, SetFrom .EXAMPLE $fs = New-HDTFakeFileSystem -File @{ 'C:\ws\rules.yaml' = $text } Import-HDTRuleDocument -Path 'C:\ws\rules.yaml' -FileSystem $fs The same call in a test, with no file on disk anywhere. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string] $Path, [Parameter(Mandatory = $true)] [ValidateNotNull()] [object] $FileSystem ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' if (-not $FileSystem.TestPath($Path)) { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $Path ` -Message 'the rules file does not exist. Every workspace declares one at its root.' ` -Category ObjectNotFound)) } $text = $FileSystem.ReadAllText($Path) return ConvertFrom-HDTRuleYaml -Yaml ([string] $text) -Path $Path } |