Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell DSC - how to pass configuration parameters to ScriptResources?

Tags:

powershell

dsc

I'm having a lot of trouble trying to get a PowerShell Desired State Configuration script working to configure an in-house application. The root of the problem is that I can't seem to pass my configuration data down into a ScriptResource (at least not with the way I'm trying to do it).

My script is supposed to create a config folder for our in-house application, and then write some settings into a file:

configuration MyApp {     param (         [string[]] $ComputerName = $env:ComputerName     )     node $ComputerName {          File ConfigurationFolder {             Type = "Directory"             DestinationPath = $Node.ConfigFolder             Ensure = "Present"         }          Script ConfigurationFile {             SetScript = {                 write-verbose "running ConfigurationFile.SetScript";                 write-verbose "folder = $($Node.ConfigFolder)";                 write-verbose "filename = $($Node.ConfigFile)";                 [System.IO.File]::WriteAllText($Node.ConfigFile, "enabled=" + $Node.Enabled);             }             TestScript = {                 write-verbose "running ConfigurationFile.TestScript";                 write-verbose "folder = $($Node.ConfigFolder)";                 write-verbose "filename = $($Node.ConfigFile)";                 return (Test-Path $Node.ConfigFile);             }             GetScript = { @{Configured = (Test-Path $Node.ConfigFile)} }                      DependsOn = "[File]ConfigurationFolder"         }      } } 

For reference, my configuration data looks like this:

$config = @{     AllNodes = @(         @{             NodeName = "*"             ConfigFolder = "C:\myapp\config"             ConfigFile = "C:\myapp\config\config.txt"         }         @{             NodeName = "ServerA"             Enabled = "true"         }         @{             NodeName = "ServerB"             Enabled = "false"         }     ) } 

And I'm applying DSC with the following:

$mof = MyApp -ConfigurationData $config; Start-DscConfiguration MyApp –Wait –Verbose; 

When I apply this configuration it happily creates the folder, but fails to do anything with the config file. Looking at the output below, it's obvious that it's because the $Node variable is null inside the scope of ConfigurationFile / TestScript, but I've got no idea how to reference it from within that block.

LCM:  [ Start  Resource ]  [[Script]ConfigurationFile] LCM:  [ Start  Test     ]  [[Script]ConfigurationFile]                            [[Script]ConfigurationFile] running ConfigurationFile.TestScript                            [[Script]ConfigurationFile] node is null = True                            [[Script]ConfigurationFile] folder =                            [[Script]ConfigurationFile] filename = LCM:  [ End    Test     ]  [[Script]ConfigurationFile]  in 0.4850 seconds. 

I've burnt off an entire day searching online for this specific problem, but all the examples of variables, parameters and configuration data all use File and Registry resources or other non-script resources, which I've already got working in the "ConfigurationFolder" block in my script. The thing I'm stuck on is how to reference the configuration data from within a Script resource like my "ConfigurationFile".

I've drawn a complete blank so any help would be greatly appreciated. If all else fails I may have to create a separate "configuration" script per server and hard-code the values, which I really don't want to do if at all possible.

Cheers,

Mike

like image 385
mclayton Avatar asked Apr 28 '14 16:04

mclayton


People also ask

What PowerShell command is used to enact as a desired state configuration or DSC?

Apply the configuration to the machine To easily configure your environment correctly, just run Set-WsManQuickConfig -Force in an elevated PowerShell Terminal. You can apply Configuration documents (MOF files) to a machine with the Start-DscConfiguration cmdlet.

Is PowerShell DSC deprecated?

DSC roadmapThe legacy puppetlabs-dsc module is now deprecated and will be officially unsupported as of July 21, 2021.

What does the PowerShell desired state configuration DSC feature allow administrators to do?

Desired State Configuration (DSC) is a feature in PowerShell 4.0 and above that helps administrators to automate the configuration of Windows and Linux operating systems (OSes). DSC provides a set of PowerShell language extensions, cmdlets and a process called declarative scripting.

Why should you use pull mode instead of push mode for DSC?

This is the biggest advantage of the pull mode; the DSC resources are downloaded automatically from the pull server on to each node (Arrow n°2). Then, at regular intervals, the nodes will send their status to the pull server to check for changes to configuration.


2 Answers

Change this: $Node.ConfigFolder to $using:Node.ConfigFolder.

If you have a variable called $Foo and you want it to be passed to a script DSC resource, then use $using:Foo

like image 58
Steve Avatar answered Sep 20 '22 11:09

Steve


Based on David's answer, I've written a utility function which converts my script block to a string and then performs a very naive search and replace to expand out references to the configuration data as follows.

function Format-DscScriptBlock() {     param(         [parameter(Mandatory=$true)]         [System.Collections.Hashtable] $node,         [parameter(Mandatory=$true)]         [System.Management.Automation.ScriptBlock] $scriptBlock     )     $result = $scriptBlock.ToString();     foreach( $key in $node.Keys )     {         $result = $result.Replace("`$Node.$key", $node[$key]);     }     return $result; } 

My SetScript then becomes:

SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock {                 write-verbose "running ConfigurationFile.SetScript";                 write-verbose "folder = $Node.ConfigFolder";                 write-verbose "filename = $Node.ConfigFile)";                 [System.IO.File]::WriteAllText("$Node.ConfigFile", "enabled=" + $Node.Enabled);             } 

You have to be mindful of quotes and escapes in your configuration data because Format-DscScriptBlock only performs literal substitution, but this was good enough for my purposes.

like image 26
mclayton Avatar answered Sep 19 '22 11:09

mclayton