Reusing Existing Configuration Scripts in PowerShell Desired State Configuration

Reusing Existing Configuration Scripts in PowerShell Desired State Configuration

Rate This
  • Comments 17

You are an expert in PowerShell DSC (or maybe not an expert, just someone playing around with configurations in DSC) and have already written fairly large and complex configurations for configuring your environment/data center. Everything is working well and you are a great fan of DSC. There’s only one problem: your work is complicated. Before long, you have a configuration that is hundreds or thousands of lines long – people from many different teams are editing it. Finding and fixing problems becomes nearly impossible… your configuration is just too unwieldy. Then comes a day when there arises a need to add something more (or maybe delete something) to your configuration. The problem looks trivial to solve right? –Just add one more resource to your (already big) configuration. But you are a forward thinking person and find yourself wondering if there is something clever you can do leverage your existing configuration scripts.


That is why we made configurations composable and reusableJ. Yes, one configuration can call another. How? That is what we are going to cover in this post.

 

The way to make a configuration reusable is by making it what we call a composite resource. Let me walk you through an example to do just that.

 

I have the following parameterized configuration (the parameters of the configuration become the properties of the composite resource) which I will turn into a composite resource:

 

Configuration xVirtualMachine

{

param

(

# Name of VMs

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String[]]$VMName,

 

# Name of Switch to create

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$SwitchName,

 

# Type of Switch to create

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$SwitchType,

 

# Source Path for VHD

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$VhdParentPath,

 

# Destination path for diff VHD

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$VHDPath,

 

# Startup Memory for VM

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$VMStartupMemory,

 

# State of the VM

[Parameter(Mandatory)]

[ValidateNotNullOrEmpty()]

[String]$VMState

)

 

# Import the module that defines custom resources

Import-DscResource -Module xComputerManagement,xHyper-V

 

# Install the HyperV role

WindowsFeature HyperV

{

    Ensure = "Present"

    Name = "Hyper-V"

}

 

# Create the virtual switch

xVMSwitch $switchName

{

    Ensure = "Present"

    Name = $switchName

    Type = $SwitchType

    DependsOn = "[WindowsFeature]HyperV"

}

 

# Check for Parent VHD file

File ParentVHDFile

{

    Ensure = "Present"

    DestinationPath = $VhdParentPath

    Type = "File"

    DependsOn = "[WindowsFeature]HyperV"

}

 

# Check the destination VHD folder

File VHDFolder

{

    Ensure = "Present"

    DestinationPath = $VHDPath

    Type = "Directory"

    DependsOn = "[File]ParentVHDFile"

}

 

 # Creae VM specific diff VHD

foreach($Name in $VMName)

{

    xVHD "VhD$Name"

    {

        Ensure = "Present"

        Name = $Name

        Path = $VhDPath

        ParentPath = $VhdParentPath

        DependsOn = @("[WindowsFeature]HyperV",

                      "[File]VHDFolder")

    }

}

 

# Create VM using the above VHD

foreach($Name in $VMName)

{

    xVMHyperV "VMachine$Name"

    {

        Ensure = "Present"

        Name = $Name

        VhDPath = (Join-Path -Path $VhDPath -ChildPath $Name)

        SwitchName = $SwitchName

        StartupMemory = $VMStartupMemory

        State = $VMState

        MACAddress = $MACAddress

        WaitForIP = $true

        DependsOn = @("[WindowsFeature]HyperV",

                      "[xVHD]Vhd$Name")

    }

}

}

 

The key is to place the configuration in a file with the extension schema.psm1. You can take a look here to find out how to deploy a DSC Resource. Here is how it looks on my machine:

PS C:\Program Files\WindowsPowerShell\Modules\TestCompositeResource\DSCResources\xVirtualMachine> dir

    Directory: C:\Program Files\WindowsPowerShell\Modules\TestCompositeResource\DSCResources\xVirtualMachine

Mode                LastWriteTime     Length Name                                                                         

----                -------------     ------ ----                                                                         

-a---         2/25/2014   8:42 PM       2642 xVirtualMachine.psd1                                                         

-a---         2/25/2014   8:42 PM       2957 xVirtualMachine.schema.psm1   

Note: Take note of the .psd1 file (xVirtualMachine.psd1) inside the DSCResources folder. On my first attempt, I did not put that file in there and wasted some time trying to figure out where I was going wrong (yes, yes, yes a valid PowerShell module must have one out of .psd1, .psm1, .cdxml, .dll extension and it took me some time to figure out the fact that .schema.psm1 does not satisfy that condition).

Inside the .psd1 file, I have this line:

RootModule = 'xVirtualMachine.schema.psm1'

 

That is it, you are done!


Edit: For the resource to be discoverable and usable, it must be part of a valid PowerShell module.  For this example to work, you would also need to create a TestCompositeResource.psd1 module manifest under the "TestCompositeResource" Folder.  The best way to do that is by running "New-ModuleManifest -path "C:\Program Files\WindowsPowerShell\Modules\TestCompositeResource\TestCompositeResource.psd1"".  Sorry for the confusion!


 

PS C:\> Get-DscResource -Name xVirtualMachine

ImplementedAs        Name                           Module                                                Properties                                      

-------------              ----                               ------                                                  ----------                                      

Composite               xVirtualMachine           TestCompositeResource                    {VMName, SwitchName, SwitchType, VhdParentPath...}

 

Your configuration shows up as a composite resource.

Let us now see how to use it:

configuration RenameVM

{

Import-DscResource -Module TestCompositeResource

 

Node localhost

{

    xVirtualMachine VM

    {

        VMName = "Test"

        SwitchName = "Internal"

        SwitchType = "Internal"

        VhdParentPath = "C:\Demo\Vhd\RTM.vhd"

        VHDPath = "C:\Demo\Vhd"

        VMStartupMemory = 1024MB

        VMState = "Running"

    }

    }

   Node "192.168.10.1"

   {  

    xComputer Name

    {

        Name = "SQL01"

        DomainName = "fourthcoffee.com"

    }                                                                                                                                                                                                                                                              

}

}

 

We have used the dynamic keyword Import-DscResource to make our composite resource type available in the configuration. The parameters of the composite resource become its properties. You can discover this in two ways, one way is to use the Get-DscResource cmdlet as above and the other is in ISE. I like the one in ISE since it does not require me to shift my focus to the command window and type in the cmdlet. You can take the cursor to the place where you have the name of the resource, and press CTRL+space. You can discover all the resources by using CTRL+Space after the configuration keyword as well. .You have to do it after Import-DscResource if importing custom resources.

Here is what ISE displays:

 

Untitled

 

Tab completion works on the names of the properties just like any other resource, isn’t that cool?

This way, I have a configuration, where I reused one of my existing configurations and added one more resource to the overall configuration of my machine. This configuration first creates a VM and then uses the xComputerResource to rename it. I can thus build upon my existing configurations as and when the need arises for more complex configurations.

 

 

 

 

Happy configuring!

Abhik Chatterjee

Windows PowerShell Developer

 

 

Leave a Comment
  • Please add 3 and 6 and type the answer here:
  • Post
  • @JBA: I tried out the xUac composite resource that we shipped in Wave 3 and was able to use it in the following config;

    configuration foo

    {

       Import-DscResource -Name xUac

       xUac x

       {

           Setting = "NotifyChanges"

       }

    }

    foo

  • @JBA: I tried out the xUac composite resource that we shipped in Wave 3 and was able to use it in the following config;

    configuration foo

    {

       Import-DscResource -Name xUac

       xUac x

       {

           Setting = "NotifyChanges"

       }

    }

    foo

    Thanks,

    Abhik

Page 2 of 2 (17 items) 12