Authoring RPS Runbooks
Runbooks are PowerShell scripts (or workflows) that can be executed within a job host such as SMA. RPS Runbooks are PowerShell Runbooks that are designed to run within the context of RPS. In general, RPS Runbooks provide concise, reusable functionality, and use the Rps-Api PowerShell module to access and update CMDB data.
The terms "Runbook", "Workflow" and "Task Item" are all used interchangeably within RPS to refer to an RPS Runbook. The assignment of a single Runbook to a Computer (Target) for execution is a Task Assignment, which is executed as one job in SMA. The Task Assignment is the smallest unit of work in RPS, and its status is tracked in the RPS CMDB.
Glossary
The following are common terms used within RPS, Runbooks and Task Automation
Term | Definition |
---|---|
RPS | Rapid Provisioning System |
CMDB | RPS [Content Management] Database |
Rps-Api | PowerShell Module used to access and manipulate RPS configuration and task data |
SMA | Server Management Automation - hosts & runs runbooks, used by RPS' Master Controller to run RPS Task Assignments |
Runbook | PowerShell script which runs a simple task, usually run in SMA |
Master Controller / MC | RPS System Runbook which issues and monitors SMA jobs |
Task Item | Identifies a task (runbook) |
Task Map | Identifies a set of steps, what order they should be performed in, and what type of target items the steps apply to |
Step | Identify a single step within a Task Map |
Target Item | A device which is the target of a task item or task map |
Task Assignment | Assignment of a task item to a target. Corresponds to a single job in SMA |
Map Assignment | The assignment of a task map to a target and its descendants. The result is a set of Task Assignments that together make up a complex orchestration |
Task Assignment States
The following table defines the Task Assignment States used by RPS. Within PowerShell, the available states can be accessed via the $Rps.TaskStates
variable.
Term | Definition |
---|---|
NotReady | Task Assignment is new or is waiting on other jobs to complete, and not ready to be executed. |
Ready | Task Assignment is ready to be started, and will be started by SMA. |
Running | Task Assignment was started as a job in SMA (or Direct) and is currently executing. |
Completed | Task Assignment is complete, and processing of other Task Assignments in the Orchestration will continue. |
ErrorContinue | Task Assignment encountered an error, but processing of Orchestration will continue. |
ErrorStop | Task Assignment failed and processing of Orchestration should stop. |
Cancelled | Task Assignment was stopped, either from SMA or manually, and processing of Orchestration may stop. |
PendingUserAction | Task Assignment requires user approval before Orchestration can continue. See section on User Approvals. |
Retry | Task Assignment should be retried due to a failure. See section on Retry. |
Hosting Runbooks in SMA vs. Direct Execution
A full instance of RPS (RPS Node) includes the CMDB as a SQL Server database and an instance of SMA to host and execute RPS runbooks. Master Controller is a system runbook that runs every 60 seconds and monitors the CMDB and SMA to manage jobs. It is the coordinator between Map Assignments and individual SMA Jobs.
With RPS v2.3.2, some of the functionality that MC uses is exposed directly via the Rps-Api module, so that Task Assignments and Task Map Assignments (Orchestrations) can be executed directly in PowerShell. This is useful for an initial RPS Install process, where SMA and MC may not be available. It also helps for developing, testing and troubleshooting runbooks. See documentation around the Invoke-RpsTaskAssignment
and Invoke-RpsTaskMapAssignment
cmdlets for more information.
RPS Runbook Guidance
The following are the three primary guidelines for authoring RPS Runbooks.
- Runbooks are PowerShell scripts saved as
.ps1
files in the\Runbooks
folder, using the Verb-Noun naming convention. - Runbooks contain a single mandatory parameter,
[guid] $TaskAssignmentId
, to identify the Task Assignment. - Runbooks use the Rps-Api to access and update CMDB data, log important information, and update Task Assignment State.
Example Runbook
The following example is a simplified version of the Wait-Random.ps1
runbook, which can be used for guidance as well as sample task execution.
<# ... #>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Guid]
$TaskAssignmentId
)
#Requires -Modules Rps-Api
# Load Task Assignment and Target Item
$workflowName = $MyInvocation.MyCommand
$taskAssignment = Get-RpsTaskAssignment -Id $TaskAssignmentId
if (-not $taskAssignment)
{
Write-RpsLogItem @LogError -MessageTemplate $LoggingEvents.TaskAssignmentNotFound -Properties ($TaskAssignmentId, $workflowName)
throw "Task Assignment not loaded properly."
}
$targetItem = $taskAssignment.TargetItem
Write-RpsLogItem @LogInformation -MessageTemplate $LoggingEvents.StartingRunbook -Properties $workflowName, $TaskAssignmentId
Update-RpsTaskAssignment -TaskAssignment $taskAssignment -TaskState Running -StatusMessage "$workflowName is running on $($targetItem.Name)"
# Generate a random sleep time from 1-5 sec
$wait = Get-Random -Min 1 -Max 5
$waitMessage = 'Assignment: {TaskAssignmentId} on {TargetItem} waiting for {Wait} sec'
$logProps = @($TaskAssignmentId, $targetItem.Name, $wait)
Write-RpsLogItem -Level Information -Component Master -MessageTemplate $waitMessage -Properties $logProps
# Sleep
Start-Sleep -s $wait
Update-RpsTaskAssignment -TaskAssignment $taskAssignment -TaskState Completed -StatusMessage "Completed"
Updating Task Assignment State from a Runbook
To reduce boilerplate code, RPS will manage the Task Assignment's state as follows:
- When a Task Assignment is started (via SMA or Direct), its
TaskState
is automatically set to Running. - When a Task Assignment is completed (via SMA or Direct), and its
TaskState
is Running, theTaskState
is automatically set to Completed. - When a Task Assignment fails (via SMA or Direct), and its
TaskState
is Running, theTaskState
is automatically set to ErrorStop.
In the example runbook, notice that the TaskState
is never updated to Running or Completed.
To set the state manually, for error handling or a custom workflow, use the Update-RpsTaskAssignment
cmdlet and the common Task States listed above.
Example: Manually set State
This example manually sets the State to ErrorContinue if an error occurs in the try
block.
try
{
# do work here
}
catch
{
# catch error but allow orchestration to continue
# additional logging or error handling here
Update-RpsTaskAssignment -TaskAssignment $taskAssignment -TaskState $Rps.TaskStates.ErrorContinue -Message 'An error occurred in non-critical process.'
}
Logging from a Runbook
RPS supports structured logging via the Write-RpsLogItem
cmdlet. See the Rps-Api documentation for full description and examples.
For RPS Runbooks, it's important to understand how to associate information to the Task Assignment for diagnostics or telemetry.
To associate log data with an executing Task Assignment, you must supply a formatted message template with named replacement tokens and the Task Assignment's Id.
Example: Logging Information to the Task Assignment
This example, from the Wait-Random
runbook, shows how to properly log information to a Task Assignment from a runbook. Notice the template is a string with replacement tokens and the properties are simply an object array to associate to the tokens in the template.
# Generate a random sleep time from 1-5 sec
$wait = Get-Random -Min 1 -Max 5
$waitMessage = 'Assignment: {TaskAssignmentId} on {TargetItem} waiting for {Wait} sec'
$logProps = @($TaskAssignmentId, $target.Name, $wait)
Write-RpsLogItem -Level Information -MessageTemplate $waitMessage -Properties $logProps
Advanced Runbook Guidance
- Establishing a secure connection to a remote computer
- Scheduled/Recurring Task Assignments
- Retrying Task Assignments
- Require User Approval
Connect to Target Computer
Many Runbooks will need to connect to the Target (Computer) to perform their duty. To connect, you must get the appropriate credential and then establish a secure connection.
In RPS Runbooks, use the Get-RpsCredential
to load the right credential for the target. Then use New-SecureSession
from Rps-Api to make the connection.
#Requires -Modules Rps-Api
# Load assignment and target
$assignment = Get-RpsTaskAssignment -Id $TaskAssignmentId
$target = $assignment.TargetItem
try
{
# Retrieve LocalAdmin credentials for target computer
$localAdmin = Get-RpsCredential -TargetItem $target -Role 'LocalAdmin'
# Establish connection to target
$session = New-SecureSession -IPAddress $target.IPAddress -Type PsSession -Credential $localAdmin
# Do work on target
}
finally
{
if ($session)
{
# Clean up connection
Remove-PSSession -Session $session
}
}
Scheduled / Recurring Task Assignments
RPS supports scheduling of Task Assignments and Map Assignments. See the RPS Tasking Guide for examples of scheduling new Map Assignments and Task Assignments.
To have a Task Assignment repeat or recur, manually adjust the StartDate
and set TaskState
to Ready and RPS will run the Task Assignment again.
Caution
To prevent MC from inadvertently completing a recurring task, make sure to clear the SMAJobId when resetting the state.
Example: Set Task Assignment to Recur every 15 minutes
Use the following code in a runbook to have the Task Assignment recur.
Tip
To set a limit on execution counts, add a custom property to the TaskAssignment and logic to update it after each run.
$taskAssignment.StartDate = (Get-Date).AddMinutes(15)
$taskAssignment.TaskState = $Rps.TaskStates.Ready
$taskAssignment.SmaJobGuid = $null
Update-RpsTaskAssignment $taskAssignment
Retry Failed Task Assignments
RPS considers the Retry state similar to Ready. The only difference is that Retry indicates that the Task Assignment failed and is executing again, instead of running for the first time.
Starting with RPS v2.3.2 there is limited support for automatic retries, which was added to support some Rps Install features. To use an automatic retry, set a RetryCount
property on the Task Assignment. If the Task Assignment fails, RPS will automatically retry it and decrement the RetryCount
until all retries have been attempted.
This behavior can be simulated in runbooks and may be promoted to a built-in feature in RPS and SMA in a future release. This would also include a RetryCount
option in the UI or PowerShell when designing a Task Map.
Example: Use RetryCount to limit failures
Place the following sample code into the error handling section of a runbook to implement a limited # of retries. This will only retry a TaskAssignment that already has the RetryCount
set.
$retryCount = [Rps.Api.Utils.Extensions]::GetProperty($TaskAssignment, 'RetryCount', 0)
if ($retryCount -gt 0)
{
$TaskAssignment.RetryCount = $retryCount - 1
Update-RpsTaskAssignment -TaskAssignment $TaskAssignment -TaskState $Rps.TaskStates.Retry -StatusMessage 'Retry from Invoke-RpsTaskAssignment'
}
else
{
throw "Error on $($computer.Name) in $runbookName. Error: $($TaskAssignment.StatusMessage)"
}
Require User Approval
Some Tasks may require manual user approval to continue or stop processing. This approval step requires setting the Task Assignment’s state to PendingUserAction and setting a prompt for the operator. The operator then approves or denies the action using RPS Web or PowerShell. If approved, the Task’s State will be set to Completed. If denied, the state is set to Cancelled.
Example: Update Task Assignment for User Approval
Setting the required approval using the New-RpsTaskAssignmentUserAction cmdlet will create a prompt for the user in RPS Web.
New-RpsTaskAssignmentUserAction -TaskAssignment $taskAssignment `
-UserActionPrompt 'Approve Domain Join?' `
-UserActionApproveLabel 'Approve' `
-UserActionDenyLabel 'Deny'
Legacy Runbooks (Workflows) Guidance
Prior to RPS v2.1, all RPS Runbooks were authored as PowerShell workflows instead of pure PowerShell scripts. Some RPS Runbooks are still Workflows, and they require special guidance.
PSDisableSerializationPreference
PowerShell Workflows, and by inheritance SMA Runbooks, serialize objects without methods. This can limit the usability of some RPS objects' method calls. To use these methods, the PSDisableSerializationPreference needs to be set to true.
$PSDisableSerializationPreference = $true
Workflow Naming
As a matter of consistency and support for the DSC resource managing RPS, the Workflow name must match the script name.
Registering Runbooks in RPS
Runbooks in the /Runbooks
folder are automatically imported into RPS during install, via the /Setup/Configuration/Import-RpsTasks.ps1
script. Once a full RPS Node is operational and SMA is running, any new or modified scripts in the runbooks folder will be automatically registered and imported into RPS and SMA, using DSC as the folder monitor.
Manually publishing a Runbook in SMA
If you're authoring and testing a Runbook directly in SMA and don't want to wait for DSC to auto-register, you must manually import and publish the Runbook via SMA.
Example: Publish Runbook directly in SMA
$path = "$contentPath\Runbooks\$runbookName.ps1"
$wse = 'https://localhost:9090'
Import-SmaRunbook -Path $path -WebServiceEndpoint wse
Publish-SmaRunbook -Name $runbookName -WebServiceEndpoint $wse