Automate the installation of DSC Resource Kit Wave 9 resources with PowerShell Desired State Configuration

Last week, in my blog article titled Creating Hyper-V VM’s with Desired State Configuration I left off with a newly created Hyper-V VM named Test01 that was created with DSC and the specific IP address of that VM was added to my trusted host list. For more details on the current state of this test environment, see that previous blog article.

Today I'll begin configuring the Test01 VM with DSC. This virtual machine will become the first Active Directory domain controller in my test environment. I want to statically assign the IP address information and I need to rename the server before I turn it into a domain controller. In order to accomplish those tasks, a few DSC resources need to be downloaded and added to the VM.

I would like to fully automate the entire build of my test environment with DSC and that task may seem overwhelming to some. Breaking it down into smaller steps makes the overall task seem much more manageable.

In this blog article, I'll focus on automating the download of the DSC Resource Kit Wave 9 resources, extract all of those resources to a temporary folder, and copy only the ones I plan to use to the appropriate location. That way I'll have all of the resources downloaded in case I need to use any of them for the other test VM's that I plan to build.

I previously talked about using an initialization script in another blog article titled Use a certificate with PowerShell DSC to add a server to Active Directory without hard coding a password and I'll take advantage of that technique here as well:

 1$ConfigData = @{
 2    AllNodes = @(
 3        @{
 4            NodeName = '192.168.29.108'
 5            DSCResources =  @(
 6                'xActiveDirectory', 'xComputerManagement', 'xNetworking'
 7            )
 8            Uri = 'https://gallery.technet.microsoft.com/scriptcenter/DSC-Resource-Kit-All-c449312d/file/131371/1/DSC%20Resource%20Kit%20Wave%209%2012172014.zip'
 9            Destination = 'C:\tmp\DSC'
10            OutFile = 'C:\tmp\DSC\DSC Resource Kit Wave 9 12172014.zip'
11        }
12    )
13}

One thing that was definitely a challenge was using variables with the DSC script resource as shown in the following example. I used PowerShell here-strings to make them work.

 1configuration AddResource {
 2    Node $AllNodes.NodeName {
 3
 4        Script DownloadResource {
 5            GetScript = @"
 6                @{
 7                    Result = (Test-Path -Path '$($Node.OutFile)' -PathType Leaf)
 8                }
 9"@
10            SetScript = @"
11                If (-not(Test-Path -Path '$($Node.Destination)' -PathType Container)) {
12                    New-Item -Path '$($Node.Destination)' -ItemType Directory
13                }
14                Invoke-WebRequest -Uri '$($Node.Uri)' -OutFile '$($Node.OutFile)'
15                Unblock-File -Path '$($Node.OutFile)'
16"@
17            TestScript = @"
18                Test-Path -Path '$($Node.OutFile)' -PathType Leaf
19"@
20        }
21
22        Archive UnzipResource {
23            Path = $Node.OutFile
24            Destination = $Node.Destination
25            Ensure = 'Present'
26            DependsOn = '[Script]DownloadResource'
27        }
28
29        $Node.DSCResources.ForEach({
30            File $_ {
31                SourcePath = "$($Node.Destination)\All Resources\$_"
32                DestinationPath = "$env:ProgramFiles\WindowsPowerShell\Modules\$_"
33                Recurse = $true
34                Type = 'Directory'
35                Ensure = 'Present'
36                DependsOn = '[Archive]UnzipResource'
37            }
38        })
39
40    }
41}

The configuration is called which creates the MOF file:

1AddResource -ConfigurationData $ConfigData

dsc-resources2a.jpg

Needless to say that there is a lot of Verbose output so I've omitted a large portion of it, but I think you'll get the idea of what's going on:

1Start-DscConfiguration -Wait -Path .\AddResource -Credential (Get-Credential) -Verbose

dsc-resources3a.jpg

Applying the configuration a second time shows that everything is already done (note that all of the sets are skipped):

1Start-DscConfiguration -Wait -Path .\AddResource -Credential (Get-Credential) -Verbose

dsc-resources5a.jpg

First, the DSC script resource is used to check to see if the DSC Resource Kit Wave 9 zip file already exists in the C:\tmp\DSC folder which of course will return false if it doesn't, it will also return false if the directory it's looking for it in doesn't exist either. If the C:\tmp\DSC folder doesn't exist, it's created, then the DSC Resource Kit Wave 9 zip file is downloaded from the TechNet script repository.

Next the DSC archive resource is used to extract the contents of the zip file to the temporary folder which ends up being C:\tmp\DSC\All Resources due to the zip file creating the All Resources folder when its contents are extracted.

Then the DSC file resource is used to copy the DSC resources that I plan to use to further configure the Test01 VM to the appropriate location (C:\Program Files\WindowsPowerShell\Modules). This portion of the code is written using the ForEach method to eliminate redundant code in the actual DSC configuration.

Last but not least, dependencies are set using DependsOn to make sure the execution occurs in the proper sequence and to prevent the configuration from continuing if a prerequisite step fails that is required by a later step in the configuration.

µ