Skip to content

Commit

Permalink
DnsServerRecursion: New resource proposal (#245)
Browse files Browse the repository at this point in the history
- DnsServerDsc
  - Added new resource
    - _DnsServerRecursion_ - resource to enforce recursion settings (issue #198).
- ResourceBase
  - Moved more logic from the resources into the base class for the method
    `Test()`, `Get()`, and `Set()`. The base class now have three methods
    `AssertProperties()`, `Modify()`, and `GetCurrentState()` where the
    two latter ones must be overridden by a resource if calling the base
    methods `Set()` and `Get()`.
  • Loading branch information
johlju authored Apr 5, 2021
1 parent 3b9df3c commit a2eedd1
Show file tree
Hide file tree
Showing 15 changed files with 1,730 additions and 60 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- DnsServerDsc
- Added new resource
- _DnsServerCache_ - resource to enforce cache settings ([issue #196](https://github.com/dsccommunity/DnsServerDsc/issues/196)).
- _DnsServerRecursion_ - resource to enforce recursion settings ([issue #198](https://github.com/dsccommunity/DnsServerDsc/issues/198)).
- Added new private function `Get-ClassName` that returns the class name
or optionally an array with the class name and all inherited base class
named.
Expand All @@ -44,7 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- DnsServerDsc
- BREAKING CHANGE: Renamed the module to DnsServerDsc ([issue #179](https://github.com/dsccommunity/DnsServerDsc/issues/179)).
- BREAKING CHANGE: Removed the prefix 'x' from all MOF-based resources ([issue #179](https://github.com/dsccommunity/DnsServerDsc/issues/179)).
- BREAKING CHANGE: Removed the prefix 'x' from all MOF-based resources
([issue #179](https://github.com/dsccommunity/DnsServerDsc/issues/179)).
- Renamed a MOF-based resource to use the prefix 'DSC' ([issue #225](https://github.com/dsccommunity/DnsServerDsc/issues/225)).
- Fix stub `Get-DnsServerResourceRecord` so it throws if it is not mocked
correctly ([issue #204](https://github.com/dsccommunity/DnsServerDsc/issues/204)).
Expand All @@ -53,6 +55,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ResourceBase
- Added support for inherit localization strings and also able to override
a localization string that exist in a base class.
- Moved more logic from the resources into the base class for the method
`Test()`, `Get()`, and `Set()`. The base class now have three methods
`AssertProperties()`, `Modify()`, and `GetCurrentState()` where the
two latter ones must be overridden by a resource if calling the base
methods `Set()` and `Get()`.
- Integration tests
- Added commands in the DnsRecord* integration tests to wait for the LCM
before moving to the next test.
Expand Down
110 changes: 107 additions & 3 deletions source/Classes/001.ResourceBase.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,45 @@ class ResourceBase
$this.localizedData = Get-LocalizedDataRecursive -ClassName ($this | Get-ClassName -Recurse)
}

[ResourceBase] Get()
{
Write-Verbose -Message ($this.localizedData.GetCurrentState -f $this.DnsServer, $this.GetType().Name)

# Get all key properties.
$keyProperty = $this |
Get-Member -MemberType 'Property' |
Select-Object -ExpandProperty Name |
Where-Object -FilterScript {
$this.GetType().GetMember($_).CustomAttributes.Where( { $_.NamedArguments.MemberName -eq 'Key' }).NamedArguments.TypedValue.Value -eq $true
}

$getParameters = @{}

# Set each key property to its value (property DnsServer is handled below).
$keyProperty |
Where-Object -FilterScript {
$_ -ne 'DnsServer'
} |
ForEach-Object -Process {
$getParameters[$_] = $this.$_
}

# Set ComputerName depending on value of DnsServer.
if ($this.DnsServer -ne 'localhost')
{
$getParameters['ComputerName'] = $this.DnsServer
}

$getCurrentStateResult = $this.GetCurrentState($getParameters)

# Call the overloaded method Get() to get the properties to return.
return ([ResourceBase] $this).Get($getCurrentStateResult)
}

<#
This overloaded method should be merged together with Get() above when
no resource uses it directly.
#>
[ResourceBase] Get([Microsoft.Management.Infrastructure.CimInstance] $CommandProperties)
{
$dscResourceObject = [System.Activator]::CreateInstance($this.GetType())
Expand All @@ -42,10 +81,44 @@ class ResourceBase

[void] Set()
{
$this.AssertProperties()

Write-Verbose -Message ($this.localizedData.SetDesiredState -f $this.DnsServer, $this.GetType().Name)

# Call the Compare method to get enforced properties that are not in desired state.
$propertiesNotInDesiredState = $this.Compare()

if ($propertiesNotInDesiredState)
{
$setDnsServerRecursionParameters = $this.GetDesiredStateForSplatting($propertiesNotInDesiredState)

$setDnsServerRecursionParameters.Keys | ForEach-Object -Process {
Write-Verbose -Message ($this.localizedData.SetProperty -f $_, $setDnsServerRecursionParameters.$_, $this.GetType().Name)
}

if ($this.DnsServer -ne 'localhost')
{
$setDnsServerRecursionParameters['ComputerName'] = $this.DnsServer
}

<#
Call the Modify() method with the properties that should be enforced
and was not in desired state.
#>
$this.Modify($setDnsServerRecursionParameters)
}
else
{
Write-Verbose -Message $this.localizedData.NoPropertiesToSet
}
}

[System.Boolean] Test()
{
Write-Verbose -Message ($this.localizedData.TestDesiredState -f $this.DnsServer, $this.GetType().Name)

$this.AssertProperties()

$isInDesiredState = $true

<#
Expand All @@ -59,20 +132,34 @@ class ResourceBase
$isInDesiredState = $false
}

if ($isInDesiredState)
{
Write-Verbose -Message ($this.localizedData.InDesiredState -f $this.DnsServer, $this.GetType().Name)
}
else
{
Write-Verbose -Message ($this.localizedData.NotInDesiredState -f $this.DnsServer, $this.GetType().Name)
}

return $isInDesiredState
}

# Returns a hashtable containing all properties that should be enforced.
<#
Returns a hashtable containing all properties that should be enforced.
This method should normally not be overridden.
#>
hidden [System.Collections.Hashtable[]] Compare()
{
$currentState = $this.Get() | ConvertTo-HashTableFromObject
$desiredState = $this | ConvertTo-HashTableFromObject

# Remove properties that have $null as the value.
<#
Remove properties that have $null as the value, and remove read
properties so that there is no chance to campare those.
#>
@($desiredState.Keys) | ForEach-Object -Process {
$isReadProperty = $this.GetType().GetMember($_).CustomAttributes.Where( { $_.NamedArguments.MemberName -eq 'NotConfigurable' }).NamedArguments.TypedValue.Value -eq $true

# Also remove read properties so that there is no chance to campare those.
if ($isReadProperty -or $null -eq $desiredState[$_])
{
$desiredState.Remove($_)
Expand Down Expand Up @@ -105,4 +192,21 @@ class ResourceBase

return $desiredState
}

# This method can be overridden if resource specific asserts are needed.
hidden [void] AssertProperties()
{
}

# This method must be overridden by a resource.
hidden [void] Modify([System.Collections.Hashtable] $properties)
{
throw $this.localizedData.ModifyMethodNotImplemented
}

# This method must be overridden by a resource.
hidden [Microsoft.Management.Infrastructure.CimInstance] GetCurrentState([System.Collections.Hashtable] $properties)
{
throw $this.localizedData.GetCurrentStateMethodNotImplemented
}
}
17 changes: 1 addition & 16 deletions source/Classes/003.DnsServerCache.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -156,23 +156,8 @@ class DnsServerCache : ResourceBase

[System.Boolean] Test()
{
$this.AssertProperties()

Write-Verbose -Message ($this.localizedData.TestDesiredState -f $this.DnsServer)

# Call the base method to test all of the properties that should be enforced.
$isInDesiredState = ([ResourceBase] $this).Test()

if ($isInDesiredState)
{
Write-Verbose -Message ($this.localizedData.InDesiredState -f $this.DnsServer)
}
else
{
Write-Verbose -Message ($this.localizedData.NotInDesiredState -f $this.DnsServer)
}

return $isInDesiredState
return ([ResourceBase] $this).Test()
}

hidden [void] AssertProperties()
Expand Down
17 changes: 1 addition & 16 deletions source/Classes/003.DnsServerEDns.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,8 @@ class DnsServerEDns : ResourceBase

[System.Boolean] Test()
{
$this.AssertProperties()

Write-Verbose -Message ($this.localizedData.TestDesiredState -f $this.DnsServer)

# Call the base method to test all of the properties that should be enforced.
$isInDesiredState = ([ResourceBase] $this).Test()

if ($isInDesiredState)
{
Write-Verbose -Message ($this.localizedData.InDesiredState -f $this.DnsServer)
}
else
{
Write-Verbose -Message ($this.localizedData.NotInDesiredState -f $this.DnsServer)
}

return $isInDesiredState
return ([ResourceBase] $this).Test()
}

hidden [void] AssertProperties()
Expand Down
132 changes: 132 additions & 0 deletions source/Classes/003.DnsServerRecursion.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<#
.SYNOPSIS
The DnsServerRecursion DSC resource manages recursion settings on a Microsoft
Domain Name System (DNS) server.
.DESCRIPTION
The DnsServerRecursion DSC resource manages recursion settings on a Microsoft
Domain Name System (DNS) server. Recursion occurs when a DNS server queries
other DNS servers on behalf of a requesting client, and then sends the answer
back to the client.
The property `SecureResponse` that can be set by the cmdlet `Set-DnsServerRecursion`
changes the same value as `EnablePollutionProtection` in the resource _DnsServerCache_
does. Use the property `EnablePollutionProtection` in the resource _DnsServerCache_
to enforce pollution protection.
.PARAMETER DnsServer
The host name of the Domain Name System (DNS) server, or use `'localhost'`
for the current node.
.PARAMETER Enable
Specifies whether the server enables recursion.
.PARAMETER AdditionalTimeout
Specifies the time interval, in seconds, that a DNS server waits as it uses
recursion to get resource records from a remote DNS server. Valid values are
in the range of `1` second to `15` seconds. See recommendation in the documentation
of [Set-DnsServerRecursion](https://docs.microsoft.com/en-us/powershell/module/dnsserver/set-dnsserverrecursion).
.PARAMETER RetryInterval
Specifies elapsed seconds before a DNS server retries a recursive lookup.
Valid values are in the range of `1` second to `15` seconds. The
recommendation is that in general this value should not be change. However,
under a few circumstances it can be considered changing the value. For
example, if a DNS server contacts a remote DNS server over a slow link and
retries the lookup before it gets a response, it could help to raise the
retry interval to be slightly longer than the observed response time.
See recommendation in the documentation of [Set-DnsServerRecursion](https://docs.microsoft.com/en-us/powershell/module/dnsserver/set-dnsserverrecursion).
.PARAMETER Timeout
Specifies the number of seconds that a DNS server waits before it stops
trying to contact a remote server. The valid value is in the range of `1`
second to `15` seconds. Recommendation is to increase this value when
recursion occurs over a slow link. See recommendation in the documentation
of [Set-DnsServerRecursion](https://docs.microsoft.com/en-us/powershell/module/dnsserver/set-dnsserverrecursion).
.NOTES
The cmdlet Set-DsnServerRecursion allows to set the value 0 (zero) for the
properties AdditionalTimeout, RetryInterval, and Timeout, but setting the
value 0 reverts the property to its respectively default value. The default
value for the properties on Windows Server 2016 is 4 seconds for property
AdditionalTimeout, 3 seconds for RetryInterval, and 8 seconds for property
Timeout. If it was allowed to set 0 (zero) as the value in this resource
for these properties then the state would never become in desired state.
#>

[DscResource()]
class DnsServerRecursion : ResourceBase
{
[DscProperty(Key)]
[System.String]
$DnsServer

[DscProperty()]
[Nullable[System.Boolean]]
$Enable

[DscProperty()]
[Nullable[System.UInt32]]
$AdditionalTimeout

[DscProperty()]
[Nullable[System.UInt32]]
$RetryInterval

[DscProperty()]
[Nullable[System.UInt32]]
$Timeout

[DnsServerRecursion] 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-DnsServerRecursion @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-DnsServerRecursion @properties
}

[System.Boolean] Test()
{
# Call the base method to test all of the properties that should be enforced.
return ([ResourceBase] $this).Test()
}

# Called by the base method Set() and Test() to assert that all properties are valid.
hidden [void] AssertProperties()
{
@(
'AdditionalTimeout'
'RetryInterval'
'Timeout'
) | ForEach-Object -Process {
$propertyValue = $this.$_

# Only evaluate properties that have a value.
if ($null -ne $propertyValue -and $propertyValue -notin (1..15))
{
$errorMessage = $this.localizedData.PropertyIsNotInValidRange -f $_, $propertyValue

New-InvalidOperationException -Message $errorMessage
}
}
}
}
17 changes: 1 addition & 16 deletions source/Classes/003.DnsServerScavenging.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -125,23 +125,8 @@ class DnsServerScavenging : ResourceBase

[System.Boolean] Test()
{
$this.AssertProperties()

Write-Verbose -Message ($this.localizedData.TestDesiredState -f $this.DnsServer)

# Call the base method to test all of the properties that should be enforced.
$isInDesiredState = ([ResourceBase] $this).Test()

if ($isInDesiredState)
{
Write-Verbose -Message ($this.localizedData.InDesiredState -f $this.DnsServer)
}
else
{
Write-Verbose -Message ($this.localizedData.NotInDesiredState -f $this.DnsServer)
}

return $isInDesiredState
return ([ResourceBase] $this).Test()
}

hidden [void] AssertProperties()
Expand Down
Loading

0 comments on commit a2eedd1

Please sign in to comment.