New Reply

Good news! We have migrated all the Q&A on this site to https://forums.inedo.com, and are currently monitoring questions there!

Here are some important links:

All posts here are permanently locked (and will be redirected soon), and if you have any issues with the new site, please submit a support ticket, use the contact form, or visit our Slack Workspace.

Hello, I want to start creating small functions of reusable code so I don't have to keep adding them to my plans. I use PSEnsure almost exclusively to maintain consistency across my roles. One of the things I would like to set up is a machine domain check, since we take care of machines in multiples domains and forests. I would basically like to call this function during my PSEnsure and have it output a variable called $DomainMembership for me to be able to utilize as need. For example:

    $GetDomain = (Get-CimInstance Win32_ComputerSystem).Domain
    
    if ($GetDomain -eq 'abc.local'){
        $DomainMembership  = 'abc.local'
    }
    elseif ($GetDomain -eq 'def.local'){
        $DomainMembership = 'def.local'
    }

I am not sure if this should be a module or script, as it is not clear to me the difference between the two, or documentation on how to get it working.

Product: Otter
Version: 2.1.3

So just to update, I have been testing some powershell scripts out. I test them by scheduling a job, and have it write the output and I can see it in the logging. they seem to work when using an Orchestration / Execution plan or job. But I am not able to get it working with a configuration / PSEnsure job. I am not sure if I am missing something or it has a limitation? I would hope one would be able to use reusable code in a Configuration /PSEnsure plan. Ideas?

<crickets>

Anyone? Am I not doing this right, or does it not work that way?

I'm not 100% sure I understand, but when I see "small functions of reusable code", the first thing that comes to mind are Modules. These are bits of OtterScript that you can from OtterScript using the call statement.

module Get-DomainMembership<$Param1, $OptionalParam2 = default, out $OutParam>
{
   set $outParam = hello;
}

call Get-DomainMembership
(
  Param1: some value,
  Param2 => $SomeVariable
);

And then there are also Script Assets, which are PowerShell scripts that you call using the pscall operation from within OtterScript.

Is this helpful?

Hello, I have a simple test function as a script asset:
function TestFunction (){
Write-Warning 'TestFunction was successful'
}

And I have the psensure. I have tried to make this is simple as possible for clarity:

##AH:UseTextMode

PSEnsure
(
Key: Test,
Value: True,
Collect: >>
$false
>>,
Configure: >>
pscall test;
>>
);

This does not work. I have not been able to call any assets in a PSensure. I have made this example as simple as possible. As far as I can tell, assets don't work in PSEnsure configurations. How can I store PowerShell functions

https://docs.microsoft.com/en-s/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-6

equivalent in Otter so I can call them in a PSEnsure? Am I doing something wrong?

To use script assets, use the CollectScript and/or ConfigureScript properties, for example:

# ensures the BuildMaster Agent service exists on the remote server, using a
# PowerShell script asset to perform the configuration
PSEnsure(
    Key: BuildMasterAgentInstalled,
    # returns the count of INEDOBMAGT services installed
    Collect: @(Get-Service | Where-Object {$_.Name -eq "INEDOBMAGT"}).Count,
    # expected value is 1
    Value: 1,
    # use script stored in InstallBmAgent asset
    ConfigureScript: InstallBmAgent,
    ConfigureScriptParams: %(
        AgentType: TCP,
        Port: 1000),
    Debug: true,
    Verbose: true
);

So looking at your example, I tried the "ConfigureScript: test". I have a powershell script asset called test with this in it:

function TestFunction (){
Write-Warning 'TestFunction was successful'
}
TestFunction

And this simple psensure:

##AH:UseTextMode

PSEnsure
(
Key: Test,
Value: True,
Collect: >>
$false

>>,
Configure: >>


>>,
ConfigureScript: Test

);

Won't run the asset as it says it can't find it, even though I see it fine under assets and when I look where my raft exists in bitbucket, it is there as well.

Even if it did run it, I can only run one script as it does not appear to be an array? That does not meet my requirement of being able to run multiple scripts/functions/assets/ whatever they are called.

So am I probably not explaining this very well. In my PSensure, I have pieces of code that I have to include many different times that I want to keep as a script asset/function, whatever. My intent is instead of duplicating this code 1000 times, I can change it in one place and just call the script from one location while doing my psensure. Make sense?

Update: so for whatever reason, after I left for lunch and came back, this particular gremlin decided to leave. I can call a single script, however, this does not meet my requirement of using separate multiple scripts for different functions, and I cannot run this with a configure block as well; it's one or the other.

So back to square one. Can this functionality be added in to run a script asset in a psensure?

Resolved via ticket:

If you want to call PowerShell functions, you need to wrap them in a PowerShell Module, then import that module in your PowerShell script asset. That's the only way I can think of that this will consistently work. I've implemented something like this before:

set $ModuleName = Hello-World;
Get-Asset $ModuleName.ps1
(
    Type: Script    
);
set $ModulePath = $PathCombine($WorkingDirectory, $ModuleName.ps1);

PSEnsure
(
    Key: Test,
    Value: True,
    Collect: "$false",
    Configure: >>
    Import-Module -Name "$ModulePath" -Verbose
    
    Hello-World "Testing 123"
    >>
);

which just writes a Hello-World script out and imports it as a PS module. You could probably figure out a better way than this e.g. creating a "PsModule" role that ensures the module is installed on any servers you're working with, then you'd only need the Import-Module command in your scripts to gain access to all your shared functions.