Skip to content

Workflow DSL Specification

Shashank Mehra edited this page Nov 16, 2017 · 17 revisions

Note: Workflow DSL spec is still experimental and will probably change in the coming days as it evolves.

You can refer to the examples while reading this: https://github.com/flowgen/codon-examples

Written in YAML, each workflow should be placed in its own file. It has the following components:

  • name: Name of the workflow. This workflow will be referenced in swagger spec using this name. This name must be unique to the project. The workflow file can be organized into any directory structures inside the folder spec/server/workflows/. The name may only have alphanumeric characters or underscores.
  • description: Arbitrary text containing workflow description. Optional.
  • tasks: Map of task names to task objects. These specify the list of tasks available to this workflow. Currently tasks cannot be shared across different workflows. (WIP)
  • start: List of tasks which form the starting point for the workflow. All these tasks will be called concurrently.
  • output: Output object to be returned by the workflow. This will be rendered as json object in response. If a template renderer is attached to this API, then this output is passed on to the template as root object.
  • output-on-error: Output object to be returned by the workflow in case of an unexpected error. (Not implemented yet)

Task Object

Have a look at the Task Phases to understand how these elements get used during task execution.

A task object has the following common attributes:

  • publish: List of variables to publish to the workflow context. Any JSON-compatible data structure optionally containing expression to select precisely what needs to be published. Published variables will be accessible for downstream tasks via using expressions. Optional.
  • publish-on-error: Same as publish but evaluated in case of task execution failures. Optional
  • on-success: List of task to boolean expression mapping which will run after the task has completed successfully. If the expression specified as value for that task evaluates to true then the task is executed. All tasks in this list are executed concurrently. Optional.
  • on-error: Like on-success but run in case of task failure. Optional. (Not implemented yet)
  • on-complete: Like on-success but these tasks are run on both success and error, and these tasks are run after on-success/on-error tasks.

A task can be of a simple type or a loop type. The attributes for a simple type are:

  • action: Name of the action associated with the task.
  • input: Map of input name to value. Value of each parameter is a JSON-compliant type such as number, string etc, dictionary or list. It can also be an expression to extract values from existing data values.
  • timeout: Currently implemented only for swagger actions. This is an integer value specifying in milliseconds the timeout for upstream HTTP requests.

A loop type task can be made to iterate over an array and call another task with a new context based on each loop element. The attributes for a loop type are:

  • with-items: An expression which specifies an array over which this task iterates.
  • loop: A loop object describing the loop. Its attributes are:
    • task: The name of the task (not action) which is called on every iteration.
    • input: Similar to input attribute for task object, but it specifies the main context of the task being called. All variables specified here become part of a new main bucket passed on to the task.
    • publish: A loop task publishes a list of results instead of a single result. This is a list of variable names to expression for an element in the list. Optional
    • publish-on-error: Same as publish but evaluated in case element task execution fails. Optional (Not implemented yet)

Actions

An action is a reference to either a generated swagger operation, or a custom task which can be placed in actions package present in the project folder. Swagger actions are referenced as clients.<client_name>.<operation_method>_<underscored path> If you are referring to GET operation on path /to/path/<some_id> for client newapi1, then the action will be clients.newapi1.get_to_path_some_id. This is not straightforward and a solution is being worked on.

Custom Actions are referred to as actions.<underscored action name>. Custom actions need to be placed in actions package with function definition like:

func MyCustomAction(all_params map[string]interface{}) (*interface{}, error) {
}

This can be referenced using both actions.my_custom_action and actions.MyCustomAction. all_params has the entire main variable bucket to act on.

Input variables

For a task containing a swagger action, the input variables correspond to the input variables specified in the swagger definition of that client. How these variables are sent (as headers, path parameter or query parameter) is specified in the swagger spec.

Expressions

Expressions can be used to extract data from the variable buckets available in that context. These buckets are:

  • main: This bucket contains the input variables to the workflow and all other temporary variables published by the previous tasks. Input variables to the workflow correspond to the attribute names specified in the main.yml swagger definition for the service.
  • constants: This bucket contains all the constants defined in the config.yml file.
  • action: This bucket has a limited scope and only refers to the object returned by an action.
  • item: This bucket has a limited scope valid only in loop definition. It refers to the current item of an array being looped over.
  • task: This bucket has a limited scope and only in loop.publish expressions. It refers to the main bucket of a child task called in the loop.

Expressions are of the format <%expression_type expression %>. Expression types currently supported:

  • jmespath

    A sample expression is:

    <%jmes main.latest_post.id %>
    

    There are some extensions added to standard jmespath to make it usable. They are documented here: Jmespath extensions.

  • Django template expression: You can specify an expression using django template tags. The rendered string is parsed as json expression. A sample expression is:

    <%jngo {{ main.latest_post.id }} %>
    

    This can be helpful for string concatenation and formatting. Note: Custom filters are not available to jngo expressions yet.

These expressions will get the variable latest_post.id from the main variables bucket. Likewise you can refer to other buckets.

Output object

Output object specifies the final output to be returned to the client, or a template renderer if a renderer is attached to the API. Output object even supports multi-level objects:

output:
    body:
        key1:
            subkey1: <%jmes main.subkey1 %>
            subkey2: <%jmes main.subkey2 %>
        key2:
            subkey3: <%jmes main.subkey3 %>
            subkey4: <%jmes main.subkey4 %>
    status_code: <%jmes main.status_code %>

Output has the following children:

  • body: json representation of the body to be returned in the response
  • status_code: integer value to be returned as status code
  • headers(optional): A dictionary object specifying the response header name to value map, to be sent to the client

All the children of output support expressions at any level. Read more about post-processing here.

Clone this wiki locally