# TODO: (MEDIUM) Implement cmdlets wrapping the class implementation # TODO: (MEDIUM) Break out Configuration\ConfigurationManager into Modules\ConfigurationManager # TODO: (MEDIUM) Ensure stack traces propogate from module functions using namespace System.Collections.Generic $ErrorActionPreference = "Stop" $InformationPreference = "Continue" $LogContext = [Stack[string]]::new() $DockerLinePrefix = " ----->" function Write-Log { Param( [Parameter(Mandatory, Position=0, ParameterSetName="PushContext")] [Parameter(Mandatory, Position=0, ParameterSetName="ExistingContext")] [string] $Context, [Parameter(Mandatory, Position=1, ParameterSetName="PushContext")] [scriptblock] $ScriptBlock ) switch ($PSCmdlet.ParameterSetName) { "PushContext" { $LogContext.Push($Context) Write-Log "" $result = &$ScriptBlock Write-Log "" $LogContext.Pop() | Out-Null if ($result -is [object]) { return $result } else { return $null } } "ExistingContext" { $stack = $LogContext.ToArray() [array]::Reverse($stack) $prefix = "$DockerLinePrefix $(Get-Date -Format "hh:mm:ss") [$($stack -join " > ")]" Write-Information "$prefix $Context" } } } function Invoke-ContextRequirement { Param( [string]$Name, [scriptblock]$Test, [scriptblock]$Set ) try { Write-Log $Name { $requirementAlreadyMet = Write-Log "Test" {&$Test} if (-not $requirementAlreadyMet) { Write-Log "Set" {&$Set | Out-Null} $requirementValidated = Write-Log "Test" {&$Test} if (-not $requirementValidated) { throw "Requirement validation failed" } } } } catch { Write-Error $_.Exception } } function Invoke-ContextDscRequirement { Param( [string]$Name, [string]$ResourceName, [string]$ModuleName, [hashtable]$Property ) $dscParams = @{ Name = $ResourceName ModuleName = $ModuleName Property = $Property } Invoke-Requirement ` -Name $Name ` -Test {Invoke-DscResource -Method "Test" @dscParams} ` -Set {Invoke-DscResource -Method "Set" @dscParams} }