Tuesday, June 2, 2015

PowerShell 5.0 - What's new for the DSC guy - Part 1

PowerShell 5.0 now allows creation of class based DSC resources so that can now define the schema and implementation in the resource itself. This makes it easier to create custom resources because there is no more need for a MOF file or a specific folder structure for DSC resources as compared to the one in PowerShell 4.0.

With the class resources, the Test-TargetResource, Set-TargetResource and Get-TargetResource functions in the module file is replaced by a Test(), Set() and Get() methods. That’s all for the introduction part now. Let’s look into the example and create a custom resource to manage SharePoint managed accounts using DSC.

$psModulePath = "C:\Program Files\WindowsPowerShell\Modules"

#Create a folder in the module path for the xSPManagedAccount
New-Item -ItemType Directory -Path "$psModulePath\xSPManagedAccount"

#Create a module manifest for the DSC resource
New-ModuleManifest  -Path "$psModulePath\xSPManagedAccount\xSPManagedAccount.psd1" `
                    -Author "Prajeesh Prathap" `
                    -CompanyName "Prowareness" `
                    -Guid ([System.Guid]::NewGuid()) `
                    -RootModule "xSPManagedAccount.psm1" `
                    -Description "DSC resource provider for managing SharePoint managed accounts" `
                    -PowerShellVersion 5.0 `
                    -DscResourcesToExport @('SPManagedAccount') `
                    -ModuleVersion 1.0 `
                    -Copyright '(c) 2015 Prajeesh Prathap. All rights reserved'

PSEDIT "$psModulePath\xSPManagedAccount\xSPManagedAccount.psd1"

#Create the module file
New-Item -ItemType File -Path "$psModulePath\xSPManagedAccount\xSPManagedAccount.psm1"

PSEDIT "$psModulePath\xSPManagedAccount\xSPManagedAccount.psm1"

The above script will create the files in the PSModulePath location and open in the ISE for adding the methods to the resource file.
In the xSPManagedAccount.psm1 file add the code as given below.

enum Ensure
{
    Absent
    Present
}

[DscResource()]
class xSPManagedAccount
{
    [DscProperty(Key)]
    [String] $Username

    [DscProperty(Mandatory)]
    [String] $Password

    [DscProperty(Mandatory)]
       [Ensure] $Ensure
             
    [void] Set()
    {       
        try
        {
               if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
            }  

            if($this.Ensure -eq [Ensure]::Present)
            {
                   $securePassword = ConvertTo-SecureString $this.Password -AsPlainText -force
                   $credentials = New-Object System.Management.Automation.PsCredential $this.Username,$securePassword
                Write-Verbose "Registering managed account $this.Username"
                New-SPManagedAccount -Credential $credentials | Out-Null
            }
            else
            {
                Write-Verbose "Removing managed account $this.Username"
                Remove-SPManagedAccount -Identity $this.Username
            }         
        }
        catch
        {
            $exception = $_
            Write-Verbose "Error occurred while executing Set function for xSPManagedAccount"
            while ($exception.InnerException -ne $null) {
                $exception = $exception.InnerException
            }

            Write-Verbose $exception
        }
        finally
        {
            if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Remove-PsSnapin Microsoft.SharePoint.PowerShell
            }
        }
    }

   
    [bool] Test()
    {
        try
        {
               if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
            } 
        
            $account = Get-SPManagedAccount | ? {$_.UserName -eq $this.Username }
               if ($account -eq $NULL)
               {
                If($this.Ensure -eq [Ensure]::Present)
                {
                    Write-Verbose "Managed account $($this.Username) was not found. A new managed account for $($this.Username) will be created"
                    return $false
                }
                else
                {
                    Write-Verbose "Managed account $($this.Username) does not exist"
                    return $true
                }
               }
            else
            {
                If($this.Ensure -eq [Ensure]::Present)
                {
                    Write-Verbose "Managed account $($this.Username) already exists."
                    return $true
                }
                else
                {
                    Write-Verbose "Managed account $($this.Username) exists. The managed account will be deleted"
                    return $false
                }
            }   

        }
        catch
        {
            $exception = $_
            Write-Verbose "Error occurred while executing Test function for xSPManagedAccount"
            while ($exception.InnerException -ne $null) {
                $exception = $exception.InnerException
            }

            Write-Verbose $exception
            return $false
        }
        finally
        {
            if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Remove-PsSnapin Microsoft.SharePoint.PowerShell
            }
        }
    }
   
   
    [xSPManagedAccount] Get()
    {
        try
        {           
               if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
            }
            $account = Get-SPManagedAccount | ? {$_.UserName -eq $this.Username }
            $this.Username = $account.Username
            $this.Password = $account.Password
            return $this
        }
        catch
        {
            $exception = $_
            Write-Verbose "Error occurred while executing Get function for xSPManagedAccount"
            while ($exception.InnerException -ne $null) {
                $exception = $exception.InnerException
            }

            Write-Verbose $exception
            return $null
        }
        finally
        {
            if ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
            {
                Remove-PsSnapin Microsoft.SharePoint.PowerShell
            }
        }      
    }
}

To create a configuration and test the resource, you can create a configuration as below.

Configuration SPManagedAccountConfig
{
    Import-Dscresource -ModuleName xSPManagedAccount    
   
    xSPManagedAccount ManagedAccount
    {
        Username = "Domain\MYUserName"
        Password = "MySecretPassword"
        Ensure = "Present"        
    }       
}

SPManagedAccountConfig 

You can execute the script file to generate a MOF file for the configuration and then use the Start-DSCConfiguration cmdlet to start the configuration on the target machine.

If you want to test whether the actual configuration on the target machine matches the desired configuration, you can use the Test-DscConfiguration cmdlet as given below.



No comments: