powershellpowershell-dsc

How to make resource level variables


For example, let's say I have a Script resource:

configuration ChocolateyServer {
    node localhost {
        Script ChocolateyPackages {
            SetScript = {
                $tools = 'googlechrome,notepadplusplus,7zip,microsoftwse,octopusdeploy.tentacle,sqlserver-cmdlineutils'
                foreach($tool in $tools.Split(',')) {
                    if(($packages | ? { $_.ToString().ToLower().StartsWith($tool) }).Count -eq 0) {
                        choco install $tool -y
                    }
                }
            }
            TestScript = {
                $tools = 'googlechrome,notepadplusplus,7zip,microsoftwse,octopusdeploy.tentacle,sqlserver-cmdlineutils'
                $packages = (choco list -lr).ToLower()

                foreach($tool in $tools.Split(',')) {
                    if(($packages | ? { $_.ToString().ToLower().StartsWith($tool) }).Count -eq 0) {
                        return $false
                    }
                }

                return $true
            }
            GetScript = { return @{ Result = "nothing" } }
        }
    }
}

I'd like to pull $tools out of these two separate functions in order to avoid code duplication. I'd be satisfied to be able to add $tools to my Script resource and share it between these two functions without having to define it twice.

However, attempting to do that gives me an error:

An attribute name for resource 'Script' was found that is not valid. An attribute name must be a simple string, and cannot contain variables or expressions. Replace '$tools' with a simple string.

How can I share this code?


Solution

  • The Script object won't allow any extra properties to be defined but I was able to define my properties at the Node level and access them inside my Script resource.

    NOTE: These variables must be referenced with a using keyword, e.g. $using:tools

    Example:

    configuration ChocolateyServer {
        node localhost {
            #defining it here is ok
            $tools = 'googlechrome,notepadplusplus,7zip,microsoftwse,octopusdeploy.tentacle,sqlserver-cmdlineutils'
    
            Script ChocolateyPackages {
                #defining it here will cause an error
    
                SetScript = {
                    foreach($tool in $using:tools.Split(',')) {
                        if(($packages | ? { $_.ToString().ToLower().StartsWith($tool) }).Count -eq 0) {
                            choco install $tool -y
                        }
                    }
                }
                TestScript = {                  
                    $packages = (choco list -lr).ToLower()
    
                    foreach($tool in $using:tools.Split(',')) {
                        if(($packages | ? { $_.ToString().ToLower().StartsWith($tool) }).Count -eq 0) {
                            return $false
                        }
                    }
    
                    return $true
                }
                GetScript = { return @{ Result = "nothing" } }
            }
        }
    }