Modules/DnsServerDsc.Common/DnsServerDsc.Common.psm1
$script:resourceHelperModulePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\Modules\DscResource.Common' Import-Module -Name $script:resourceHelperModulePath $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS Converts a string to a fully qualified DNS domain name, if its not already. .DESCRIPTION This function is used to convert a string into a fully qualified DNS domain name by appending a '.' to the end. .PARAMETER Name A string with the value to convert. .OUTPUTS System.String #> function ConvertTo-FollowRfc1034 { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [System.String] $Name ) if (-not $Name.EndsWith('.')) { return "$Name." } return $Name } <# .SYNOPSIS Converts root hints like the DNS cmdlets are run. .DESCRIPTION This function is used to convert a CimInstance array containing MSFT_KeyValuePair objects into a hashtable. .PARAMETER CimInstance An array of CimInstances or a single CimInstance object to convert. .OUTPUTS System.Collections.Hashtable #> function Convert-RootHintsToHashtable { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.Object[]] [AllowEmptyCollection()] $RootHints ) $r = @{ } foreach ($rootHint in $RootHints) { if (-not $rootHint.IPAddress) { continue } $ip = if ($rootHint.IPAddress.RecordData.IPv4Address) { $rootHint.IPAddress.RecordData.IPv4Address.IPAddressToString -join ',' } else { $rootHint.IPAddress.RecordData.IPv6Address.IPAddressToString -join ',' } $r.Add($rootHint.NameServer.RecordData.NameServer, $ip) } return $r } <# .SYNOPSIS Tests the status of DSC resource parameters. .DESCRIPTION This function tests the parameter status of DSC resource parameters against the current values present on the system. .PARAMETER CurrentValues A hashtable with the current values on the system, obtained by e.g. Get-TargetResource. .PARAMETER DesiredValues The hashtable of desired values. .PARAMETER ValuesToCheck The values to check if not all values should be checked. .PARAMETER TurnOffTypeChecking Indicates that the type of the parameter should not be checked. .PARAMETER ReverseCheck Indicates that a reverse check should be done. The current and desired state are swapped for another test. .PARAMETER SortArrayValues If the sorting of array values does not matter, values are sorted internally before doing the comparison. .NOTES This function is enhanced with additional parameters compared to the function Test-DscParameterState that is available in the module DscResource.Common. These enhancements should be merged into DscResource.Common; https://github.com/dsccommunity/DscResource.Common/blob/master/source/Public/Test-DscParameterState.ps1. #> function Test-DscDnsParameterState { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.Object] $CurrentValues, [Parameter(Mandatory = $true)] [System.Object] $DesiredValues, [Parameter()] [System.String[]] $ValuesToCheck, [Parameter()] [switch] $TurnOffTypeChecking, [Parameter()] [switch] $ReverseCheck, [Parameter()] [switch] $SortArrayValues ) $returnValue = $true if ($CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance] -or $CurrentValues -is [Microsoft.Management.Infrastructure.CimInstance[]]) { $CurrentValues = ConvertTo-HashTable -CimInstance $CurrentValues } if ($DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance] -or $DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance[]]) { $DesiredValues = ConvertTo-HashTable -CimInstance $DesiredValues } $types = 'System.Management.Automation.PSBoundParametersDictionary', 'System.Collections.Hashtable', 'Microsoft.Management.Infrastructure.CimInstance' if ($DesiredValues.GetType().FullName -notin $types) { New-InvalidArgumentException ` -Message ($script:localizedData.InvalidDesiredValuesError -f $DesiredValues.GetType().FullName) ` -ArgumentName 'DesiredValues' } if ($CurrentValues.GetType().FullName -notin $types) { New-InvalidArgumentException ` -Message ($script:localizedData.InvalidCurrentValuesError -f $CurrentValues.GetType().FullName) ` -ArgumentName 'CurrentValues' } if ($DesiredValues -is [Microsoft.Management.Infrastructure.CimInstance] -and -not $ValuesToCheck) { New-InvalidArgumentException ` -Message $script:localizedData.InvalidValuesToCheckError ` -ArgumentName 'ValuesToCheck' } $desiredValuesClean = Remove-CommonParameter -Hashtable $DesiredValues if (-not $ValuesToCheck) { $keyList = $desiredValuesClean.Keys } else { $keyList = $ValuesToCheck } foreach ($key in $keyList) { $desiredValue = $desiredValuesClean.$key $currentValue = $CurrentValues.$key if ($desiredValue -is [Microsoft.Management.Infrastructure.CimInstance] -or $desiredValue -is [Microsoft.Management.Infrastructure.CimInstance[]]) { $desiredValue = ConvertTo-HashTable -CimInstance $desiredValue } if ($currentValue -is [Microsoft.Management.Infrastructure.CimInstance] -or $currentValue -is [Microsoft.Management.Infrastructure.CimInstance[]]) { $currentValue = ConvertTo-HashTable -CimInstance $currentValue } if ($null -ne $desiredValue) { $desiredType = $desiredValue.GetType() } else { $desiredType = @{ Name = 'Unknown' } } if ($null -ne $currentValue) { $currentType = $currentValue.GetType() } else { $currentType = @{ Name = 'Unknown' } } if ($currentType.Name -ne 'Unknown' -and $desiredType.Name -eq 'PSCredential') { # This is a credential object. Compare only the user name if ($currentType.Name -eq 'PSCredential' -and $currentValue.UserName -eq $desiredValue.UserName) { Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $currentValue.UserName, $desiredValue.UserName) continue } else { Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $currentValue.UserName, $desiredValue.UserName) $returnValue = $false } # Assume the string is our username when the matching desired value is actually a credential if ($currentType.Name -eq 'string' -and $currentValue -eq $desiredValue.UserName) { Write-Verbose -Message ($script:localizedData.MatchPsCredentialUsernameMessage -f $currentValue, $desiredValue.UserName) continue } else { Write-Verbose -Message ($script:localizedData.NoMatchPsCredentialUsernameMessage -f $currentValue, $desiredValue.UserName) $returnValue = $false } } if (-not $TurnOffTypeChecking) { if (($desiredType.Name -ne 'Unknown' -and $currentType.Name -ne 'Unknown') -and $desiredType.FullName -ne $currentType.FullName) { Write-Verbose -Message ($script:localizedData.NoMatchTypeMismatchMessage -f $key, $currentType.Name, $desiredType.Name) $returnValue = $false continue } } if ($currentValue -eq $desiredValue -and -not $desiredType.IsArray) { Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.Name, $key, $currentValue, $desiredValue) continue } if ($desiredValuesClean.GetType().Name -in 'HashTable', 'PSBoundParametersDictionary') { $checkDesiredValue = $desiredValuesClean.ContainsKey($key) } else { $checkDesiredValue = Test-DscObjectHasProperty -Object $desiredValuesClean -PropertyName $key } if (-not $checkDesiredValue) { Write-Verbose -Message ($script:localizedData.MatchValueMessage -f $desiredType.Name, $key, $currentValue, $desiredValue) continue } if ($desiredType.IsArray) { Write-Verbose -Message ($script:localizedData.TestDscParameterCompareMessage -f $key) if (-not $currentValue) { Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.Name, $key, $currentValue, $desiredValue) $returnValue = $false continue } elseif ($currentValue.Count -ne $desiredValue.Count) { Write-Verbose -Message ($script:localizedData.NoMatchValueDifferentCountMessage -f $desiredType.Name, $key, $currentValue.Count, $desiredValue.Count) $returnValue = $false continue } else { $desiredArrayValues = $desiredValue $currentArrayValues = $currentValue if ($SortArrayValues) { $desiredArrayValues = $desiredArrayValues | Sort-Object $currentArrayValues = $currentArrayValues | Sort-Object } for ($i = 0; $i -lt $desiredArrayValues.Count; $i++) { if ($null -ne $desiredArrayValues[$i]) { $desiredType = $desiredArrayValues[$i].GetType() } else { $desiredType = @{ Name = 'Unknown' } } if ($null -ne $currentArrayValues[$i]) { $currentType = $currentArrayValues[$i].GetType() } else { $currentType = @{ Name = 'Unknown' } } if (-not $TurnOffTypeChecking) { if (($desiredType.Name -ne 'Unknown' -and $currentType.Name -ne 'Unknown') -and $desiredType.FullName -ne $currentType.FullName) { Write-Verbose -Message ($script:localizedData.NoMatchElementTypeMismatchMessage -f $key, $i, $currentType.Name, $desiredType.Name) $returnValue = $false continue } } if ($desiredArrayValues[$i] -ne $currentArrayValues[$i]) { Write-Verbose -Message ($script:localizedData.NoMatchElementValueMismatchMessage -f $i, $desiredType.Name, $key, $currentArrayValues[$i], $desiredArrayValues[$i]) $returnValue = $false continue } else { Write-Verbose -Message ($script:localizedData.MatchElementValueMessage -f $i, $desiredType.Name, $key, $currentArrayValues[$i], $desiredArrayValues[$i]) continue } } } } elseif ($desiredType -eq [System.Collections.Hashtable] -and $currentType -eq [System.Collections.Hashtable]) { $param = $PSBoundParameters $param.CurrentValues = $currentValue $param.DesiredValues = $desiredValue [void]$param.Remove('ValuesToCheck') if ($returnValue) { $returnValue = Test-DscDnsParameterState @param } else { Test-DscDnsParameterState @param | Out-Null } continue } else { if ($desiredValue -ne $currentValue) { Write-Verbose -Message ($script:localizedData.NoMatchValueMessage -f $desiredType.Name, $key, $currentValue, $desiredValue) $returnValue = $false } } } if ($ReverseCheck) { Write-Verbose -Message $script:localizedData.StartingReverseCheck $reverseCheckParameters = $PSBoundParameters $reverseCheckParameters.CurrentValues = $DesiredValues $reverseCheckParameters.DesiredValues = $CurrentValues [void] $reverseCheckParameters.Remove('ReverseCheck') if ($returnValue) { $returnValue = Test-DscDnsParameterState @reverseCheckParameters } else { Test-DscDnsParameterState @reverseCheckParameters | Out-Null } } Write-Verbose -Message ($script:localizedData.TestDscParameterResultMessage -f $returnValue) return $returnValue } |