PSPuppetOrchestrator.psm1
Function Wait-PuppetNodePCPBroker { <# .SYNOPSIS Returns Hello world .DESCRIPTION Wait-PuppetNodePCPBroker was originally written in an effort to detect when nodes rebooted by evaluating a nodes's PCP Broker connected state. Since the advent of the reboot plan as seen in https://github.com/puppetlabs/puppetlabs-reboot/blob/master/plans/init.pp Wait-PuppetNodePCPBroker is no longer a viable solution. Never was to begin with really. .PARAMETER Timeout x .PARAMETER Token x .PARAMETER Master x .PARAMETER Node x .EXAMPLE PS> Get-HelloWorld Runs the command #> Param( [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master, [Parameter(Mandatory)] [string]$Node, [Parameter()] [int]$Timeout = 300 ) $detailsSplat = @{ token = $Token master = $master node = $node } # create a timespan $timespan = New-TimeSpan -Seconds $timeout # start a timer $stopwatch = [diagnostics.stopwatch]::StartNew() # get the broker status every 5 seconds until our timeout is met while ($stopwatch.elapsed -lt $timespan) { # get the broker status if (($one = Get-PuppetNodePCPBrokerDetails @detailsSplat).connected -eq $false) { # broker status is disconnected, sleep 5s and check again to confirm not a blip or false positive Write-Verbose "Broker status is $($one.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." Write-Verbose "Sleping 5 seconds and checking again." Start-Sleep -Seconds 5 if (($two = Get-PuppetNodePCPBrokerDetails @detailsSplat).connected -eq $false) { Write-Verbose "Broker status is still $($two.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." # broker status is disconnected, break out of the loop break } } else { Write-Verbose "Broker status is $($one.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." } Start-Sleep -Seconds 5 } if ($stopwatch.elapsed -ge $timespan) { Write-Error "Timeout of $Timeout`s has exceeded." break } Write-Verbose "$Node broker status confirmed disconnected." # get the broker status every 5 seconds until our timeout is met while ($stopwatch.elapsed -lt $timespan) { # get the broker status if (($three = Get-PuppetNodePCPBrokerDetails @detailsSplat).connected -eq $true) { # broker status is connected, sleep 5s and check again to confirm not a blip or false positive Write-Verbose "Broker status is $($three.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." Write-Verbose "Sleping 5 seconds and checking again." Start-Sleep -Seconds 5 if (($four = Get-PuppetNodePCPBrokerDetails @detailsSplat).connected -eq $true) { Write-Verbose "Broker status is still $($four.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." # broker status is connected, break out of the loop break } } else { Write-Verbose "Broker status is $($three.connected), (timeout: $($stopwatch.elapsed.TotalSeconds)s of $Timeout`s elapsed)." } Start-Sleep -Seconds 5 } if ($stopwatch.elapsed -ge $timespan) { Write-Error "Timeout of $Timeout`s has exceeded." break } Write-Verbose "$Node broker status confirmed connected." } Function Get-PuppetJob { <# .SYNOPSIS Get details on a Puppet job. .DESCRIPTION Get details on a Puppet job. .PARAMETER ID The ID of the job. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetJob -Token $token -Master $master -ID 906 description : report : @{id=https://puppet:8143/orchestrator/v1/jobs/906/report} name : 906 events : @{id=https://puppet:8143/orchestrator/v1/jobs/906/events} command : task type : task state : failed nodes : @{id=https://puppet:8143/orchestrator/v1/jobs/906/nodes} status : {@{state=ready; enter_time=2019-09-04T16:50:09Z; exit_time=2019-09-04T16:50:10Z}, @{state=running; enter_time=2019-09-04T16:50:10Z; exit_time=2019-09-04T16:50:43Z}, @{state=failed; enter_time=2019-09-04T16:50:43Z; exit_time=}} id : https://puppet:8143/orchestrator/v1/jobs/906 environment : @{name=production} options : @{description=; transport=pxp; noop=False; task=powershell_tasks::getkb; sensitive=System.Object[]; params=; scope=; environment=production} timestamp : 2019-09-04T16:50:43Z owner : @{email=; is_revoked=False; last_login=2019-09-04T16:48:50.049Z; is_remote=False; login=admin; is_superuser=True; id=42bf351c-f9ec-40af-84ad-e976fec7f4bd; role_ids=System.Object[]; display_name=Administrator; is_group=False} node_count : 3 node_states : @{failed=1; finished=2} #> Param( [Parameter(Mandatory)] [int]$ID, [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master ) $hoststr = "https://$master`:8143/orchestrator/v1/jobs/$id" $headers = @{'X-Authentication' = $Token} $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers $content = $result Write-Output $content } Function Get-PuppetJobReport { <# .SYNOPSIS Get the report for a given Puppet job. .DESCRIPTION Get the report for a given Puppet job. .PARAMETER ID The ID of the job. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetJobReport -Master $master -Token $token -ID 906 node state start_timestamp finish_timestamp timestamp events ---- ----- --------------- ---------------- --------- ------ den3w108r2psv2 failed 2019-09-04T16:50:10Z 2019-09-04T16:50:12Z 2019-09-04T16:50:12Z {} den3w108r2psv3 finished 2019-09-04T16:50:10Z 2019-09-04T16:50:42Z 2019-09-04T16:50:42Z {} den3w108r2psv4 finished 2019-09-04T16:50:10Z 2019-09-04T16:50:43Z 2019-09-04T16:50:43Z {} #> Param( [Parameter(Mandatory)] [int]$ID, [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master ) $hoststr = "https://$master`:8143/orchestrator/v1/jobs/$id/report" $headers = @{'X-Authentication' = $Token} $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers $result.count foreach ($server in $result.report) { Write-Output $server } } Function Get-PuppetJobResults { <# .SYNOPSIS Get the results from a Puppet job. .DESCRIPTION Get the results from a Puppet job. .PARAMETER ID The ID of the job. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetJobResults -Master $master -Token $token -ID 930 finish_timestamp : 10/4/19 3:45:26 PM transaction_uuid : start_timestamp : 10/4/19 3:45:18 PM name : den3w108r2psv5 duration : 7.767 state : finished details : result : @{Source=DEN3W108R2PSV5; HotFixID=KB2620704; Description=Security Update; InstalledBy=NT AUTHORITY\SYSTEM; InstalledOn=Thursday, September 06, 2018 12:00:00 AM} latest-event-id : 5709 timestamp : 10/4/19 3:45:26 PM finish_timestamp : 10/4/19 3:45:34 PM transaction_uuid : start_timestamp : 10/4/19 3:45:19 PM name : den3w108r2psv3 duration : 15.264 state : finished details : result : @{Source=DEN3W108R2PSV3; HotFixID=KB2620704; Description=Security Update; InstalledBy=; InstalledOn=Friday, September 07, 2018 12:00:00 AM} latest-event-id : 5712 timestamp : 10/4/19 3:45:34 PM finish_timestamp : 10/4/19 3:45:34 PM transaction_uuid : start_timestamp : 10/4/19 3:45:19 PM name : den3w108r2psv4 duration : 15.505 state : finished details : result : @{Source=DEN3W108R2PSV4; HotFixID=KB2620704; Description=Security Update; InstalledBy=; InstalledOn=Friday, September 07, 2018 12:00:00 AM} latest-event-id : 5713 timestamp : 10/4/19 3:45:34 PM #> Param( [Parameter(Mandatory)] [int]$ID, [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master ) $hoststr = "https://$master`:8143/orchestrator/v1/jobs/$id/nodes" $headers = @{'X-Authentication' = $Token} $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers Write-Output $result.items } Function Get-PuppetPCPNodeBrokerDetails { <# .SYNOPSIS Get a node's PCP broker details. .DESCRIPTION Get a node's PCP broker details. This is useful if you want to know the status of PCP before executing a task or plan. .PARAMETER Node The Puppet node name. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetPCPNodeBrokerDetails -Master $master -Token $token -Node 'den3w108r2psv3' name : den3w108r2psv3 connected : True broker : pcp://puppet/server timestamp : 10/2/19 2:01:53 AM #> Param( [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master, [Parameter(Mandatory)] [string]$Node ) $hoststr = "https://$master`:8143/orchestrator/v1/inventory/$node" $headers = @{'X-Authentication' = $Token} $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers Write-Output $result } Function Get-PuppetTask { <# .SYNOPSIS Get details on a Puppet task. .DESCRIPTION Get details on a Puppet task. .PARAMETER Module The module of the puppet task, if applicable. .PARAMETER Name The name of the Puppet task. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetTask -Master $master -Token $token -Name 'reboot' id : https://puppet:8143/orchestrator/v1/tasks/reboot/init name : reboot permitted : True metadata : @{description=Reboots a machine; implementations=System.Object[]; input_method=stdin; parameters=; supports_noop=False} files : {@{filename=init.rb; sha256=fb7e0e0de640b82844be931e59405de73e1e290c9540c204a6c79838a0e39fce; size_bytes=2556; uri=}, @{filename=nix.sh; sha256=dfb2ddfe17056c316d7260bcce853aabc5b18a266888f76b23314d0d4c8daee5; size_bytes=692; uri=}, @{filename=win.ps1; sha256=155f5ab7d63f1913ccf8f4f5563f1b2be2a49130a4787a8c48ff770cfe8e6415; size_bytes=785; uri=}} environment : @{name=production; code_id=} .EXAMPLE PS> Get-PuppetTask -Master $master -Token $token -Module 'powershell_tasks' -Name 'disablesmbv1' id : https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/disablesmbv1 name : powershell_tasks::disablesmbv1 permitted : True metadata : @{description=A task to test if SMBv1 is enabled and optionally disable it.; input_method=powershell; parameters=; puppet_task_version=1} files : {@{filename=disablesmbv1.ps1; sha256=c10f3ae37a6e2686c419ec955ee51f9894109ed073bf5c3b3280255b3785e0dc; size_bytes=3536; uri=}} environment : @{name=production; code_id=} #> Param( [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master, [Parameter()] [string]$Module, [Parameter(Mandatory)] [string]$Name ) $hoststr = "https://$master`:8143/orchestrator/v1/tasks/$Module/$Name" $headers = @{'X-Authentication' = $Token} # try and get the task in it's standard form $moduleName/$taskName try { $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers -ErrorAction SilentlyContinue } catch { # try and get the task again assuming it's built in with a default task name of 'init' (e.g. reboot/init) try { $hoststr = "https://$master`:8143/orchestrator/v1/tasks/$name/init" $result = Invoke-RestMethod -Uri $hoststr -Method Get -Headers $headers } catch { Write-Error $_.exception.message } } if ($result) { Write-Output $result } } Function Get-PuppetTasks { <# .SYNOPSIS Get a list of Puppet Tasks. .DESCRIPTION Get a list of Puppet Tasks. .PARAMETER Environment The environment to use. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE PS> Get-PuppetTasks -token $token -master $master id name permitted -- ---- --------- https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/getkb powershell_tasks::getkb True https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/account_audit powershell_tasks::account_audit True https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/switch powershell_tasks::switch True https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/ps1exec powershell_tasks::ps1exec True https://puppet:8143/orchestrator/v1/tasks/powershell_tasks/disablesmbv1 powershell_tasks::disablesmbv1 True #> Param( [Parameter(Mandatory)] [string]$token, [Parameter(Mandatory)] [string]$master, [Parameter()] [string]$environment='production' ) $uri = "https://$master`:8143/orchestrator/v1/tasks" $headers = @{'X-Authentication' = $Token} $body = @{'environment' = $environment} $result = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -Body $body Write-Output $result.items } Function Invoke-PuppetTask { <# .SYNOPSIS Invoke a Puppet task. .DESCRIPTION Invoke a Puppet task. .PARAMETER Task The name of the Puppet task to invoke. .PARAMETER Environment The name of the Puppet task environment. .PARAMETER Parameters A hash of parameters to supply the Puppet task, e.g. $Parameters = @{tp1 = 'foo';tp2 = 'bar'; tp3 = $true}. .PARAMETER Description A description to submit along with the task. .PARAMETER Scope An array of nodes the Puppet task will be invoked against, e.g. $Scope = @('DEN3W108R2PSV5','DEN3W108R2PSV4','DEN3W108R2PSV3'). .PARAMETER ScopeType When executing tasks against the /command/task API endpoint you can either use a scope type of 'node' or 'query'. At this time, PSPuppetOrchestrator only supports a ScopeType of 'node' which is the DEFAULT and only allowed option for the ScopeType parameter. .PARAMETER Wait An optional wait value in seconds that Invoke-PuppetTask will use to wait until the invoked task completes. If the wait time is exceeded Invoke-PuppetTask will return a warning. .PARAMETER WaitLoopInterval An optional time in seconds that the wait feature will re-check the invoked task. DEFAULTS to 5s. .PARAMETER Token The Puppet API orchestrator token. .PARAMETER Master The Puppet master. .EXAMPLE $invokePuppetTaskSplat = @{ Token = $token Master = $master Task = 'powershell_tasks::disablesmbv1' Environment = 'production' Parameters = @{action = 'set'; reboot = $true} Description = 'Disable smbv1 on 08r2 nodes.' Scope = @('DEN3W108R2PSV5','DEN3W108R2PSV4','DEN3W108R2PSV3') ScopeType = 'nodes' Wait = 120 WaitLoopInterval = 2 } PS> Invoke-PuppetTask @invokePuppetTaskSplat #> Param( [Parameter(Mandatory)] [string]$Token, [Parameter(Mandatory)] [string]$Master, [Parameter(Mandatory)] [string]$Task, [Parameter()] [string]$Environment = 'production', [Parameter()] [hashtable]$Parameters = @{}, [Parameter()] [string]$Description = '', [Parameter(Mandatory)] [string[]]$Scope, [Parameter()] [ValidateSet('nodes')] [string]$ScopeType = 'nodes', [Parameter()] [int]$Wait, [Parameter()] [int]$WaitLoopInterval = 5 ) $req = [PSCustomObject]@{ environment = $Environment task = $Task params = $Parameters description = $Description scope = [PSCustomObject]@{ $ScopeType = $Scope } } | ConvertTo-Json $req $hoststr = "https://$master`:8143/orchestrator/v1/command/task" $headers = @{'X-Authentication' = $Token} $result = Invoke-RestMethod -Uri $hoststr -Method Post -Headers $headers -Body $req $content = $result if ($wait) { # sleep 5s for the job to register Start-Sleep -Seconds 5 $jobSplat = @{ token = $Token master = $master id = $content.job.name } # create a timespan $timespan = New-TimeSpan -Seconds $Wait # start a timer $stopwatch = [diagnostics.stopwatch]::StartNew() # get the job state every 5 seconds until our timeout is met while ($stopwatch.elapsed -lt $timespan) { # options are new, ready, running, stopping, stopped, finished, or failed $job = Get-PuppetJob @jobSplat Write-Verbose $job.node_states if (($job.State -eq 'stopped') -or ($job.State -eq 'finished') -or ($job.State -eq 'failed')) { Write-Output $job break } Start-Sleep -Seconds $WaitLoopInterval } if ($stopwatch.elapsed -ge $timespan) { Write-Warning "Timeout of $wait`s has exceeded. Job $($job.name) may still be running. Last job status: $($job.State)." break } } else { Write-Output $content.job } } |