Skip to content

Events

GA

v2.11 and after

Overview

To support external webhooks, we have this endpoint /api/v1/events/{namespace}/{discriminator}. Events can be sent to that can be any JSON data.

These events can submit workflow templates or cluster workflow templates.

You may also wish to read about webhooks.

Authentication and Security

Clients wanting to send events to the endpoint need an access token.

It is only possible to submit workflow templates your access token has access to: example role.

Example (note the trailing slash):

curl https://localhost:2746/api/v1/events/argo/ \
  -H "Authorization: $ARGO_TOKEN" \
  -d '{"message": "hello"}'

With a discriminator:

curl https://localhost:2746/api/v1/events/argo/my-discriminator \
  -H "Authorization: $ARGO_TOKEN" \
  -d '{"message": "hello"}'

The event endpoint will always return in under 10 seconds because the event will be queued and processed asynchronously. This means you will not be notified synchronously of failure. It will return a failure (503) if the event processing queue is full.

Processing Order

Events may not always be processed in the order they are received.

Workflow Template triggered by the event

Before the binding between an event and a workflow template, you must create the workflow template that you want to trigger. The following one takes in input the "message" parameter specified into the API call body, passed through the WorkflowEventBinding parameters section, and finally resolved here as the message of the whalesay image.

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: my-wf-tmple
  namespace: argo
spec:
  templates:
    - name: main
      inputs:
        parameters:
          - name: message
            value: "{{workflow.parameters.message}}"
      container:
        image: docker/whalesay:latest
        command: [cowsay]
        args: ["{{inputs.parameters.message}}"]
  entrypoint: main

Submitting A Workflow From A Workflow Template

A workflow template will be submitted (i.e. workflow created from it) and that can be created using parameters from the event itself. The following example will be triggered by an event with "message" in the payload. That message will be used as an argument for the created workflow. Note that the name of the metadata header "x-argo-e2e" is lowercase in the selector to match. Incoming header names are converted to lowercase.

apiVersion: argoproj.io/v1alpha1
kind: WorkflowEventBinding
metadata:
  name: event-consumer
spec:
  event:
    # metadata header name must be lowercase to match in selector
    selector: payload.message != "" && metadata["x-argo-e2e"] == ["true"] && discriminator == "my-discriminator"
  submit:
    workflowTemplateRef:
      name: my-wf-tmple
    arguments:
      parameters:
      - name: message
        valueFrom:
          event: payload.message
Please, notice that "workflowTemplateRef" refers to a template with the name "my-wf-tmple", this template has to be created before the triggering of the event. After that you have to apply the above explained WorkflowEventBinding (in this example this is called event-template.yml) to realize the binding between Workflow Template and event (you can use kubectl to do that):

kubectl apply -f event-template.yml   

Finally you can trigger the creation of your first parametrized workflow template, by using the following call:

Event:

curl $ARGO_SERVER/api/v1/events/argo/my-discriminator \
    -H "Authorization: $ARGO_TOKEN" \
    -H "X-Argo-E2E: true" \
    -d '{"message": "hello events"}'

Malformed Expressions

If the expression is malformed, this is logged. It is not visible in logs or the UI.

Customizing the Workflow Metadata

You can customize the name of the submitted workflow as well as add annotations and labels. This is done by adding a metadata object to the submit object.

Normally the name of the workflow created from an event is simply the name of the template with a timestamp appended. This can be customized by setting the name in the metadata object.

Annotations and labels are added in the same fashion.

All the values for the name, annotations and labels are treated as expressions (see below for details). The metadata object is the same metadata type as on all Kubernetes resources and as such is parsed in the same manner. It is best to enclose the expression in single quotes to avoid any problems when submitting the event binding to Kubernetes.

This is an example snippet of how to set the name, annotations and labels. This is based on the workflow binding from above, and the first event.

  submit:
    metadata:
      annotations:
        anAnnotation: 'event.payload.message'
      name: 'event.payload.message + "-world"'
      labels:
        someLabel: '"literal string"'
This will result in the workflow being named "hello-world" instead of my-wf-tmple-<timestamp>. There will be an extra label with the key "someLabel" and a value of "literal string". There will also be an extra annotation with the key "anAnnotation" and a value of "hello"

Be careful when setting the name. If the name expression evaluates to that of a currently existing workflow, the new workflow will fail to submit.

The name, annotation and label expression must evaluate to a string and follow the normal Kubernetes naming requirements.

Event Expression Syntax and the Event Expression Environment

Event expressions are expressions that are evaluated over the event expression environment.

Expression Syntax

Because the endpoint accepts any JSON data, it is the user's responsibility to write a suitable expression to correctly filter the events they are interested in. Therefore, DO NOT assume the existence of any fields, and guard against them using a nil check.

Learn more about expression syntax.

Expression Environment

The event environment contains:

  • payload the event payload.
  • metadata event metadata, including HTTP headers.
  • discriminator the discriminator from the URL.

Payload

This is the JSON payload of the event.

Example:

payload.repository.clone_url == "http://gihub.com/argoproj/argo"

MetaData

Metadata is data about the event, this includes headers:

Headers

HTTP header names are lowercase and only include those that have x- as their prefix. Their values are lists, not single values.

  • Wrong: metadata["X-Github-Event"] == "push"
  • Wrong: metadata["x-github-event"] == "push"
  • Wrong: metadata["X-Github-Event"] == ["push"]
  • Wrong: metadata["github-event"] == ["push"]
  • Wrong: metadata["authorization"] == ["push"]
  • Right: metadata["x-github-event"] == ["push"]

Example:

metadata["x-argo"] == ["yes"]

Discriminator

This is only for edge-cases where neither the payload, or metadata provide enough information to discriminate. Typically, it should be empty and ignored.

Example:

discriminator == "my-discriminator"

High-Availability

Run Minimum 2 Replicas

You MUST run a minimum of two Argo Server replicas if you do not want to lose events.

If you are processing large numbers of events, you may need to scale up the Argo Server to handle them. By default, a single Argo Server can be processing 64 events before the endpoint will start returning 503 errors.

Vertically you can:

  • Increase the size of the event operation queue --event-operation-queue-size (good for temporary event bursts).
  • Increase the number of workers --event-worker-count (good for sustained numbers of events).

Horizontally you can:

  • Run more Argo Servers (good for sustained numbers of events AND high-availability).