Pseudo-Splatting DSC Resources

Here’s a quick function to allow you something close to splatting with DSC resources:


function Get-DscSplattedResource {
[CmdletBinding()]
Param(
[String]
$ResourceName,
[String]
$ExecutionName,
[hashtable]
$Properties
)
$stringBuilder = [System.Text.StringBuilder]::new()
$null = $stringBuilder.AppendLine("Param([hashtable]`$Parameters)")
$null = $stringBuilder.AppendLine(" $ResourceName $ExecutionName { ")
foreach($PropertyName in $Properties.keys) {
$null = $stringBuilder.AppendLine("$PropertyName = `$(`$Parameters['$PropertyName'])")
}
$null = $stringBuilder.AppendLine("}")
Write-Debug ("Generated Resource Block = {0}" -f $stringBuilder.ToString())
[scriptblock]::Create($stringBuilder.ToString()).Invoke($Properties)
}
Set-Alias Name x Value Get-DscSplattedResource

Here’s why you may need it.

In DSC, quite often you need to specify a resource with some values like so:


Configuration MyDscConfig {
$Allnodes.nodename {
ChocolateyPackage Putty {
Ensure = 'Present'
Name = 'Putty'
Version = 'Latest'
ChocolateyOptions = @{ source = 'https://chocolatey.org/api/v2/' }
}
}
}

But what if you have an hashtable readily available:


#Assuming you already have this hashtable
$MyHash = @{
Ensure = 'Present'
Name = 'Putty'
Version = 'Latest'
ChocolateyOptions = @{ source = 'https://chocolatey.org/api/v2/' }
}
Configuration MyDscConfig {
$Allnodes.nodename {
ChocolateyPackage Putty {
Ensure = $MyHash['Ensure']
Name = $MyHash['Name']
Version = $MyHash['Version']
ChocolateyOptions = $MyHash['ChocolateyOptions']
}
}
}

Or if you’re iterating through a list of  hashtable, and some don’t contain a value:


#Assuming you already have this hashtable
$MyHashes = @(
@{
Ensure = 'Present'
Name = 'Putty'
Version = 'Latest'
ChocolateyOptions = @{ source = 'https://chocolatey.org/api/v2/' }
},
@{
Ensure = 'Absent'
Name = 'notepadplusplus'
}
)
Configuration MyDscConfig {
$Allnodes.nodename {
#The second Item will error because of missing properties
foreach($MyHash in $MyHashes) {
ChocolateyPackage Putty {
Ensure = $MyHash['Ensure']
Name = $MyHash['Name']
Version = $MyHash['Version']
ChocolateyOptions = $MyHash['ChocolateyOptions']
}
}
}
}

Well, until splatting is supported natively in DSC, you could use the following function as a way to support splatting in your configurations:


function Get-DscSplattedResource {
[CmdletBinding()]
Param(
[String]
$ResourceName,
[String]
$ExecutionName,
[hashtable]
$Properties
)
$stringBuilder = [System.Text.StringBuilder]::new()
$null = $stringBuilder.AppendLine("Param([hashtable]`$Parameters)")
$null = $stringBuilder.AppendLine(" $ResourceName $ExecutionName { ")
foreach($PropertyName in $Properties.keys) {
$null = $stringBuilder.AppendLine("$PropertyName = `$(`$Parameters['$PropertyName'])")
}
$null = $stringBuilder.AppendLine("}")
Write-Debug ("Generated Resource Block = {0}" -f $stringBuilder.ToString())
[scriptblock]::Create($stringBuilder.ToString()).Invoke($Properties)
}
Set-Alias Name x Value Get-DscSplattedResource

Be careful in which scope you’re executing this function, because DSC expect the scriptblock invoke in its own scope, not from another module.

But using this trick you can now do something like:


#Assuming you already have this hashtable
$MyHashes = @(
@{
Ensure = 'Present'
Name = 'Putty'
Version = 'Latest'
ChocolateyOptions = @{ source = 'https://chocolatey.org/api/v2/' }
},
@{
Ensure = 'Absent'
Name = 'notepadplusplus'
}
)
. .\Get-DscSplattedResource.ps1
Configuration MyDscConfig {
$Allnodes.nodename {
#The second Item will now work
foreach($MyHash in $MyHashes) {
# 'x' is an alias for my Get-DscSplattedResource function
x ChocolateyPackage $MyHash['name'] $MyHash
}
}
}

3 thoughts on “Pseudo-Splatting DSC Resources

  1. Thank you for this valuable idea! I tried it on a 1300 line DSC config and reduced it to under 200 lines. Much more readable with less duplication. One minor thing I noticed, after the config completed, was that the DependsOn values retrieved from Get-DscConfigurationStatus showed duplicate entries (i.e. the DependsOn value showed up twice). This didn’t affect the outcome as far as I can tell, and it may be my implementation of your suggestion that may have caused it so just wondering if you’ve observed it too. Thanks again well done.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s