In recent customer conversations, we got feedback that documentation on writing a custom Windows PowerShell Desired State Configuration (DSC) resource is still something which can use improvement, especially in the areas of step-by-step examples. Therefore, I have decided to write up a “silly” custom DSC resource to get our readers quickly up and running with writing custom DSC resources. In the next blog posts, I will guide you through writing a real-life example for managing your servers, and what kind of challenges come with that.
Assumptions and primers
If you’re new to DSC, or just didn’t have the time to start yet and want to start reading, please revisit some blog posts we have released previously on DSC.
The anatomy of a DSC resource
When you explore a DSC resource more closely, you will find that it consists of 3 components:
- The DSC module – a PowerShell module file with the extension psm1
- The DSC data file – a PowerShell data file with the extension psd1
- The DSC schema file – a Managed Object Format file with extension MOF
We require these 3 components for our custom resource. Luckily, the Windows PowerShell team has provided us with the Resource Designer Tool, which enables you to generate the DSC module and schema files, and helps prevent you from making syntax errors. You don’t have to use the Resource Designer Tool, but it makes writing your first DSC resource a lot easier. After you play around a bit, you will figure out that you could also leverage a boilerplate approach, as mentioned by Michael Greene in this blog post. Effectively, its about reusing templates, which makes total sense if you’re writing multiple custom DSC resources.
The objective of our “silly” DSC resource
When I start with a new technology I would like to understand better, I tend to keep things as simple as I can to focus on the concepts. So in this blog post I will walk you through the creation of a custom DSC resource. The sample resource won't be of any use to you other then to understand the authoring process better. There will always be multiple options to choose from if it comes to writing PowerShell scripts. So please consider this blog post as an conceptual example for writing a custom DSC resource. For that reason, no error handling has been added, which in a production environment, should always be the case. In addition, I didn’t want to change any configuration on my machine to test-drive DSC.
In my “silly” example I simply want to check if a text file has the value of either Red, Blue or None. For that to happen we will leverage the DSC keywords Present and Absent. So if I use the the combination of Present and Red, DSC makes sure that the value of Red is set. If I use the combination of Absent and Red, DSC makes sure that the value is not Red. That leads me to think about what kind of parameters I want to use in my example. So far, I’ve come up with the color I need to validate, so that’s 1. Oh, and of course, I need the path and file name to check, so that makes 2. Let’s call those parameters $Color and $ColorFilePath, and start with those.
Time to download and install the Resource Designer Tool from here. Unzip the files under the $env:ProgramFiles\WindowsPowerShell\Modules folder. Make sure that the module is available by opening a Windows PowerShell window and run Get-Module –ListAvailable to verify that xDscResourceDesigner is listed.
Now that we have that in place, we can start authoring our “silly” custom DSC resource.
The skeleton of our “silly” custom DSC resource
The previously-mentioned blog post already talks about the Resource Designer Tool in depth, so no need to repeat that content here. Let’s start with writing up our definition by starting a Windows PowerShell ISE session, and start to define our custom resource:
I first need to import the DSC Resource Designer module. Then I need to define my parameters. In addition to my Color and ColorFilePath parameter, I also need to define the Ensure parameter. This takes care of the Present and Absent keywords I’ve mentioned earlier. Notice that I’m using ValidateSet to constrain my values, but besides that, I’m using normal attributes like Type to define my parameter types
On line 009, I invoke the creation of my new DSC resource, and specify its name, path and friendly name. Make sure that your Property values match your variables, or this will throw an error. This is likely to happen when you forget a parameter, and try to add it without using Update-DscResource, but decided to generate your DSC resource all over.
At this point, you could also update your MOF file directly in any editor if you know what to edit. If you do so, make sure that you validate it by running Test-DscSchema which returns a true – we’re all good – or false – you probably made a syntax error somewhere. Now that we have our DSC schema in place, it's time to examine the files that were created by our New-xDscResource command. In your specified path, you will find a new DSC module and MOF file:
If we open our new DSC module in Windows PowerShell ISE, you will find our parameters, and the three core DSC TargetResource functions:
- Get – this will get whatever we need to validate
- Set – this will set whatever we need to set
- Test – this will validate whatever it is we need to validate and will return a true or false state
The DSC data file
A DSC resource depends on the existence of a DSC data file, a Windows PowerShell psd1 file. The fastest and easiest way to create one is to copy an existing one and modify it. Since you’ve already installed the xDSCResourceDesigner module, you have a DSC data file which you can use.
Copy the xDSCResourceDesigner.psd1 file to your custom DSC module folder, and rename it to match your module name. So in my example, I’ve copied and renamed it to SillyDSCresource.psd1. Make sure that you locate it directly under your module folder at the same level as the DSCResources folder.
Make sure that you modify the values as highlighted in the example above. To generate a unique GUID, open up a new Windows PowerShell window, and run the command [guid]::newguid() to generate a new GUID:
Authoring our “silly” DSC module
Now let’s start modifying our silly DSC module file, and open the module (psm1) file. We will work on the Get-TargetResource function first to make our param section more complete; we'll also configure our returnValue parameter:
Now we have that in place, we can start working on the most interesting part: the make it so section under Set-TargetResource. Here is where we set the desired value (if required). Since this is all PowerShell, we can even write to a log file to log our actions or do other things:
Finally, there's the Test-TargetResource section, where we validate our configuration, which returns true or false. This is also the place where you can add Write-Verbose commands to display output to the user, which shows up when you invoke the Start-DscConfiguration command:
Now that we have configured our three core DSC functions, we can save it to our module folder, and create a configuration to be deployed.
Creating our “silly” DSC configuration
With our Get, Set and Test DSC functions in place, it should be really straightforward to create a configuration:
Before we apply our DSC configuration, let’s make sure that we have a text file with a value in it, stored in our ColorFilePath:
Applying and testing our DSC configuration
When we run our DSC script, and have invoked Start-DscConfiguration, we can see our configuration being applied nicely:
Did you notice the verbose output as defined in the Test-TargetResource?
And we even have our log file as configured under the Set-TargetResource section, nice!
When we invoke Test-DscConfiguration, we should be good; let’s check if the value actually changed:
Test driving configuration drift
Let’s see what happens if we change our configuration, we set Ensure to Absent, and we invoke Start-DscConfiguration:
Import-DscResource -ModuleName SillyDSCmodule
Ensure = 'Absent'
Color = 'Red'
ColorFilePath = 'c:\DSC\color.txt'
$MOFpath = "c:\DSC\MOF"
SillyTest -MachineName "localhost" -OutputPath $MOFpath
Start-DscConfiguration -ComputerName 'localhost' -wait -force -verbose -path $MOFpath
Remember that the value of our c:\DSC\color.txt file is still Red.
Let’s check our C:\DSC\color.txt value:
If you are surprised at the None outcome, revisit the Set-TargetResource section (hint: look at line 035).
If we now change the value of C:\DSC\color.txt to Red, and run Test-DscConfiguration, we should see false as our output:
If we then run Start-DscConfiguration, this is nicely corrected again.
I hope you found this “silly” DSC example useful. Stay tuned for a real-life example in the next blog post!
To wrap up, I’m including the full module here below. Until next time, happy automating!