Create a Composite PowerShell DSC Resource

The composite resource allows you to create a single PowerShell DSC configuration with references to several "non-composite" resources and share it across multiple machines.

Desired State Configuration (DSC) is an amazing technology. It’s an efficient and convenient way to define what a system should look like and run a configuration. This magic is built upon resources that are combined to form configurations. Microsoft provides lots of built-in resources, such as WindowsFeature, File, Registry, and so on. Administrators can also create custom resources, as well. Even though DSC resources are useful by themselves, managing them efficiently can quickly become problematic if an administrator needs to apply the same set of resources across different machines.

For example, if an administrator needs to ensure that a Windows feature and a particular file exist on more than one server, they would have to duplicate the same configuration multiple times. This can lead to things like fat-finger syndrome and become a major hassle when the configuration needs to be changed. If the same configuration is applied to many different servers, each instance of that configuration will have to be modified. This isn’t a good situation to be in.

A solution to this shared configuration problem is to create a composite resource. A composite resource is a way to create a single configuration and share it across multiple machines. Creating a composite resource is essentially creating a single DSC configuration with references to several “non-composite” resources, like normal. However, it is then wrapped up in a way that DSC can see it as a single DSC resource. Machines are none the wiser that your composite resource actually is a group of multiple resources together.

To demonstrate creating a composite resource, I’ll be using PowerShell v5. It’s possible to do this with v4, but v5 makes things a little easier. I’ll be creating a composite resource to represent my default server configuration. A composite resource lives in a module, so I’ll create that first. I’ll call it DefaultConfiguration, since I might want to add other default resources in this module later.

I’ll first create the module that will hold the resource. Unlike other “regular” modules, you don’t need a PSM1. You actually just need a PSD1 manifest. I’ll create the module folder and the manifest.

$parentModulePath = 'C:\Program Files\WindowsPowerShell\Modules\DefaultConfiguration'
mkdir $parentModulePath
New-ModuleManifest  -RootModule DefaultConfiguration –Path "$parentModulePath\DefaultConfiguration.psd1"

Next, I’ll need to create a subfolder called DSCResources. It will contain one or more composite resources that will exist inside of the DefaultConfiguration module. Here I’ll need to create both the PSM1 (providing the resource itself) and a manifest (PSD1) for each resource.

$resourceModulePath = "$parentModulePath\DSCResources\DefaultServer"
mkdir "$parentModulePath\DSCResources"
mkdir $resourceModulePath
New-ModuleManifest  -RootModule 'DefaultServer.schema.psm1' –Path "$resourceModulePath\DefaultServer.psd1"
Add-Content –Path "$resourceModulePath\DefaultServer.schema.psm1" –Value ''

Note: The module name must end in schema.psm1. This designates the module as a composite resource.

Now that I have the file structure laid out, I’ll now create the resource itself. You’ll find that this is just like creating a typical configuration; there’s nothing special here. I’ll just create one to add a Windows feature and create a text file somewhere as an example.

configuration DefaultServer {
    WindowsFeature 'InstallGUI'
        Ensure = 'Present'
        Name = 'Server-Gui-Shell'
    File 'SomeFile' {
        DestinationPath = 'C:\SomeFile.txt'
        Contents = 'something here'
        Ensure = 'Present'
I’ll save this to “$resourceModulePath\DefaultServer.psm1.” Notice that I don’t have a Node statement at the top as is normally required. This is the major difference with a typical DSC configuration and a configuration that will be used to build a resource.

Now that I have created a module and composite resource, I can now simply apply this as a standard DSC resource. Below I’ve built a configuration for my MEMBERSRV1 and have copied my composite resource to that server.

configuration SpecificServerConfiguration {
    Node 'MEMBERSRV1' {
        DefaultServer {
You can see that I don’t have any properties to define under DefaultServer. That’s because I didn’t have any parameters on the configuration I built earlier. I’ll save this to C:\MEMBERSRV1_Config.ps1.

I’ll now ensure that my composite resource shows up on MEMBERSRV1.
Invoke-Command –ComputerName MEMBERSRV1 –ScriptBlock {Get-DscResource –Name DefaultServer } 

The composite resource shows up on MEMBERSRV1

Great! It’s showing up. I’ll now create the MOF and run the configuration on MEMBERSRV1. If all goes well, it should apply the composite configuration.

. C:\MEMBERSRV1_Config.ps1

The composite configuration applied

Start-DscConfigurationManager –Path .\SpecificServerConfiguration –ComputerName MEMBERSRV1 –Wait -Verbose

End result

Credit: Adam Bertram

No comments:

Powered by Blogger.