Introduction

For JS7 - Rollout of Scheduling Objects it is an option to use JS7 - Inventory Export and Import.

Besides import of objects the suggested rollout procedure considers a number of use cases:

  • Deploying/releasing scheduling objects.
  • Transferring existing orders to the latest version version of a workflow.
  • Removing inventory objects that are not included with the import archive.

The article explains automation of rollout using the JS7 - PowerShell Module.

Alternatively, users can implement rollout procedures from their preferred scripting/programming languages using the JS7 - REST Web Service API.

Rollout Script

The example of a Rollout Script is available for Linux, MacOS® and Windows. The Rollout Script makes use of the JS7 PowerShell Module release v2.0.21.

The script is intended as a baseline example for customization by JS7 users and by SOS within the scope of professional services.

Download: Rollout-SchedulingObjects.ps1


Example how to rollout scheduling objects
# Example for rollout of scheduling objects from an archive file

# ----- begin: adjust to your environment -----
$Url = 'https://apmacwin:4243/'
$Credential = ( New-Object -typename System.Management.Automation.PSCredential -ArgumentList 'root', ( 'root' | ConvertTo-SecureString -AsPlainText -Force) )
$ControllerId = "jobscheduler"

$ArchiveFile = "/tmp/export.zip"
$TempDir = "$env:TEMP"

$debugPreference = 'continue'
$verbosePreference = 'continue'
# Start-Transcript -Path ./console.log
# ----- end: adjust to your environment -----


# load module and authenticate
Import-Module JS7
Connect-JS7 -Url $Url -Credential $Credential -Id $ControllerId

# prepare
$suspendedOrders = @()
$blockedOrders = @()
$objectTypesToFileExtensions = @{   'WORKFLOW'='.workflow.json'; 
                                    'JOBRESOURCE'='.jobresource.json'; 
                                    'LOCK'='.lock.json'; 
                                    'NOTICEBOARD'='noticeboard.json'; 
                                    'FILEORDERSOURCE'='fileordersource.json'; 
                                    'WORKINGDAYSCALENDAR'='.calendar.json'; 
                                    'NONWORKINGDAYSCALENDAR'='.calendar.json'; 
                                    'SCHEDULE'='.schedule.json'; 
                                    'JOBTEMPLATE'='.jobtemplate.json'; 
                                    'INCLUDESCRIPT'='.includescript.json'; 
                                    'REPORT'='.report.json'
}

# step 1: import archive file
Import-JS7InventoryItem -FilePath $ArchiveFile -TargetFolder / -Overwrite

#         get top-level folders from archive file
$archiveDir = New-Item -Path $TempDir -Name $(New-Guid) -ItemType Directory
Expand-Archive -Path $ArchiveFile -DestinationPath $archiveDir

$topLevelFolders = Get-ChildItem -Path $archiveDir -Directory

try
{
    # step 2: deploy/release scheduling objects
    #         release baseline objects
    foreach( $folder in $topLevelFolders )
    {
        Publish-JS7ReleasableItem -Folder "/$($folder.Name)" -Recursive -Type 'INCLUDESCRIPT','JOBTEMPLATE'
    }
    
    #         deployable items
    foreach( $folder in $topLevelFolders )
    {
        Publish-JS7DeployableItem -ControllerId $ControllerId -Folder "/$($folder.Name)" -Recursive
    }
    
    #         release complex scheduling objects
    foreach( $folder in $topLevelFolders )
    {
        Publish-JS7ReleasableItem -Folder "/$($folder.Name)" -Recursive
    }
    
    
    # step 3: transfer orders to latest workflow version
    foreach( $folder in $topLevelFolders )
    {
        $workflows = Get-JS7Workflow -Folder $folder.Name -Recursive
        foreach( $workflow in $workflows )
        {
            # identify previous workflow versions
            if ( !$workflow.isCurrentVersion )
            {
                # check for non-transferable orders
                $orders = Get-JS7Order -WorkflowPath $workflow.path -WorkflowVersionId $workflow.versionId -Blocked
                if ( $orders.count )
                {
                    Write-Warning "blocked orders found for workflow $($workflow.path), orders will not be transferred to latest workflow version"
                    $blockedOrders += $orders
                }
    
                # check for suspended orders
                $orders = Get-JS7Order -WorkflowPath $workflow.path -WorkflowVersionId $workflow.versionId -Suspended
                if ( $orders.count )
                {
                    Write-Warning "suspended orders found for workflow $($workflow.path), orders will not be resumed"
                    $suspendedOrders += $orders
                }
    
                # suspend in progress and waiting orders
                $orders = ( Get-JS7Order -WorkflowPath $workflow.path -WorkflowVersionId $workflow.versionId -InProgress -Waiting | Suspend-JS7Order )
    
                # transfer orders to latest workflow version
                Set-JS7Order -Transfer -WorkflowPath $workflow.path -WorkflowVersionId $workflow.versionId
                
                # resume suspended orders
                $orders | Resume-JS7Order
            }
        }
    }
    
    if ( $blockedOrders.count )
    {
        Write-Warning "The following $($blockedOrders.count) blocked orders are preseent and cannot be transferred to latest workflow versions"
        Write-Warning $blockedOrders
    }
    
    if ( $suspendedOrders.count )
    {
        Write-Warning "The following $($suspended.count) suspended orders are preseent and have not beeen transferred to latest workflow versions"
        Write-Warning $suspendedOrders
    }
    
    # step 4: remove scheduling objects not available from archive file
    foreach( $folder in $topLevelFolders )
    {
        $objects = Get-JS7InventoryFolder -Folder $folder.Name -Recursive
        foreach( $object in $objects.PSObject.properties.value )
        {
            if ( $object.id )
            {
                # Write-Output "Test-Path -Path $($archiveDir)$($object.path)$($objectTypesToFileExtensions[$object.objectType])"
                if ( !(Test-Path -Path "$($archiveDir)$($object.path)$($objectTypesToFileExtensions[$object.objectType])") )
                {
                    # Remove-JS7InventoryItem -Path $object.path -Type $object.objectType
                    Write-Output "Remove-JS7InventoryItem -Path $($object.path) -Type $($object.objectType)"
                }
            }
        }
    }
} catch {
    $message = $_.Exception | Format-List -Force | Out-String
    throw "Exception occurred in line number $($_.InvocationInfo.ScriptLineNumber)`n$($message)"
} finally {
    # cleanup
    Remove-Item -Path $archiveDir -Force -Recurse
    Disconnect-JS7
    # Stop-Transcript
}

Parameterization

The first few lines of the Rollout Script specify variables that are used to adjust the script to individual environments:

CategoryVariableValue
AuthenticationUrl

Specifies the JOC Cockpit URL. A number of ways are offered how to connect using HTTP and HTTPS using account/password authentication and certificate based authentication.

For details see JS7 - How to connect to JOC Cockpit using the PowerShell Module.


CredentialSpecifies the credential object if account/password authentication is used.

ControllerIdSpecifies the ID of the Controller to which objects should be deployed.
ImportArchiveFileSpecifies the path to the import archive file that holds scheduling objects.

TempDir

Specifies a directory for temporary files:

Unix: /tmp

Windows: $env:TEMP

LoggingdebugPreference

Enables/disables debug output for cmdlets of the JS7 PowerShell Module:

$debugPreference = "continue" # enable debug output

$debugPreference = "silentlycontinue" # disable debug output


verbosePreference

Enables/disables verbose output for cmdlets of the JS7 PowerShell Module:

$verbosePreference = "continue" # ensable verbose output

$verbosePreference = "silentlycontinue" # disable verbose output

Step 1: Import Archive File

This step works from a call to the Import-JS7InventoryItem cmdlet.

Existing objects such as workflows, schedules etc. that are available from the archive file will be overwritten.

Step 2: Deploy/Release Scheduling Objects

This step carries out the following sub-steps:

Step 3: Transfer Orders to latest Workflow Version

If a new workflow version is deployed then JS7 keeps the previous version of a workflow for which orders exist. The reason being that orders assigned the previous workflow version that have been started should be able to continue in the previous workflow version. If no orders exist for a previous workflow version, then this version will disappear. For details see JS7 - Workflows - Status Operations on Orders.

For users who wish to transfer existing orders to the latest workflow version the Rollout Script implements the desired behavior.

  • A number of order states such as INPROGRESS and WAITING for specific events do not suggest orders to be transferred. Such orders are suspended to allow transfer to the latest workflow version and are later on resumed.
  • BLOCKED orders cannot be transferred as they indicate missing connections from a Controller to the related Agent.
  • RUNNING orders are ignored as they are assumed to complete the workflow.

This step makes use of the Get-JS7WorkflowGet-JS7OrderSuspend-JS7OrderResume-JS7Order and Set-JS7Order cmdlets.

Step 4: Remove Scheduling Objects not available from Archive File

If an import archive file includes fewer objects than available from the inventory then this can indicate that such objects should be removed.

The Rollout Script implements synchronization between the import archive file and the inventory based on top-level folders available from the import archive file.

The Get-JS7InventoryFolder cmdlet is used to traverse the inventory, the Remove-JS7InventoryItem cmdlet can be used to remove scheduling objects from the inventory.

Further Resources