Desired State Configuration resources are used to model and change the state of different components of the system. In an earlier blog post, we discussed details about deploying and discovering those resources and introduced Import-DscResource dynamic keyword. In this post, we will discuss some more details about the usage and internal working of this dynamic keyword. This keyword is only available inside configuration block. Its syntax looks like PowerShell cmdlet but it’s not a cmdlet and behaves differently.
When authoring the DSC configuration in ISE, the PowerShell parser, provides IntelliSence for resources and resource properties by auto loading the resource definitions from $pshome module path. Moreover, the same resource definitions are used during compilation step (generation of MOF document) to validate the entries of the configuration. E.g. resource schema validation is done for following:
-
Only properties defined in schema are used
-
The data types for each property is correct
-
Keys properties are specified
-
No read only property is used
-
Validation on value maps types
Consider this configuration:
Configuration SchemaValidationInCorrectEnumValue
{
WindowsFeature ROLE1
{
Name = “Telnet-Client”
Ensure = “Invalid”
}
}
Compiling it will result in error:
PSDesiredStateConfiguration\WindowsFeature: At least one of the values ‘Invalid’ is not supported or valid for property ‘Ensure’ on class ‘WindowsFeature’. Please specify only supported values: Present, Absent.
This allows catching most of the errors during parse and compilation time instead of delaying it till run time (configuration application).
DSC provides a mechanism to add new custom DSC resources. These resources should be deployed outside of $pshome module path, preferably under $env:SystemDrive\Program Files\WindowsPowerShell\Modules path. For configuration that use custom DSC resources, authoring and compilation steps need to know the additional resources that should be loaded for validation – that’s where Import-DscResource comes into play. In absence of an import mechanism, parsing and compilation steps could be very slow because they have to look up entire $PSModulePath entries to find module containing required DSC resource. Also Import-DscResource is used to import both composite and PowerShell DSC resources.
Import-DscResource currently supports two non-positional parameters Name and ModuleName.
-Name is the name of the resource to import. The name of the resource has to be the class name used when defining schema for the resource and not the friendly name. E.g.
[ClassVersion(“1.1.0”),FriendlyName(“Website”)]
class WebsiteResource : OMI_BaseResource
{
}
In above example resource name is WebsiteResource and not the friendly name “Website”.
Name can contain any numbers of resources to be imported. If only –Name parameter is used then resources can belong to different PowerShell modules as well. e.g.
Import-DSCResource –Name MSFT_xADDomain , MSFT_xSmbShare
The above command will loop through all modules installed in all paths in $env:PSModulePath to find the ones containing resources whose names are specified as value for –Name parameter. Things to consider when using only the Name parameter:
1- It has performance implications because it is resource intensive operation. It can use lots of memory on machine depending on how many modules are installed on machine.
2- It will load the first resource found with given name so in case there are more than one resource with same name deployed on machine, it can end up loading different resource then the one desired.
The recommended way is to specify –ModuleName as well as described below.
-ModuleName is the name of the module that contains the resources to be imported. This parameter can contain either string array of module names or modules specification object. e.g.
Import-DSCResource –ModuleName xActiveDirectory, xSmbShare
Above command will import all resources defined inside modules xActiveDirectory and xSmbShare unless we specify –Name parameter as well to only load selected resources.
Module specification object is just a hash table. The valid members that can be added to it are ModuleName, ModuleVersion and GUID.
Import-DscResource –ModuleName @{ModuleName=”xActiveDirectory”},@{ModuleName=” xSmbShare”}
The Import-DscResource command only tries to find resources inside specific module when ModuleName parameter is specified, which solves any delays/performance issues during resource discovery. Also its lets user control which exact version of module to load when there are multiple versions of same module installed on machine.
DSC Resource Versioning
DSC resources have same version as that of container Modules. Version is determined by ModuleVersion property defined in .psd1 of container module. DSC resources can also define their own .psd1 file which might have ModuleVersion defined as well, but version property is used from container module .psd1 to load resources.
Any updates in resources should result in update to container module version and configuration author can select which version of Resource/Module to load by using command like:
Import-DscResource -ModuleName @{ModuleName=”xActiveDirectory”;GUID=”caedd1418493-4af3-bda0-eef11e9ca2be”;ModuleVersion=”2.0″},@{ModuleName=” xSmbShare”;ModuleVersion=”1.0″}
Above command will fail if it is not able to find exact module version for each module.
The Module version number along with module name is included in each resource instance in output MOF generated during compilation. It looks like this:
instance of MSFT_xADDomain as $MSFT_xADDomain1ref
{
ResourceID = “[xADDomain]FirstDS”;
ModuleName = “xActiveDirectory”;
ModuleVersion = “2.0”;
}
This gives the LCM information about which version of resource was used to generate the MOF. That is the version against which we validated resource properties during compilation so LCM attempts to find/load the same version at runtime. Incase same version does not exist on target node, execution behavior is different for Push vs Pull configuration modes. In case of Push mode execution fails and error is returned to user pushing the configuration. For Pull mode LCM attempts to download required module from Pull server and installs it on target node before execution, if it is unable to find that version on pull server execution fails.
Support for Wild Card operator and Partial Parameter Names
Import-DSCResource also supports partial parameter names
Import-DscResource -N MSFT_xADDomain -Mod ” xActiveDirectory “
We can also use wildcard while specifying resource Names
Import-DscResource -Name * -ModuleName =”xActiveDirectory”;
Import-DscResource -Name MSFT* -ModuleName =”xActiveDirectory”;
Wildcards are not supported for –ModuleName parameter because value can map to multiple module names and is error prone. Below command will result in error during configuration compilation.
Import-DscResource -Name * -ModuleName UserConfigPro*
Also specifying multiple values for Resource names and modules names in same command are not supported. It can have non-deterministic behavior about which resource to load from which module in case same resource exists in multiple modules. Below command will result in error during compilation as well.
Import-DscResource -Name UserConfigProvider*,TestLogger1 -ModuleName UserConfigProv,PsModuleForTestLogger
Fayza Sultan
PowerShell Team
This is an obscure thing that probably only affected me, but trying to learn DSC rather late in the game, I found this post.Watch out copying from the a Submitrticle, "Import-DSCResource –Name MSFT_xADDomain , MSFT_xSmbShare" will cause you no end of trouble, because that's not dash(-) in fron of Name, that's an "em-dash" (–), and the Powershell lexer in VSCode won't flag it, but compiling a config with it will give you weird errors.