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 callsGet()
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 anEnsure
value of 'Absent'. - The
Test()
method then uses theCompare-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 theProperties
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
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 😉