adding WindowsFeature

This commit is contained in:
Mariah Breakey
2016-10-31 14:30:44 -07:00
parent 03899ad8dc
commit 825aebf654
8 changed files with 1553 additions and 0 deletions
@@ -0,0 +1,543 @@
# Global needed to indicate if a restart is required
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '')]
param ()
Import-Module -Name (Join-Path -Path (Split-Path $PSScriptRoot -Parent) `
-ChildPath 'CommonResourceHelper.psm1')
# Localized messages for verbose and error messages in this resource
$script:localizedData = Get-LocalizedData -ResourceName 'MSFT_WindowsFeature'
<#
.SYNOPSIS
Retrieves the status of the role or feature with the given name on the target machine.
.PARAMETER Name
The name of the role or feature to retrieve
.PARAMETER Credential
The credential (if required) to retrieve the role or feature.
Optional.
.NOTES
If the specified role or feature does not contain any subfeatures then
IncludeAllSubFeature will be set to $false. If the specified feature contains one
or more subfeatures then IncludeAllSubFeature will be set to $true only if all the
subfeatures are installed. Otherwise, IncludeAllSubFeature will be set to $false.
#>
function Get-TargetResource
{
[CmdletBinding()]
[OutputType([Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Write-Verbose -Message ($script:localizedData.GetTargetResourceStartMessage -f $Name)
Import-ServerManager
Write-Verbose -Message ($script:localizedData.QueryFeature -f $Name)
$isWinServer2008R2SP1 = Test-IsWinServer2008R2SP1
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
$feature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $Name } `
-ComputerName . `
-Credential $Credential `
}
else
{
$feature = Get-WindowsFeature @PSBoundParameters
}
Assert-SingleFeatureExists -Feature $feature -Name $Name
$includeAllSubFeature = $true
if ($feature.SubFeatures.Count -eq 0)
{
$includeAllSubFeature = $false
}
else
{
foreach ($currentSubFeatureName in $feature.SubFeatures)
{
$getWindowsFeatureParameters = @{
Name = $currentSubFeatureName
}
if ($PSBoundParameters.ContainsKey('Credential'))
{
$getWindowsFeatureParameters['Credential'] = $Credential
}
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
<#
Calling Get-WindowsFeature through Invoke-Command to start a new process with
the given credential since Get-WindowsFeature doesn't support the Credential
attribute on this server.
#>
$subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $currentSubFeatureName } `
-ComputerName . `
-Credential $Credential `
}
else
{
$subFeature = Get-WindowsFeature @getWindowsFeatureParameters
}
Assert-SingleFeatureExists -Feature $subFeature -Name $currentSubFeatureName
if (-not $subFeature.Installed)
{
$includeAllSubFeature = $false
break
}
}
}
if ($feature.Installed)
{
$ensureResult = 'Present'
}
else
{
$ensureResult = 'Absent'
}
Write-Verbose -Message ($script:localizedData.GetTargetResourceEndMessage -f $Name)
# Add all feature properties to the hash table
return @{
Name = $Name
DisplayName = $feature.DisplayName
Ensure = $ensureResult
IncludeAllSubFeature = $includeAllSubFeature
}
}
<#
.SYNOPSIS
Installs or uninstalls the role or feature with the given name on the target machine
with the option of installing or uninstalling all subfeatures as well.
.PARAMETER Name
The name of the role or feature to install or uninstall.
.PARAMETER Ensure
Specifies whether the role or feature should be installed ('Present')
or uninstalled ('Absent').
By default this is set to Present.
.PARAMETER IncludeAllSubFeature
Specifies whether or not all subfeatures should be installed or uninstalled with
the specified role or feature. Default is false.
If this property is true and Ensure is set to Present, all subfeatures will be installed.
If this property is false and Ensure is set to Present, subfeatures will not be installed or uninstalled.
If Ensure is set to Absent, all subfeatures will be uninstalled.
.PARAMETER Credential
The credential (if required) to install or uninstall the role or feature.
Optional.
.PARAMETER LogPath
The custom path to the log file to log this operation.
If not passed in, the default log path will be used (%windir%\logs\ServerManager.log).
#>
function Set-TargetResource
{
[CmdletBinding(SupportsShouldProcess = $true)]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[ValidateSet('Present', 'Absent')]
[String]
$Ensure = 'Present',
[Boolean]
$IncludeAllSubFeature = $false,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[ValidateNotNullOrEmpty()]
[String]
$LogPath
)
Write-Verbose -Message ($script:localizedData.SetTargetResourceStartMessage -f $Name)
Import-ServerManager
$isWinServer2008R2SP1 = Test-IsWinServer2008R2SP1
if ($Ensure -eq 'Present')
{
$addWindowsFeatureParameters = @{
Name = $Name
IncludeAllSubFeature = $IncludeAllSubFeature
}
if ($PSBoundParameters.ContainsKey('LogPath'))
{
$addWindowsFeatureParameters['LogPath'] = $LogPath
}
Write-Verbose -Message ($script:localizedData.InstallFeature -f $Name)
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
<#
Calling Add-WindowsFeature through Invoke-Command to start a new process with
the given credential since Add-WindowsFeature doesn't support the Credential
attribute on this server.
#>
$feature = Invoke-Command -ScriptBlock { Add-WindowsFeature @addWindowsFeatureParameters } `
-ComputerName . `
-Credential $Credential
}
else
{
if ($PSBoundParameters.ContainsKey('Credential'))
{
$addWindowsFeatureParameters['Credential'] = $Credential
}
$feature = Add-WindowsFeature @addWindowsFeatureParameters
}
if ($null -ne $feature -and $feature.Success)
{
Write-Verbose -Message ($script:localizedData.InstallSuccess -f $Name)
# Check if reboot is required, if so notify the Local Configuration Manager.
if ($feature.RestartNeeded -eq 'Yes')
{
Write-Verbose -Message $script:localizedData.RestartNeeded
$global:DSCMachineStatus = 1
}
}
else
{
New-InvalidOperationException -Message ($script:localizedData.FeatureInstallationFailureError -f $Name)
}
}
# Ensure = 'Absent'
else
{
$removeWindowsFeatureParameters = @{
Name = $Name
}
if ($PSBoundParameters.ContainsKey('LogPath'))
{
$removeWindowsFeatureParameters['LogPath'] = $LogPath
}
Write-Verbose -Message ($script:localizedData.UninstallFeature -f $Name)
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
<#
Calling Remove-WindowsFeature through Invoke-Command to start a new process with
the given credential since Remove-WindowsFeature doesn't support the Credential
attribute on this server.
#>
$feature = Invoke-Command -ScriptBlock { Remove-WindowsFeature @removeWindowsFeatureParameters } `
-ComputerName . `
-Credential $Credential
}
else
{
if ($PSBoundParameters.ContainsKey('Credential'))
{
$addWindowsFeatureParameters['Credential'] = $Credential
}
$feature = Remove-WindowsFeature @removeWindowsFeatureParameters
}
if ($null -ne $feature -and $feature.Success)
{
Write-Verbose ($script:localizedData.UninstallSuccess -f $Name)
# Check if reboot is required, if so notify the Local Configuration Manager.
if ($feature.RestartNeeded -eq 'Yes')
{
Write-Verbose -Message $script:localizedData.RestartNeeded
$global:DSCMachineStatus = 1
}
}
else
{
New-InvalidOperationException -Message ($script:localizedData.FeatureUninstallationFailureError -f $Name)
}
}
Write-Verbose -Message ($script:localizedData.SetTargetResourceEndMessage -f $Name)
}
<#
.SYNOPSIS
Tests if the role or feature with the given name is in the desired state.
.PARAMETER Name
The name of the role or feature to test the state of.
.PARAMETER Ensure
Specifies whether the role or feature should be installed ('Present')
or uninstalled ('Absent').
By default this is set to Present.
.PARAMETER IncludeAllSubFeature
Specifies whether the subfeatures of the indicated role or feature should also be checked
to ensure they are in the desired state. If Ensure is set to 'Present' and this is set to
$true then each subfeature is checked to ensure it is installed as well. If Ensure is set to
Absent and this is set to $true, then each subfeature is checked to ensure it is uninstalled.
As of now, this test can't be used to check if a feature is Installed but all of its
subfeatures are uninstalled.
By default this is set to $false.
.PARAMETER Credential
The Credential (if required) to test the status of the role or feature.
Optional.
.PARAMETER LogPath
The path to the log file to log this operation.
Not used in Test-TargetResource.
#>
function Test-TargetResource
{
[CmdletBinding()]
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[ValidateSet('Present', 'Absent')]
[String]
$Ensure = 'Present',
[Boolean]
$IncludeAllSubFeature = $false,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[ValidateNotNullOrEmpty()]
[String]
$LogPath
)
Write-Verbose -Message ($script:localizedData.TestTargetResourceStartMessage -f $Name)
Import-ServerManager
$testTargetResourceResult = $false
$getWindowsFeatureParameters = @{
Name = $Name
}
if ($PSBoundParameters.ContainsKey('Credential'))
{
$getWindowsFeatureParameters['Credential'] = $Credential
}
Write-Verbose -Message ($script:localizedData.QueryFeature -f $Name)
$isWinServer2008R2SP1 = Test-IsWinServer2008R2SP1
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
<#
Calling Get-WindowsFeature through Invoke-Command to start a new process with
the given credential since Get-WindowsFeature doesn't support the Credential
attribute on this server.
#>
$feature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $Name } `
-ComputerName . `
-Credential $Credential
}
else
{
$feature = Get-WindowsFeature @getWindowsFeatureParameters
}
Assert-SingleFeatureExists -Feature $feature -Name $Name
# Check if the feature is in the requested Ensure state.
if (($Ensure -eq 'Present' -and $feature.Installed -eq $true) -or `
($Ensure -eq 'Absent' -and $feature.Installed -eq $false))
{
$testTargetResourceResult = $true
if ($IncludeAllSubFeature)
{
# Check if each subfeature is in the requested state.
foreach ($currentSubFeatureName in $feature.SubFeatures)
{
$getWindowsFeatureParameters['Name'] = $currentSubFeatureName
if ($isWinServer2008R2SP1 -and $PSBoundParameters.ContainsKey('Credential'))
{
<#
Calling Get-WindowsFeature through Invoke-Command to start a new process with
the given credential since Get-WindowsFeature doesn't support the Credential
attribute on this server.
#>
$subFeature = Invoke-Command -ScriptBlock { Get-WindowsFeature -Name $currentSubFeatureName } `
-ComputerName . `
-Credential $Credential
}
else
{
$subFeature = Get-WindowsFeature @getWindowsFeatureParameters
}
Assert-SingleFeatureExists -Feature $subFeature -Name $currentSubFeatureName
if (-not $subFeature.Installed -and $Ensure -eq 'Present')
{
$testTargetResourceResult = $false
break
}
if ($subFeature.Installed -and $Ensure -eq 'Absent')
{
$testTargetResourceResult = $false
break
}
}
}
}
else
{
# Ensure is not in the correct state
$testTargetResourceResult = $false
}
Write-Verbose -Message ($script:localizedData.TestTargetResourceEndMessage -f $Name)
return $testTargetResourceResult
}
<#
.SYNOPSIS
Asserts that a single instance of the given role or feature exists.
.PARAMETER Feature
The role or feature object to check.
.PARAMETER Name
The name of the role or feature to include in any error messages that are thrown.
(Not used to assert validity of the feature).
#>
function Assert-SingleFeatureExists
{
[CmdletBinding()]
param
(
[PSObject]
$Feature,
[String]
$Name
)
if ($null -eq $Feature)
{
New-InvalidOperationException -Message ($script:localizedData.FeatureNotFoundError -f $Name)
}
if ($Feature.Count -gt 1)
{
New-InvalidOperationException -Message ($script:localizedData.MultipleFeatureInstancesError -f $Name)
}
}
<#
.SYNOPSIS
Sets up the ServerManager module on the target node.
Throws an error if not on a machine running Windows Server.
#>
function Import-ServerManager
{
param
()
<#
Enable ServerManager-PSH-Cmdlets feature if OS is WS2008R2 Core.
Datacenter = 12, Standard = 13, Enterprise = 14
#>
$serverCoreOSCodes = @( 12, 13, 14 )
$operatingSystem = Get-CimInstance -Class 'Win32_OperatingSystem'
# Check if this operating system needs an update to the ServerManager cmdlets
if ($operatingSystem.Version.StartsWith('6.1.') -and `
$serverCoreOSCodes -contains $operatingSystem.OperatingSystemSKU)
{
Write-Verbose -Message $script:localizedData.EnableServerManagerPSHCmdletsFeature
<#
ServerManager-PSH-Cmdlets has a depndency on Powershell 2 update: MicrosoftWindowsPowerShell,
so enabling the MicrosoftWindowsPowerShell update.
#>
$null = Dism\online\enable-feature\FeatureName:MicrosoftWindowsPowerShell
$null = Dism\online\enable-feature\FeatureName:ServerManager-PSH-Cmdlets
}
try
{
Import-Module -Name 'ServerManager'
}
catch
{
Write-Verbose -Message $script:localizedData.ServerManagerModuleNotFoundMessage
New-InvalidOperationException -Message $script:localizedData.SkuNotSupported
}
}
<#
.SYNOPSIS
Tests if the machine is a Windows Server 2008 R2 SP1 machine.
.NOTES
Since Assert-PrequisitesValid ensures that ServerManager is available on the machine,
this function only checks the OS version.
#>
function Test-IsWinServer2008R2SP1
{
param
()
return ([Environment]::OSVersion.Version.ToString().Contains('6.1.'))
}
Export-ModuleMember -Function *-TargetResource
@@ -0,0 +1,11 @@
[ClassVersion("1.0.0.0"), FriendlyName("WindowsFeature")]
class MSFT_WindowsFeature : OMI_BaseResource
{
[Key, Description("The name of the role or feature to install or uninstall.")] String Name;
[Write, Description("Specifies whether the role or feature should be installed or uninstalled. To install the feature, set this property to Present. To uninstall the feature, set the property to Absent."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
[Write, Description("Specifies whether the subfeatures of the main feature should also be installed.")] Boolean IncludeAllSubFeature;
[Write, Description("The path to the log file to log this operation.")] String LogPath;
[Write, Description("A credential, if needed, to install or uninstall the role or feature."), EmbeddedInstance("MSFT_Credential")] String Credential;
[Read, Description("The display name of the retrieved role or feature.")] String DisplayName;
};
@@ -0,0 +1,23 @@
# Localized strings for MSFT_WindowsFeature.psd1
ConvertFrom-StringData @'
FeatureNotFoundError = The requested feature {0} could not be found on the target machine.
MultipleFeatureInstancesError = Failure to get the requested feature {0} information from the target machine. Wildcard pattern is not supported in the feature name.
FeatureInstallationFailureError = Failure to successfully install the feature {0} .
FeatureUninstallationFailureError = Failure to successfully uninstall the feature {0} .
QueryFeature = Querying for feature {0} using Server Manager cmdlet Get-WindowsFeature.
InstallFeature = Trying to install feature {0} using Server Manager cmdlet Add-WindowsFeature.
UninstallFeature = Trying to uninstall feature {0} using Server Manager cmdlet Remove-WindowsFeature.
RestartNeeded = The Target machine needs to be restarted.
GetTargetResourceStartMessage = Begin executing Get functionality on the {0} feature.
GetTargetResourceEndMessage = End executing Get functionality on the {0} feature.
SetTargetResourceStartMessage = Begin executing Set functionality on the {0} feature.
SetTargetResourceEndMessage = End executing Set functionality on the {0} feature.
TestTargetResourceStartMessage = Begin executing Test functionality on the {0} feature.
TestTargetResourceEndMessage = End executing Test functionality on the {0} feature.
ServerManagerModuleNotFoundMessage = ServerManager module is not installed on the machine.
SkuNotSupported = Installing roles and features using PowerShell Desired State Configuration is supported only on Server SKU's. It is not supported on Client SKU.
EnableServerManagerPSHCmdletsFeature = Windows Server 2008R2 Core operating system detected: ServerManager-PSH-Cmdlets feature has been enabled.
UninstallSuccess = Successfully uninstalled the feature {0}.
InstallSuccess = Successfully installed the feature {0}.
'@
+45
View File
@@ -0,0 +1,45 @@
<#
Create a custom configuration by passing in whatever values you need.
$Name is the only parameter that is required which indicates which
Windows Feature you want to install (or uninstall if you set Ensure to Absent).
LogPath and Credential are not included here, but if you would like to specify
a custom log path or need a credential just pass in the desired values and add
LogPath = $LogPath and/or Credential = $Credential to the configuration here
#>
Configuration 'Install_Feature_Telnet_Client'
{
param
(
[System.String]
$Name = 'Telnet-Client',
[ValidateSet('Present', 'Absent')]
[System.String]
$Ensure = 'Present',
[System.Boolean]
$IncludeAllSubFeature = $false,
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential,
[ValidateNotNullOrEmpty()]
[System.String]
$LogPath
)
Import-DscResource -ModuleName 'PSDscResources'
Node Localhost {
WindowsFeature WindowsFeatureTest
{
Name = $Name
Ensure = $Ensure
IncludeAllSubFeature = $IncludeAllSubFeature
}
}
}
@@ -0,0 +1,297 @@
<#
Integration tests for Installing/uninstalling a Windows Feature. Currently Telnet-Client is
set as the feature to test since it's fairly small and doesn't require a restart. ADRMS
is set as the feature to test installing/uninstalling a feature with subfeatures,
but this takes a good chunk of time, so by default these tests are set to be skipped.
If there's any major changes to the resource, then set the skipLongTests variable to $false
and run those tests at least once to test the new functionality more completely.
#>
# Suppressing this rule since we need to create a plaintext password to test this resource
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param ()
Import-Module -Name (Join-Path -Path (Split-Path $PSScriptRoot -Parent) `
-ChildPath 'CommonTestHelper.psm1') `
-Force
$script:testEnvironment = Enter-DscResourceTestEnvironment `
-DscResourceModuleName 'PSDscResources' `
-DscResourceName 'MSFT_WindowsFeature' `
-TestType 'Integration'
$script:testFeatureName = 'Telnet-Client'
$script:testFeatureWithSubFeaturesName = 'ADRMS'
$script:installStateOfTestFeature
$script:installStateOfTestWithSubFeatures
<#
If this is set to $true then the tests that test installing/uninstalling a feature with
its subfeatures will not run.
#>
$script:skipLongTests = $false
try {
#Saving the state so we can clean up afterwards
$testFeature = Get-WindowsFeature -Name $script:testFeatureName
$script:installStateOfTestFeature = $testFeature.Installed
$testFeatureWithSubFeatures = Get-WindowsFeature -Name $script:testFeatureWithSubFeaturesName
$script:installStateOfTestWithSubFeatures = $testFeatureWithSubFeatures.Installed
$configFile = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_WindowsFeature.config.ps1'
Describe 'WindowsFeature Integration Tests' {
$testIncludeAllSubFeature = $false
Remove-WindowsFeature -Name $script:testFeatureName
Context "Should Install the Windows Feature: $script:testFeatureName" {
$configurationName = 'MSFT_WindowsFeature_InstallFeature'
$configurationPath = Join-Path -Path $TestDrive -ChildPath $configurationName
$logPath = Join-Path -Path $TestDrive -ChildPath 'InstallFeatureTest.log'
try
{
# Ensure the feature is not already on the machine
Remove-WindowsFeature -Name $script:testFeatureName
It 'Should compile without throwing' {
{
. $configFile -ConfigurationName $configurationName
& $configurationName -Name $script:testFeatureName `
-IncludeAllSubFeature $testIncludeAllSubFeature `
-Ensure 'Present' `
-OutputPath $configurationPath `
-ErrorAction 'Stop'
Start-DscConfiguration -Path $configurationPath -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should be able to call Get-DscConfiguration without throwing' {
{ Get-DscConfiguration -ErrorAction 'Stop' } | Should Not Throw
}
It 'Should return the correct configuration' {
$currentConfig = Get-DscConfiguration -ErrorAction 'Stop'
$currentConfig.Name | Should Be $script:testFeatureName
$currentConfig.IncludeAllSubFeature | Should Be $testIncludeAllSubFeature
$currentConfig.Ensure | Should Be 'Present'
}
It 'Should be Installed' {
$feature = Get-WindowsFeature -Name $script:testFeatureName
$feature.Installed | Should Be $true
}
}
finally
{
if (Test-Path -Path $logPath) {
Remove-Item -Path $logPath -Recurse -Force
}
if (Test-Path -Path $configurationPath)
{
Remove-Item -Path $configurationPath -Recurse -Force
}
}
}
Context "Should Uninstall the Windows Feature: $script:testFeatureName" {
$configurationName = 'MSFT_WindowsFeature_UninstallFeature'
$configurationPath = Join-Path -Path $TestDrive -ChildPath $configurationName
$logPath = Join-Path -Path $TestDrive -ChildPath 'UninstallFeatureTest.log'
try
{
It 'Should compile without throwing' {
{
. $configFile -ConfigurationName $configurationName
& $configurationName -Name $script:testFeatureName `
-IncludeAllSubFeature $testIncludeAllSubFeature `
-Ensure 'Absent' `
-OutputPath $configurationPath `
-ErrorAction 'Stop'
Start-DscConfiguration -Path $configurationPath -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should be able to call Get-DscConfiguration without throwing' {
{ Get-DscConfiguration -ErrorAction 'Stop' } | Should Not Throw
}
It 'Should return the correct configuration' {
$currentConfig = Get-DscConfiguration -ErrorAction 'Stop'
$currentConfig.Name | Should Be $script:testFeatureName
$currentConfig.IncludeAllSubFeature | Should Be $testIncludeAllSubFeature
$currentConfig.Ensure | Should Be 'Absent'
}
It 'Should not be installed' {
$feature = Get-WindowsFeature -Name $script:testFeatureName
$feature.Installed | Should Be $false
}
}
finally
{
if (Test-Path -Path $logPath) {
Remove-Item -Path $logPath -Recurse -Force
}
if (Test-Path -Path $configurationPath)
{
Remove-Item -Path $configurationPath -Recurse -Force
}
}
}
Context "Should Install the Windows Feature: $script:testFeatureWithSubFeaturesName" {
$configurationName = 'MSFT_WindowsFeature_InstallFeatureWithSubFeatures'
$configurationPath = Join-Path -Path $TestDrive -ChildPath $configurationName
$logPath = Join-Path -Path $TestDrive -ChildPath 'InstallSubFeatureTest.log'
try
{
if (-not $script:skipLongTests)
{
# Ensure that the feature is not already installed
Remove-WindowsFeature -Name $script:testFeatureWithSubFeaturesName
}
It 'Should compile without throwing' -Skip:$script:skipLongTests {
{
. $configFile -ConfigurationName $configurationName
& $configurationName -Name $script:testFeatureWithSubFeaturesName `
-IncludeAllSubFeature $true `
-Ensure 'Present' `
-OutputPath $configurationPath `
-ErrorAction 'Stop'
Start-DscConfiguration -Path $configurationPath -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should be able to call Get-DscConfiguration without throwing' -Skip:$script:skipLongTests {
{ Get-DscConfiguration -ErrorAction 'Stop' } | Should Not Throw
}
It 'Should return the correct configuration' -Skip:$script:skipLongTests {
$currentConfig = Get-DscConfiguration -ErrorAction 'Stop'
$currentConfig.Name | Should Be $script:testFeatureWithSubFeaturesName
$currentConfig.IncludeAllSubFeature | Should Be $true
$currentConfig.Ensure | Should Be 'Present'
}
It 'Should be Installed (includes check for subFeatures)' -Skip:$script:skipLongTests {
$feature = Get-WindowsFeature -Name $script:testFeatureWithSubFeaturesName
$feature.Installed | Should Be $true
foreach ($subFeatureName in $feature.SubFeatures)
{
$subFeature = Get-WindowsFeature -Name $subFeatureName
$subFeature.Installed | Should Be $true
}
}
}
finally
{
if (Test-Path -Path $logPath) {
Remove-Item -Path $logPath -Recurse -Force
}
if (Test-Path -Path $configurationPath)
{
Remove-Item -Path $configurationPath -Recurse -Force
}
}
}
Context "Should Uninstall the Windows Feature: $script:testFeatureWithSubFeaturesName" {
$configurationName = 'MSFT_WindowsFeature_UninstallFeatureWithSubFeatures'
$configurationPath = Join-Path -Path $TestDrive -ChildPath $configurationName
$logPath = Join-Path -Path $TestDrive -ChildPath 'UninstallSubFeatureTest.log'
try
{
It 'Should compile without throwing' -Skip:$script:skipLongTests {
{
. $configFile -ConfigurationName $configurationName
& $configurationName -Name $script:testFeatureWithSubFeaturesName `
-IncludeAllSubFeature $true `
-Ensure 'Absent' `
-OutputPath $configurationPath `
-ErrorAction 'Stop'
Start-DscConfiguration -Path $configurationPath -ErrorAction 'Stop' -Wait -Force
} | Should Not Throw
}
It 'Should be able to call Get-DscConfiguration without throwing' -Skip:$script:skipLongTests {
{ Get-DscConfiguration -ErrorAction 'Stop' } | Should Not Throw
}
It 'Should return the correct configuration' -Skip:$script:skipLongTests {
$currentConfig = Get-DscConfiguration -ErrorAction 'Stop'
$currentConfig.Name | Should Be $script:testFeatureWithSubFeaturesName
$currentConfig.IncludeAllSubFeature | Should Be $false
$currentConfig.Ensure | Should Be 'Absent'
}
It 'Should not be installed (includes check for subFeatures)' -Skip:$script:skipLongTests {
$feature = Get-WindowsFeature -Name $script:testFeatureWithSubFeaturesName
$feature.Installed | Should Be $false
foreach ($subFeatureName in $feature.SubFeatures)
{
$subFeature = Get-WindowsFeature -Name $subFeatureName
$subFeature.Installed | Should Be $false
}
}
}
finally
{
if (Test-Path -Path $logPath) {
Remove-Item -Path $logPath -Recurse -Force
}
if (Test-Path -Path $configurationPath)
{
Remove-Item -Path $configurationPath -Recurse -Force
}
}
}
}
}
finally
{
# Ensure that features used for testing are re-installed/uninstalled
if ($script:installStateOfTestFeature)
{
Add-WindowsFeature -Name $script:testFeatureName
}
else
{
Remove-WindowsFeature -Name $script:testFeatureName
}
if (-not $script:skipLongTests)
{
if ($script:installStateOfTestWithSubFeatures)
{
Add-WindowsFeature -Name $script:testFeatureWithSubFeaturesName -IncludeAllSubFeature
}
else
{
Remove-WindowsFeature -Name $script:testFeatureWithSubFeaturesName
}
}
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
}
@@ -0,0 +1,37 @@
param
(
[Parameter(Mandatory)]
[System.String]
$ConfigurationName
)
Configuration $ConfigurationName
{
param
(
[Parameter(Mandatory = $true)]
[System.String]
$Name,
[ValidateSet('Present', 'Absent')]
[System.String]
$Ensure = 'Present',
[System.Boolean]
$IncludeAllSubFeature = $false
)
Import-DscResource -ModuleName 'PSDscResources'
Node Localhost {
WindowsFeature WindowsFeatureTest
{
Name = $Name
Ensure = $Ensure
IncludeAllSubFeature = $IncludeAllSubFeature
}
}
}
+597
View File
@@ -0,0 +1,597 @@
# Needed to create a fake credential
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param ()
Import-Module -Name (Join-Path -Path (Split-Path $PSScriptRoot -Parent) `
-ChildPath (Join-Path -Path 'TestHelpers' `
-ChildPath 'CommonTestHelper.psm1')) `
-Force
$script:testEnvironment = Enter-DscResourceTestEnvironment `
-DSCResourceModuleName 'PSDscResources' `
-DSCResourceName 'MSFT_WindowsFeature' `
-TestType Unit
try {
InModuleScope 'MSFT_WindowsFeature' {
$testUserName = 'TestUserName12345'
$testUserPassword = 'StrongOne7.'
$testSecurePassword = ConvertTo-SecureString -String $testUserPassword -AsPlainText -Force
$testCredential = New-Object -TypeName PSCredential -ArgumentList ($testUserName, $testSecurePassword)
$testWindowsFeatureName1 = 'Test1'
$testWindowsFeatureName2 = 'Test2'
$testSubFeatureName1 = 'SubTest1'
$testSubFeatureName2 = 'SubTest2'
$testSubFeatureName3 = 'SubTest3'
$mockWindowsFeatures = @{
Test1 = @{
Name = 'Test1'
DisplayName = 'Test Feature 1'
Description = 'Test Feature with 3 subfeatures'
Installed = $false
InstallState = 'Available'
FeatureType = 'Role Service'
Path = 'Test1'
Depth = 1
DependsOn = @()
Parent = ''
ServerComponentDescriptor = 'ServerComponent_Test_Cert_Authority'
Subfeatures = @('SubTest1','SubTest2','SubTest3')
SystemService = @()
Notification = @()
BestPracticesModelId = $null
EventQuery = $null
PostConfigurationNeeded = $false
AdditionalInfo = @('MajorVersion', 'MinorVersion', 'NumericId', 'InstallName')
}
SubTest1 = @{
Name = 'SubTest1'
DisplayName = 'Sub Test Feature 1'
Description = 'Sub Test Feature with parent as test1'
Installed = $true
InstallState = 'Available'
FeatureType = 'Role Service'
Path = 'Test1\SubTest1'
Depth = 2
DependsOn = @()
Parent = 'Test1'
ServerComponentDescriptor = $null
Subfeatures = @()
SystemService = @()
Notification = @()
BestPracticesModelId = $null
EventQuery = $null
PostConfigurationNeeded = $false
AdditionalInfo = @('MajorVersion', 'MinorVersion', 'NumericId', 'InstallName')
}
SubTest2 = @{
Name = 'SubTest2'
DisplayName = 'Sub Test Feature 2'
Description = 'Sub Test Feature with parent as test1'
Installed = $true
InstallState = 'Available'
FeatureType = 'Role Service'
Path = 'Test1\SubTest2'
Depth = 2
DependsOn = @()
Parent = 'Test1'
ServerComponentDescriptor = $null
Subfeatures = @()
SystemService = @()
Notification = @()
BestPracticesModelId = $null
EventQuery = $null
PostConfigurationNeeded = $false
AdditionalInfo = @('MajorVersion', 'MinorVersion', 'NumericId', 'InstallName')
}
SubTest3 = @{
Name = 'SubTest3'
DisplayName = 'Sub Test Feature 3'
Description = 'Sub Test Feature with parent as test1'
Installed = $true
InstallState = 'Available'
FeatureType = 'Role Service'
Path = 'Test\SubTest3'
Depth = 2
DependsOn = @()
Parent = 'Test1'
ServerComponentDescriptor = $null
Subfeatures = @()
SystemService = @()
Notification = @()
BestPracticesModelId = $null
EventQuery = $null
PostConfigurationNeeded = $false
AdditionalInfo = @('MajorVersion', 'MinorVersion', 'NumericId', 'InstallName')
}
Test2 = @{
Name = 'Test2'
DisplayName = 'Test Feature 2'
Description = 'Test Feature with 0 subfeatures'
Installed = $true
InstallState = 'Available'
FeatureType = 'Role Service'
Path = 'Test2'
Depth = 1
DependsOn = @()
Parent = ''
ServerComponentDescriptor = 'ServerComponent_Test_Cert_Authority'
Subfeatures = @()
SystemService = @()
Notification = @()
BestPracticesModelId = $null
EventQuery = $null
PostConfigurationNeeded = $false
AdditionalInfo = @('MajorVersion', 'MinorVersion', 'NumericId', 'InstallName')
}
}
Describe 'WindowsFeature/Get-TargetResource' {
Mock -CommandName Import-ServerManager -MockWith {}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testWindowsFeatureName2 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testWindowsFeatureName2]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testWindowsFeatureName1 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testWindowsFeatureName1]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName1 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName1]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName2 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName2]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName3 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName3]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Context 'Windows Feature exists with no sub features' {
It 'Should return the correct hashtable when not on a 2008 Server' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$getTargetResourceResult = Get-TargetResource -Name $testWindowsFeatureName2
$getTargetResourceResult.Name | Should Be $testWindowsFeatureName2
$getTargetResourceResult.DisplayName | Should Be $mockWindowsFeatures[$testWindowsFeatureName2].DisplayName
$getTargetResourceResult.Ensure | Should Be 'Present'
$getTargetResourceResult.IncludeAllSubFeature | Should Be $false
}
It 'Should return the correct hashtable when on a 2008 Server' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $true }
$getTargetResourceResult = Get-TargetResource -Name $testWindowsFeatureName2
$getTargetResourceResult.Name | Should Be $testWindowsFeatureName2
$getTargetResourceResult.DisplayName | Should Be $mockWindowsFeatures[$testWindowsFeatureName2].DisplayName
$getTargetResourceResult.Ensure | Should Be 'Present'
$getTargetResourceResult.IncludeAllSubFeature | Should Be $false
}
It 'Should return the correct hashtable when on a 2008 Server and Credential is passed' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $true }
Mock -CommandName Invoke-Command -MockWith {
$windowsFeature = $mockWindowsFeatures[$testWindowsFeatureName2]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
$getTargetResourceResult = Get-TargetResource -Name $testWindowsFeatureName2 -Credential $testCredential
$getTargetResourceResult.Name | Should Be $testWindowsFeatureName2
$getTargetResourceResult.DisplayName | Should Be $mockWindowsFeatures[$testWindowsFeatureName2].DisplayName
$getTargetResourceResult.Ensure | Should Be 'Present'
$getTargetResourceResult.IncludeAllSubFeature | Should Be $false
Assert-MockCalled -CommandName Invoke-Command -Times 1 -Exactly -Scope It
}
}
Context 'Windows Feature exists with sub features' {
It 'Should return the correct hashtable when all subfeatures are installed' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$getTargetResourceResult = Get-TargetResource -Name $testWindowsFeatureName1
$getTargetResourceResult.Name | Should Be $testWindowsFeatureName1
$getTargetResourceResult.DisplayName | Should Be $mockWindowsFeatures[$testWindowsFeatureName1].DisplayName
$getTargetResourceResult.Ensure | Should Be 'Absent'
$getTargetResourceResult.IncludeAllSubFeature | Should Be $true
Assert-MockCalled -CommandName Test-IsWinServer2008R2SP1 -Times 1 -Exactly -Scope It
}
It 'Should return the correct hashtable when not all subfeatures are installed' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$mockWindowsFeatures[$testSubFeatureName3].Installed = $false
$getTargetResourceResult = Get-TargetResource -Name $testWindowsFeatureName1
$getTargetResourceResult.Name | Should Be $testWindowsFeatureName1
$getTargetResourceResult.DisplayName | Should Be $mockWindowsFeatures[$testWindowsFeatureName1].DisplayName
$getTargetResourceResult.Ensure | Should Be 'Absent'
$getTargetResourceResult.IncludeAllSubFeature | Should Be $false
Assert-MockCalled -CommandName Test-IsWinServer2008R2SP1 -Times 1 -Exactly -Scope It
$mockWindowsFeatures[$testSubFeatureName3].Installed = $true
}
}
Context 'Windows Feature does not exist' {
It 'Should throw invalid operation exception' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$invalidName = 'InvalidFeature'
{ Get-TargetResource -Name $invalidName } | Should Throw ($script:localizedData.FeatureNotFoundError -f $invalidName)
}
}
}
Describe 'WindowsFeature/Set-TargetResource' {
Mock -CommandName Import-ServerManager -MockWith {}
Context 'Install/Uninstall successful' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
Mock -CommandName Add-WindowsFeature -MockWith {
$windowsFeature = @{
Success = $true
RestartNeeded = 'No'
FeatureResult = @($testWindowsFeatureName2)
ExitCode = 'Success'
}
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Remove-WindowsFeature -MockWith {
$windowsFeature = @{
Success = $true
RestartNeeded = 'No'
FeatureResult = @($testWindowsFeatureName2)
ExitCode = 'Success'
}
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
It 'Should call Add-WindowsFeature when Ensure set to Present' {
{ Set-TargetResource -Name $testWindowsFeatureName2 -Ensure 'Present' } | Should Not Throw
Assert-MockCalled -CommandName Add-WindowsFeature -Times 1 -Exactly -Scope It
}
It 'Should call Remove-WindowsFeature when Ensure set to Absent' {
{ Set-TargetResource -Name $testWindowsFeatureName2 -Ensure 'Absent' } | Should Not Throw
Assert-MockCalled -CommandName Remove-WindowsFeature -Times 1 -Exactly -Scope It
}
}
Context 'Install/Uninstall unsuccessful' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
Mock -CommandName Add-WindowsFeature -MockWith {
$windowsFeature = @{
Success = $false
RestartNeeded = 'No'
FeatureResult = @($testWindowsFeatureName2)
ExitCode = 'Nothing succeeded'
}
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Remove-WindowsFeature -MockWith {
$windowsFeature = @{
Success = $false
RestartNeeded = 'No'
FeatureResult = @($testWindowsFeatureName2)
ExitCode = 'Nothing succeeded'
}
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
It 'Should throw invalid operation exception when Ensure set to Present' {
{ Set-TargetResource -Name $testWindowsFeatureName2 -Ensure 'Present' } |
Should Throw ($script:localizedData.FeatureInstallationFailureError -f $testWindowsFeatureName2)
Assert-MockCalled -CommandName Add-WindowsFeature -Times 1 -Exactly -Scope It
}
It 'Should throw invalid operation exception when Ensure set to Absent' {
{ Set-TargetResource -Name $testWindowsFeatureName2 -Ensure 'Absent' } |
Should Throw ($script:localizedData.FeatureUninstallationFailureError -f $testWindowsFeatureName2)
Assert-MockCalled -CommandName Remove-WindowsFeature -Times 1 -Exactly -Scope It
}
}
Context 'Uninstall/Install with R2/SP1' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $true }
Mock -CommandName Invoke-Command -MockWith {
$windowsFeature = @{
Success = $true
RestartNeeded = 'No'
FeatureResult = @($testWindowsFeatureName2)
ExitCode = 'Success'
}
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
It 'Should install the feature when Ensure set to Present and Credential passed in' {
{
Set-TargetResource -Name $testWindowsFeatureName2 `
-Ensure 'Present' `
-Credential $testCredential
} | Should Not Throw
Assert-MockCalled -CommandName Invoke-Command -Times 1 -Exactly -Scope It
Assert-MockCalled -CommandName Add-WindowsFeature -Times 0 -Scope It
}
It 'Should uninstall the feature when Ensure set to Absent and Credential passed in' {
{
Set-TargetResource -Name $testWindowsFeatureName2 `
-Ensure 'Absent' `
-Credential $testCredential
} | Should Not Throw
Assert-MockCalled -CommandName Invoke-Command -Times 1 -Exactly -Scope It
Assert-MockCalled -CommandName Remove-WindowsFeature -Times 0 -Scope It
}
}
}
Describe 'WindowsFeature/Test-TargetResource' {
Mock -CommandName Import-ServerManager -MockWith {}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testWindowsFeatureName1 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testWindowsFeatureName1]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName1 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName1]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName2 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName2]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Mock -CommandName Get-WindowsFeature -ParameterFilter { $Name -eq $testSubFeatureName3 } -MockWith {
$windowsFeature = $mockWindowsFeatures[$testSubFeatureName3]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
# Used as Get-WindowsFeature when on R2/SP1 2008
Mock -CommandName Invoke-Command -MockWith {
$windowsFeature = $mockWindowsFeatures[$testWindowsFeatureName1]
$windowsFeatureObject = New-Object -TypeName PSObject -Property $windowsFeature
$windowsFeatureObject.PSTypeNames[0] = 'Microsoft.Windows.ServerManager.Commands.Feature'
return $windowsFeatureObject
}
Context 'Feature is in the desired state' {
It 'Should return true when Ensure set to Absent and Feature not installed' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Absent' `
-IncludeAllSubFeature $false
$testTargetResourceResult | Should Be $true
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
}
It 'Should return true when Ensure set to Present and Feature installed not checking subFeatures' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $true
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $false
$testTargetResourceResult | Should Be $true
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $false
}
It 'Should return true when Ensure set to Present and Feature and subFeatures installed' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $true
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $true
$testTargetResourceResult | Should Be $true
Assert-MockCalled -CommandName Get-WindowsFeature -Times 4 -Exactly -Scope It
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $false
}
It 'Should return true when Ensure set to Absent and Feature not installed and on R2/SP1 2008' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $true }
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Absent' `
-IncludeAllSubFeature $false `
-Credential $testCredential
$testTargetResourceResult | Should Be $true
Assert-MockCalled -CommandName Invoke-Command -Times 1 -Exactly -Scope It
}
}
Context 'Feature is not in the desired state' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $false }
It 'Should return false when Ensure set to Present and Feature not installed' {
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $false
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
}
It 'Should return false when Ensure set to Absent and Feature installed not checking subFeatures' {
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $true
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Absent' `
-IncludeAllSubFeature $false
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $false
}
It 'Should return false when Ensure set to Present, Feature not installed and subFeatures installed' {
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $true
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
}
It 'Should return false when Ensure set to Absent and Feature not installed but subFeatures installed' {
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Absent' `
-IncludeAllSubFeature $true
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 2 -Exactly -Scope It
}
It 'Should return false when Ensure set to Absent and Feature installed and subFeatures installed' {
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $true
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Absent' `
-IncludeAllSubFeature $true
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 1 -Exactly -Scope It
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $false
}
It 'Should return false when Ensure set to Present and Feature installed but not all subFeatures installed' {
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $true
$mockWindowsFeatures[$testSubFeatureName2].Installed = $false
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $true
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Get-WindowsFeature -Times 3 -Exactly -Scope It
$mockWindowsFeatures[$testWindowsFeatureName1].Installed = $false
$mockWindowsFeatures[$testSubFeatureName2].Installed = $true
}
It 'Should return false when Ensure set to Present and Feature not installed and on R2/SP1 2008' {
Mock -CommandName Test-IsWinServer2008R2SP1 -MockWith { return $true }
$testTargetResourceResult = Test-TargetResource -Name $testWindowsFeatureName1 `
-Ensure 'Present' `
-IncludeAllSubFeature $false `
-Credential $testCredential
$testTargetResourceResult | Should Be $false
Assert-MockCalled -CommandName Invoke-Command -Times 1 -Exactly -Scope It
}
}
}
Describe 'WindowsFeature/Assert-SingleFeatureExists' {
$multipleFeature = @{
Name = 'MultiFeatureName'
Count = 2
}
It 'Should throw invalid operation when feature equals null' {
$nonexistentName = 'NonexistentFeatureName'
{ Assert-SingleFeatureExists -Feature $null -Name $nonexistentName } |
Should Throw ($script:localizedData.FeatureNotFoundError -f $nonexistentName)
}
It 'Should throw invalid operation when there are multiple features with the given name' {
{ Assert-SingleFeatureExists -Feature $multipleFeature -Name $multipleFeature.Name } |
Should Throw ($script:localizedData.MultipleFeatureInstancesError -f $multipleFeature.Name)
}
}
Describe 'WindowsFeature/Import-ServerManager' {
$mockOperatingSystem = @{
Name = 'mockOS'
Version = '6.1.'
OperatingSystemSKU = 10
}
Mock -CommandName Get-WmiObject -MockWith { return $mockOperatingSystem }
It 'Should Not Throw' {
Mock -CommandName Import-Module -MockWith {}
{ Import-ServerManager } | Should Not Throw
}
It 'Should throw invalid operation exception' {
Mock -CommandName Import-Module -MockWith { Throw }
{ Import-ServerManager } | Should Throw ($script:localizedData.SkuNotSupported)
}
}
}
}
finally
{
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
}