Modules/StackDefinition.psm1
Import-Module (Join-Path (Split-Path $PSScriptRoot -Parent) "Helpers\GeneralHelper.psm1") -Force function Get-StackDefinition { [OutputType([String])] [CmdletBinding()] Param( [Parameter( Mandatory=$True, Position=0 )] [ValidateScript({Test-Path $_})] [String]$Path ) return ConvertFrom-YamlFile $Path } function Set-StackDefinition { [CmdletBinding()] Param( [Parameter( Mandatory=$True, Position=0 )] [ValidateScript({Test-ObjectValidYaml $_})] [Alias('sd', 'definition', 'def')] [HashTable]$StackDefinition, [Parameter( Mandatory=$True, Position=1 )] [String]$Path ) $Parent = Split-Path $Path -Parent if (!([String]::Empty -eq $Parent) -And !(Test-Path $Parent)) { New-Item $Parent -ItemType Directory } (ConvertTo-Yaml $StackDefinition) | Set-Content $Path -Force } function Invoke-StackDefinitionInterpolation { [CmdletBinding(DefaultParameterSetName='InPlace')] Param( [Parameter( Mandatory=$True, Position=0 )] [ValidateScript({Test-ObjectValidYaml $_})] [Alias('sd', 'definition', 'def')] [Hashtable]$StackDefinition, [Parameter( Mandatory=$True, Position=1 )] [ValidateScript({ Test-Path $_ })] [ValidateScript({ try { ConvertFrom-YamlFile $_; return $True } catch { return $False } })] [String]$Path, [Parameter( Mandatory=$False, Position=2, ParameterSetName='NotInPlace' )] [Switch]$NotInPlace, [Parameter( Mandatory=$True, Position=3, ParameterSetName='NotInPlace' )] [String]$Destination, [Switch]$Passthru ) Write-Verbose "Starting Interpolation..." if ($NotInPlace) { $Parent = Split-Path $Destination -Parent } else { $Parent = Split-Path $Path -Parent } $NewDefinition = Invoke-Interpolation $StackDefinition (ConvertFrom-YamlFile $Path) $NewDefinition.Version = "'$($NewDefinition.Version)'" Write-Verbose "Finished Interpolation." if (!([String]::Empty -eq $Parent) -And !(Test-Path $Parent)) { Write-Verbose "Creating Directory: $Parent" New-Item $Parent -ItemType Directory } if ($Passthru) { Write-Verbose "Outputting Passthru..." return $NewDefinition } Write-Verbose "Setting $Path to interpolated YAML." if ($NotInPlace) { (ConvertTo-Yaml $NewDefinition) | Set-Content $Destination -Force } else { (ConvertTo-Yaml $NewDefinition) | Set-Content $Path -Force } } function Invoke-Interpolation { [OutputType([Hashtable])] [CmdletBinding()] Param( [Parameter( Mandatory=$True, Position=0 )] [Alias('sd', 'definition', 'def', 'sdef')] [Object] $StackDefinition, [Parameter( Mandatory=$True, Position=1 )] [Alias('nd', 'newdef', 'ndef')] [Object]$NewDefinition ) Write-Verbose "Merging properties of source definition and new definition" $Extended = Add-PropertyRecurse $StackDefinition $NewDefinition $Clone = $Extended.Clone() $Extended ` | Get-Member -Type NoteProperty, Property ` | ForEach-Object { Write-Verbose "Removing non-stack object $($_.Name) from new definition" $Clone.PSObject.Properties.Remove($_.Name) } $Extended.GetEnumerator() ` | Where-Object { $_.Key -Like 'x-*' } ` | ForEach-Object { $Clone.Remove($_.Key) } return $Clone } function Add-PropertyRecurse { [OutputType([Hashtable])] [CmdletBinding()] Param( [Parameter( Mandatory=$False, Position=0 )] [Alias('sd', 'definition', 'def', 'sdef')] [Object] $StackDefinition, [Parameter( Mandatory=$False, Position=1 )] [Alias('nd', 'newdef', 'ndef')] [Object]$NewDefinition ) if ($StackDefinition -Is [Hashtable]) { $Clone = $StackDefinition.Clone() foreach ($Property in $Clone.GetEnumerator()) { Write-Verbose "Encountered $($Property.Key)" if ($Null -eq $NewDefinition.Item($Property.Key)) { $Type = $StackDefinition.Item($Property.Key).GetType() if ($Type.Name -eq "Object[]") { Write-Verbose "$($Property.Key) is a mapping sequence -> declaring it as Object[]" $NewDefinition.Item($Property.Key) = New-Object @(@{}) } elseif ($Type.Name -ne "String") { Write-Verbose "$($Property.Key) is not a primitive type -> declaring it as $($Type.Name)" $NewDefinition.Item($Property.Key) = New-Object $Type } Write-Verbose "Setting the value of $($Property.Key) to $($StackDefinition.Item($Property.Key))" $NewDefinition.Item($Property.Key) = $StackDefinition.Item($Property.Key) } else { Write-Verbose "Recursing Add-PropertyRecurse on $($Property.Key)" $NewDefinition.Item($Property.Key) = Add-PropertyRecurse $StackDefinition.Item($Property.Key) $NewDefinition.Item($Property.Key) } } } else { Write-Verbose "Setting the value of new definition to $($StackDefinition)" $NewDefinition = $StackDefinition } return $NewDefinition } |