DSC Composite Resources and optional variables

Hi all,

Possibly a simple syntax issue, but it seems like that no matter how I setup the parameters of a DSC composite resource, the primary configuration will return an error if a configuration node doesn’t provide a value.

For example, lets take a simple configuration:

Configuration MasterConfig
{
    Import-DscResource -Module Contoso_cCompositeConfiguration
    
    Node $AllNodes.NodeName {    
        cBase BaseConfig
        {
            DNSServerAddresses = $Node.DNSServerAddresses
            Location = $Node.Location
        }
    }
    

Now in the said resource “cBase” I’ll put in some base configs that are switched depending on the location, and allows me to input “override” DNS entries for things like DCs. straight forward so far:

Configuration cBase
{
    param (
        [Parameter(Mandatory=$false)][array]$DNSServerAddresses,
        [Parameter(Mandatory=$true)][ValidateNotNullorEmpty()][string]$Location
        )
    
    Import-DSCResource -ModuleName xNetworking

    If ($DNSServerAddresses) {
        xDNSServerAddress  DNSCustom {
            Address = $DNSServerAddresses
            InterfaceAlias = "Ethernet"
            AddressFamily = "IPV4"
            }
        }

    If (($Location -eq "Private") -and !($DNSServerAddresses)) {
        xDNSServerAddress  DNSPrivate {
            Address = "192.168.1.100","192.168.1.102"
            InterfaceAlias = "Ethernet"
            AddressFamily = "IPV4"
            }
        }
}

Now the “idea” is i can then drop in some configuraiton data and only some of the nodes will actually have “DNSServerAddresses” defined, but when I do that, I fail to compile a mof and get an error message that a required parameter is missing.

I’ve temporarily gotten around this by calling “cBase” (in this example) multiple times like this:

Node $AllNodes.where{$_.DNSServerAddresses}.NodeName {    
        cBase BaseConfig
        {
            DNSServerAddresses = $Node.DNSServerAddresses
            Location =$Node.Location
        }
    }
    
    Node $AllNodes.where{!$_.DNSServerAddresses}.NodeName {    
        cBase BaseConfig
        {
            Location =$Node.Location
        }
    }

… but that feels like excessive amounts of coding and … well … I’m lazy.

Is there a better way to structure this?

Well, but you’ve defined DNSServerAddress as mandatory, right? That’ll cause a fail during the schema check if you haven’t provided that value.

That sound you hear is my head as it collides with the desk…

EDIT: OK I just looked at my actual code to verify I didn’t make that silly mistake … I only did it in the fast example. I edited my original post to reflect that better.

So to clarify, the cbase resource is NOT set to mandatory, but if i define it in the main configuration it will still error.

OK I"m re-reading your response Don, and it may be that I’m simply misunderstanding how the configuration works. Maybe you could clarify.

When I do something like this in the configuration:

cBase BaseConfig
        {
            DNSServerAddresses = $Node.DNSServerAddresses
            Location = $Node.Location
        }

I thought I was merely defining which variables to pass to the resource. Does this statement actually make those variables mandatory because it checks for that value? Will it automatically pass variables to the resource that aren’t called out in the configuration?

So, that example assumes DNSServerAddresses and Location are defined as parameters of the cBase resource. It’s the Param() block in cBase, where you’ve put [Parameter(Mandatory=$True)] that makes them mandatory.

It might be helpful if you posted your actual cBase definition, at least the Param() block from it.

OK i went back to my real resource and imediately saw the error … I’m returning to banging my head against the desk. For your enjoyment:

[Parameter(Mandatory=$false)][ValidateNotNullorEmpty()][array]$DNSServerAddresses,

Yeah … Mandatory is false … then I say validate not null or empty … sigh …

You win! I clearly need to walk away from the keyboard now …