adding script resource

This commit is contained in:
Mariah Breakey
2016-12-15 19:08:38 -08:00
parent b9aa4e9e58
commit ca45108e98
11 changed files with 1116 additions and 1 deletions
@@ -0,0 +1,283 @@
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
# Import CommonResourceHelper for Get-LocalizedData
$script:dscResourcesFolderFilePath = Split-Path $PSScriptRoot -Parent
$script:commonResourceHelperFilePath = Join-Path -Path $script:dscResourcesFolderFilePath -ChildPath 'CommonResourceHelper.psm1'
Import-Module -Name $script:commonResourceHelperFilePath
# Localized messages for verbose and error statements in this resource
$script:localizedData = Get-LocalizedData -ResourceName 'MSFT_ScriptResource'
<#
.SYNOPSIS
Runs the given get script.
Should return a hashtable.
.PARAMETER GetScript
The script to retrieve the current state of the resource.
.PARAMETER SetScript
Not used in Get-TargetResource.
.PARAMETER TestScript
Not used in Get-TargetResource.
.PARAMETER Credential
The Credential to run the get script under if needed.
#>
function Get-TargetResource
{
[OutputType([Hashtable])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$SetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$TestScript,
[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Write-Verbose -Message $script:localizedData.GetTargetResourceStartVerboseMessage
$invokeScriptParameters = @{
ScriptBlock = [ScriptBlock]::Create($GetScript)
}
if ($PSBoundParameters.ContainsKey('Credential'))
{
$invokeScriptParameters['Credential'] = $Credential
}
$invokeScriptResult = Invoke-Script @invokeScriptParameters
if ($invokeScriptResult -is [System.Management.Automation.ErrorRecord])
{
New-InvalidOperationException -Message $script:localizedData.GetScriptThrewError -ErrorRecord $invokeScriptResult
}
$invokeScriptResultAsHashTable = $invokeScriptResult -as [Hashtable]
if ($null -eq $invokeScriptResultAsHashTable)
{
New-InvalidArgumentException -ArgumentName 'TestScript' -Message $script:localizedData.GetScriptDidNotReturnHashtable
}
Write-Verbose -Message $script:localizedData.GetTargetResourceEndVerboseMessage
return $invokeScriptResultAsHashTable
}
<#
.SYNOPSIS
Runs the given set script.
Should not return.
.PARAMETER GetScript
Not used in Set-TargetResource.
.PARAMETER SetScript
The script to set the resource to the desired state.
.PARAMETER TestScript
Not used in Set-TargetResource.
.PARAMETER Credential
The Credential to run the set script under if needed.
#>
function Set-TargetResource
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$SetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$TestScript,
[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Write-Verbose -Message $script:localizedData.SetTargetResourceStartVerboseMessage
$invokeScriptParameters = @{
ScriptBlock = [ScriptBlock]::Create($SetScript)
}
if ($PSBoundParameters.ContainsKey('Credential'))
{
$invokeScriptParameters['Credential'] = $Credential
}
$invokeScriptResult = Invoke-Script @invokeScriptParameters
if ($invokeScriptResult -is [System.Management.Automation.ErrorRecord])
{
New-InvalidOperationException -Message $script:localizedData.SetScriptThrewError -ErrorRecord $invokeScriptResult
}
Write-Verbose -Message $script:localizedData.SetTargetResourceEndVerboseMessage
}
<#
.SYNOPSIS
Runs the given test script.
Should return true if the resource is in the desired state and false otherwise.
.PARAMETER GetScript
Not used in Test-TargetResource.
.PARAMETER SetScript
Not used in Test-TargetResource.
.PARAMETER TestScript
The script to validate whether or not the resource is in the desired state.
.PARAMETER Credential
The Credential to run the test script under if needed.
#>
function Test-TargetResource
{
[OutputType([Boolean])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$GetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$SetScript,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$TestScript,
[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Write-Verbose -Message $script:localizedData.TestTargetResourceStartVerboseMessage
$invokeScriptParameters = @{
ScriptBlock = [ScriptBlock]::Create($TestScript)
}
if ($PSBoundParameters.ContainsKey('Credential'))
{
$invokeScriptParameters['Credential'] = $Credential
}
$invokeScriptResult = Invoke-Script @invokeScriptParameters
# If the script is returing multiple objects, then we consider the last object to be the result of the script execution.
if ($invokeScriptResult -is [Object[]] -and $invokeScriptResult.Count -gt 0)
{
$invokeScriptResult = $invokeScriptResult[$invokeScriptResult.Count - 1]
}
if ($invokeScriptResult -is [System.Management.Automation.ErrorRecord])
{
New-InvalidOperationException -Message $script:localizedData.TestScriptThrewError -ErrorRecord $invokeScriptResult
}
if ($null -eq $invokeScriptResult -or -not ($invokeScriptResult -is [Boolean]))
{
New-InvalidArgumentException -ArgumentName 'TestScript' -Message $script:localizedData.TestScriptDidNotReturnBoolean
}
Write-Verbose -Message $script:localizedData.TestTargetResourceEndVerboseMessage
return $invokeScriptResult
}
<#
.SYNOPSIS
Invokes the given script block.
The output of the script will be returned unless the script throws an error.
If the script throws an error, the ErrorRecord will be returned rather than thrown.
.PARAMETER ScriptBlock
The script block to invoke.
.PARAMETER Credential
The credential to run the script under if needed.
#>
function Invoke-Script
{
[OutputType([Object])]
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ScriptBlock]
$ScriptBlock,
[Parameter()]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
$scriptResult = $null
try
{
Write-Verbose -Message ($script:localizedData.ExecutingScriptMessage -f $ScriptBlock)
if ($null -ne $Credential)
{
$scriptResult = Invoke-Command -ScriptBlock $ScriptBlock -Credential $Credential -ComputerName .
}
else
{
$scriptResult = & $ScriptBlock
}
}
catch
{
# Surfacing the error thrown by the execution of the script
$scriptResult = $_
}
return $scriptResult
}
@@ -0,0 +1,10 @@
[ClassVersion("1.0.0"),FriendlyName("Script")]
class MSFT_ScriptResource : OMI_BaseResource
{
[Key, Description("A string that can be used to create a PowerShell script block that retrieves the current state of the resource.")] String GetScript;
[Key, Description("A string that can be used to create a PowerShell script block that sets the resource to the desired state.")] String SetScript;
[Key, Description("A string that can be used to create a PowerShell script block that validates whether or not the resource is in the desired state.")] String TestScript;
[Write, EmbeddedInstance("MSFT_Credential"), Description("The credential of the user account to run the script under if needed.")] String Credential;
[Read, Description("The result from the GetScript script block.")] String Result;
};
@@ -0,0 +1,16 @@
# Localized MSFT_ScriptResource.strings.psd1
ConvertFrom-StringData @'
GetTargetResourceStartVerboseMessage = Begin executing get script.
GetScriptThrewError = The get script threw an error.
GetScriptDidNotReturnHashtable = The get script did not return a hashtable.
GetTargetResourceEndVerboseMessage = End executing get script.
SetTargetResourceStartVerboseMessage = Begin executing set script.
SetScriptThrewError = The set script threw an error.
SetTargetResourceEndVerboseMessage = End executing set script.
TestTargetResourceStartVerboseMessage = Begin executing test script.
TestScriptThrewError = The test script threw an error.
TestScriptDidNotReturnBoolean = The test script did not return a boolean.
TestTargetResourceEndVerboseMessage = End executing test script.
ExecutingScriptMessage = Executing script: {0}
'@
+62
View File
@@ -0,0 +1,62 @@
<#
.SYNOPSIS
Creates a file at the given file path with the specified content through the Script resource.
.PARAMETER FilePath
The path at which to create the file.
.PARAMETER FileContent
The content to set for the new file.
#>
Configuration ScriptExample {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FilePath,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FileContent
)
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Script ScriptExample
{
SetScript = {
$streamWriter = New-Object -TypeName 'System.IO.StreamWriter' -ArgumentList @( $using:FilePath )
$streamWriter.WriteLine($using:FileContent)
$streamWriter.Close()
}
TestScript = {
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
return $fileContent -eq $using:FileContent
}
else
{
return $false
}
}
GetScript = {
$fileContent = $null
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
}
return @{
Result = Get-Content -Path $fileContent
}
}
}
}
}
+1 -1
View File
@@ -73,7 +73,7 @@ VariablesToExport = '*'
AliasesToExport = @()
# DSC resources to export from this module
DscResourcesToExport = 'Group', 'Service', 'User', 'WindowsFeature', 'WindowsOptionalFeature', 'WindowsPackageCab', 'WindowsProcess'
DscResourcesToExport = 'Group', 'Script', 'Service', 'User', 'WindowsFeature', 'WindowsOptionalFeature', 'WindowsPackageCab', 'WindowsProcess'
# List of all modules packaged with this module
# ModuleList = @()
+27
View File
@@ -35,6 +35,7 @@ Please check out the common DSC Resources [contributing guidelines](https://gith
## Resources
* [Group](#group): Provides a mechanism to manage local groups on a target node.
* [Script](#script): Provides a mechanism to run PowerShell script blocks on a target node.
* [Service](#service): Provides a mechanism to configure and manage Windows services on a target node.
* [User](#user): Provides a mechanism to manage local users on a target node.
* [WindowsFeature](#windowsfeature): Provides a mechanism to install or uninstall Windows roles or features on a target node.
@@ -45,6 +46,7 @@ Please check out the common DSC Resources [contributing guidelines](https://gith
### Resources that Work on Nano Server
* [Group](#group)
* [Script](#script)
* [Service](#service)
* [User](#user)
* [WindowsOptionalFeature](#windowsoptionalfeature)
@@ -78,6 +80,30 @@ None
* [Set members of a group](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Group_SetMembers.ps1)
* [Remove members of a group](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Group_RemoveMembers.ps1)
### Script
Provides a mechanism to run PowerShell script blocks on a target node.
This resource works on Nano Server.
#### Requirements
None
#### Parameters
* **[String] GetScript** _(Key)_: A string that can be used to create a PowerShell script block that retrieves the current state of the resource. This script block runs when the Get-DscConfiguration cmdlet is called. This script block should return a hash table containing one key named Result with a string value.
* **[String] SetScript** _(Key)_: A string that can be used to create a PowerShell script block that sets the resource to the desired state. This script block runs conditionally when the Start-DscConfiguration cmdlet is called. The TestScript script block will run first. If the TestScript block returns False, this script block will run. If the TestScript block returns True, this script block will not run. This script block should not return.
* **[String] TestScript** _(Key)_: A string that can be used to create a PowerShell script block that validates whether or not the resource is in the desired state. This script block runs when the Start-DscConfiguration cmdlet is called or when the Test-DscConfiguration cmdlet is called. This script block should return a boolean with True meaning that the resource is in the desired state and False meaning that the resource is not in the desired state.
* **[PSCredential] Credential** _(Write)_: The credential of the user account to run the script under if needed.
#### Read-Only Properties from Get-TargetResource
* **[String] Result** _(Read)_: The result from the GetScript script block.
#### Examples
* [Create a file with content through xScript](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_Script.ps1)
### Service
Provides a mechanism to configure and manage Windows services on a target node.
@@ -273,6 +299,7 @@ None
* Updated resource module, unit tests, integration tests, and examples to reflect the changes made in xPSDesiredStateConfiguration.
* Group:
* Updated resource module, examples, and integration tests to reflect the changes made in xPSDesiredStateConfiguration.
* Added Script
### 2.1.0.0
@@ -0,0 +1,135 @@
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
if ($PSVersionTable.PSVersion.Major -lt 5 -or $PSVersionTable.PSVersion.Minor -lt 1)
{
Write-Warning -Message 'Cannot run PSDscResources integration tests on PowerShell versions lower than 5.1'
return
}
# Import CommonTestHelper for Enter-DscResourceTestEnvironment, Exit-DscResourceTestEnvironment
$script:moduleRootPath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent
$script:testPath = Split-Path -Path $PSScriptRoot -Parent
$script:testHelpersPath = Join-Path -Path $script:testPath -ChildPath 'TestHelpers'
Import-Module -Name (Join-Path -Path $script:testHelpersPath -ChildPath 'CommonTestHelper.psm1')
$script:testEnvironment = Enter-DscResourceTestEnvironment `
-DscResourceModuleName 'PSDscResources' `
-DscResourceName 'MSFT_ScriptResource' `
-TestType 'Integration'
try
{
Describe 'Script Integration Tests' {
BeforeAll {
# Import Script module for Get-TargetResource, Test-TargetResource
$dscResourcesFolderFilePath = Join-Path -Path $script:moduleRootPath -ChildPath 'DscResources'
$scriptResourceFolderFilePath = Join-Path -Path $dscResourcesFolderFilePath -ChildPath 'MSFT_ScriptResource'
$scriptResourceModuleFilePath = Join-Path -Path $scriptResourceFolderFilePath -ChildPath 'MSFT_ScriptResource.psm1'
Import-Module -Name $scriptResourceModuleFilePath
$script:configurationNoCredentialFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_ScriptResource_NoCredential.config.ps1'
$script:configurationWithCredentialFilePath = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_ScriptResource_WithCredential.config.ps1'
# Cannot use $TestDrive here because script is run outside of Pester
$script:testFilePath = Join-Path -Path $env:SystemDrive -ChildPath 'TestFile.txt'
if (Test-Path -Path $script:testFilePath)
{
Remove-Item -Path $script:testFilePath -Force
}
}
AfterAll {
if (Test-Path -Path $script:testFilePath)
{
Remove-Item -Path $script:testFilePath -Force
}
}
Context 'Get, set, and test scripts specified and Credential not specified' {
if (Test-Path -Path $script:testFilePath)
{
Remove-Item -Path $script:testFilePath -Force
}
$configurationName = 'TestScriptNoCredential'
# Cannot use $TestDrive here because script is run outside of Pester
$resourceParameters = @{
FilePath = $script:testFilePath
FileContent = 'Test file content'
}
It 'Should have removed test file before config runs' {
Test-Path -Path $resourceParameters.FilePath | Should Be $false
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationNoCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should have created the test file' {
Test-Path -Path $resourceParameters.FilePath | Should Be $true
}
It 'Should have set file content correctly' {
Get-Content -Path $resourceParameters.FilePath -Raw | Should Be "$($resourceParameters.FileContent)`r`n"
}
}
Context 'Get, set, and test scripts specified and Credential specified' {
if (Test-Path -Path $script:testFilePath)
{
Remove-Item -Path $script:testFilePath -Force
}
$configurationName = 'TestScriptWithCredential'
# Cannot use $TestDrive here because script is run outside of Pester
$resourceParameters = @{
FilePath = $script:testFilePath
FileContent = 'Test file content'
Credential = Get-AppVeyorAdministratorCredential
}
It 'Should have removed test file before config runs' {
Test-Path -Path $resourceParameters.FilePath | Should Be $false
}
$configData = @{
AllNodes = @(
@{
NodeName = 'localhost'
PSDscAllowPlainTextPassword = $true
PSDscAllowDomainUser = $true
}
)
}
It 'Should compile and apply the MOF without throwing' {
{
. $script:configurationWithCredentialFilePath -ConfigurationName $configurationName
& $configurationName -OutputPath $TestDrive -ConfigurationData $configData @resourceParameters
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should have created the test file' {
Test-Path -Path $resourceParameters.FilePath | Should Be $true
}
It 'Should have set file content correctly' {
Get-Content -Path $resourceParameters.FilePath -Raw | Should Be "$($resourceParameters.FileContent)`r`n"
}
}
}
}
finally
{
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
}
@@ -0,0 +1,60 @@
param
(
[Parameter(Mandatory = $true)]
[String]
$ConfigurationName
)
Configuration $ConfigurationName
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FilePath,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FileContent
)
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Script ScriptExample
{
SetScript = {
$streamWriter = New-Object -TypeName 'System.IO.StreamWriter' -ArgumentList @( $using:FilePath )
$streamWriter.WriteLine($using:FileContent)
$streamWriter.Close()
}
TestScript = {
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
return $fileContent -eq $using:FileContent
}
else
{
return $false
}
}
GetScript = {
$fileContent = $null
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
}
return @{
Result = Get-Content -Path $fileContent
}
}
}
}
}
@@ -0,0 +1,67 @@
param
(
[Parameter(Mandatory = $true)]
[String]
$ConfigurationName
)
Configuration $ConfigurationName
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FilePath,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$FileContent,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Import-DscResource -ModuleName 'PSDscResources'
Node localhost
{
Script Script1
{
SetScript = {
$streamWriter = New-Object -TypeName 'System.IO.StreamWriter' -ArgumentList @( $using:FilePath )
$streamWriter.WriteLine($using:FileContent)
$streamWriter.Close()
}
TestScript = {
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
return $fileContent -eq $using:FileContent
}
else
{
return $false
}
}
GetScript = {
$fileContent = $null
if (Test-Path -Path $using:FilePath)
{
$fileContent = Get-Content -Path $using:filePath -Raw
}
return @{
Result = Get-Content -Path $fileContent
}
}
Credential = $Credential
}
}
}
+455
View File
@@ -0,0 +1,455 @@
$errorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'
# Import CommonTestHelper for Enter-DscResourceTestEnvironment, Exit-DscResourceTestEnvironment
$script:moduleRootPath = Split-Path -Path $PSScriptRoot -Parent
$script:testHelpersPath = Join-Path -Path $script:moduleRootPath -ChildPath 'TestHelpers'
Import-Module -Name (Join-Path -Path $script:testHelpersPath -ChildPath 'CommonTestHelper.psm1')
$script:testEnvironment = Enter-DscResourceTestEnvironment `
-DSCResourceModuleName 'PSDscResources' `
-DSCResourceName 'MSFT_ScriptResource' `
-TestType 'Unit'
try
{
InModuleScope 'MSFT_ScriptResource' {
$testUsername = 'TestUsername'
$testPassword = 'TestPassword'
$secureTestPassword = ConvertTo-SecureString -String $testPassword -AsPlainText -Force
$script:testCredenital = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList @( $testUsername, $secureTestPassword )
Describe 'Script\Get-TargetResource' {
Mock -CommandName 'Invoke-Script' -MockWith { }
Context 'Specified get script returns null' {
$getTargetResourceParameters = @{
GetScript = 'return $null'
TestScript = 'NotUsed'
SetScript = 'NotUsed'
}
It 'Should throw an error for malformed get script' {
$errorMessage = $script:localizedData.GetScriptDidNotReturnHashtable
{ $null = Get-TargetResource @getTargetResourceParameters } | Should Throw $errorMessage
}
}
Mock -CommandName 'Invoke-Script' -MockWith { return "String" }
Context 'Specified get script returns a string' {
$getTargetResourceParameters = @{
GetScript = 'return "String"'
TestScript = 'NotUsed'
SetScript = 'NotUsed'
}
It 'Should throw an error for malformed get script' {
$errorMessage = $script:localizedData.GetScriptDidNotReturnHashtable
{ $null = Get-TargetResource @getTargetResourceParameters } | Should Throw $errorMessage
}
}
$testException = New-Object -TypeName 'System.Exception' -ArgumentList @()
$newErrorRecoredArguments = @( $testException, 'Test', [System.Management.Automation.ErrorCategory]::InvalidOperation, $null )
$testErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList $newErrorRecoredArguments
Mock -CommandName 'Invoke-Script' -MockWith { return $testErrorRecord }
Context 'Specified get script throws an error' {
$getTargetResourceParameters = @{
GetScript = 'throw "Error"'
TestScript = 'NotUsed'
SetScript = 'NotUsed'
}
It 'Should throw error from get script' {
{ $null = Get-TargetResource @getTargetResourceParameters } | Should Throw $testErrorRecord
}
}
$testScriptResult = @{ TestResult = 'Value1' }
Mock -CommandName 'Invoke-Script' -MockWith { return $testScriptResult }
Context 'Specified get script returns a hashtable and Credential not specified' {
$getTargetResourceParameters = @{
GetScript = 'return "something"'
TestScript = 'NotUsed'
SetScript = 'NotUsed'
}
It 'Should not throw' {
{ $null = Get-TargetResource @getTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script' {
$expectedScriptBlock = [ScriptBlock]::Create($getTargetResourceParameters.GetScript)
$null = Get-TargetResource @getTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
return $scriptBlockParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
It 'Should return a hashtable' {
$getTargetResourceResult = Get-TargetResource @getTargetResourceParameters
$getTargetResourceResult -is [Hashtable] | Should Be $true
}
It 'Should return the output from the specified get script' {
$getTargetResourceResult = Get-TargetResource @getTargetResourceParameters
Compare-Object -ReferenceObject $testScriptResult -DifferenceObject $getTargetResourceResult | Should Be $null
}
}
Context 'Specified get script returns a hashtable and Credential specified' {
$getTargetResourceParameters = @{
GetScript = 'return "something"'
TestScript = 'NotUsed'
SetScript = 'NotUsed'
Credential = $script:testCredenital
}
It 'Should not throw' {
{ $null = Get-TargetResource @getTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script with the specified Credential' {
$expectedScriptBlock = [ScriptBlock]::Create($getTargetResourceParameters.GetScript)
$null = Get-TargetResource @getTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
$credentialParameterCorrect = $null -eq (Compare-Object -ReferenceObject $getTargetResourceParameters.Credential -DifferenceObject $Credential)
return $scriptBlockParameterCorrect -and $credentialParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
It 'Should return a hashtable' {
$getTargetResourceResult = Get-TargetResource @getTargetResourceParameters
$getTargetResourceResult -is [Hashtable] | Should Be $true
}
It 'Should return the output from the specified get script' {
$getTargetResourceResult = Get-TargetResource @getTargetResourceParameters
Compare-Object -ReferenceObject $testScriptResult -DifferenceObject $getTargetResourceResult | Should Be $null
}
}
}
Describe 'Script\Set-TargetResource' {
Mock -CommandName 'Invoke-Script' -MockWith { }
Context 'Specified set script returns correctly and Credential not specified' {
$setTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'NotUsed'
SetScript = '$assignedVariable = "Value1"'
}
It 'Should not throw' {
{ Set-TargetResource @setTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script' {
$expectedScriptBlock = [ScriptBlock]::Create($setTargetResourceParameters.SetScript)
Set-TargetResource @setTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
return $scriptBlockParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
}
Context 'Specified set script returns correctly and Credential specified' {
$setTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'NotUsed'
SetScript = '$assignedVariable = "Value1"'
Credential = $script:testCredenital
}
It 'Should not throw' {
{ Set-TargetResource @setTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script with specified Credential' {
$expectedScriptBlock = [ScriptBlock]::Create($setTargetResourceParameters.SetScript)
Set-TargetResource @setTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
$credentialParameterCorrect = $null -eq (Compare-Object -ReferenceObject $setTargetResourceParameters.Credential -DifferenceObject $Credential)
return $scriptBlockParameterCorrect -and $credentialParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
}
$testException = New-Object -TypeName 'System.Exception' -ArgumentList @()
$newErrorRecoredArguments = @( $testException, 'Test', [System.Management.Automation.ErrorCategory]::InvalidOperation, $null )
$testErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList $newErrorRecoredArguments
Mock -CommandName 'Invoke-Script' -MockWith { return $testErrorRecord }
Context 'Specified set script returns an error' {
$setTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'NotUsed'
SetScript = 'throw "Error"'
}
It 'Should throw error from set script' {
{ Set-TargetResource @setTargetResourceParameters } | Should Throw $testErrorRecord
}
}
}
Describe 'Script\Test-TargetResource' {
Mock -CommandName 'Invoke-Script' -MockWith { }
Context 'Specified test script returns null' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'return $null'
SetScript = 'NotUsed'
}
It 'Should throw an error for malformed test script' {
$errorMessage = $script:localizedData.TestScriptDidNotReturnBoolean
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Throw $errorMessage
}
}
$testException = New-Object -TypeName 'System.Exception' -ArgumentList @()
$newErrorRecoredArguments = @( $testException, 'Test', [System.Management.Automation.ErrorCategory]::InvalidOperation, $null )
$testErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' -ArgumentList $newErrorRecoredArguments
Mock -CommandName 'Invoke-Script' -MockWith { return $testErrorRecord }
Context 'Specified test script returns an error' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'throw "Error"'
SetScript = 'NotUsed'
}
It 'Should throw error from test script' {
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Throw $testErrorRecord
}
}
$expectedBoolean = $true
Mock -CommandName 'Invoke-Script' -MockWith { return $expectedBoolean }
Context 'Specified test script returns one boolean and Credential not specified' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'return $true'
SetScript = 'NotUsed'
}
It 'Should not throw' {
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script' {
$expectedScriptBlock = [ScriptBlock]::Create($testTargetResourceParameters.TestScript)
$null = Test-TargetResource @testTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
return $scriptBlockParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
It 'Should return the expected boolean' {
$testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
$testTargetResourceResult | Should Be $expectedBoolean
}
}
Context 'Specified test script returns one boolean and Credential specified' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'return $true'
SetScript = 'NotUsed'
Credential = $script:testCredenital
}
It 'Should not throw' {
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script with specified Credential' {
$expectedScriptBlock = [ScriptBlock]::Create($testTargetResourceParameters.TestScript)
$null = Test-TargetResource @testTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
$credentialParameterCorrect = $null -eq (Compare-Object -ReferenceObject $testTargetResourceParameters.Credential -DifferenceObject $Credential)
return $scriptBlockParameterCorrect -and $credentialParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
It 'Should return the expected boolean' {
$testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
$testTargetResourceResult | Should Be $expectedBoolean
}
}
$expectedBoolean = $false
Mock -CommandName 'Invoke-Script' -MockWith { return @( (-not $expectedBoolean), $expectedBoolean ) }
Context 'Specified test script returns multiple booleans' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'return $true, $false'
SetScript = 'NotUsed'
}
It 'Should not throw' {
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Not Throw
}
It 'Should use script execution helper to run script' {
$expectedScriptBlock = [ScriptBlock]::Create($testTargetResourceParameters.TestScript)
$null = Test-TargetResource @testTargetResourceParameters
$invokeScriptParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $expectedScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
return $scriptBlockParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Script' -ParameterFilter $invokeScriptParameterFilter -Times 1 -Scope 'It'
}
It 'Should return the expected boolean' {
$testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
$testTargetResourceResult | Should Be $expectedBoolean
}
}
Mock -CommandName 'Invoke-Script' -MockWith { return 'Value1' }
Context 'Specified test script returns a string' {
$testTargetResourceParameters = @{
GetScript = 'NotUsed'
TestScript = 'return "MyString"'
SetScript = 'NotUsed'
}
It 'Should throw an error for malformed test script' {
$errorMessage = $script:localizedData.TestScriptDidNotReturnBoolean
{ $null = Test-TargetResource @testTargetResourceParameters } | Should Throw $errorMessage
}
}
}
Describe 'Script\Invoke-Script' {
Mock -CommandName 'Invoke-Command' -MockWith { }
Context 'Specified script throws an error' {
$testErrorMessage = 'Script execution helper test error message'
$scriptExecutionHelperParameters = @{
ScriptBlock = { throw $testErrorMessage }
}
It 'Should not throw' {
{ $null = Invoke-Script @scriptExecutionHelperParameters } | Should Not Throw
}
It 'Should return an error record' {
$scriptExecutionHelperResult = Invoke-Script @scriptExecutionHelperParameters
$scriptExecutionHelperResult -is [System.Management.Automation.ErrorRecord] | Should Be $true
}
It 'Should return an error record' {
$scriptExecutionHelperResult = Invoke-Script @scriptExecutionHelperParameters
$scriptExecutionHelperResult -is [System.Management.Automation.ErrorRecord] | Should Be $true
}
It 'Should return error with expected message from script' {
$scriptExecutionHelperResult = Invoke-Script @scriptExecutionHelperParameters
$scriptExecutionHelperResult.Exception.Message | Should Be $testErrorMessage
}
}
Context 'Specified script returns nothing and Credential specified' {
$scriptExecutionHelperParameters = @{
ScriptBlock = { return $null }
Credential = $script:testCredenital
}
It 'Should not throw' {
{ $null = Invoke-Script @scriptExecutionHelperParameters } | Should Not Throw
}
It 'Should run script through Invoke-Command using the specified Credential' {
$null = Invoke-Script @scriptExecutionHelperParameters
$invokeCommandParameterFilter = {
$scriptBlockParameterCorrect = $null -eq (Compare-Object -ReferenceObject $scriptExecutionHelperParameters.ScriptBlock.Ast -DifferenceObject $ScriptBlock.Ast)
$credentialParameterCorrect = $null -eq (Compare-Object -ReferenceObject $scriptExecutionHelperParameters.Credential -DifferenceObject $Credential)
return $scriptBlockParameterCorrect -and $credentialParameterCorrect
}
Assert-MockCalled -CommandName 'Invoke-Command' -ParameterFilter $invokeCommandParameterFilter -Times 1 -Scope 'It'
}
It 'Should return nothing' {
$scriptExecutionHelperResult = Invoke-Script @scriptExecutionHelperParameters
$scriptExecutionHelperResult | Should Be $null
}
}
Context 'Specified script returns a result and Credential not specified' {
$testScriptResult = 'Script result'
$scriptExecutionHelperParameters = @{
ScriptBlock = { return $testScriptResult }
}
It 'Should not run script through Invoke-Command' {
$null = Invoke-Script @scriptExecutionHelperParameters
Assert-MockCalled -CommandName 'Invoke-Command' -Times 0 -Scope 'It'
}
It 'Should return result of script' {
$scriptExecutionHelperResult = Invoke-Script @scriptExecutionHelperParameters
$scriptExecutionHelperResult | Should Be $testScriptResult
}
}
}
}
}
finally
{
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
}