In this topic, we will take a look at how to create a configuration using the Configuration
and Class
keywords. Configuration creates MOF, and this MOF needs to be pushed to or pulled by the target nodes. While using class, we will define the DSC resource and deploy the configurations.
We know that DSC is a declarative syntax, and this really helps developers and IT professionals to do more. In this section, we will see what developers can do with DSC.
We have discussed a few basic concepts of DSC and its stages; using this knowledge, let's build a web server. Most organizations face operational issues: the IT professional thinks that the infrastructure is good, and the code is at fault, but on the other hand, developers state that the code works fine in test but not in production. So, test and production are not identical. To fix this gap, we can use DSC and code our infrastructure.
Let's build a test web server using DSC. In this exercise, we will install IIS, as follows:
Configuration WebServer { Node $env:COMPUTERNAME { WindowsFeature IIS { Name = 'Web-Server' Ensure = 'Present' IncludeAllSubFeature = $true } } } WebServer
While deploying this configuration, I did not note that my OS build version is 10074—Windows Server Technical Preview. This is a known issue, so the IIS installation failed as well, as shown in the following message:
Failed to start automatic updating for installed components. Error: 0x80040154
To fix this, we need to use sconfig.cmd
and enter option 6
—sounds weird! However, this is another bug in Technical Preview 2 Server OS, so let's download and install the updates.
This calls Cscript.exe
to download and install updates; just give your system a reboot after this!
Now, we will fix the password issue and rerun the configuration script through the following code:
configuration WebServers { Node $env:COMPUTERNAME { WindowsFeature WebServer { Name = 'Web-Server' Ensure = 'Present' IncludeAllSubFeature = $true } } } WebServers Start-DSCOnfiguration .WebServers –Wait –Verbose -Force
Yes, we can access localhost now, as shown in the following image:
Now, let's remove IIS—do remember that this requires a reboot. So, it's good to check the LCM Meta Configuration. All we need is action to continue after the reboot and reboot if needed, set to true. Execute the following code:
[DscLocalConfigurationManager()] Configuration LCM { Node localhost { Settings { RebootNodeIfNeeded = $true ActionAfterReboot = "ContinueConfiguration" } } } LCM Set-DscLocalConfigurationManager .LCM
To uninstall the Windows feature, we will use the same code; however, we will change Present
to Absent
:
configuration WebServers { Node $env:COMPUTERNAME { WindowsFeature WebServer { Name = 'Web-Server' Ensure = 'Absent' IncludeAllSubFeature = $true } } }
The system reboots itself because we set the Meta. In the next topic, we will create a custom DSC resource using Class.
To know more about Class, you can read the help document.
From version 5.0 onward, Windows PowerShell adds the language syntax to define classes and other user-defined types using formal syntax and semantics that are similar to other object-oriented programming languages.
You can refer to the release notes of WMF 5.0 for the class structure and more details.
Refer to the following link for the WMF 5.0 release notes on the skeleton class structure: https://www.microsoft.com/en-us/download/details.aspx?id=46889
Execute the following command:
enum Ensure { Absent Present } [DscResource()] class StringLiteral { [DscProperty(Key)] [string]$Path [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Mandatory)] [string] $SourcePath [DscProperty(NotConfigurable)] [Nullable[datetime]] $CreationTime [void] Set() { } [bool] Test() { } [StringLiteral] Get() { } }
Now, using the Class
keyword, let's define a DSC Resource. The significant benefits of this are as follows:
DSCResource
folder inside the module folder is not neededIn this exercise, we will follow a step-by-step procedure to create a Class-based DSC resource, which will simply create a file or directory.
$env: psmodulepath (folder) |- MyDscResources (folder) |- MyDscResource.psm1 MyDscResource.psd1
New-ModuleManifest
cmdlet.Let's create a DSC resource using the following code:
enum Ensure { Absent Present } [DscResource()] class MyTestClassResource{ [DscProperty(Key)] [string]$Path [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Mandatory)] [ValidateSet("Directory","File")] [string]$ItemType #Replaces Get-TargetResource [MyTestClassResource] Get() { $Item = Test-Path $This.Path If($Item -eq $True) { $This.Ensure = [Ensure]::Present } Else { $This.Ensure = [Ensure]::Absent } Return $This } #Replaces Test-TargetResource [bool] Test() { $Item = Test-Path $This.Path If($This.Ensure -eq [Ensure]::Present) { Return $Item } Else { Return -not $Item } } #Replaces Set-TargetResource [void] Set() { $Item = Test-Path $This.Path If($This.Ensure -eq [Ensure]::Present) { If(-not $Item) { Write-Verbose "Creating Folder" New-Item -ItemType Directory -Path $This.Path } } #If [Ensure]::Absent Else { If($Item) { Write-Verbose "File exists and should be absent. Deleting file" Remove-Item -Path $This.Path } } } }
Save the preceding code as a PSM1 file and create a module manifest. Save the files in C:Program FilesWindowsPowerShellModulesClassResourceDemo
.
Save your class resource code as ClassResourceDemo.PSM1
in the folder that we created named ClassResourceDemo
.
Now, create a module manifest using the New-ModuleManifest
cmdlet, executing the following code:
New-ModuleManifest -Path 'C:Windowssystem32WindowsPowerShellv1.0ModulesDemoDemoClass.psd1' ` -DscResourcesToExport 'MyTestClassResource' -PowerShellVersion 5.0 -Description 'Class based DSC resource' -ModuleVersion '1.0.0.0' -Guid $([guid]::NewGuid()) -Author 'Chen' ` -RootModule '.DemoClass.psm1' -CompanyName 'Something'
That's it! We are ready to test the resource using the following configuration code:
Configuration Test { Import-DscResource -ModuleName ClassResourceDemo Node Localhost { MyTestClassResource Testing { Ensure = 'Present' Path = 'C:Test1' ItemType = 'Directory' } } } Test
Use the Start-DscConfiguration
cmdlet to deploy the configuration, as shown in the following image:
How does this work?
Take a look at the eight main steps in the following image:
enum
keyword and named it Ensure
[DscResource()]
attribute to specify that the class is a DSC resourceMyTestClassResource
Ensure
property is the enum type and is set to Mandatory
Get()
method returns the instance of the classTest()
method returns a boolean value, true
or false
; this is called first, so check whether or not the resource is in the desired stateSet()
method sets the resources to the desired stateHere are a few key things to note:
enum
, no numbers are allowedenum
DscResourcesToExport
parameter and pass your classname; or else, you won't see the resource in the Get-DscResource
output.Now that you have created your first Class-based DSC resource, it's easy and in a human, very readable format. To know more about Class and writing custom DSC resources, use the help document as follows:
help New-ModuleManifest -Detailed help about_Classes -Detailed help about_Modules -Detailed