In reviewing the App Orchestration API documentation, I realized that there is a section missing: the page explaining how to extend the AO agents somehow was missed when compiling the documentation into the product.

So now I present “The missing manual” for the AO 2.0 agent workflow extension mechanism. We will make sure this is included in the in-product help for the next version of AO.


API Documentation – Supplemental: Extending Agent Functionality

App Orchestration performs configuration on the products and components which it manages by executing workflows on agents. Each administrative task or configuration change may result in one or more workflows being executed, potentially across multiple products, domains, and datacenters. App Orchestration manages the scheduling of these workflows, and the dependencies between them.

The workflow logic is implemented as PowerShell functions on the machines which run App Orchestration agents. Each of these PowerShell functions can be extended or overridden.

Extending a workflow function

Create and sign your own PowerShell script files with function definitions that provide your workflow customizations, as described below.

Next, place this script in a folder on all of the agent machines within the workflow scope; for example, if the workflow is executed by XenDesktop delivery controllers, place the script onto all of the delivery controllers in the delivery site(s) where you wish your modification to take effect.

Configure the agents on these machines to pick up the override script by configuring the folder path where it resides:


<pre>    Import-Module CitrixCamAgent
    Set-CamAgentConfiguration -ExtensionsFolderPath <i>[Path]</i>
    Restart-Service CitrixCamAgent
</pre>

The agent will now execute your functions when running workflows.

Adding synchronous actions

This is the easiest way to extend the built-in workflows, as it provides a high level of compatibility across versions. If the built-in workflow logic is changed in a future version of App Orchestration, your override will continue to function without affecting the new logic.

Examples: logging before or after a workflow executes, or calling a 3rd party component to do some extra actions that complete quickly.

You may provide a function that executes before the workflow logic, by naming it with the verb Initialize and specifying the name of the workflow (without dashes) as the noun.
For example, to execute your own logic before the “Update-OU” workflow, create a function named Initialize-UpdateOU.

You may also provide a function that executes after the workflow logic, by naming it with
specifying the name of the workflow (without dashes) as the noun. For example, to execute your own logic after the “Update-OU” workflow, create a function named Complete-UpdateOU.

These functions should take as input the workflow data, and should return $True to indicate that the built-in logic can continue executing, following this pattern:


<pre>    Function Initialize-UpdateOU
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
            [PSObject] $WorkflowStep
        )

        process(
            # Your logic to execute before the built-in logic
            return $True
        )
    }

    Function Complete-UpdateOU
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
            [PSObject] $WorkflowStep
        )

        process(
            # Your logic to execute after the built-in logic
            return $True
        )
    }
</pre>

If the built-in logic changes, the override script will work with the new changes automatically.

Adding long-running actions

This method of overriding workflows is more complex, but still provides a high level of compatibility across versions. If the built-in workflow logic is changed in a future version of App Orchestration, your override will continue to function without affecting the new logic.

Where this differs from Adding synchronous actions is that the new logic you add can take an arbitrary amount of time to complete.

Examples: waiting for human intervention before the workflow continues, integration with a 3rd party component that takes an indeterminate amount of time to complete.

To do this, your application must be able to know when it is in progress, and when it has completed. You can perform long-running operations before or after built-in workflow logic using the Initialize and Complete verbs in function overrides, as described in Adding synchronous actions. However, you can return $False to indicate that your action is long running and has not completed yet.


<pre>    Function Initialize-UpdateOU
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
            [PSObject] $WorkflowStep
        )

        process(
            if (!(IsStarted $WorkflowStep))
            {
                StartMyProcess
            }
            if (!(IsComplete $WorkflowStep))
            {
                return $False
            }
            return $True
        )
    }
</pre>

In this example, you would need to provide the implementation of the functions <b>IsStarted</b>, <b>StartMyProcess</b>, and <b>IsComplete</b>.

Whenever your override function returns $False, it may take 5 minutes or more before it is queried again to determine completion.

Replacing a workflow function

This is the most difficult method of extending workflow functionality. It has two major challenges:

  1. The built-in logic for workflows is often quite complex. Altering them may have unintended consequences on the ability of App Orchestration to ensure correctness of the configuration.

  2. Adopting new versions of the App Orchestration components from Citrix will be challenging, as any new functionality will need to be emulated or extended manually by your override functions.

However, there may be cases where the extent of the customization you want requires this approach. It gives you ultimate flexibility in how the workflow executes.

The best approach for doing this is to start by finding the built-in workflow logic. It is
located in:

<pre>    %Program Files%\Citrix\CloudAppManagement\Agent\CitrixCamAgent</pre>

Search the files under this directory for the entry point of the workflow function. Workflow functions have Cam prepended on the noun portion of the function name; for example, the workflow “Update-OU” is located in a function called Update-CamOU.

Next, copy this logic into your own function with the same name, and tweak it where necessary for your customizations. Keeping your changes minimal is the best way to minimize the risk of unintended consequences in the rest of App Orchestration’s configuration system.

As long as your function has the same name and signature, and exists in the ExtensionsFolderPath configured as described in Extending a workflow function, the agent will use your function in place of the built-in logic.