• No results found

} }

RegistryDemo

This concludes our discussion on the Registry resource. Using the knowledge you’ve gained so far in using the DSC resources, try to determine the need for setting the Force property to $true and create a configuration script that demonstrates this behavior.

Script Resource

The Script resource is a special DSC resource. It does not represent any specific resource that can be configured, but this resource provides a way to execute script blocks on the target node(s). This is equivalent to executing any random or ad hoc code on a target node. While this may not sound very interesting to some of you, the Script resource actually has a couple of very good use cases. First of all, the way the Script resource works is how the DSC resources work internally. The properties of the Script resource, shown in Table 5-10, can be used to visualize the working internals of a DSC resource. So, it is important that we look at a few examples of this, so that it becomes familiar by the time we start discussing how to create custom DSC resources. The second advantage of the Script resource is that it provides a quick method to validate the code you want to create for a custom resource.

Figure 5-20. Registry key and value creation using DSC Registry resource

As shown in Table 5-10, the three properties, GetScript, TestScript, and SetScript are mandatory. The Script resource works by first executing the script block supplied as an argument to the TestScript property. This script block must return a Boolean value. Let us see an example of this and understand what happens when we the script block doesn’t result in or return a Boolean value.

Configuration ScriptDemo { Node WSR2-1 {

Script ScriptDemo { GetScript = {

#Ignore this for now }

SetScript = {

#Ignore this for now }

TestScript = {

"This is what we return"

} } } }

ScriptDemo

In the preceding example, we are not returning any Boolean value as a part of the TestScript execution. Instead, we are simply returning a string. When we apply this configuration, we see an error message indicating what is expected from the TestScript execution. This is shown in Figure 5-21.

Table 5-10. Properties of the Script DSC Resource

Property Name Description Required?

GetScript Specifies the script block that returns a hash table of the configuration Yes TestScript Specifies the script block that verifies the state of configuration on the target

system. This function should return only a Boolean value based on the tests.

Yes

SetScript Specifies the script block that can be used to configure a resource Yes Credential Specifies the credentials to use for executing the script resource No DependsOn Specifies the resource(s) that must be configured before configuring this resource No

So, the script block associated with the TestScript property must return a Boolean value. If the TestScript returns $false, the script block assigned to the SetScript property will be executed. So, to understand this, think of TestScript as a method of verifying whether or not an entity on the target node is configured the way we want. If it is not, the TestScript should return $false, and the SetScript should execute to configure the entity as desired. With this knowledge, let us look at another example that explains this behavior.

Configuration ScriptDemo { Node WSR2-1 {

Script ScriptDemo { GetScript = {

#Ignore this for now }

SetScript = {

Set-service -Name AudioSrv -Status Running }

TestScript = {

(Get-Service -Name Audiosrv).Status -eq 'Running' } }

} }

ScriptDemo

As you see in the example here, we are using the TestScript property to verify whether or not AudioSrv service is running. If it is not running, we are returning $false. The SetScript then gets executed and starts the AudioSrv service. If the service is already in the running status, you can see that the resource skips the SetScript script block (see Figure 5-22).

Figure 5-21. Error when the TestScript does not return a Boolean value

Now, the other mandatory property we did not yet see is the GetScript property. As you can infer from the preceding examples, the script block associated with this property has no direct impact on the configuration change.

It is used only when we run the Get-DscConfiguration cmdlet. The script block for this property must always return a hash table. Let’s suppose we don’t return a hash table from GetScript. After we reenact this configuration using the Start-DscConfiguration cmdlet, what will the Get-DscConfiguration cmdlet result in? An error, of course! See Figure 5-23.

Configuration ScriptDemo { Node WSR2-1 {

Script ScriptDemo { GetScript = {

"Return a string for now"

}

SetScript = {

Set-service -Name AudioSrv -Status Running }

TestScript = {

(Get-Service -Name Audiosrv).Status -eq 'Running' } }

} }

ScriptDemo

$CimSession = New-CimSession -ComputerName WSR2-1 Get-DscConfiguration -CimSession $CimSession

Figure 5-22. TestScript and SetScript usage in the Script resource

Figure 5-23. Error from Get-DscConfiguration when the GetScript property does not return a hash table

The hash table that the GetScript script block returns should have the same properties defined in the Script resource schema definition. We can get this information by looking at the Script resource schema file MSFT_

ScriptResource.schema.mof located at $pshome\Modules\PSDesiredStateConfiguration\DSCResources\MSFT_

ScriptResource\. This is shown in Figure 5-24.

Figure 5-24. The MOF schema contents for the Script resource

As we see in the Script resource MOF schema, there are five properties, but the Credential property cannot be returned as a part of the hash table. So, the hash table that we construct as a part of GetScript should include the properties GetScript, SetScript, TestScript, and Result. The Result property should contain the result from the configuration change done by SetScript. Going back to our example, Result should contain the status of the AudioSrv service on the target node. For the rest of the properties, such as GetScript, SetScript, and TestScript, we simply assign the same script block that was in the configuration script. So, the final code for our Script resource example would look like the following:

Configuration ScriptDemo { Node WSR2-1 {

Script ScriptDemo { GetScript = { @{

GetScript = $GetScript SetScript = $SetScript TestScript = $TestScript

Result = (Get-Service -Name Audiosrv).Status }

}

SetScript = {

Set-service -Name AudioSrv -Status Running }

TestScript = {

(Get-Service -Name Audiosrv).Status -eq 'Running' } }

} }

ScriptDemo

In this example, we assign $GetScript, $SetScript, and $TestScript variables to the hash table values

GetScript, SetScript, and TestScript. For the Result property, we determine the status of the AudioSrv service. So, after we reapply this configuration, we use the Start-DscConfiguration cmdlet and then the Get-DscConfiguration to verify what the result of the configuration change or the current state of the configuration we pushed was. The result from the Get-DscConfiguration is shown in Figure 5-25.

Figure 5-25. Output from the Get-DscConfiguration

While this does not make a lot of sense in a real-world scenario, I like the fact that the Script resource helps us understand how the DSC resources actually work. We will see more about writing custom DSC resources in Chapter 9.

I am sure that the knowledge you gained here will be helpful in understanding custom resource development.

Before we conclude this discussion of the Script resource, it is important to note that the values provided as arguments to the GetScript, SetScript, and TestScript properties get converted to a string representation when the configuration MOF is generated. Variable expansion is not done in these script blocks. So, if you use any variable names inside the script blocks used as the arguments to any of the Script resource properties, they won’t be replaced by the variable values. You can observe this by editing the resulting configuration MOF file. If you need to expand variable values in these script blocks, you can use Using scope modifier. Try this yourself.