One can pass function definitions as parameters to a ScriptBlock using the method described in this post (https://powershell.org/forums/topic/pass-function-definitions-to-scriptblock/), but this method only saves space in the ScriptBlock; it doesn’t prevent the functions from being defined twice.
I tried implementing actual lambda functions using this syntax:
$TestFunction = { param($server) write-host $server } $TestFunction.invoke($server)
This works for this simple example (the server name is returned), but implemented as follows in a larger script, the functions do not execute (i.e., running ScriptName.ps1 -ConfigFile Chef.config does not error out, but kicks back to the command prompt without doing anything).
Any ideas why the functions wouldn’t execute in this script?
Any help is appreciated.
$BootStrap = { param($Server,$Username,$Password) $NodeList = @(knife node list) if($NodeList -notcontains $server) { try { #knife bootstrap windows winrm $server --winrm-user $username --winrm-password $password --node-name $server --y Invoke-WebRequest https://devops-api.prd.costargroup.com/api/chef/bootstrap?server_name=$server Invoke-Command $server { chef-client } Write-Host `n"$server" -ForegroundColor Cyan -NoNewline; Write-Host " Bootstrap SUCCESS" -ForegroundColor Green [boolean]$BootstrapSuccess = "true" return [boolean]$BootstrapSuccess } catch { $ErrorMessage = $_.Exception.Message Write-Host "The error message was $ErrorMessage" [boolean]$BootstrapSuccess = "false" return [boolean]$BootstrapSuccess } } else{ Write-Host "$Server already exists in Chef, processing next server..." -ForegroundColor Yellow } } $RunChefClient = { param($server) Invoke-Command $server {chef-client} } $TestFunction = { param($server) write-host $server } $SetEnvironment = { param($Server,$Environment) if(!([string]::IsNullOrWhiteSpace($Environment))) { try{ knife node environment_set $server $environment 2> $null Write-Host `n"$server" -ForegroundColor Cyan -NoNewline; Write-Host " Environment set SUCCESS" -ForegroundColor Green } catch { $ErrorMessage = $_.Exception.Message Write-Host "The error message was $ErrorMessage" Throw "Environment set failed, stopping script..." Exit } } else {Write-Host "No valid environment to set, exiting..."; exit} } $SetTags = { param($Server,$Tags) foreach ($tag in $Tags) { try{ knife tag create $Server $Tag 2> $null write-host $Server -ForegroundColor Cyan -NoNewline; write-host " $($Tag) "-ForegroundColor Yellow -NoNewline; write-host "Tag Applied Successfully" -ForegroundColor Green } catch{ $ErrorMessage = $_.Exception.Message Write-Host "The error message was $ErrorMessage" Throw "Tag application failed, stopping script..." Exit } } } $SetRoles = { param($Server,$Roles) foreach ($role in $Roles) { try{ knife node run_list add $Server role[$($role)] 2> $null write-host $Server -ForegroundColor Cyan -NoNewline; write-host " $($role) "-ForegroundColor Yellow -NoNewline; write-host "Role Applied Successfully" -ForegroundColor Green } catch{ $ErrorMessage = $_.Exception.Message Write-Host "The error message was $ErrorMessage" Throw "Role application failed, stopping script..." Exit } } } $DisplayJobStatus = { $activity = 'Bootstrapping servers in $Servers and setting Chef environment...' #Get and display job status $RunningJobs = get-job | ? { $_.state -eq "running" } $InitialRunningJobsCount = $RunningJobs.count $CurrentRunningJobsCount = $RunningJobs.count while($CurrentRunningJobsCount -gt 0) { $PercentComplete=[math]::Round((($InitialRunningJobsCount-$CurrentRunningJobsCount)/$InitialRunningJobsCount * 100),2) write-progress -activity "$activity" -status "Progress: $PercentComplete%" -percentcomplete (($InitialRunningJobsCount-$CurrentRunningJobsCount)/$InitialRunningJobsCount*100) $Jobs | Receive-Job $CurrentRunningJobsCount = (get-job | ? { $_.state -eq "running" }).Count } } #Create bootstrap job for each server, pass lambda functions to Scriptblock for execution. if(($Username -ne $null) -and ($Password -ne $null)) { ForEach($HashTable in $Config) { $Server = $HashTable.Server $Roles = $HashTable.Roles $Tags = $HashTable.Tags $Environment = $HashTable.Environment $ScriptBlock = { param ($Server,$Roles,$Tags,$Environment,$Username,$Password,$BootStrap,$RunChefClient,$SetEnvironment,$SetTags,$SetRoles) if(($BootStrap.invoke($Server,$Username,$Password))) { $SetEnvironment.invoke($Server,$Environment) $SetTags.invoke($Server,$Tags) $SetRoles.invoke($Server,$Roles) $RunChefClient.invoke($Server) } else {Write-Host "Bootstrap failed, processing next server..."; return} } $Jobs += Start-Job -ScriptBlock $ScriptBlock -ArgumentList @($Server,$Roles,$Tags,$Environment,$Username,$Password,$BootStrap,$RunChefClient,$SetEnvironment,$SetTags,$SetRoles,$DisplayJobStatus) } #$DisplayJobStatus.invoke() } else {Write-Host "Username or password is missing, exiting..." -ForegroundColor Red; exit} } Main