dsccommunity / DnsServerDsc

This module contains DSC resources for the management and configuration of Windows Server DNS Server.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DnsRecordBase: Test returns that desired state and current state is equal even if the record does not exist

johlju opened this issue · comments

I wasn't expecting to see that current state and desired state to be equal in the integration test. I would have expected it to just report that the record is missing and not comparing the other properties. 🤔

VERBOSE: [fv-az59-142]: LCM:  [ Start  Test     ]  [[DnsRecordSrv]Integration_Test]
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] Calling GetResourceRecord() from the DnsRecordSrv class to get the object's current state.
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] Getting DNS record '_dummy._tcp' with target of 'dummy.contoso.com' (SRV) in zone 'srv.test' from 'localhost'.
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] A matching DNS resource record not found.
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.String') for property 'SymbolicName' does match. Current state is 'dummy' and desired state is 'dummy'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.UInt16') for property 'Weight' does match. Current state is '20' and desired state is '20'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.String') for property 'DnsServer' does match. Current state is 'localhost' and desired state is 'localhost'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.String') for property 'ZoneName' does match. Current state is 'srv.test' and desired state is 'srv.test'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.UInt16') for property 'Port' does match. Current state is '33179' and desired state is '33179'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.String') for property 'Target' does match. Current state is 'dummy.contoso.com' and desired state is 'dummy.contoso.com'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] NOTMATCH: Value (type 'Ensure') for property 'Ensure' does not match. Current state is 'Absent' and desired state is 'Present'. (DRC0021)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.UInt16') for property 'Priority' does match. Current state is '10' and desired state is '10'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] MATCH: Value (type 'System.String') for property 'Protocol' does match. Current state is 'TCP' and desired state is 'TCP'. (DRC0020)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] Compare-DscParameterState result : Property 'Ensure' is in desired state 'False' . (DRC0026)
VERBOSE: [fv-az59-142]:                            [[DnsRecordSrv]Integration_Test] DNS record is NOT in the desired state.
VERBOSE: [fv-az59-142]: LCM:  [ End    Test     ]  [[DnsRecordSrv]Integration_Test]  in 0.5560 seconds.

Originally posted by @johlju in #201 (comment)

@johlju , below is my analysis of the issue. I would be interested to hear your take.

Process flow:

  • The Test() method calls Get() to compare the current state with the desired state.
  • The Get() method determines the resource was not found, sets the expected values in the object, and flags the object returned with an Ensure value of 'Absent'.
  • The Test() method then uses the Compare-DscParameterState function to determine whether the current state and desired state match. This function evaluates against the entire object.

Possible courses of action:

  • The process flow is working as intended. Leave it as-is.
  • The process flow is working as intended. Add another verbose message explaining that the current state is being compared to the desired state.
  • Short-circuit the call to Compare-DscParameterState with the full set of parameters by explicitly comparing current and expected Ensure values first in DnsRecordBase (Compare-DscParameterState can still be used here. It just requires a preemptive call passing only 'Ensure' to the Properties parameter).
  • Modify the Compare-DscParameterState function to short-circuit itself based on the Ensure value comparisons.

Thoughts:

I believe that the process is working as intended and that additional comments would just be stating that the test is occurring - which users of DSC should already understand. I am happy to leave it as-is.

If, however, the desire is to cut down the processing that occurs in making this determination, I believe a change would be more appropriate in Compare-DscParameterState than in DnsRecordBase.

I think we Test() should just call Compare-DscParameterState if Ensure for desired state and actual state is Present.
So the code

https://github.com/dsccommunity/xDnsServer/blob/2303e2e46e87ffc8e1678bc58b257ba812a862a3/source/Classes/001.DnsRecordBase.ps1#L209-L226

Would become.

if ($this.Ensure -eq 'Present')
{
    if ($currentState.Ensure -eq 'Present')
    {
        # Remove properties that have $null as the value
        @($desiredState.Keys) | ForEach-Object -Process {
            if ($null -eq $desiredState[$_])
            {
                $desiredState.Remove($_)
            }
        }

        # Returns all enforced properties not in desires state, or $null if all enforced properties are in desired state
        $propertiesNotInDesiredState = Compare-DscParameterState -CurrentValues $currentState -DesiredValues $desiredState -Properties $desiredState.Keys -ExcludeProperties @('Ensure')

        if ($propertiesNotInDesiredState)
        {
            $isInDesiredState = $false
        }
    }
    else 
    {
        $isInDesiredState = $false
    }
}

It adds an evaluate of the Ensure property. If the record exist the Ensure property is excluded from Compare-DscParameterState using ExcludeProperties when comparing the state of the properties since it has already been evaluated

Would that work?

That looks clean and makes sense. I'm good with it. Would you like to work the change, or would you prefer I take it for action?

Note: For the sake of anyone reading in the future, we have agreed on course of action # 3 above.

I can fix it, it is a small change, then you can focus on the large changes like adding new resources 😉