diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aafee0..1e84d18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added CMAssetIntelligencePoint Resource - Added VSCode Project Settings and PS Script Analyzer rules - Added Issue and PR template. +- Added CMFallbackStatusPoint Resource ### Changed diff --git a/README.md b/README.md index f54298a..8937fb7 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ Please check out common DSC Community [contributing guidelines](https://dsccommu management points. - **CMAssetIntelligencePoint**: Provides a resource for creating and managing the SCCM Asset Intelligence Synchronization Point role. +- **CMFallbackStatusPoint**: Provides a resource for creating and managing + the SCCM Fallback Status Point role. ### CMAccounts @@ -358,3 +360,22 @@ Please check out common DSC Community [contributing guidelines](https://dsccommu - [CMAssetIntelligencePoint_Absent](Source\Examples\Resources\CMAssetIntelligencePoint\CMAssetIntelligencePoint_Absent.ps1) - [CMAssetIntelligencePoint_Present](Source\Examples\Resources\CMAssetIntelligencePoint\CMAssetIntelligencePoint_Present.ps1) + +### CMFallbackStatusPoint + +- **[String] SiteCode** _(Key)_: Specifies the Site Code for the Configuration + Manager site. +- **[String] SiteServerName** _(Key)_: Specifies the Site Server to install + or configure the role on. +- **[UInt32] StateMessageCount** _(Write)_: Specifies the number of state messages + that a fallback status point can send to Configuration Manager within a throttle + interval. +- **[UInt32] ThrottleSec** _(Write)_: Specifies the throttle interval in seconds. +- **[String] Ensure** _(Write)_: Specifies whether the fallback status point is + present or absent. + - Values include: { Present | Absent } + +#### CMFallbackStatusPoint Examples + +- [CMFallbackStatusPoint_Absent](Source\Examples\Resources\CMFallbackStatusPoint\CMFallbackStatusPoint_Absent.ps1) +- [CMFallbackStatusPoint_Present](Source\Examples\Resources\CMFallbackStatusPoint\CMFallbackStatusPoint_Present.ps1) diff --git a/source/ConfigMgrCBDsc.psd1 b/source/ConfigMgrCBDsc.psd1 index a1ab2f6..1a48ad7 100644 --- a/source/ConfigMgrCBDsc.psd1 +++ b/source/ConfigMgrCBDsc.psd1 @@ -51,6 +51,7 @@ 'CMBoundaryGroups' 'CMManagementPoint' 'CMAssetIntelligencePoint' + 'CMFallbackStatusPoint' ) <# @@ -64,7 +65,7 @@ # Tags applied to this module. These help with module discovery in online galleries. Tags = @('DesiredStateConfiguration', 'DSC', 'DSCResourceKit', 'DSCResource', 'ConfigMgrCBDsc','CMAccounts','CMIniFile','Collections', - 'CMBoundaries','CMForestDiscovery','ClientStatusSettings','BoundaryGroups','ManagementPoint','CMAssetIntelligencePoint') + 'CMBoundaries','CMForestDiscovery','ClientStatusSettings','BoundaryGroups','ManagementPoint','CMAssetIntelligencePoint','CMFallbackStatusPoint') # A URL to the license for this module. LicenseUri = 'https://github.com/dsccommunity/ConfigMgrCBDsc/blob/master/LICENSE' diff --git a/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.psm1 b/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.psm1 new file mode 100644 index 0000000..4bd0abe --- /dev/null +++ b/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.psm1 @@ -0,0 +1,269 @@ +$script:dscResourceCommonPath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\DscResource.Common' +$script:configMgrResourcehelper = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\ConfigMgrCBDsc.ResourceHelper' + +Import-Module -Name $script:dscResourceCommonPath +Import-Module -Name $script:configMgrResourcehelper + +$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' + + <# + .SYNOPSIS + This will return a hashtable of results. + + .PARAMETER SiteCode + Specifies the site code for Configuration Manager site. + + .PARAMETER SiteServerName + Specifies the Site Server to install or configure the role on. + + .Notes + This must be ran on the Primary servers to install the fallback status point role. + The Primary server computer account must be in the local + administrators group to perform the install. +#> +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [String] + $SiteServerName + ) + + Write-Verbose -Message $script:localizedData.RetrieveSettingValue + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + + $fspProps = (Get-CMFallbackStatusPoint -SiteCode $SiteCode -SiteSystemServerName $SiteServerName).Props + + if ($fspProps) + { + foreach ($fspProp in $fspProps) + { + switch ($fspProp.PropertyName) + { + 'Throttle Count' { $throttleCount = $fspProp.Value } + 'Throttle Interval' { $throttleInterval = $fspProp.Value/1000 } + } + } + $status = 'Present' + } + else + { + $status = 'Absent' + } + + return @{ + SiteServerName = $SiteServerName + SiteCode = $SiteCode + StateMessageCount = $throttleCount + ThrottleSec = $throttleInterval + Ensure = $status + } +} + + <# + .SYNOPSIS + This will set the desired state. + + .PARAMETER SiteCode + Specifies a site code for the Configuration Manager site. + + .PARAMETER SiteServerName + Specifies the Site Server to install or configure the role on. + + .PARAMETER StateMessageCount + Specifies the number of state messages that a fallback status point can send to Configuration Manager within a throttle interval. + + .PARAMETER ThrottleSec + Specifies the throttle interval in seconds. + + .PARAMETER Ensure + Specifies whether the fallback status point is present or absent. + + .Notes + This must be ran on the Primary servers to install the fallback status point role. + The Primary server computer account must be in the local + administrators group to perform the install. +#> +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [String] + $SiteServerName, + + [Parameter()] + [ValidateRange(100,100000)] + [UInt32] + $StateMessageCount, + + [Parameter()] + [ValidateRange(60,86400)] + [UInt32] + $ThrottleSec, + + [Parameter()] + [ValidateSet('Present','Absent')] + [String] + $Ensure = 'Present' + ) + + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + $state = Get-TargetResource -SiteCode $SiteCode -SiteServerName $SiteServerName + + try + { + if ($Ensure -eq 'Present') + { + if ($state.Ensure -eq 'Absent') + { + if ($null -eq (Get-CMSiteSystemServer -SiteCode $SiteCode -SiteSystemServerName $SiteServerName)) + { + Write-Verbose -Message ($script:localizedData.SiteServerRole -f $SiteServerName) + New-CMSiteSystemServer -SiteCode $SiteCode -SiteSystemServerName $SiteServerName + } + + Write-Verbose -Message ($script:localizedData.AddFSPRole -f $SiteServerName) + Add-CMFallbackStatusPoint -SiteSystemServerName $SiteServerName -SiteCode $SiteCode + } + + $evalList = @('StateMessageCount','ThrottleSec') + + foreach ($param in $PSBoundParameters.GetEnumerator()) + { + if ($evalList -contains $param.key) + { + if ($param.Value -ne $state[$param.key]) + { + Write-Verbose -Message ($script:localizedData.SettingValue -f $param.Key, $param.Value) + $buildingParams += @{ + $param.Key = $param.Value + } + } + } + } + + if ($buildingParams) + { + Set-CMFallbackStatusPoint -SiteSystemServerName $SiteServerName -SiteCode $SiteCode @buildingParams + } + } + elseif ($state.Ensure -eq 'Present') + { + Write-Verbose -Message ($script:localizedData.RemoveFSPRole -f $SiteServerName) + Remove-CMFallbackStatusPoint -SiteSystemServerName $SiteServerName -SiteCode $SiteCode + } + } + catch + { + throw $_ + } + finally + { + Set-Location -Path "$env:temp" + } +} + +<# + .SYNOPSIS + This will test the desired state. + + .PARAMETER SiteCode + Specifies a site code for the Configuration Manager site. + + .PARAMETER SiteServerName + Specifies the Site Server to install or configure the role on. + + .PARAMETER StateMessageCount + Specifies the number of state messages that a fallback status point can send to Configuration Manager within a throttle interval. + + .PARAMETER ThrottleSec + Specifies the throttle interval in seconds. + + .PARAMETER Ensure + Specifies whether the fallback status point is present or absent. + + .Notes + This must be ran on the Primary servers to install the fallback status point role. + The Primary server computer account must be in the local + administrators group to perform the install. +#> +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [String] + $SiteServerName, + + [Parameter()] + [ValidateRange(100,100000)] + [UInt32] + $StateMessageCount, + + [Parameter()] + [ValidateRange(60,86400)] + [UInt32] + $ThrottleSec, + + [Parameter()] + [ValidateSet('Present','Absent')] + [String] + $Ensure = 'Present' + ) + + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + $state = Get-TargetResource -SiteCode $SiteCode -SiteServerName $SiteServerName + $result = $true + + if ($Ensure -eq 'Present') + { + if ($state.Ensure -eq 'Absent') + { + Write-Verbose -Message ($script:localizedData.FSPNotInstalled -f $SiteServerName) + $result = $false + } + else + { + $testParams = @{ + CurrentValues = $state + DesiredValues = $PSBoundParameters + ValuesToCheck = @('StateMessageCount','ThrottleSec') + } + + $result = Test-DscParameterState @testParams -Verbose -TurnOffTypeChecking + } + } + elseif ($state.Ensure -eq 'Present') + { + Write-Verbose -Message ($script:localizedData.FSPAbsent -f $SiteServerName) + $result = $false + } + + Write-Verbose -Message ($script:localizedData.TestState -f $result) + Set-Location -Path "$env:temp" + return $result +} + +Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.schema.mof b/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.schema.mof new file mode 100644 index 0000000..bbb908d --- /dev/null +++ b/source/DSCResources/DSC_CMFallbackStatusPoint/DSC_CMFallbackStatusPoint.schema.mof @@ -0,0 +1,9 @@ +[ClassVersion("1.0.0"), FriendlyName("CMFallbackStatusPoint")] +class DSC_CMFallbackStatusPoint: OMI_BaseResource +{ + [Key, Description("Specifies the SiteCode for the Configuration Manager site.")] String SiteCode; + [Key, Description("Specifies the Site Server to install or configure the role on.")] String SiteServerName; + [Write, Description("Specifies the number of state messages that a fallback status point can send to Configuration Manager within a throttle interval.")] UInt32 StateMessageCount; + [Write, Description("Specifies the throttle interval in seconds.")] UInt32 ThrottleSec; + [Write, Description("Specifies whether the fallback status point is present or absent."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; +}; diff --git a/source/DSCResources/DSC_CMFallbackStatusPoint/en-US/DSC_CMFallbackStatusPoint.strings.psd1 b/source/DSCResources/DSC_CMFallbackStatusPoint/en-US/DSC_CMFallbackStatusPoint.strings.psd1 new file mode 100644 index 0000000..53f96ac --- /dev/null +++ b/source/DSCResources/DSC_CMFallbackStatusPoint/en-US/DSC_CMFallbackStatusPoint.strings.psd1 @@ -0,0 +1,10 @@ +ConvertFrom-StringData @' + RetrieveSettingValue = Getting information for the specified Fallback Status Point. + FSPNotInstalled = Fallback Status Point is not installed on server: {0}. + FSPAbsent = {0} Fallback Status Point expected absent returned Present. + SiteServerRole = {0} is not currently a site system server adding site system role. + TestState = Test-TargetResource compliance check returned: {0}. + AddFSPRole = Adding Fallback Status Point role to {0}. + SettingValue = Setting value: {0} to {1}. + RemoveFSPRole = Removing Fallback Status Point role from {0}. +'@ diff --git a/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Absent.ps1 b/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Absent.ps1 new file mode 100644 index 0000000..826f5b5 --- /dev/null +++ b/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Absent.ps1 @@ -0,0 +1,18 @@ +<# + .SYNOPSIS + A DSC configuration script to remove a fallback status point from Configuration Manager. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMFallbackStatusPoint ExampleSettings + { + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + Ensure = 'Absent' + } + } +} diff --git a/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Present.ps1 b/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Present.ps1 new file mode 100644 index 0000000..bd4645c --- /dev/null +++ b/source/Examples/Resources/CMFallbackStatusPoint/CMFallbackStatusPoint_Present.ps1 @@ -0,0 +1,20 @@ +<# + .SYNOPSIS + A DSC configuration script to add a fallback status point to Configuration Manager. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMFallbackStatusPoint ExampleSettings + { + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + Ensure = 'Present' + StateMessageCount = '10000' + ThrottleSec = '3600' + } + } +} diff --git a/tests/Unit/CMFallbackStatusPoint.tests.ps1 b/tests/Unit/CMFallbackStatusPoint.tests.ps1 new file mode 100644 index 0000000..3c1821b --- /dev/null +++ b/tests/Unit/CMFallbackStatusPoint.tests.ps1 @@ -0,0 +1,343 @@ +param () + +$script:dscModuleName = 'ConfigMgrCBDsc' +$script:dscResourceName = 'DSC_CMFallbackStatusPoint' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import Stub function + $script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) + Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'Stubs\ConfigMgrCBDscStub.psm1') -Force -WarningAction SilentlyContinue +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +#Begin Testing +try +{ + InModuleScope $script:dscResourceName { + Describe 'ConfigMgrCBDsc - DSC_CMFallbackStatusPoint\Get-TargetResource' -Tag 'Get'{ + BeforeAll{ + $getInput = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + } + + $getFSPReturn = @{ + SiteCode = 'Lab' + Props = @( + @{ + PropertyName = 'Throttle Count' + Value = '10000' + } + @{ + PropertyName = 'Throttle Interval' + Value = '3600000' + } + ) + } + + Mock -CommandName Import-ConfigMgrPowerShellModule + Mock -CommandName Set-Location + } + + Context 'When retrieving fallback status point settings' { + + It 'Should return desired result when fallback status point is not currently installed' { + Mock -CommandName Get-CMFallbackStatusPoint + + $result = Get-TargetResource @getInput + $result | Should -BeOfType System.Collections.HashTable + $result.SiteCode | Should -Be -ExpectedValue 'Lab' + $result.SiteServerName | Should -Be -ExpectedValue 'FSP01.contoso.com' + $result.StateMessageCount | Should -Be -ExpectedValue $null + $result.ThrottleSec | Should -Be -ExpectedValue $null + $result.Ensure | Should -Be -ExpectedValue 'Absent' + } + + It 'Should return desired result when fallback status point is currently installed' { + Mock -CommandName Get-CMFallbackStatusPoint -MockWith { $getFSPReturn } + + $result = Get-TargetResource @getInput + $result | Should -BeOfType System.Collections.HashTable + $result.SiteCode | Should -Be -ExpectedValue 'Lab' + $result.SiteServerName | Should -Be -ExpectedValue 'FSP01.contoso.com' + $result.StateMessageCount | Should -Be -ExpectedValue '10000' + $result.ThrottleSec | Should -Be -ExpectedValue '3600' + $result.Ensure | Should -Be -ExpectedValue 'Present' + } + } + } + + Describe 'ConfigMgrCBDsc - DSC_CMFallbackStatusPoint\Set-TargetResource' -Tag 'Set'{ + BeforeAll{ + $inputAbsent = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + Ensure = 'Absent' + } + + $inputMismatch = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = '10001' + ThrottleSec = '3601' + Ensure = 'Present' + } + + $getReturnAll = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = '10000' + ThrottleSec = '3600' + Ensure = 'Present' + } + + $getReturnAbsent = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = $null + ThrottleSec = $null + Ensure = 'Absent' + } + + Mock -CommandName Import-ConfigMgrPowerShellModule + Mock -CommandName Set-Location + Mock -CommandName Get-CMSiteSystemServer + Mock -CommandName New-CMSiteSystemServer + Mock -CommandName Add-CMFallbackStatusPoint + Mock -CommandName Set-CMFallbackStatusPoint + Mock -CommandName Remove-CMFallbackStatusPoint + } + + Context 'When Set-TargetResource runs successfully' { + + It 'Should call expected commands for when changing settings' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAll } + + Set-TargetResource @inputMismatch + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands when fallback status point is absent' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAbsent } + + Set-TargetResource @getReturnAll + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands when fallback status point exists and expected absent' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAll } + + Set-TargetResource @inputAbsent + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + } + } + + Context 'When Set-TargetResource throws' { + + It 'Should call expected commands and throw if Get-CMSiteSystemServer throws' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAbsent } + Mock -CommandName Get-CMSiteSystemServer -MockWith { throw } + + { Set-TargetResource @getReturnAll } | Should -Throw + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands and throw if New-CMSiteSystemServer throws' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAbsent } + Mock -CommandName Get-CMSiteSystemServer + Mock -CommandName New-CMSiteSystemServer -MockWith { throw } + + { Set-TargetResource @getReturnAll } | Should -Throw + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands and throw if Add-CMFallbackStatusPoint throws' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAbsent } + Mock -CommandName New-CMSiteSystemServer -MockWith { $true } + Mock -CommandName Add-CMFallbackStatusPoint -MockWith { throw } + + { Set-TargetResource @getReturnAll } | Should -Throw + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 1 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands and throw if Set-CMFallbackStatusPoint throws' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAll } + Mock -CommandName Set-CMFallbackStatusPoint -MockWith { throw } + + { Set-TargetResource @inputMismatch } | Should -Throw + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands and throw if Remove-CMFallbackStatusPoint throws' { + Mock -CommandName Get-TargetResource -MockWith { $getReturnAll } + Mock -CommandName Remove-CMFallbackStatusPoint -MockWith { throw } + + { Set-TargetResource @inputAbsent } | Should -Throw + Assert-MockCalled Import-ConfigMgrPowerShellModule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-Location -Exactly -Times 2 -Scope It + Assert-MockCalled Get-TargetResource -Exactly -Times 1 -Scope It + Assert-MockCalled Get-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled New-CMSiteSystemServer -Exactly -Times 0 -Scope It + Assert-MockCalled Add-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMFallbackStatusPoint -Exactly -Times 0 -Scope It + Assert-MockCalled Remove-CMFallbackStatusPoint -Exactly -Times 1 -Scope It + } + } + } + + Describe 'ConfigMgrCBDsc - DSC_CMFallbackStatusPoint\Test-TargetResource' -Tag 'Test'{ + BeforeAll{ + $inputPresent = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + Ensure = 'Present' + } + + $inputAbsent = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + Ensure = 'Absent' + } + + $inputMismatch = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = '10001' + ThrottleSec = '3601' + Ensure = 'Present' + } + + $getReturnAll = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = '10000' + ThrottleSec = '3600' + Ensure = 'Present' + } + + $getReturnAbsent = @{ + SiteCode = 'Lab' + SiteServerName = 'FSP01.contoso.com' + StateMessageCount = $null + ThrottleSec = $null + Ensure = 'Absent' + } + + Mock -CommandName Import-ConfigMgrPowerShellModule + Mock -CommandName Set-Location + } + + Context 'When running Test-TargetResource and Get-TargetResource Returns ' { + BeforeEach{ + Mock -CommandName Get-TargetResource -MockWith { $getReturnAll } + } + + It 'Should return desired result false when ensure = absent and FSP is present' { + + Test-TargetResource @inputAbsent | Should -Be $false + } + + It 'Should return desired result true when all returned values match inputs' { + + Test-TargetResource @getReturnAll | Should -Be $true + } + + It 'Should return desired result false when there is a mismatch between returned values and inputs' { + + Test-TargetResource @inputMismatch | Should -Be $false + } + } + + Context 'When running Test-TargetResource and Get-TargetResource Returns absent' { + BeforeEach{ + Mock -CommandName Get-TargetResource -MockWith { $getReturnAbsent } + } + + It 'Should return desired result false when ensure = present and FSP is absent' { + + Test-TargetResource @inputPresent | Should -Be $false + } + + It 'Should return desired result true when ensure = absent and FSP is absent' { + + Test-TargetResource @inputAbsent | Should -Be $true + } + } + } + } +} +finally +{ + Invoke-TestCleanup +}