Access Reusable helper function in Script resources

Tagged: 

This topic contains 9 replies, has 4 voices, and was last updated by  JrdnRgrs 11 months, 2 weeks ago.

  • Author
    Posts
  • #55166

    Sameer Kumar
    Participant

    To follow DRY principle, I have created a helper function in my DSC script. However I can't access it from inside Script resource. After some research I found that SetScript block is actually a string. Do you have a workaround or real solution for this? Here is my sample flow:

    function Get-WebsiteCurrentPhysicalPath($webSiteName, $defaultPath) {
        $website = Get-Website -Name "$webSiteName"
        if($website -eq $null) {
            return $defaultPath
        }
        else {
            return Get-ItemProperty IIS:\Sites\$webSiteName -name physicalPath
        }
    }
    
    Configuration WebsiteConfiguration {
    Node ('localhost')
        {
            ## Bootstrap
            $MasterConfig = @{
                CurrentIISWebsitePhysicalPath = Get-WebsiteCurrentPhysicalPath $siteName $path
            }
            Script NewWebsiteDefaults
            {
                GetScript = {return $using:MasterConfig}
                TestScript = {return $false}
                SetScript = {
                    $state = $GetScript
                    # Following line doesnot work
                    $script:CurrentPhysicalPath = Get-WebsiteCurrentPhysicalPath $siteName $path
                    # I tried this following line, even this doesnot work
                    $script:CurrentPhysicalPath =  $using:state['CurrentIISWebsitePhysicalPath']
                }
            }
        }
    }
  • #55167

    Don Jones
    Keymaster

    Hmm. I don't think I've ever tried that; I tend to avoid Script resources like a plague.

    But I'm perhaps not following your need. Do you want your function only available when the Configuration is run? As-is, it looks like you want it available on the target nodes. Just because the function is in the same .ps1 file as the Configuration, doesn't make the function available on target nodes. The Configuration produces a MOF; your function isn't included in that.

    Can you help me understand the goal?

  • #55168

    Don Jones
    Keymaster

    (similarly, your $script modifiers won't have any effect when the Script is run on the target node; the Get/Set/Test blocks are run in their own PowerShell process)

    • #55170

      Sameer Kumar
      Participant

      If I replace Line#25 with this

      $script:CurrentPhysicalPath = Get-ItemProperty IIS:\Sites\$using:siteName -name physicalPath

      then it works like a charm! So apparently, built-in cmdlets works but not custom functions?

      • This reply was modified 11 months, 2 weeks ago by  Sameer Kumar.
  • #55172

    Don Jones
    Keymaster

    Yeah, so, the thing is, when you run a Configuration, it creates a MOF. That MOF won't contain your function. And, when Script resource Get/Set/Test blocks run, there's no shared $script context for them.

    So what's happening to you is this:

    1. You run the Configuration
    2. MOFs are produced
    3. You deploy the MOFs to target nodes
    4. The target nodes try to run Get-WebsiteCurrentPhysicalPath, but it doesn't exist on the target nodes

    The only way to make this work is to put your function into a script module, and deploy it to your target nodes. You'll also need to resolve your use of $script, which isn't actually going to work.

    The CORRECT answer, from a DSC perspective, is to Never Use Script Resources. Build your own custom resource (which is really just three functions; you've already done all the work) and deploy it to your target nodes. Your custom resource is a script module, so it CAN include a helper function like you've written here.

  • #55173

    Don Jones
    Keymaster


    If I replace Line#25 with this
    $script:CurrentPhysicalPath = Get-ItemProperty IIS:\Sites\$using:siteName -name physicalPath
    then it works like a charm! So apparently, built-in cmdlets works but not custom functions

    Also, the $script is completely unnecessary. $CurrentPhysicalPath would do the same thing.

    The problem is, I think, that you're maybe not understanding what the target nodes are running. They are NOT running your Configuration block. The target nodes do not have your .ps1 file, and they do not have your custom function. When a Configuration runs, it doesn't even execute the Script resource. It simply produces a MOF. Try running your Configuration – and then opening the resulting MOF in Notepad. You'll see your Script block, plain as day. You'll also NOT see your custom function – which is why the target nodes don't have it.

    • #55189

      Sameer Kumar
      Participant

      Thanks for the explanation. Very helpful.

  • #55235

    Arie H
    Participant

    Actually, the CORRECT answer, from a DSC perspective, is to NEVER Use Script Resources for Logic, is what Don means more likely 🙂

    You should not add logic to your DSC configuration scripts, but if you need a script to run, then yes, that's why the Script DSC resource exists. Problem is its a bit misused, but I wouldn't go as far as saying NEVER use the script DSC resources all together 🙂

  • #55246

    JrdnRgrs
    Participant

    Yeah I believe you'd be better off writing your own custom resource for what you're trying to do.

    This will allow you to run whatever custom functions/logic you need, as you can just contain them in the resource.

    Check this page out for more info

You must be logged in to reply to this topic.