Merge-DscConfigData.psm1
#Requires -Version 4 Function Merge-DscConfigData { [CmdletBinding()] Param( [Parameter(Mandatory=$True,Position=0)] [string]$BaseConfigFilePath, [Parameter(Mandatory=$True,Position=1)] [string]$OverrideConfigFilePath ) $BaseConfigText = (Get-Content $BaseConfigFilePath | Out-String).Trim() # The base config should never be null or empty If ( -not($BaseConfigText) ) { Throw "The base configuration data file is empty. This is not allowed." } $OverrideConfigText = (Get-Content $OverrideConfigFilePath | Out-String).Trim() # When we standardize on PowerShell 5.x, we'll be able to use the much safer Import-PowerShellDataFile $BaseConfig = $BaseConfigText | Invoke-Expression # Merge the environment specific config only if it is NOT null or empty If ( $OverrideConfigText ) { Write-Verbose "Content of the override config data file : `r`n$OverrideConfigText" Try { $OverrideConfig = $OverrideConfigText | Invoke-Expression -ErrorAction Stop } Catch { throw "An error occurred when evaluating the content of $OverrideConfigFilePath as a PowerShell expression" } # Proceeding with the merge only if $OverrideConfig is not null and has been evaluated as a hashtable If ( $OverrideConfig -and ($OverrideConfig -is [hashtable]) ) { #Casting the AllNodes array to a list in order to add elements to it $BaseNodes = $BaseConfig.AllNodes -as [System.Collections.ArrayList] Foreach ( $Node in $OverrideConfig.AllNodes ) { $NodeInBaseConfig = $BaseNodes | Where-Object { $_.NodeName -eq $Node.NodeName } If ( $NodeInBaseConfig ) { Write-Verbose "The node $($Node.NodeName) is already present in the base config." # Removing the NodeName entry from the current Node to keep only the actual settings $Node.Remove('NodeName') Foreach ($OverrideSettingKey in $Node.keys) { # Checking if the setting already exists in the Base config $KeyExistsInBaseNode = $NodeInBaseConfig.ContainsKey($OverrideSettingKey) If ( $KeyExistsInBaseNode ) { Write-Verbose "The setting $OverrideSettingKey is present in the base config, overriding its value." $NodeInBaseConfig.$($OverrideSettingKey) = $Node.$($OverrideSettingKey) } Else { Write-Verbose "The setting $OverrideSettingKey is absent in the base config, adding it." $NodeInBaseConfig.add($OverrideSettingKey, $Node.$($OverrideSettingKey)) } } } Else { # If the node is not already present in the base base config Write-Verbose "The node $($Node.NodeName) is absent in the base config, adding it." $Null = $BaseNodes.Add($Node) } } $MergedConfig = $BaseConfig # Converting AllNodes back to an [array] because PSDesiredStateConfiguration doesn't accept an [ArrayList] $NodesBackToArray = $BaseNodes -as [array] $MergedConfig.AllNodes = $NodesBackToArray return $MergedConfig } Else { return $BaseConfig } } } |