From 8f05924c8aa25f7b4afe0a018490a23b7179107b Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Wed, 22 Jul 2020 10:21:41 -0400 Subject: [PATCH 1/8] Initial Sync --- CHANGELOG.md | 1 + README.md | 34 + source/ConfigMgrCBDsc.psd1 | 3 +- .../DSC_CMUserDiscovery.psm1 | 529 ++++++++++++++ .../DSC_CMUserDiscovery.schema.mof | 13 + .../en-US/DSC_CMUserDiscovery.strings.psd1 | 18 + .../CMUserDiscovery_Disabled.ps1 | 17 + .../CMUserDiscovery_Enabled.ps1 | 25 + .../CMUserDiscovery_Exclude.ps1 | 25 + .../CMUserDiscovery_Include.ps1 | 25 + .../CMUserDiscovery_ScheduleNone.ps1 | 24 + tests/Unit/CMUserDiscovery.tests.ps1 | 676 ++++++++++++++++++ 12 files changed, 1389 insertions(+), 1 deletion(-) create mode 100644 source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 create mode 100644 source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.schema.mof create mode 100644 source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 create mode 100644 source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Disabled.ps1 create mode 100644 source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Enabled.ps1 create mode 100644 source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Exclude.ps1 create mode 100644 source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Include.ps1 create mode 100644 source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_ScheduleNone.ps1 create mode 100644 tests/Unit/CMUserDiscovery.tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index a8fc0bf..5c4bb68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Compare-MultipleCompares to the ResourceHelper - Added CMDistributionGroup Resource - Added CMSiteSystemServer Resource +- Added CMUserDiscovery Resource ### Changed diff --git a/README.md b/README.md index beb775d..74d2871 100644 --- a/README.md +++ b/README.md @@ -953,3 +953,37 @@ Please check out common DSC Community [contributing guidelines](https://dsccommu - [CMSiteSystemServer_Present](Source\Examples\Resources\CMSiteSystemServer\CMSiteSystemServer_Present.ps1) - [CMSiteSystemServer_Absent](Source\Examples\Resources\CMSiteSystemServer\CMSiteSystemServer_Absent.ps1) + +### CMUserDiscovery + +- **[String] SiteCode** _(Key)_: Specifies the Site Code for the Configuration + Manager site. +- **[Boolean] Enabled** _(Key)_: Specifies the enablement of the User + Discovery method. If settings is set to $false no other value provided will be + evaluated for compliance. +- **[Boolean] EnableDeltaDiscovery** _(Write)_: Indicates whether Configuration + Manager discovers resources created or modified in AD DS since the last + discovery cycle. +- **[UInt32] DeltaDiscoveryMins** _(Write)_: Specifies the number of minutes for + the delta discovery. +- **[String] ADContainers[]** _(Write)_: Specifies an array of names of Active Directory + containers to match to the discovery. +- **[String] ADContainersToInclude[]** _(Write)_: Specifies an array of names of + Active Directory containers to add to the discovery. +- **[String] ADContainersToExclude[]** _(Write)_: Specifies an array of names of + Active Directory containers to exclude to the discovery. +- **[String] ScheduleInterval** _(Write)_: Specifies the time when the scheduled + event recurs in hours and days. + - Values include: { None| Days| Hours | Minutes } +- **[UInt32] ScheduleCount** _(Write)_: Specifies how often the recur interval + is run. If hours are specified the max value is 23. Anything over 23 will result + in 23 to be set. If days are specified the max value is 31. Anything over 31 will + result in 31 being set. + +#### CMUserDiscovery Examples + +- [CMUserDiscovery_Disabled](Source\Examples\Resources\CMUserDiscovery\CMUserDiscovery_Disabled.ps1) +- [CMUserDiscovery_Enabled](Source\Examples\Resources\CMUserDiscovery\CMUserDiscovery_Enabled.ps1) +- [CMUserDiscovery_Exclude](Source\Examples\Resources\CMUserDiscovery\CMUserDiscovery_Exclude.ps1) +- [CMUserDiscovery_Include](Source\Examples\Resources\CMUserDiscovery\CMUserDiscovery_Include.ps1) +- [CMUserDiscovery_ScheduleNone](Source\Examples\Resources\CMUserDiscovery\CMUserDiscovery_ScheduleNone.ps1) diff --git a/source/ConfigMgrCBDsc.psd1 b/source/ConfigMgrCBDsc.psd1 index 161e54b..9b4847e 100644 --- a/source/ConfigMgrCBDsc.psd1 +++ b/source/ConfigMgrCBDsc.psd1 @@ -69,6 +69,7 @@ 'CMAdministrativeUser' 'CMDistributionGroup' 'CMSiteSystemServer' + 'CMUserDiscovery' ) <# @@ -85,7 +86,7 @@ 'SccmSqlSetup','SCCMInstall','CMIniFile','Collections','Boundaries','ForestDiscovery','ClientStatusSettings','BoundaryGroups', 'ManagementPoint','AssetIntelligencePoint','FallbackStatusPoint','SoftwareUpdatePoint','DistrubtionPoint','HeartbeatDiscovery', 'ServiceConnectionPoint','NetworkDiscovery','ReportingServicePoint','SystemDiscovery','PXEDistributionPoint','PullDistributionPoint', - 'SiteMaintenance','AdministrativeUser','DistributionGroup','SiteSystemServer') + 'SiteMaintenance','AdministrativeUser','DistributionGroup','SiteSystemServer','UserDiscovery') # A URL to the license for this module. LicenseUri = 'https://github.com/dsccommunity/ConfigMgrCBDsc/blob/master/LICENSE' diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 new file mode 100644 index 0000000..75eaf11 --- /dev/null +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -0,0 +1,529 @@ +$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 Enabled + Specifies the enablement of the User Discovery method. +#> +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [Boolean] + $Enabled + ) + + Write-Verbose -Message $script:localizedData.RetrieveSettingValue + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + + $userDiscovery = Get-CMDiscoveryMethod -Name ActiveDirectoryUserDiscovery -SiteCode $SiteCode + + foreach ($prop in $userDiscovery.Props) + { + switch ($prop.PropertyName) + { + 'Settings' { $enabledStatus = ($prop.Value1 -eq 'Active') } + 'Full Sync Schedule' { $userSchedule = $prop.Value1 } + 'Enable Incremental Sync' { $deltaEnabled = $prop.Value } + 'Startup Schedule' { $userDelta = $prop.Value1 } + } + } + + $adContainersList = ($userDiscovery.Proplists | Where-Object -FilterScript {$_.PropertyListName -eq 'AD Containers'}).Values + foreach ($line in $adContainersList) + { + if ($line -match 'LDAP://') + { + [array]$adContainerArray += $line + } + } + + if ($deltaEnabled -eq 0) + { + $userSchedule = $userDelta + $userDelta = $null + } + + $scheduleConvert = ConvertTo-ScheduleInterval -ScheduleString $userSchedule + + if (-not [string]::IsNullOrEmpty($userDelta)) + { + $uDelta = Convert-CMSchedule -ScheduleString $userDelta + + if ($uDelta.HourSpan -eq 1) + { + $syncDelta = 60 + } + else + { + $syncDelta = $uDelta.MinuteSpan + } + } + + return @{ + SiteCode = $SiteCode + Enabled = $enabledStatus + ScheduleInterval = $scheduleConvert.Interval + ScheduleCount = $scheduleConvert.Count + EnableDeltaDiscovery = $deltaEnabled + DeltaDiscoveryMins = $syncDelta + ADContainers = $adContainerArray + } +} + +<# + .SYNOPSIS + This will set the desired state. + + .PARAMETER SiteCode + Specifies the site code for Configuration Manager site. + + .PARAMETER Enabled + Specifies the enablement of the User Discovery method. + + .PARAMETER EnableDeltaDiscovery + Indicates whether Configuration Manager discovers resources created or modified in AD DS + since the last discovery cycle. If you specify a value of $True for this parameter, + specify a value for the DeltaDiscoveryMins parameter. + + .PARAMETER DeltaDiscoveryMins + Specifies the number of minutes for the delta discovery. + + .PARAMETER ADContainers + Specifies an array of names of Active Directory containers to match to the discovery. + + .PARAMETER ADContainersToInclude + Specifies an array of names of Active Directory containers to add to the discovery. + + .PARAMETER ADContainersToExclude + Specifies an array of names of Active Directory containers to exclude to the discovery. + + .PARAMETER ScheduleInterval + Specifies the time when the scheduled event recurs. + + .PARAMETER ScheduleCount + Specifies how often the recur interval is run. +#> +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [Boolean] + $Enabled, + + [Parameter()] + [Boolean] + $EnableDeltaDiscovery, + + [Parameter()] + [ValidateRange(1,60)] + [UInt32] + $DeltaDiscoveryMins, + + [Parameter()] + [String[]] + $ADContainers, + + [Parameter()] + [String[]] + $ADContainersToInclude, + + [Parameter()] + [String[]] + $ADContainersToExclude, + + [Parameter()] + [ValidateSet('None','Days','Hours','Minutes')] + [String] + $ScheduleInterval, + + [Parameter()] + [UInt32] + $ScheduleCount + ) + + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + + try + { + $state = Get-TargetResource -SiteCode $SiteCode -Enabled $Enabled + + if ($Enabled -eq $true) + { + if (($PSBoundParameters.DeltaDiscoveryMins) -and ($PSBoundParameters.EnableDeltaDiscovery -eq $false -or + ($state.EnableDeltaDiscovery -eq $false -and + [string]::IsNullOrEmpty($PSBoundParameters.EnableDeltaDiscovery)))) + { + throw $script:localizedData.MissingDeltaDiscovery + } + + if (($PSBoundParameters.ContainsKey('ScheduleInterval') -and $PSBoundParameters.ScheduleInterval -ne 'None') -and (-not $PSBoundParameters.ContainsKey('ScheduleCount'))) + { + throw $script:localizedData.IntervalCount + } + + $paramsToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins') + + foreach ($param in $PSBoundParameters.GetEnumerator()) + { + if ($paramsToCheck -contains $param.Key) + { + if ($param.Value -ne $state[$param.Key]) + { + Write-Verbose -Message ($script:localizedData.SetCommonSettings -f $param.Key, $param.Value) + $buildingParams += @{ + $param.Key = $param.Value + } + } + } + } + + if (-not [string]::IsNullOrEmpty($ScheduleInterval)) + { + if ($ScheduleInterval -ne $state.ScheduleInterval) + { + Write-Verbose -Message ($script:localizedData.UIntervalSet -f $ScheduleInterval) + $setSchedule = $true + } + + if (($ScheduleInterval -ne 'None') -and ($ScheduleCount -ne $state.ScheduleCount)) + { + Write-Verbose -Message ($script:localizedData.UCountSet -f $ScheduleCount) + $setSchedule = $true + } + + if ($setSchedule -eq $true) + { + if ($ScheduleInterval -eq 'None') + { + $pschedule = New-CMSchedule -Nonrecurring + } + else + { + $pScheduleSet = @{ + RecurInterval = $ScheduleInterval + RecurCount = $ScheduleCount + } + + $pschedule = New-CMSchedule @pScheduleSet + } + + $buildingParams += @{ + PollingSchedule = $pSchedule + } + } + } + + if (($ADContainers) -or ($ADContainersToInclude)) + { + if ($ADContainers) + { + $includes = $ADContainers + } + else + { + $includes = $ADContainersToInclude + } + + foreach ($adContainer in $includes) + { + if ($state.ADContainers -notcontains $adContainer) + { + Write-Verbose -Message ($script:localizedData.AddADContainer -f $adContainer) + [array]$addAdContainers += $adContainer + } + } + + if (-not [string]::IsNullOrEmpty($addAdContainers)) + { + $buildingParams += @{ + AddActiveDirectoryContainer = $addAdContainers + } + } + } + + if (($ADContainers) -or ($ADContainersToExclude)) + { + if (-not [string]::IsNullOrEmpty($state.ADContainers)) + { + if ($ADContainers) + { + $excludes = $ADContainers + } + else + { + $excludes = $ADContainersToExclude + } + + $compares = Compare-Object -ReferenceObject $state.ADContainers -DifferenceObject $excludes -IncludeEqual + foreach ($compare in $compares) + { + if ($ADContainers) + { + if ($compare.SideIndicator -eq '<=') + { + Write-Verbose -Message ($script:localizedData.RemoveADContainer -f $compare.InputObject) + [array]$removeADContainers += $compare.InputObject + } + } + else + { + if ($compare.SideIndicator -eq '==') + { + Write-Verbose -Message ($script:localizedData.RemoveADContainer -f $compare.InputObject) + [array]$removeADContainers += $compare.InputObject + } + } + } + + if (-not [string]::IsNullOrEmpty($removeADContainers)) + { + $buildingParams += @{ + RemoveActiveDirectoryContainer = $removeADContainers + } + } + } + } + + if ($buildingParams) + { + Set-CMDiscoveryMethod -ActiveDirectoryUserDiscovery -SiteCode $SiteCode @buildingParams + } + } + else + { + if ($state.Enabled -eq $true) + { + Write-Verbose -Message $script:localizedData.SetDisabled + Set-CMDiscoveryMethod -ActiveDirectoryUserDiscovery -Enabled $false -SiteCode $SiteCode + } + } + } + catch + { + throw $_ + } + finally + { + Set-Location -Path "$env:temp" + } +} + +<# + .SYNOPSIS + This will set the desired state. + + .PARAMETER SiteCode + Specifies the site code for Configuration Manager site. + + .PARAMETER Enabled + Specifies the enablement of the User Discovery method. + + .PARAMETER EnableDeltaDiscovery + Indicates whether Configuration Manager discovers resources created or modified in AD DS + since the last discovery cycle. If you specify a value of $True for this parameter, + specify a value for the DeltaDiscoveryMins parameter. + + .PARAMETER DeltaDiscoveryMins + Specifies the number of minutes for the delta discovery. + + .PARAMETER ADContainers + Specifies an array of names of Active Directory containers to match to the discovery. + + .PARAMETER ADContainersToInclude + Specifies an array of names of Active Directory containers to add to the discovery. + + .PARAMETER ADContainersToExclude + Specifies an array of names of Active Directory containers to exclude to the discovery. + + .PARAMETER ScheduleInterval + Specifies the time when the scheduled event recurs. + + .PARAMETER ScheduleCount + Specifies how often the recur interval is run. +#> +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [String] + $SiteCode, + + [Parameter(Mandatory = $true)] + [Boolean] + $Enabled, + + [Parameter()] + [Boolean] + $EnableDeltaDiscovery, + + [Parameter()] + [ValidateRange(1,60)] + [UInt32] + $DeltaDiscoveryMins, + + [Parameter()] + [String[]] + $ADContainers, + + [Parameter()] + [String[]] + $ADContainersToInclude, + + [Parameter()] + [String[]] + $ADContainersToExclude, + + [Parameter()] + [ValidateSet('None','Days','Hours','Minutes')] + [String] + $ScheduleInterval, + + [Parameter()] + [UInt32] + $ScheduleCount + ) + + Import-ConfigMgrPowerShellModule -SiteCode $SiteCode + Set-Location -Path "$($SiteCode):\" + $state = Get-TargetResource -SiteCode $SiteCode -Enabled $Enabled + $result = $true + + if ($Enabled -eq $true) + { + $testParams = @{ + CurrentValues = $state + DesiredValues = $PSBoundParameters + ValuesToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins') + } + + $result = Test-DscParameterState @testParams -TurnOffTypeChecking -Verbose + + if ($PSBoundParameters.ContainsKey('ScheduleInterval')) + { + if ($ScheduleInterval -ne 'None' -and -not $PSBoundParameters.ContainsKey('ScheduleCount')) + { + Write-Verbose -Message $script:localizedData.IntervalCount + $result = $false + } + else + { + if ($ScheduleInterval -ne $state.SCheduleInterval) + { + Write-Verbose -Message ($script:localizedData.UIntervalTest -f $ScheduleInterval, $State.ScheduleInterval) + $result = $false + } + + if (($ScheduleInterval -ne 'None') -and ($ScheduleCount -ne $state.ScheduleCount)) + { + Write-Verbose -Message ($script:localizedData.UCountTest -f $ScheduleCount, $State.ScheduleCount) + $result = $false + } + } + } + + if (($ADContainers) -or ($ADContainersToInclude)) + { + if ($ADContainers) + { + if ($PSBoundParameters.ContainsKey('ADContainersToInclude') -or + $PSBoundParameters.ContainsKey('ADContainersToExclude')) + { + Write-Warning -Message $script:localizedData.ADIgnore + } + $includes = $ADContainers + } + else + { + $includes = $ADContainersToInclude + } + + foreach ($adContainer in $includes) + { + if ($state.ADContainers -notcontains $adContainer) + { + Write-Verbose -Message ($script:localizedData.ExpectedADContainer -f $adContainer) + $result = $false + } + } + } + + if (($ADContainers) -or ($ADContainersToExclude)) + { + if (-not [string]::IsNullOrEmpty($state.ADContainers)) + { + if ($ADContainers) + { + $excludes = $ADContainers + } + else + { + $excludes = $ADContainersToExclude + } + + $compares = Compare-Object -ReferenceObject $state.ADContainers -DifferenceObject $excludes -IncludeEqual + foreach ($compare in $compares) + { + if ($ADContainers) + { + if ($compare.SideIndicator -eq '<=') + { + Write-Verbose -Message ($script:localizedData.ExcludeADContainer -f $compare.InputObject) + $result = $false + } + } + else + { + if ($compare.SideIndicator -eq '==') + { + Write-Verbose -Message ($script:localizedData.ExcludeADContainer -f $compare.InputObject) + $result = $false + } + } + } + } + } + } + else + { + if ($state.Enabled -eq $true) + { + Write-Verbose -Message $script:localizedData.TestDisabled + $result = $false + } + } + + Write-Verbose -Message ($script:localizedData.TestState -f $result) + return $result +} + +Export-ModuleMember -Function *-TargetResource diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.schema.mof b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.schema.mof new file mode 100644 index 0000000..40a5549 --- /dev/null +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.schema.mof @@ -0,0 +1,13 @@ +[ClassVersion("1.0.0"), FriendlyName("CMUserDiscovery")] +class DSC_CMUserDiscovery : OMI_BaseResource +{ + [Key, Description("Specifies the SiteCode for the Configuration Manager site.")] String SiteCode; + [Key, Description("Specifies the enablement of the User Discovery method.")] Boolean Enabled; + [Write, Description("Indicates whether Configuration Manager discovers resources created or modified in AD DS since the last discovery cycle.")] Boolean EnableDeltaDiscovery; + [Write, Description("Specifies the number of minutes for the delta discovery.")] UInt32 DeltaDiscoveryMins; + [Write, Description("Specifies an array of names of Active Directory containers to match to the discovery.")] String ADContainers[]; + [Write, Description("Specifies an array of names of Active Directory containers to add to the discovery.")] String ADContainersToInclude[]; + [Write, Description("Specifies an array of names of Active Directory containers to exclude to the discovery.")] String ADContainersToExclude[]; + [Write, Description("Specifies the time when the scheduled event recurs."), ValueMap{"None","Days","Hours","Minutes"}, Values{"None","Days","Hours","Minutes"}] String ScheduleInterval; + [Write, Description("Specifies how often the recur interval is run.")] UInt32 ScheduleCount; +}; diff --git a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 new file mode 100644 index 0000000..73f700d --- /dev/null +++ b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 @@ -0,0 +1,18 @@ +ConvertFrom-StringData @' + RetrieveSettingValue = Getting results for Configuration Manager User Discovery method. + IntervalCount = Invalid parameter usage specifying an Interval and didn't specify count. + UIntervalTest = NOT MATCH: Schedule interval expected: {0} returned {1}. + UCountTest = NOT MATCH: Schedule count expected: {0} returned {1}. + ADIgnore = ADContainers was specified, ADContainersInclude and ADContainersExclude will be ignored. + ExpectedADContainer = Expected AD Container: {0} to be present. + ExcludeADContainer = Expected AD Container: {0} to be absent. + TestDisabled = Expected User Discovery to be set to disabled returned enabled. + TestState = Test-TargetResource compliance check returned: {0}. + MissingDeltaDiscovery = When changing delta schedule, delta schedule must be enabled. + SetCommonSettings = Setting {0} to desired setting {1}. + UIntervalSet = Setting Schedule interval to {0}. + UCountSet = Setting Schedule count to {0}. + AddADContainer = Adding AD Container: {0}. + RemoveADContainer = Removing AD Container: {0}. + SetDisabled = Setting User Discovery to disabled. +'@ diff --git a/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Disabled.ps1 b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Disabled.ps1 new file mode 100644 index 0000000..bf6c975 --- /dev/null +++ b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Disabled.ps1 @@ -0,0 +1,17 @@ +<# + .SYNOPSIS + A DSC configuration script to set user discovery disabled. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMUserDiscovery ExampleSettings + { + SiteCode = 'Lab' + Enabled = $false + } + } +} diff --git a/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Enabled.ps1 b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Enabled.ps1 new file mode 100644 index 0000000..63d56d5 --- /dev/null +++ b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Enabled.ps1 @@ -0,0 +1,25 @@ +<# + .SYNOPSIS + A DSC configuration script to set user discovery enabled. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMUserDiscovery ExampleSettings + { + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Days' + ScheduleCount = 7 + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 50 + ADContainers = @( + 'LDAP://OU=Far,DC=contoso,DC=com','LDAP://OU=Far,OU=Domain Controllers,DC=contoso,DC=com', + 'LDAP://OU=Far,OU=Deployables,DC=contoso,DC=com' + ) + } + } +} diff --git a/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Exclude.ps1 b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Exclude.ps1 new file mode 100644 index 0000000..dd07333 --- /dev/null +++ b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Exclude.ps1 @@ -0,0 +1,25 @@ +<# + .SYNOPSIS + A DSC configuration script for user discovery to exclude ad containers. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMUserDiscovery ExampleSettings + { + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Days' + ScheduleCount = 7 + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 50 + ADContainersToExclude = @( + 'LDAP://OU=Far,DC=contoso,DC=com','LDAP://OU=Far,OU=Domain Controllers,DC=contoso,DC=com', + 'LDAP://OU=Far,OU=Deployables,DC=contoso,DC=com' + ) + } + } +} diff --git a/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Include.ps1 b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Include.ps1 new file mode 100644 index 0000000..c34ba8c --- /dev/null +++ b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_Include.ps1 @@ -0,0 +1,25 @@ +<# + .SYNOPSIS + A DSC configuration script for user discovery to include ad containers. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMUserDiscovery ExampleSettings + { + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Days' + ScheduleCount = 7 + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 50 + ADContainersToInclude = @( + 'LDAP://OU=Far,DC=contoso,DC=com','LDAP://OU=Far,OU=Domain Controllers,DC=contoso,DC=com', + 'LDAP://OU=Far,OU=Deployables,DC=contoso,DC=com' + ) + } + } +} diff --git a/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_ScheduleNone.ps1 b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_ScheduleNone.ps1 new file mode 100644 index 0000000..27b6527 --- /dev/null +++ b/source/Examples/Resources/CMUserDiscovery/CMUserDiscovery_ScheduleNone.ps1 @@ -0,0 +1,24 @@ +<# + .SYNOPSIS + A DSC configuration script to user discovery set to a custom schedule to none. +#> +Configuration Example +{ + Import-DscResource -ModuleName ConfigMgrCBDsc + + Node localhost + { + CMUserDiscovery ExampleSettings + { + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'None' + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 50 + ADContainers = @( + 'LDAP://OU=Far,DC=contoso,DC=com','LDAP://OU=Far,OU=Domain Controllers,DC=contoso,DC=com', + 'LDAP://OU=Far,OU=Deployables,DC=contoso,DC=com' + ) + } + } +} diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 new file mode 100644 index 0000000..6f9aaa8 --- /dev/null +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -0,0 +1,676 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] +param () + +$script:dscModuleName = 'ConfigMgrCBDsc' +$script:dscResourceName = 'DSC_CMUserDiscovery' + +$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) + +Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'Stubs\ConfigMgrCBDscStub.psm1') -Force -WarningAction 'SilentlyContinue' + + # Import DscResource.Test Module +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.' +} + +# Variables used for each Initialize-TestEnvironment +$testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -TestType Unit + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +# Begin Testing +try +{ + InModuleScope $script:dscResourceName { + + Describe "ConfigMgrCBDsc - DSC_CMUserDiscovery\Get-TargetResource" -Tag 'Get' { + BeforeAll { + $getInput = @{ + SiteCode = 'Lab' + Enabled = $true + } + + $getCMDiscoveryEnabled = @{ + Props = @( + @{ + PropertyName = 'Enable Incremental Sync' + Value = 1 + } + @{ + PropertyName = 'Startup Schedule' + Value1 = '000120000015A000' + } + @{ + PropertyName = 'Full Sync Schedule' + Value1 = '000120000015A000' + } + @{ + PropertyName = 'Settings' + Value1 = 'Active' + } + ) + PropLists = @( + @{ + PropertyListName = 'AD Containers' + Values = @( + 'LDAP://OU=Test,DC=contoso,DC=com' + '0' + '1' + 'LDAP://OU=Test1,DC=contoso,DC=com' + '0' + '1' + ) + } + ) + } + + $getCMDiscoveryDisabled = @{ + Props = @( + @{ + PropertyName = 'Enable Incremental Sync' + Value = 0 + } + @{ + PropertyName = 'Startup Schedule' + Value1 = '000120000015A000' + } + @{ + PropertyName = 'Full Sync Schedule' + Value1 = '000120000015A000' + } + @{ + PropertyName = 'Settings' + Value1 = 'Active' + } + ) + PropLists = @( + @{ + PropertyListName = 'AD Containers' + Values = @( + 'LDAP://OU=Test,DC=contoso,DC=com' + '0' + '1' + 'LDAP://OU=Test1,DC=contoso,DC=com' + '0' + '1' + ) + } + ) + } + + $adContainersReturn = @( + 'LDAP://OU=Test,DC=contoso,DC=com' + 'LDAP://OU=Test1,DC=contoso,DC=com' + ) + + $intervalDays = @{ + Interval = 'Days' + Count = '7' + } + + $intervalHours = @{ + Interval = 'Hours' + Count = 5 + } + + $intervalNone = @{ + Interval = 'None' + Count = $null + } + + $cmScheduleHours = @{ + DayDuration = 0 + DaySpan = 0 + HourDuration = 0 + HourSpan = 1 + IsGMT = $false + MinuteDuration = 0 + MinuteSpan = 0 + } + + $cmScheduleMins = @{ + DayDuration = 0 + DaySpan = 0 + HourDuration = 0 + HourSpan = 0 + IsGMT = $false + MinuteDuration = 0 + MinuteSpan = 45 + } + + Mock -CommandName Import-ConfigMgrPowerShellModule + Mock -CommandName Set-Location + } + + Context 'When retrieving User Discovery settings' { + + It 'Should return desired result when delta schedule returns hour' { + Mock -CommandName Get-CMDiscoveryMethod -MockWith { $getCMDiscoveryEnabled } + Mock -CommandName ConvertTo-ScheduleInterval -MockWith { $intervalDays } + Mock -CommandName Convert-CMSchedule -MockWith { $cmScheduleHours } + + $result = Get-TargetResource @getInput + $result | Should -BeOfType System.Collections.HashTable + $result.SiteCode | Should -Be -ExpectedValue 'Lab' + $result.Enabled | Should -Be -ExpectedValue $true + $result.EnableDeltaDiscovery | Should -Be -ExpectedValue $true + $result.DeltaDiscoveryMins | Should -Be -ExpectedValue 60 + $result.ADContainers | Should -Be -ExpectedValue $adContainersReturn + $result.ScheduleInterval | Should -Be -ExpectedValue 'Days' + $result.ScheduleCount | Should -Be -ExpectedValue 7 + } + + It 'Should return desired result when delta schedule returns minutes' { + Mock -CommandName Get-CMDiscoveryMethod -MockWith { $getCMDiscoveryEnabled } + Mock -CommandName ConvertTo-ScheduleInterval -MockWith { $intervalHours } + Mock -CommandName Convert-CMSchedule -MockWith { $cmScheduleMins } + + $result = Get-TargetResource @getInput + $result | Should -BeOfType System.Collections.HashTable + $result.SiteCode | Should -Be -ExpectedValue 'Lab' + $result.Enabled | Should -Be -ExpectedValue $true + $result.EnableDeltaDiscovery | Should -Be -ExpectedValue $true + $result.DeltaDiscoveryMins | Should -Be -ExpectedValue 45 + $result.ADContainers | Should -Be -ExpectedValue $adContainersReturn + $result.ScheduleInterval | Should -Be -ExpectedValue 'Hours' + $result.ScheduleCount | Should -Be -ExpectedValue 5 + } + + It 'Should return desired result when delta discovery is disabled' { + Mock -CommandName Get-CMDiscoveryMethod -MockWith { $getCMDiscoveryDisabled } + Mock -CommandName ConvertTo-ScheduleInterval -MockWith { $intervalNone } + Mock -CommandName Convert-CMSchedule + + $result = Get-TargetResource @getInput + $result | Should -BeOfType System.Collections.HashTable + $result.SiteCode | Should -Be -ExpectedValue 'Lab' + $result.Enabled | Should -Be -ExpectedValue $true + $result.EnableDeltaDiscovery | Should -Be -ExpectedValue $false + $result.DeltaDiscoveryMins | Should -Be -ExpectedValue $null + $result.ADContainers | Should -Be -ExpectedValue $adContainersReturn + $result.ScheduleInterval | Should -Be -ExpectedValue 'None' + $result.ScheduleCount | Should -Be -ExpectedValue $null + } + } + } + + Describe "ConfigMgrCBDsc - DSC_CMUserDiscovery\Set-TargetResource" -Tag 'Set' { + BeforeAll { + $adContainersReturn = @( + 'LDAP://OU=Test,DC=contoso,DC=com' + 'LDAP://OU=Test1,DC=contoso,DC=com' + ) + + $getTargetResourceStandardReturn = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = [UInt32]60 + ADContainers = $adContainersReturn + ScheduleInterval = 'Days' + ScheduleCount = 7 + } + + $getTargetResourceStandardNoSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 60 + ADContainers = $adContainersReturn + ScheduleInterval = 'None' + ScheduleCount = $null + } + + $inputParamsHours = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Hours' + ScheduleCount = 8 + } + + $adContainersMismatch = 'LDAP://OU=Test2,DC=contoso,DC=com' + + $inputParamsADContainersMismatch = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainers = $adContainersMismatch + } + + Mock -CommandName Import-ConfigMgrPowerShellModule + Mock -CommandName Set-Location + Mock -CommandName Set-CMDiscoveryMethod + } + + Context 'When Set-TargetResource runs successfully' { + BeforeEach { + + $inputParamsDisable = @{ + SiteCode = 'Lab' + Enabled = $false + } + + $cmScheduleNull = @{ + DayDuration = 0 + HourDuration = 0 + IsGMT = $false + MinuteDuration = 0 + } + + $inputParamsDeltaMismatch = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 45 + } + + $inputParamsNoSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'None' + } + + $cmScheduleHours = @{ + DayDuration = 0 + DaySpan = 0 + HourDuration = 0 + HourSpan = 1 + IsGMT = $false + MinuteDuration = 0 + MinuteSpan = 0 + } + + $adContainersMismatch = 'LDAP://OU=Test2,DC=contoso,DC=com' + + $inputParamsADContainersInclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersMismatch + } + + $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + + $inputParamsADContainersExclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToExclude = $adContainersExclude + } + + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + } + + It 'Should call expected commands for disabling User Discovery' { + Mock -CommandName New-CMSchedule + + Set-TargetResource @inputParamsDisable + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands for delta schedule mismatch' { + Mock -CommandName New-CMSchedule + + Set-TargetResource @inputParamsDeltaMismatch + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands when setting schedule to none' { + Mock -CommandName New-CMSchedule -MockWith { $cmScheduleNull } + + Set-TargetResource @inputParamsNoSchedule + 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 New-CMSchedule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands schedule mismatch' { + Mock -CommandName New-CMSchedule -MockWith { $cmScheduleHours } -ParameterFilter { $RecurInterval -eq 'Hours' } + + Set-TargetResource @inputParamsHours + 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 New-CMSchedule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands for mismatch AD container' { + Mock -CommandName New-CMSchedule + + Set-TargetResource @inputParamsADContainersMismatch + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands for include AD container' { + Mock -CommandName New-CMSchedule + + Set-TargetResource @inputParamsADContainersInclude + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected commands for exclude AD container' { + Mock -CommandName New-CMSchedule + + Set-TargetResource @inputParamsADContainersExclude + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + } + + Context 'When running Set-TargetResource with no schedule return' { + BeforeEach { + $cmScheduleDays = @{ + DayDuration = 0 + DaySpan = 1 + HourDuration = 0 + HourSpan = 0 + IsGMT = $false + MinuteDuration = 0 + MinuteSpan = 0 + } + + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardNoSchedule } + } + + It 'Should call expected commands when current schedule set to none' { + Mock -CommandName New-CMSchedule -MockWith { $cmScheduleDays } + + Set-TargetResource @inputParamsHours + 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 New-CMSchedule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + } + + Context 'When running Set-TargetResource should throw' { + BeforeEach { + + $inputParamsBadSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Days' + } + + $inputDeltaThrow = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $false + DeltaDiscoveryMins = 60 + } + + $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' + + $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." + + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + } + + It 'Should call expected when specifying ScheduleInterval and not including ScheduleCount' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputParamsBadSchedule } | Should -Throw -ExpectedMessage $scheduleThrow + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + + It 'Should call expected when Set-CMDiscovery throws' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod -MockWith { throw } + + { Set-TargetResource @inputParamsADContainersMismatch } | 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 1 -Scope It + } + + It 'Should call expected when new-CMSchedule throws' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule -MockWith { throw } + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputParamsHours } | 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 New-CMSchedule -Exactly -Times 1 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + + It 'Should call expected commands when delta discover is disabled and specifying delta schedule' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputDeltaThrow } | Should -Throw -ExpectedMessage $deltaThrow + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + + It 'Should call expected when Get-TargetResource throws' { + Mock -CommandName Get-TargetResource -MockWith { throw } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputParamsHours } | 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + } + } + + Describe "ConfigMgrCBDsc - DSC_CMUserDiscovery\Test-TargetResource" -Tag 'Test' { + BeforeAll { + $adContainersReturn = @( + 'LDAP://OU=Test,DC=contoso,DC=com' + 'LDAP://OU=Test1,DC=contoso,DC=com' + ) + + $getTargetResourceStandardReturn = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = [UInt32]60 + ADContainers = $adContainersReturn + ScheduleInterval = 'Days' + ScheduleCount = 7 + } + + $getTargetResourceStandardNoSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 60 + ADContainers = $adContainersReturn + ScheduleInterval = 'None' + ScheduleCount = $null + } + + $inputParamsHours = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Hours' + ScheduleCount = 8 + } + + $inputParamsDisable = @{ + SiteCode = 'Lab' + Enabled = $false + } + + $inputParamsNoSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'None' + } + + Mock -CommandName Set-Location + Mock -CommandName Import-ConfigMgrPowerShellModule + } + + Context 'When running Test-TargetResource with returned schedule settings' { + BeforeEach { + $adContainersMismatch = 'LDAP://OU=Test2,DC=contoso,DC=com' + $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + + $iputAllParamsMatch = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 60 + ADContainers = $adContainersReturn + ScheduleInterval = 'Days' + ScheduleCount = 7 + } + + $inputParamsDeltaMismatch = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + DeltaDiscoveryMins = 45 + } + + $inputParamsADContainersMismatch = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainers = $adContainersMismatch + } + + $inputParamsADContainersMultiple = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainers = $adContainersMismatch + ADContainersToExclude = $adContainersExclude + } + + $inputParamsADContainersInclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersMismatch + } + + $inputParamsADContainersExclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToExclude = $adContainersExclude + } + + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + } + + It 'Should return desired result true when User Discovery settings match' { + Test-TargetResource @iputAllParamsMatch | Should -Be $true + } + + It 'Should return desired result false when delta schedule mismatch' { + Test-TargetResource @inputParamsDeltaMismatch | Should -Be $false + } + + It 'Should return desired result false when User Discovery schedules do not match' { + Test-TargetResource @inputParamsHours | Should -Be $false + } + + It 'Should return desired result false when User Discovery desires none schedule to be set' { + Test-TargetResource @inputParamsNoSchedule | Should -Be $false + } + + It 'Should return desired result false when User Discovery ADContainers are not correct add and remove' { + Test-TargetResource @inputParamsADContainersMismatch | Should -Be $false + } + + It 'Should return desired result false when User Discovery ADContainers and ADContainersExclude are specified' { + Test-TargetResource @inputParamsADContainersMultiple | Should -Be $false + } + + It 'Should return desired result false when User Discovery ADContainersInclude are not correct' { + Test-TargetResource @inputParamsADContainersInclude | Should -Be $false + } + + It 'Should return desired result false when User Discovery ADContainersExclude is not correct' { + Test-TargetResource @inputParamsADContainersExclude | Should -Be $false + } + + It 'Should return desired result false when User Discovery set to Enabled and expected value disabled' { + Test-TargetResource @inputParamsDisable | Should -Be $false + } + } + + Context 'When running Test-TargetResource with returned schedule settings of none' { + BeforeEach { + $inputParamsBadSchedule = @{ + SiteCode = 'Lab' + Enabled = $true + ScheduleInterval = 'Days' + } + + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardNoSchedule } + } + + It 'Should return desired result false when current state returns null schedule' { + Test-TargetResource @inputParamsDisable | Should -Be $false + } + + It 'Should return desired result true when current schedule and desired schedule are none' { + Test-TargetResource @inputParamsNoSchedule | Should -Be $true + } + + It 'Should return desired result false when current schedule is none and desired schedule is set' { + Test-TargetResource @inputParamsHours | Should -Be $false + } + + It 'Should return desired result false when input param is setting schedule is count is missing' { + Test-TargetResource @inputParamsBadSchedule | Should -Be $false + } + } + } + } +} +catch +{ + Invoke-TestCleanup +} From e496ea68ed1fa2bf3721f80613c5357e4dc88105 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 07:18:03 -0400 Subject: [PATCH 2/8] Resolving Grammar and Spacing comments --- .../DSC_CMUserDiscovery.psm1 | 21 +++++++------------ tests/Unit/CMUserDiscovery.tests.ps1 | 3 --- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 index 75eaf11..08a4262 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -183,7 +183,8 @@ function Set-TargetResource throw $script:localizedData.MissingDeltaDiscovery } - if (($PSBoundParameters.ContainsKey('ScheduleInterval') -and $PSBoundParameters.ScheduleInterval -ne 'None') -and (-not $PSBoundParameters.ContainsKey('ScheduleCount'))) + if (($PSBoundParameters.ContainsKey('ScheduleInterval') -and $PSBoundParameters.ScheduleInterval -ne 'None') -and + (-not $PSBoundParameters.ContainsKey('ScheduleCount'))) { throw $script:localizedData.IntervalCount } @@ -316,13 +317,10 @@ function Set-TargetResource Set-CMDiscoveryMethod -ActiveDirectoryUserDiscovery -SiteCode $SiteCode @buildingParams } } - else + elseif ($state.Enabled -eq $true) { - if ($state.Enabled -eq $true) - { - Write-Verbose -Message $script:localizedData.SetDisabled - Set-CMDiscoveryMethod -ActiveDirectoryUserDiscovery -Enabled $false -SiteCode $SiteCode - } + Write-Verbose -Message $script:localizedData.SetDisabled + Set-CMDiscoveryMethod -ActiveDirectoryUserDiscovery -Enabled $false -SiteCode $SiteCode } } catch @@ -513,13 +511,10 @@ function Test-TargetResource } } } - else + elseif ($state.Enabled -eq $true) { - if ($state.Enabled -eq $true) - { - Write-Verbose -Message $script:localizedData.TestDisabled - $result = $false - } + Write-Verbose -Message $script:localizedData.TestDisabled + $result = $false } Write-Verbose -Message ($script:localizedData.TestState -f $result) diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index 6f9aaa8..ad2fca4 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -33,7 +33,6 @@ function Invoke-TestCleanup try { InModuleScope $script:dscResourceName { - Describe "ConfigMgrCBDsc - DSC_CMUserDiscovery\Get-TargetResource" -Tag 'Get' { BeforeAll { $getInput = @{ @@ -416,7 +415,6 @@ try Context 'When running Set-TargetResource should throw' { BeforeEach { - $inputParamsBadSchedule = @{ SiteCode = 'Lab' Enabled = $true @@ -431,7 +429,6 @@ try } $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' - $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } From c86867c5cc84b6086fcc5bf88748046ebb82818f Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 08:43:22 -0400 Subject: [PATCH 3/8] Adding throw and warn, also to System Discovery --- .../DSC_CMSystemDiscovery.psm1 | 22 ++++++++++++ .../en-US/DSC_CMSystemDiscovery.strings.psd1 | 1 + .../DSC_CMUserDiscovery.psm1 | 22 ++++++++++++ .../en-US/DSC_CMUserDiscovery.strings.psd1 | 1 + tests/Unit/CMSystemDiscovery.tests.ps1 | 35 +++++++++++++++++++ tests/Unit/CMUserDiscovery.tests.ps1 | 34 ++++++++++++++++++ 6 files changed, 115 insertions(+) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 index bac6358..d714f51 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 @@ -228,6 +228,17 @@ function Set-TargetResource throw $script:localizedData.IntervalCount } + if ($ADContainersToInclude -and $ADContainersToExclude) + { + foreach ($item in $ADContainersToInclude) + { + if ($ADContainersToExclude -contains $item) + { + throw ($script:localizedData.ContainersInEx -f $item) + } + } + } + $paramsToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins','EnableFilteringExpiredLogon', 'TimeSinceLastLogonDays','EnableFilteringExpiredPassword','TimeSinceLastPasswordUpdateDays') @@ -525,6 +536,17 @@ function Test-TargetResource } } + if ($ADContainersToInclude -and $ADContainersToExclude) + { + foreach ($item in $ADContainersToInclude) + { + if ($ADContainersToExclude -contains $item) + { + Write-Warning -Message ($script:localizedData.ContainersInEx -f $item) + } + } + } + if (($ADContainers) -or ($ADContainersToInclude)) { if ($ADContainers) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 index 4fbcd76..a65e169 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 @@ -15,4 +15,5 @@ ConvertFrom-StringData @' SetDisabled = Setting System Discovery to disabled. MissingDeltaDiscovery = When changing delta schedule, delta schedule must be enabled. ADIgnore = ADContainers was specified, ADContainersInclude and ADContainersExclude will be ignored. + ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. '@ diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 index 08a4262..cfe44b5 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -189,6 +189,17 @@ function Set-TargetResource throw $script:localizedData.IntervalCount } + if ($ADContainersToInclude -and $ADContainersToExclude) + { + foreach ($item in $ADContainersToInclude) + { + if ($ADContainersToExclude -contains $item) + { + throw ($script:localizedData.ContainersInEx -f $item) + } + } + } + $paramsToCheck = @('Enabled','EnableDeltaDiscovery','DeltaDiscoveryMins') foreach ($param in $PSBoundParameters.GetEnumerator()) @@ -449,6 +460,17 @@ function Test-TargetResource } } + if ($ADContainersToInclude -and $ADContainersToExclude) + { + foreach ($item in $ADContainersToInclude) + { + if ($ADContainersToExclude -contains $item) + { + Write-Warning -Message ($script:localizedData.ContainersInEx -f $item) + } + } + } + if (($ADContainers) -or ($ADContainersToInclude)) { if ($ADContainers) diff --git a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 index 73f700d..20e0260 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 @@ -15,4 +15,5 @@ ConvertFrom-StringData @' AddADContainer = Adding AD Container: {0}. RemoveADContainer = Removing AD Container: {0}. SetDisabled = Setting User Discovery to disabled. + ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. '@ diff --git a/tests/Unit/CMSystemDiscovery.tests.ps1 b/tests/Unit/CMSystemDiscovery.tests.ps1 index 94784d1..4f83d11 100644 --- a/tests/Unit/CMSystemDiscovery.tests.ps1 +++ b/tests/Unit/CMSystemDiscovery.tests.ps1 @@ -482,6 +482,17 @@ try DeltaDiscoveryMins = 60 } + $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + + $inputParamsIncludeExcludeThrow = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersExclude + ADContainersToExclude = $adContainersExclude + } + + $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -498,6 +509,19 @@ try Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It } + It 'Should call expected when specifying the same container in include and exclude' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputParamsIncludeExcludeThrow } | Should -Throw -ExpectedMessage $excludeThrow + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + It 'Should call expected when Set-CMDiscovery throws' { Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } Mock -CommandName New-CMSchedule @@ -660,6 +684,13 @@ try ADContainersToExclude = $adContainersExclude } + $inputParamsIncludeExclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersExclude + ADContainersToExclude = $adContainersExclude + } + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -667,6 +698,10 @@ try Test-TargetResource @iputAllParamsMatch | Should -Be $true } + It 'Should return desired result false when ad containers mismatch' { + Test-TargetResource @inputParamsIncludeExclude | Should -Be $false + } + It 'Should return desired result false when delta schedule mismatch' { Test-TargetResource @inputParamsDeltaMismatch | Should -Be $false } diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index ad2fca4..fc6994f 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -428,8 +428,18 @@ try DeltaDiscoveryMins = 60 } + $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + + $inputParamsIncludeExcludeThrow = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersExclude + ADContainersToExclude = $adContainersExclude + } + $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." + $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -447,6 +457,19 @@ try Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It } + It 'Should call expected when specifying the same container in include and exclude' { + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @inputParamsIncludeExcludeThrow } | Should -Throw -ExpectedMessage $excludeThrow + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + It 'Should call expected when Set-CMDiscovery throws' { Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } Mock -CommandName New-CMSchedule @@ -597,6 +620,13 @@ try ADContainersToExclude = $adContainersExclude } + $inputParamsIncludeExclude = @{ + SiteCode = 'Lab' + Enabled = $true + ADContainersToInclude = $adContainersExclude + ADContainersToExclude = $adContainersExclude + } + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -604,6 +634,10 @@ try Test-TargetResource @iputAllParamsMatch | Should -Be $true } + It 'Should return desired result false when ad containers mismatch' { + Test-TargetResource @inputParamsIncludeExclude | Should -Be $false + } + It 'Should return desired result false when delta schedule mismatch' { Test-TargetResource @inputParamsDeltaMismatch | Should -Be $false } From ff7074f77c0aacf72d4fb7824e108f59119ea569 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 08:45:37 -0400 Subject: [PATCH 4/8] Updated Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c4bb68..a44604b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed newline in the CMIniFile resource. - Removed WSUS top level feature. - Added Security Scopes to CMDistributionGroup Resource +- Updated CMSystemDiscovery Resource to add needed throw and warn messages. ### Removed From 14dd7f306c6aded037763c79235bf169cdebd121 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 10:46:19 -0400 Subject: [PATCH 5/8] Added throws and warns to user/system disco --- .../DSC_CMSystemDiscovery.psm1 | 15 +++++++- .../en-US/DSC_CMSystemDiscovery.strings.psd1 | 1 + .../DSC_CMUserDiscovery.psm1 | 12 ++++++ .../en-US/DSC_CMUserDiscovery.strings.psd1 | 1 + tests/Unit/CMSystemDiscovery.tests.ps1 | 38 +++++++++++++++++++ tests/Unit/CMUserDiscovery.tests.ps1 | 38 +++++++++++++++++++ 6 files changed, 104 insertions(+), 1 deletion(-) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 index d714f51..055a345 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 @@ -223,11 +223,18 @@ function Set-TargetResource throw $script:localizedData.MissingDeltaDiscovery } - if (($PSBoundParameters.ContainsKey('ScheduleInterval') -and $PSBoundParameters.ScheduleInterval -ne 'None') -and (-not $PSBoundParameters.ContainsKey('ScheduleCount'))) + if (($PSBoundParameters.ContainsKey('ScheduleInterval') -and $PSBoundParameters.ScheduleInterval -ne 'None') -and + (-not $PSBoundParameters.ContainsKey('ScheduleCount'))) { throw $script:localizedData.IntervalCount } + if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) + { + throw $script:localizedData.DeltaNoInterval + } + if ($ADContainersToInclude -and $ADContainersToExclude) { foreach ($item in $ADContainersToInclude) @@ -536,6 +543,12 @@ function Test-TargetResource } } + if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) + { + Write-Warning -Message $script:localizedData.DeltaNoInterval + } + if ($ADContainersToInclude -and $ADContainersToExclude) { foreach ($item in $ADContainersToInclude) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 index a65e169..0f949f7 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 @@ -16,4 +16,5 @@ ConvertFrom-StringData @' MissingDeltaDiscovery = When changing delta schedule, delta schedule must be enabled. ADIgnore = ADContainers was specified, ADContainersInclude and ADContainersExclude will be ignored. ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. + DeltaNoInterval = DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery. '@ diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 index cfe44b5..1ac5e35 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -189,6 +189,12 @@ function Set-TargetResource throw $script:localizedData.IntervalCount } + if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) + { + throw $script:localizedData.DeltaNoInterval + } + if ($ADContainersToInclude -and $ADContainersToExclude) { foreach ($item in $ADContainersToInclude) @@ -460,6 +466,12 @@ function Test-TargetResource } } + if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) + { + Write-Warning -Message $script:localizedData.DeltaNoInterval + } + if ($ADContainersToInclude -and $ADContainersToExclude) { foreach ($item in $ADContainersToInclude) diff --git a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 index 20e0260..07ab909 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 @@ -16,4 +16,5 @@ ConvertFrom-StringData @' RemoveADContainer = Removing AD Container: {0}. SetDisabled = Setting User Discovery to disabled. ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. + DeltaNoInterval = DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery. '@ diff --git a/tests/Unit/CMSystemDiscovery.tests.ps1 b/tests/Unit/CMSystemDiscovery.tests.ps1 index 4f83d11..21d7d43 100644 --- a/tests/Unit/CMSystemDiscovery.tests.ps1 +++ b/tests/Unit/CMSystemDiscovery.tests.ps1 @@ -484,6 +484,12 @@ try $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + $enableDeltaThrow = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + } + $inputParamsIncludeExcludeThrow = @{ SiteCode = 'Lab' Enabled = $true @@ -492,6 +498,7 @@ try } $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." + $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -522,6 +529,19 @@ try Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It } + It 'Should call expected when enabling delta discovery without specifying an interval' { + Mock -CommandName Get-TargetResource -MockWith { $inputDeltaThrow } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @enableDeltaThrow } | Should -Throw -ExpectedMessage $enableDeltaThrowMsg + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + It 'Should call expected when Set-CMDiscovery throws' { Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } Mock -CommandName New-CMSchedule @@ -743,6 +763,18 @@ try ScheduleInterval = 'Days' } + $disableDelta = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $false + } + + $enableDelta = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + } + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardNoSchedule } } @@ -761,6 +793,12 @@ try It 'Should return desired result false when input param is setting schedule is count is missing' { Test-TargetResource @inputParamsBadSchedule | Should -Be $false } + + It 'Should return desired result false when enabling delta discovery without interval' { + Mock -CommandName Get-TargetResource -MockWith { $disableDelta } + + Test-TargetResource @enableDelta | Should -Be $false + } } } } diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index fc6994f..5faec9e 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -430,6 +430,12 @@ try $adContainersExclude = 'LDAP://OU=Test1,DC=contoso,DC=com' + $enableDeltaThrow = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + } + $inputParamsIncludeExcludeThrow = @{ SiteCode = 'Lab' Enabled = $true @@ -440,6 +446,7 @@ try $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." + $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } } @@ -470,6 +477,19 @@ try Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It } + It 'Should call expected when enabling delta discovery without specifying an interval' { + Mock -CommandName Get-TargetResource -MockWith { $inputDeltaThrow } + Mock -CommandName New-CMSchedule + Mock -CommandName Set-CMDiscoveryMethod + + { Set-TargetResource @enableDeltaThrow } | Should -Throw -ExpectedMessage $enableDeltaThrowMsg + 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 New-CMSchedule -Exactly -Times 0 -Scope It + Assert-MockCalled Set-CMDiscoveryMethod -Exactly -Times 0 -Scope It + } + It 'Should call expected when Set-CMDiscovery throws' { Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } Mock -CommandName New-CMSchedule @@ -679,6 +699,18 @@ try ScheduleInterval = 'Days' } + $disableDelta = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $false + } + + $enableDelta = @{ + SiteCode = 'Lab' + Enabled = $true + EnableDeltaDiscovery = $true + } + Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardNoSchedule } } @@ -697,6 +729,12 @@ try It 'Should return desired result false when input param is setting schedule is count is missing' { Test-TargetResource @inputParamsBadSchedule | Should -Be $false } + + It 'Should return desired result false when enabling delta discovery without interval' { + Mock -CommandName Get-TargetResource -MockWith { $disableDelta } + + Test-TargetResource @enableDelta | Should -Be $false + } } } } From 4ef57bdff00220f13558a922eff34bfdf88f7785 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 12:42:37 -0400 Subject: [PATCH 6/8] Resolving PR Comments --- .../DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 | 4 ++-- .../en-US/DSC_CMSystemDiscovery.strings.psd1 | 2 +- .../DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 | 4 ++-- .../en-US/DSC_CMUserDiscovery.strings.psd1 | 2 +- tests/Unit/CMUserDiscovery.tests.ps1 | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 index 055a345..b6e1e72 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 @@ -229,7 +229,7 @@ function Set-TargetResource throw $script:localizedData.IntervalCount } - if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) { throw $script:localizedData.DeltaNoInterval @@ -543,7 +543,7 @@ function Test-TargetResource } } - if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) { Write-Warning -Message $script:localizedData.DeltaNoInterval diff --git a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 index 0f949f7..de5f8ac 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/en-US/DSC_CMSystemDiscovery.strings.psd1 @@ -15,6 +15,6 @@ ConvertFrom-StringData @' SetDisabled = Setting System Discovery to disabled. MissingDeltaDiscovery = When changing delta schedule, delta schedule must be enabled. ADIgnore = ADContainers was specified, ADContainersInclude and ADContainersExclude will be ignored. - ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. + ContainersInEx = ADContainersToExclude and ADContainersToInclude contain to same entry {0}, remove from one of the arrays. DeltaNoInterval = DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery. '@ diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 index 1ac5e35..e37013b 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -189,7 +189,7 @@ function Set-TargetResource throw $script:localizedData.IntervalCount } - if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) { throw $script:localizedData.DeltaNoInterval @@ -466,7 +466,7 @@ function Test-TargetResource } } - if (($EnableDeltaDiscovery -eq $true -and $State.EnableDeltaDiscovery -eq $false) -and + if (($EnableDeltaDiscovery -eq $true -and $state.EnableDeltaDiscovery -eq $false) -and (-not $PSBoundParameters.ContainsKey('DeltaDiscoveryMins'))) { Write-Warning -Message $script:localizedData.DeltaNoInterval diff --git a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 index 07ab909..d000ce3 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 +++ b/source/DSCResources/DSC_CMUserDiscovery/en-US/DSC_CMUserDiscovery.strings.psd1 @@ -15,6 +15,6 @@ ConvertFrom-StringData @' AddADContainer = Adding AD Container: {0}. RemoveADContainer = Removing AD Container: {0}. SetDisabled = Setting User Discovery to disabled. - ContainersInEx = ADContainersToToExclude and ADContainersToToInclude contain to same entry {0}, remove from one of the arrays. + ContainersInEx = ADContainersToExclude and ADContainersToInclude contain to same entry {0}, remove from one of the arrays. DeltaNoInterval = DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery. '@ diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index 5faec9e..5edb81d 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -253,7 +253,6 @@ try Context 'When Set-TargetResource runs successfully' { BeforeEach { - $inputParamsDisable = @{ SiteCode = 'Lab' Enabled = $false From dbf37cd6abbfb7316fdf80dfaaa53f9ab5eac3c7 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 13:24:46 -0400 Subject: [PATCH 7/8] Resolving PR COmments --- .../DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 | 2 +- .../DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 | 2 +- tests/Unit/CMSystemDiscovery.tests.ps1 | 2 +- tests/Unit/CMUserDiscovery.tests.ps1 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 index b6e1e72..8b6441f 100644 --- a/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 +++ b/source/DSCResources/DSC_CMSystemDiscovery/DSC_CMSystemDiscovery.psm1 @@ -524,7 +524,7 @@ function Test-TargetResource { if ($ScheduleInterval -ne 'None' -and -not $PSBoundParameters.ContainsKey('ScheduleCount')) { - Write-Verbose -Message $script:localizedData.IntervalCount + Write-Warning -Message $script:localizedData.IntervalCount $result = $false } else diff --git a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 index e37013b..c464324 100644 --- a/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 +++ b/source/DSCResources/DSC_CMUserDiscovery/DSC_CMUserDiscovery.psm1 @@ -447,7 +447,7 @@ function Test-TargetResource { if ($ScheduleInterval -ne 'None' -and -not $PSBoundParameters.ContainsKey('ScheduleCount')) { - Write-Verbose -Message $script:localizedData.IntervalCount + Write-Warning -Message $script:localizedData.IntervalCount $result = $false } else diff --git a/tests/Unit/CMSystemDiscovery.tests.ps1 b/tests/Unit/CMSystemDiscovery.tests.ps1 index 21d7d43..feaedfb 100644 --- a/tests/Unit/CMSystemDiscovery.tests.ps1 +++ b/tests/Unit/CMSystemDiscovery.tests.ps1 @@ -497,7 +497,7 @@ try ADContainersToExclude = $adContainersExclude } - $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." + $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry LDAP://OU=Test1,DC=contoso,DC=com, remove from one of the arrays." $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index 5edb81d..e183f05 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -444,7 +444,7 @@ try $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." - $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry $adContainersExclude, remove from one of the arrays." + $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry LDAP://OU=Test1,DC=contoso,DC=com, remove from one of the arrays." $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } From 3f3cf7d99c97c5e743e97320cc25c39dfb195f30 Mon Sep 17 00:00:00 2001 From: Nicholas Ellis Date: Fri, 24 Jul 2020 13:51:09 -0400 Subject: [PATCH 8/8] Fixing Pester Issue --- tests/Unit/CMSystemDiscovery.tests.ps1 | 2 +- tests/Unit/CMUserDiscovery.tests.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/CMSystemDiscovery.tests.ps1 b/tests/Unit/CMSystemDiscovery.tests.ps1 index feaedfb..5576068 100644 --- a/tests/Unit/CMSystemDiscovery.tests.ps1 +++ b/tests/Unit/CMSystemDiscovery.tests.ps1 @@ -497,7 +497,7 @@ try ADContainersToExclude = $adContainersExclude } - $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry LDAP://OU=Test1,DC=contoso,DC=com, remove from one of the arrays." + $excludeThrow = "ADContainersToExclude and ADContainersToInclude contain to same entry $adContainersExclude, remove from one of the arrays." $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn } diff --git a/tests/Unit/CMUserDiscovery.tests.ps1 b/tests/Unit/CMUserDiscovery.tests.ps1 index e183f05..4d98c73 100644 --- a/tests/Unit/CMUserDiscovery.tests.ps1 +++ b/tests/Unit/CMUserDiscovery.tests.ps1 @@ -444,7 +444,7 @@ try $deltaThrow = 'When changing delta schedule, delta schedule must be enabled.' $scheduleThrow = "Invalid parameter usage specifying an Interval and didn't specify count." - $excludeThrow = "ADContainersToToExclude and ADContainersToToInclude contain to same entry LDAP://OU=Test1,DC=contoso,DC=com, remove from one of the arrays." + $excludeThrow = "ADContainersToExclude and ADContainersToInclude contain to same entry $adContainersExclude, remove from one of the arrays." $enableDeltaThrowMsg = "DeltaDiscoveryMins is not specified, specify DeltaDiscoveryMins when enabling Delta Discovery." Mock -CommandName Get-TargetResource -MockWith { $getTargetResourceStandardReturn }