Configurations

At the heart of DSC are configurations—your infrastructure as code. Configurations are repeatable and can be versioned, verified, and idempotent. Moreover, they are transportable between different environments—provided those environments should look alike.

When compiled and deployed, configurations will do the same as your existing scripts. While those are imperative (install feature, deploy web app), DSC is declarative.

Take the following example, which illustrates the difference:

# Imperative

Install-WindowsFeature -Name AD-Domain-Services, RSAT-AD-Tools -IncludeAllSubFeature

# What happens if the feature cannot be enabled in your build script?
$param = @{
DomainName = 'contoso.com'
SafeModeAdministratorPassword = Read-Host -AsSecureString -Prompt 'Safemode password'
Credential = Get-Credential
ForestMode = 'WinThreshold'
NoRebootOnCompletion = $true
}
Install-ADDSForest @param

# Declarative
configuration Domain
{
param
(
[pscredential] $Credential
)
Import-DscResource -ModuleName PSDesiredStateConfiguration, xActiveDirectory

node DC01
{
foreach ($feature in @('AD-Domain-Services', 'RSAT-AD-Tools'))
{
WindowsFeature $feature
{
Name = $feature
Ensure = 'Present'
}
}

xADDomain contoso
{
DomainName = 'contoso.com'
DomainAdministratorCredential = $Credential
SafemodeAdministratorPassword = $Credential
ForestMode = 'WinThreshold'
DependsOn = '[WindowsFeature]AD-Domain-Services', '[WindowsFeature]RSAT-AD-Tools'
}
}
}

While the imperative configuration for this simple example consumes fewer lines of code to accomplish the same thing, there are some caveats. What happens when your deployment script fails in the middle? How can you cope with dependencies between your imperative statements?

Desired State Configuration is able to simply set dependencies between resources such as a Windows feature and the domain deployment. You can even configure dependencies between configurations on different nodes, but more on that later.

The configuration can be called just like any function or workflow, by using its name. It can take parameters, and you can simply use PowerShell inside your configurations. Just keep in mind that the entire configuration will usually be compiled on your build machine, and all cmdlet calls inside your configuration will target your own system:

# Compiling a configuration
$configurationData = @{
AllNodes = @(
@{
NodeName = '*'
PSDSCAllowPlaintextPassword = $true
PSDSCAllowDomainUser = $true
}
@{
NodeName = 'DC01'
}
)
}

Domain -Credential (Get-Credential) -ConfigurationData $configurationData

# For each node, one MOF file is created
# Notice that we allowed plaintext credentials
Get-Content .DomainDC01.mof

Calling a configuration will produce one or more MOF files, usually one for each node. These MOF could be written by hand—the DSC, DSL, and PowerShell are just tools that help with it. In the MOF file instances of CIM, classes are generated and the whole configuration is an OMI document. The local configuration manager interprets the document and enacts the configuration.

In the code sample, we are using a special construct, a hashtable called ConfigurationData with a preset structure. Configuration data can be used to scale the node deployment:

# We used ConfigurationData to set certain properties like
# allowing plaintext passwords and credentials
@{
# AllNodes is predefined and will be available in $AllNodes
AllNodes = @(
@{
# These settings are valid for all nodes
NodeName = '*'
PSDSCAllowPlaintextPassword = $true
PSDSCAllowDomainUser = $true
}
@{
# For each node one hashtable exists with specific settings
NodeName = 'DC01'
Role = 'DC'
Features = 'AD-Domain-Services','RSAT-AD-Tools'

# If a CertificateFile is used, the configuration will be encrypted
# on the build system as well
CredentialFile = 'C:SomePublicKey.cer'
}
)

# You can add additional keys to build out your data
Domains = @{
'contoso.com' = @{
DFL = 5
FFL = 5
}
'a.contoso.com' = @{
DFL = 7
}
}
}
Be sure to check out our deep-dive into a DSC release pipeline in Chapter 17PowerShell Deep Dives to find out how configuration data can be generated easily that is human-readable!

In your configurations, the AllNodes, ConfigurationData, and Node variables will become available when using configuration data.

AllNodes is an array of hashtables that you can filter on inside your configuration. A very common example is to set roles for nodes and filter on roles later:

# Filtering AllNodes
configuration WithFilter
{
node $AllNodes.Where({$_.Role -eq 'DC'}).NodeName
{
# DC specific stuff
}

node $AllNodes.Where({$_.Role -eq 'FileServer'}).NodeName
{
# File server specific stuff
}
}

In each of your node blocks, the $Node variable will contain the $AllNodes array entry of that is currently being processed. You can use every property of your node like any other hashtable.

At any point in your configuration, you can use the entire configuration data hashtable in the $ConfigurationData variable—with all the scripting power that PowerShell provides.

..................Content has been hidden....................

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