3

I'm stuck with a problem applying filters to Nodes in a DSC Configuration block when zero computer nodes match the filter criteria. For example:

configuration MyApp {
    node $AllNodes.Where{ $_.Role -Match "role1|role2" }.NodeName {
        File ApplicationFolder {
            Type = "Directory"
            DestinationPath = $Node.ApplicationFolder
            Ensure = "Present"
        }
    }
}

$configData = @{
    AllNodes = @(
        @{
            NodeName = "*"
        }
        @{
            NodeName = $env:COMPUTERNAME
            Role = "role3"
            ApplicationFolder = "E:\MyApp"
        }
    )
}

$mof = MyApp -ConfigurationData $configData;
Start-DscConfiguration MyApp -ComputerName $env:COMPUTERNAME -Wait -Verbose;

Running this script gives the following error:

PSDesiredStateConfiguration\node : Node processing is skipped since the node name is empty.
At E:\test\test.ps1:3 char:5
+     node $AllNodes.Where{ $_.Role -Match "role1|role2" }.NodeName {
+     ~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : NodeNameIsRequired,PSDesiredStateConfiguration\node
Errors occurred while processing configuration 'MyApp'.
At
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:2088 char:5
+     throw $errorRecord
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (MyApp:String) [], InvalidOperationException
    + FullyQualifiedErrorId : FailToProcessConfiguration

The best solution I've come up with so far is to wrap every Node in an "if {}" that checks for null values - e.g.

configuration MyApp {
    $nodeNames = $AllNodes.Where{ $_.Role -Match "role1|role2" }.NodeName;
    if( $nodeNames -ne $null )
    {
        node $nodeNames {
            File ApplicationFolder {
                Type = "Directory"
                DestinationPath = $Node.ApplicationFolder
                Ensure = "Present"
            }
        }
    }
}

but this feels like a bit of a hack and is filling my configurations blocks up with a lot of cruft. Is there a cleaner way to avoid this error when there are zero nodes matching the filter?

(For context, I'm building multiple dev, test and uat environments where we're only deploying partial sets of server roles to each environment, so I don't want to change the logic of the Node filter expression or remove nodes from the Configuration block because they're required in production and I want to use the same scripts everywhere).

mclayton
  • 8,025
  • 2
  • 21
  • 26

2 Answers2

2

In the end I settled for adding a check around the nodes that have a filter. It's a bit kludgy and very repetitive when there's a lot of different filters, but at least it keeps the workaround close to where the issue is, and if you squint it doesn't look that different to the original code.

configuration MyApp {

    $nodeNames = $AllNodes.Where{ $_.Role -Match "role1|role2" }.NodeName;
    if( $nodeNames -ne $null )
    {
        node $nodeNames {
            File ApplicationFolder {
                Type = "Directory"
                DestinationPath = $Node.ApplicationFolder
                Ensure = "Present"
            }
        }
    }

}
mclayton
  • 8,025
  • 2
  • 21
  • 26
0

How about adding -ErrorAction SilentlyContinue and -ErrorVariable DscErrors to your call to Start-DscConfiguration?

configuration foo {
    param ([string[]] $ComputerName)
    node $ComputerName {
        File dsctest.txt {
            DestinationPath = 'c:\test\dsctest.txt';
            Contents = 'dsctest';
        }
    }
}

foo -ComputerName dc01,dc02,dc03,dc04,dc05;

Start-DscConfiguration -Path .\foo -Wait -ErrorAction SilentlyContinue -ErrorVariable DscErrors;

$FailedList = ($DscErrors.OriginInfo.PSComputerName | Sort-Object) -join ', ';
Write-Host -ForegroundColor Red -Object ('The following systems failed to process: {0}' -f $FailedList);

Here's what the output looks like, in my lab environment:

DSC Screenshot

  • Unfortunately, it looks like the DSC error takes precedence over the "SilentlyContinue". If I replace "node $ComputerName {" with " node $AllNodes.Where{ $_.Role -eq "db" }.NodeName {" in your example it still gives the terminating "node name is empty" error rather than capture it into the error variable :-(. – mclayton Jul 04 '14 at 07:50