Creating configuration scripts

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.

Creating a configuration with MOF

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:

Creating a configuration with MOF

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.

Creating a Class-defined DSC resource

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:

  • There is no need for schema MOF anymore
  • A DSCResource folder inside the module folder is not needed
  • Multiple DSC resources can be packaged as a single module script file

In 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.

  1. Refer to the TechNet article for reference using the URL https://technet.microsoft.com/en-us/library/dn948461.aspx.
  2. Create a folder structure. Run the following command:
    $env: psmodulepath (folder)
        |- MyDscResources (folder)
            |- MyDscResource.psm1
               MyDscResource.psd1
    
  3. Create a DSC resource using Class and save it as a PSM1 file.
  4. Create a module manifest using the New-ModuleManifest cmdlet.
  5. Test the configuration.

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:

Creating a Class-defined DSC resource

How does this work?

Take a look at the eight main steps in the following image:

Creating a Class-defined DSC resource
  • 1: Here, we used the enum keyword and named it Ensure
  • 2: Here, we used the [DscResource()] attribute to specify that the class is a DSC resource
  • 3: Here, we created a class named MyTestClassResource
  • 4: Here, we declared DSC properties—this value will be set before calling the instance
  • 5: The Ensure property is the enum type and is set to Mandatory
  • 6: The Get() method returns the instance of the class
  • 7: The Test() method returns a boolean value, true or false; this is called first, so check whether or not the resource is in the desired state
  • 8: The Set() method sets the resources to the desired state

Note

Here are a few key things to note:

  • Inside enum, no numbers are allowed
  • No separators are required in enum
  • While creating a module manifest, do remember to use the DscResourcesToExport parameter and pass your classname; or else, you won't see the resource in the Get-DscResource output.
  • You can create multiple class files and make use of the resources

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
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset