diff --git a/CHANGELOG.md b/CHANGELOG.md index 5124f752..dbe182c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new resource to manage NS records - DnsRecordNsScoped - Added new resource to manage scoped NS records +- DnsServerDsSetting + - Added new resource to manage AD-integrated DNS settings ### Changed diff --git a/source/Classes/001.ResourceBase.ps1 b/source/Classes/001.ResourceBase.ps1 index b0b33380..0fd5f54e 100644 --- a/source/Classes/001.ResourceBase.ps1 +++ b/source/Classes/001.ResourceBase.ps1 @@ -3,7 +3,7 @@ A class with methods that are equal for all class-based resources. .DESCRIPTION - A class with methods that are equal for all class-based resources. + A class with methods that are equal for all class-based resources. .NOTES This class should not contain any DSC properties. @@ -81,22 +81,22 @@ class ResourceBase if ($propertiesNotInDesiredState) { - $setDnsServerRecursionParameters = $this.GetDesiredStateForSplatting($propertiesNotInDesiredState) + $propertiesToModify = $this.GetDesiredStateForSplatting($propertiesNotInDesiredState) - $setDnsServerRecursionParameters.Keys | ForEach-Object -Process { - Write-Verbose -Message ($this.localizedData.SetProperty -f $_, $setDnsServerRecursionParameters.$_, $this.GetType().Name) + $propertiesToModify.Keys | ForEach-Object -Process { + Write-Verbose -Message ($this.localizedData.SetProperty -f $_, $propertiesToModify.$_, $this.GetType().Name) } if ($this.DnsServer -ne 'localhost') { - $setDnsServerRecursionParameters['ComputerName'] = $this.DnsServer + $propertiesToModify['ComputerName'] = $this.DnsServer } <# Call the Modify() method with the properties that should be enforced and was not in desired state. #> - $this.Modify($setDnsServerRecursionParameters) + $this.Modify($propertiesToModify) } else { @@ -146,7 +146,7 @@ class ResourceBase <# Remove properties that have $null as the value, and remove read - properties so that there is no chance to campare those. + properties so that there is no chance to compare those. #> @($desiredState.Keys) | ForEach-Object -Process { $isReadProperty = $this.GetType().GetMember($_).CustomAttributes.Where( { $_.NamedArguments.MemberName -eq 'NotConfigurable' }).NamedArguments.TypedValue.Value -eq $true diff --git a/source/Classes/003.DnsServerDsSetting.ps1 b/source/Classes/003.DnsServerDsSetting.ps1 new file mode 100644 index 00000000..3b235495 --- /dev/null +++ b/source/Classes/003.DnsServerDsSetting.ps1 @@ -0,0 +1,163 @@ +<# + .SYNOPSIS + The DnsServerDsSetting DSC resource manages DNS Active Directory settings + on a Microsoft Domain Name System (DNS) server. + + .DESCRIPTION + The DnsServerDsSetting DSC resource manages DNS Active Directory settings + on a Microsoft Domain Name System (DNS) server. + + .PARAMETER DnsServer + The host name of the Domain Name System (DNS) server, or use `'localhost'` + for the current node. + + .PARAMETER DirectoryPartitionAutoEnlistInterval + Specifies the interval, during which a DNS server tries to enlist itself + in a DNS domain partition and DNS forest partition, if it is not already + enlisted. We recommend that you limit this value to the range one hour to + 180 days, inclusive, but you can use any value. We recommend that you set + the default value to one day. You must set the value 0 (zero) as a flag + value for the default value. However, you can allow zero and treat it + literally. + + .PARAMETER LazyUpdateInterval + Specifies a value, in seconds, to determine how frequently the DNS server + submits updates to the directory server without specifying the + LDAP_SERVER_LAZY_COMMIT_OID control ([MS-ADTS] section 3.1.1.3.4.1.7) at + the same time that it processes DNS dynamic update requests. We recommend + that you limit this value to the range 0x00000000 to 0x0000003c. You must + set the default value to 0x00000003. You must set the value zero to + indicate that the DNS server does not specify the + LDAP_SERVER_LAZY_COMMIT_OID control at the same time that it processes + DNS dynamic update requests. For more information about + LDAP_SERVER_LAZY_COMMIT_OID, see LDAP_SERVER_LAZY_COMMIT_OID control + code. The LDAP_SERVER_LAZY_COMMIT_OID control instructs the DNS server + to return the results of a directory service modification command after + it is completed in memory but before it is committed to disk. In this + way, the server can return results quickly and save data to disk without + sacrificing performance. The DNS server must send this control only to + the directory server that is attached to an LDAP update that the DNS + server initiates in response to a DNS dynamic update request. If the + value is nonzero, LDAP updates that occur during the processing of DNS + dynamic update requests must not specify the LDAP_SERVER_LAZY_COMMIT_OID + control if a period of less than DsLazyUpdateInterval seconds has passed + since the last LDAP update that specifies this control. If a period that + is greater than DsLazyUpdateInterval seconds passes, during which time + the DNS server does not perform an LDAP update that specifies this + control, the DNS server must specify this control on the next update. + + .PARAMETER MinimumBackgroundLoadThreads + Specifies the minimum number of background threads that the DNS server + uses to load zone data from the directory service. You must limit this + value to the range 0x00000000 to 0x00000005, inclusive. You must set the + default value to 0x00000001, and you must treat the value zero as a flag + value for the default value. + + .PARAMETER PollingInterval + Specifies how frequently the DNS server polls Active Directory Domain + Services (AD DS) for changes in Active Directory-integrated zones. You + must limit the value to the range 30 seconds to 3,600 seconds, inclusive. + + .PARAMETER RemoteReplicationDelay + Specifies the minimum interval, in seconds, that the DNS server waits + between the time that it determines that a single object has changed on + a remote directory server, to the time that it tries to replicate a + single object change. You must limit the value to the range 0x00000005 + to 0x00000E10, inclusive. You must set the default value to 0x0000001E, + and you must treat the value zero as a flag value for the default value. + + .PARAMETER TombstoneInterval + Specifies the amount of time that DNS keeps tombstoned records alive in + Active Directory. We recommend that you limit this value to the range + three days to eight weeks, inclusive, but you can set it to any value in + the range 82 hours to 8 weeks. We recommend that you set the default + value to 14 days and treat the value zero as a flag value for the + default. However, you can allow the value zero and treat it literally. + At 2:00 A.M. local time every day, the DNS server must search all + directory service zones for nodes that have the Active Directory + dnsTombstoned attribute set to True, and for a directory service + EntombedTime (section 2.2.2.2.3.23 of MS-DNSP) value that is greater + than previous directory service DSTombstoneInterval seconds. You must + permanently delete all such nodes from the directory server. +#> + +[DscResource()] +class DnsServerDsSetting : ResourceBase +{ + [DscProperty(Key)] + [System.String] + $DnsServer + + [DscProperty()] + [System.String] + $DirectoryPartitionAutoEnlistInterval + + [DscProperty()] + [Nullable[System.UInt32]] + $LazyUpdateInterval + + [DscProperty()] + [Nullable[System.UInt32]] + $MinimumBackgroundLoadThreads + + [DscProperty()] + [System.String] + $PollingInterval + + [DscProperty()] + [Nullable[System.UInt32]] + $RemoteReplicationDelay + + [DscProperty()] + [System.String] + $TombstoneInterval + + [DnsServerDsSetting] Get() + { + # Call the base method to return the properties. + return ([ResourceBase] $this).Get() + } + + # Base method Get() call this method to get the current state as a CimInstance. + [Microsoft.Management.Infrastructure.CimInstance] GetCurrentState([System.Collections.Hashtable] $properties) + { + return (Get-DnsServerDsSetting @properties) + } + + [void] Set() + { + # Call the base method to enforce the properties. + ([ResourceBase] $this).Set() + } + + <# + Base method Set() call this method with the properties that should be + enforced and that are not in desired state. + #> + [void] Modify([System.Collections.Hashtable] $properties) + { + Set-DnsServerDsSetting @properties + } + + [System.Boolean] Test() + { + # Call the base method to test all of the properties that should be enforced. + return ([ResourceBase] $this).Test() + } + + hidden [void] AssertProperties() + { + @( + 'DirectoryPartitionAutoEnlistInterval', + 'TombstoneInterval' + ) | ForEach-Object -Process { + $valueToConvert = $this.$_ + + # Only evaluate properties that have a value. + if ($null -ne $valueToConvert) + { + Assert-TimeSpan -PropertyName $_ -Value $valueToConvert -Minimum '0.00:00:00' + } + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/1-DnsServerDsSetting_DirectoryPartitionAutoEnlistInterval_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/1-DnsServerDsSetting_DirectoryPartitionAutoEnlistInterval_Config.ps1 new file mode 100644 index 00000000..6fa1c845 --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/1-DnsServerDsSetting_DirectoryPartitionAutoEnlistInterval_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID a822d4a5-c575-45f9-ba1a-aaea21a43c00 + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the Directory Partition Auto Enlist + Interval in Active Directory. +#> + +configuration DnsServerDsSetting_DirectoryPartitionAutoEnlistInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/2-DnsServerDsSetting_LazyUpdateInterval_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/2-DnsServerDsSetting_LazyUpdateInterval_Config.ps1 new file mode 100644 index 00000000..cb881bcb --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/2-DnsServerDsSetting_LazyUpdateInterval_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID 57cdc411-d737-4dc2-9ede-86ffea596094 + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the Lazy Update + Interval in Active Directory. +#> + +configuration DnsServerDsSetting_LazyUpdateInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + LazyUpdateInterval = 3 + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/3-DnsServerDsSetting_MinimumBackgroundLoadThreads_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/3-DnsServerDsSetting_MinimumBackgroundLoadThreads_Config.ps1 new file mode 100644 index 00000000..990d561c --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/3-DnsServerDsSetting_MinimumBackgroundLoadThreads_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID 0feef9f4-1d8f-4d56-be15-7599cf2ed3b2 + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the Minimum Background Load Threads + in Active Directory. +#> + +configuration DnsServerDsSetting_MinimumBackgroundLoadThreads_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + MinimumBackgroundLoadThreads = 1 + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/4-DnsServerDsSetting_PollingInterval_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/4-DnsServerDsSetting_PollingInterval_Config.ps1 new file mode 100644 index 00000000..3270677c --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/4-DnsServerDsSetting_PollingInterval_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID a3fe8c61-350d-4ac3-b9ac-d4ebcb6a5aaf + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the Polling + Interval in Active Directory. +#> + +configuration DnsServerDsSetting_PollingInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + PollingInterval = 180 + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/5-DnsServerDsSetting_RemoteReplicationDelay_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/5-DnsServerDsSetting_RemoteReplicationDelay_Config.ps1 new file mode 100644 index 00000000..2e682224 --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/5-DnsServerDsSetting_RemoteReplicationDelay_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID d251e713-716d-4305-a7e0-136ae5083ad6 + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the Remote Replication Delay + in Active Directory. +#> + +configuration DnsServerDsSetting_RemoteReplicationDelay_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + RemoteReplicationDelay = 30 + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/6-DnsServerDsSetting_TombstoneInterval_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/6-DnsServerDsSetting_TombstoneInterval_Config.ps1 new file mode 100644 index 00000000..82e0826f --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/6-DnsServerDsSetting_TombstoneInterval_Config.ps1 @@ -0,0 +1,54 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID de58ff19-8b02-4bf9-8742-a5846e44599c + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will change the DNS Tombstone + Interval in Active Directory. +#> + +configuration DnsServerDsSetting_TombstoneInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + TombstoneInterval = '14.00:00:00' + } + } +} diff --git a/source/Examples/Resources/DnsServerDsSetting/7-DnsServerDsSetting_All_Config.ps1 b/source/Examples/Resources/DnsServerDsSetting/7-DnsServerDsSetting_All_Config.ps1 new file mode 100644 index 00000000..74b9b9d5 --- /dev/null +++ b/source/Examples/Resources/DnsServerDsSetting/7-DnsServerDsSetting_All_Config.ps1 @@ -0,0 +1,59 @@ +<#PSScriptInfo + +.VERSION 1.0.0 + +.GUID b20e9d5c-ba74-4686-9293-08077e53cb8f + +.AUTHOR DSC Community + +.COMPANYNAME DSC Community + +.COPYRIGHT DSC Community contributors. All rights reserved. + +.TAGS DSCConfiguration + +.LICENSEURI https://github.com/dsccommunity/DnsServerDsc/blob/main/LICENSE + +.PROJECTURI https://github.com/dsccommunity/DnsServerDsc + +.ICONURI https://dsccommunity.org/images/DSC_Logo_300p.png + +.EXTERNALMODULEDEPENDENCIES + +.REQUIREDSCRIPTS + +.EXTERNALSCRIPTDEPENDENCIES + +.RELEASENOTES +First version. + +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core + +#> + +#Requires -Module DnsServerDsc + +<# + .DESCRIPTION + This configuration will set all Active Directory-based DNS settings on + the specified server. +#> + +configuration DnsServerDsSetting_All_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node localhost + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } +} diff --git a/source/en-US/DnsServerDsSetting.strings.psd1 b/source/en-US/DnsServerDsSetting.strings.psd1 new file mode 100644 index 00000000..82c8af98 --- /dev/null +++ b/source/en-US/DnsServerDsSetting.strings.psd1 @@ -0,0 +1,14 @@ +<# + .SYNOPSIS + The localized resource strings in English (en-US) for the + resource DnsServerDsSetting. +#> + +ConvertFrom-StringData @' + GetCurrentState = Getting the current state of the directory services settings for the server '{0}'. (DSDS0001) + TestDesiredState = Determining the current state of the directory services settings for the server '{0}'. (DSDS0002) + SetDesiredState = Setting the desired state for the directory services settings for the server '{0}'. (DSDS0003) + NotInDesiredState = The directory services settings for the server '{0}' is not in desired state. (DSDS0004) + InDesiredState = The directory services settings for the server '{0}' is in desired state. (DSDS0005) + SetProperty = The directory services property '{0}' will be set to '{1}'. (DSDS0006) +'@ diff --git a/tests/Integration/Classes/DnsServerDsSetting.Integration.Tests.ps1 b/tests/Integration/Classes/DnsServerDsSetting.Integration.Tests.ps1 new file mode 100644 index 00000000..48db02d2 --- /dev/null +++ b/tests/Integration/Classes/DnsServerDsSetting.Integration.Tests.ps1 @@ -0,0 +1,367 @@ +$script:dscModuleName = 'DnsServerDsc' +$script:dscResourceName = 'DnsServerDsSetting' + +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 'Integration' + +try +{ + $configFile = Join-Path -Path $PSScriptRoot -ChildPath "$($script:dscResourceName).config.ps1" + . $configFile + + Describe "$($script:dscResourceName)_Integration" { + BeforeAll { + $resourceId = "[$($script:dscResourceName)]Integration_Test" + } + + $configurationName = "$($script:dscResourceName)_DirectoryPartitionAutoEnlistInterval_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.DirectoryPartitionAutoEnlistInterval | Should -Be '1.00:00:00' + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_LazyUpdateInterval_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.LazyUpdateInterval | Should -Be 3 + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_MinimumBackgroundLoadThreads_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.MinimumBackgroundLoadThreads | Should -Be 1 + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_PollingInterval_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.PollingInterval | Should -Be 180 + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_RemoteReplicationDelay_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.RemoteReplicationDelay | Should -Be 30 + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_TombstoneInterval_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.TombstoneInterval | Should -Be '14.00:00:00' + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + + $configurationName = "$($script:dscResourceName)_All_Config" + + Context ('When using configuration {0}' -f $configurationName) { + It 'Should compile and apply the MOF without throwing' { + { + $configurationParameters = @{ + OutputPath = $TestDrive + ConfigurationData = $ConfigurationData + } + + & $configurationName @configurationParameters + + $startDscConfigurationParameters = @{ + Path = $TestDrive + ComputerName = 'localhost' + Wait = $true + Verbose = $true + Force = $true + ErrorAction = 'Stop' + } + + Start-DscConfiguration @startDscConfigurationParameters + } | Should -Not -Throw + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { + $script:currentConfiguration = Get-DscConfiguration -Verbose -ErrorAction Stop + } | Should -Not -Throw + } + + It 'Should have set the resource and all the parameters should match' { + $resourceCurrentState = $script:currentConfiguration | Where-Object -FilterScript { + $_.ConfigurationName -eq $configurationName ` + -and $_.ResourceId -eq $resourceId + } + + $resourceCurrentState.DirectoryPartitionAutoEnlistInterval | Should -Be '1.00:00:00' + $resourceCurrentState.LazyUpdateInterval | Should -Be 3 + $resourceCurrentState.MinimumBackgroundLoadThreads | Should -Be 1 + $resourceCurrentState.PollingInterval | Should -Be 180 + $resourceCurrentState.RemoteReplicationDelay | Should -Be 30 + $resourceCurrentState.TombstoneInterval | Should -Be '14.00:00:00' + } + + It 'Should return ''True'' when Test-DscConfiguration is run' { + Test-DscConfiguration -Verbose | Should -Be 'True' + } + } + + Wait-ForIdleLcm -Clear + } +} +finally +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} diff --git a/tests/Integration/Classes/DnsServerDsSetting.config.ps1 b/tests/Integration/Classes/DnsServerDsSetting.config.ps1 new file mode 100644 index 00000000..2225f9a2 --- /dev/null +++ b/tests/Integration/Classes/DnsServerDsSetting.config.ps1 @@ -0,0 +1,139 @@ +$ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = 'localhost' + CertificateFile = $env:DscPublicCertificatePath + } + ) +} + +<# + .SYNOPSIS + Sets the Directory Partition AutoEnlist Interval. +#> +configuration DnsServerDsSetting_DirectoryPartitionAutoEnlistInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + } + } +} + +<# + .SYNOPSIS + Configure the Lazy Update Interval. +#> +configuration DnsServerDsSetting_LazyUpdateInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + LazyUpdateInterval = 3 + } + } +} + +<# + .SYNOPSIS + Configures the Minimum Background Load Threads. +#> +configuration DnsServerDsSetting_MinimumBackgroundLoadThreads_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + MinimumBackgroundLoadThreads = 1 + } + } +} + +<# + .SYNOPSIS + Configures the Polling Interval. +#> +configuration DnsServerDsSetting_PollingInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + PollingInterval = 180 + } + } +} + +<# + .SYNOPSIS + Configure the Remote Replication Delay. +#> +configuration DnsServerDsSetting_RemoteReplicationDelay_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + RemoteReplicationDelay = 30 + } + } +} + +<# + .SYNOPSIS + Set cache timeout. +#> +configuration DnsServerDsSetting_TombstoneInterval_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + TombstoneInterval = '14.00:00:00' + } + } +} + +<# + .SYNOPSIS + Set cache timeout. +#> +configuration DnsServerDsSetting_All_Config +{ + Import-DscResource -ModuleName 'DnsServerDsc' + + node $AllNodes.NodeName + { + DnsServerDsSetting 'Integration_Test' + { + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } +} diff --git a/tests/Unit/Classes/DnsServerDsSetting.Tests.ps1 b/tests/Unit/Classes/DnsServerDsSetting.Tests.ps1 new file mode 100644 index 00000000..02a567c5 --- /dev/null +++ b/tests/Unit/Classes/DnsServerDsSetting.Tests.ps1 @@ -0,0 +1,395 @@ +$ProjectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$ProjectName = ( + Get-ChildItem $ProjectPath\*\*.psd1 | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $( + try + { + Test-ModuleManifest $_.FullName -ErrorAction Stop + } + catch + { + $false + } + ) + } +).BaseName + +Import-Module $ProjectName + +Get-Module -Name 'DnsServer' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot\..\Stubs\DnsServer.psm1" + +Describe 'DnsServerDsSetting\AssertProperties()' -Tag 'HiddenMember' { + BeforeAll { + Mock -CommandName Assert-Module -ModuleName $ProjectName + } + + Context 'When providing an invalid interval' { + BeforeEach { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + } + + Context 'When the value is a string that cannot be converted to [System.TimeSpan]' { + It 'Should throw the correct error' { + $mockInvalidTime = '235.a:00:00' + + $mockDnsServerDsSettingInstance.DirectoryPartitionAutoEnlistInterval = $mockInvalidTime + + $mockExpectedErrorMessage = InModuleScope $ProjectName { + $script:localizedData.PropertyHasWrongFormat + } + + { $mockDnsServerDsSettingInstance.Test() } | Should -Throw ($mockExpectedErrorMessage -f 'DirectoryPartitionAutoEnlistInterval', $mockInvalidTime) + } + } + + Context 'When the time is below minimum allowed value' { + It 'Should throw the correct error' { + $mockInvalidTime = '-1.00:00:00' + + $mockDnsServerDsSettingInstance.TombstoneInterval = $mockInvalidTime + + $mockExpectedErrorMessage = InModuleScope $ProjectName { + $script:localizedData.TimeSpanBelowMinimumValue + } + + { $mockDnsServerDsSettingInstance.Test() } | Should -Throw ($mockExpectedErrorMessage -f 'TombstoneInterval', $mockInvalidTime, '00:00:00') + } + } + } +} + +Describe 'DnsServerDsSetting\Get()' -Tag 'Get' { + Context 'When the system is in the desired state' { + BeforeAll { + Mock -CommandName Assert-Module -ModuleName $ProjectName + Mock -CommandName Get-DnsServerDsSetting -ModuleName $ProjectName -MockWith { + return New-CimInstance -ClassName 'DnsServerDsSetting' -Namespace 'root/Microsoft/Windows/DNS' -ClientOnly -Property @{ + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } + } + + BeforeEach { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + } + + It 'Should have correctly instantiated the resource class' { + $mockDnsServerDsSettingInstance | Should -Not -BeNullOrEmpty + $mockDnsServerDsSettingInstance.GetType().Name | Should -Be 'DnsServerDsSetting' + } + + It 'Should return the correct values for the properties when DnsServer is set to ''''' -TestCases @( + @{ + HostName = 'localhost' + } + @{ + HostName = 'dns.company.local' + } + ) { + param + ( + $HostName + ) + + $mockDnsServerDsSettingInstance.DnsServer = $HostName + + $getResult = $mockDnsServerDsSettingInstance.Get() + + $getResult.DirectoryPartitionAutoEnlistInterval | Should -Be '1.00:00:00' + $getResult.LazyUpdateInterval | Should -Be 3 + $getResult.MinimumBackgroundLoadThreads | Should -Be 1 + $getResult.PollingInterval | Should -Be 180 + $getResult.RemoteReplicationDelay | Should -Be 30 + $getResult.TombstoneInterval | Should -Be '14.00:00:00' + + Assert-MockCalled -CommandName Get-DnsServerDsSetting -ModuleName $ProjectName -Exactly -Times 1 -Scope It + } + } +} + +Describe 'DnsServerDsSetting\Test()' -Tag 'Test' { + BeforeAll { + Mock -CommandName Assert-Module -ModuleName $ProjectName + } + + Context 'When the system is in the desired state' { + BeforeAll { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + + $mockDnsServerDsSettingInstance.DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + $mockDnsServerDsSettingInstance.LazyUpdateInterval = 3 + $mockDnsServerDsSettingInstance.MinimumBackgroundLoadThreads = 1 + $mockDnsServerDsSettingInstance.PollingInterval = 180 + $mockDnsServerDsSettingInstance.RemoteReplicationDelay = 30 + $mockDnsServerDsSettingInstance.TombstoneInterval = '14.00:00:00' + + # Override Get() method + $mockDnsServerDsSettingInstance | + Add-Member -Force -MemberType ScriptMethod -Name Get -Value { + return InModuleScope $ProjectName { + [DnsServerDsSetting] @{ + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } + } + } + + It 'Should return the $true' { + $getResult = $mockDnsServerDsSettingInstance.Test() + + $getResult | Should -BeTrue + } + } + + Context 'When the system is not in the desired state' { + BeforeAll { + $testCases = @( + @{ + PropertyName = 'DirectoryPartitionAutoEnlistInterval' + PropertyValue = "2.00:00:00" + } + @{ + PropertyName = 'LazyUpdateInterval' + PropertyValue = 1 + } + @{ + PropertyName = 'MinimumBackgroundLoadThreads' + PropertyValue = 0 + } + @{ + PropertyName = 'PollingInterval' + PropertyValue = 0 + } + @{ + PropertyName = 'RemoteReplicationDelay' + PropertyValue = 0 + } + @{ + PropertyName = 'TombstoneInterval' + PropertyValue = '01:00:00' + } + ) + } + + BeforeEach { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + + # Override Get() method + $mockDnsServerDsSettingInstance | + Add-Member -Force -MemberType ScriptMethod -Name Get -Value { + return InModuleScope $ProjectName { + [DnsServerDsSetting] @{ + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } + } + } + + It 'Should return the $false when property is not in desired state' -TestCases $testCases { + param + ( + $PropertyName, + $PropertyValue + ) + + $mockDnsServerDsSettingInstance.$PropertyName = $PropertyValue + + $getResult = $mockDnsServerDsSettingInstance.Test() + + $getResult | Should -BeFalse + } + } +} + +Describe 'DnsServerDsSetting\Set()' -Tag 'Set' { + BeforeAll { + Mock -CommandName Assert-Module -ModuleName $ProjectName + } + + Context 'When the system is in the desired state' { + BeforeAll { + Mock -CommandName Set-DnsServerDsSetting -ModuleName $ProjectName + + $testCases = @( + @{ + PropertyName = 'DirectoryPartitionAutoEnlistInterval' + PropertyValue = "1.00:00:00" + } + @{ + PropertyName = 'LazyUpdateInterval' + PropertyValue = 3 + } + @{ + PropertyName = 'MinimumBackgroundLoadThreads' + PropertyValue = 1 + } + @{ + PropertyName = 'PollingInterval' + PropertyValue = 180 + } + @{ + PropertyName = 'RemoteReplicationDelay' + PropertyValue = 30 + } + @{ + PropertyName = 'TombstoneInterval' + PropertyValue = '14.00:00:00' + } + ) + } + + BeforeEach { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + + $mockDnsServerDsSettingInstance.DnsServer = 'localhost' + + # Override Get() method + $mockDnsServerDsSettingInstance | + Add-Member -Force -MemberType ScriptMethod -Name Get -Value { + return InModuleScope $ProjectName { + [DnsServerDsSetting] @{ + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } + } + } + + It 'Should not call any mock to set a value for property ''''' -TestCases $testCases { + param + ( + $PropertyName, + $PropertyValue + ) + + $mockDnsServerDsSettingInstance.$PropertyName = $PropertyValue + + { $mockDnsServerDsSettingInstance.Set() } | Should -Not -Throw + + Assert-MockCalled -CommandName Set-DnsServerDsSetting -ModuleName $ProjectName -Exactly -Times 0 -Scope It + } + } + + Context 'When the system is not in the desired state' { + BeforeAll { + Mock -CommandName Set-DnsServerDsSetting -ModuleName $ProjectName + + $testCases = @( + @{ + PropertyName = 'DirectoryPartitionAutoEnlistInterval' + PropertyValue = "2.00:00:00" + } + @{ + PropertyName = 'LazyUpdateInterval' + PropertyValue = 1 + } + @{ + PropertyName = 'MinimumBackgroundLoadThreads' + PropertyValue = 0 + } + @{ + PropertyName = 'PollingInterval' + PropertyValue = 0 + } + @{ + PropertyName = 'RemoteReplicationDelay' + PropertyValue = 0 + } + @{ + PropertyName = 'TombstoneInterval' + PropertyValue = '01:00:00' + } + ) + } + + BeforeEach { + $mockDnsServerDsSettingInstance = InModuleScope $ProjectName { + [DnsServerDsSetting]::new() + } + + # Override Get() method + $mockDnsServerDsSettingInstance | + Add-Member -Force -MemberType ScriptMethod -Name Get -Value { + return InModuleScope $ProjectName { + [DnsServerDsSetting] @{ + DnsServer = 'localhost' + DirectoryPartitionAutoEnlistInterval = '1.00:00:00' + LazyUpdateInterval = 3 + MinimumBackgroundLoadThreads = 1 + PollingInterval = 180 + RemoteReplicationDelay = 30 + TombstoneInterval = '14.00:00:00' + } + } + } + } + + Context 'When parameter DnsServer is set to ''localhost''' { + It 'Should set the desired value for property ''''' -TestCases $testCases { + param + ( + $PropertyName, + $PropertyValue + ) + + $mockDnsServerDsSettingInstance.DnsServer = 'localhost' + $mockDnsServerDsSettingInstance.$PropertyName = $PropertyValue + + { $mockDnsServerDsSettingInstance.Set() } | Should -Not -Throw + + Assert-MockCalled -CommandName Set-DnsServerDsSetting -ModuleName $ProjectName -Exactly -Times 1 -Scope It + } + } + + Context 'When parameter DnsServer is set to ''dns.company.local''' { + It 'Should set the desired value for property ''''' -TestCases $testCases { + param + ( + $PropertyName, + $PropertyValue + ) + + $mockDnsServerDsSettingInstance.DnsServer = 'dns.company.local' + $mockDnsServerDsSettingInstance.$PropertyName = $PropertyValue + + { $mockDnsServerDsSettingInstance.Set() } | Should -Not -Throw + + Assert-MockCalled -CommandName Set-DnsServerDsSetting -ModuleName $ProjectName -Exactly -Times 1 -Scope It + } + } + } +}