Check out what's in the latest release of Kabanero Learn More

Events operator specification

The main components of events infrastructure are:

  1. Event mediator: a definition of the events to be run within one container. It consists of a list of mediations and an optional HTTPS listener.

  2. Event mediation: user-defined logic used to transform or route events.

  3. Event connection: a definition of the connections between mediations.

Event mediator

An event mediator is a custom resource file that defines a list of mediations. For example:

apiVersion: events.kabanero.io/v1alpha1
kind: EventMediator
metadata:
  name: webhook
spec:
  createListener: true
  createRoute: true
  mediations:
    - mediation:
        name: webhook
        sendTo: [ "dest"  ]
        body:
          - = : 'sendEvent(dest, message)'

When the attribute createListener is true, an HTTPS listener is created to receive JSON data as input. In addition, a Kubernetes Service with the same name as the name of the mediator is created, to make the listener accessible. An OpenShift service that serves a self-signed TLS certificate is automatically created to secure the communications. No authentication or authorization is currently implemented.

The URL to send a JSON message to the mediation within the mediator is https://<mediator_name>/<mediation_name>; (for example, https://webhook/webhook). The <mediation_name> portion of the URL specifies a mediation within the mediator.

When both attributes createListener and createRoute are set to true, a new Kubernetes Route with the same name as the mediator is created to allow external access to the mediator. The external host name for the Route is installation- specific. The default URL to send a message to the mediation is https://<external_name>/<mediation_name>; (for example, https://webhook-default.apps.example.com/webhook).

Event Mediations

In the event mediator custom resource, each event mediation defines one path for message processing. The basic form is:

  mediations:
    - mediation:
        name: <mediation name>
        variables:
            - name: <variable-name-1>
              value: <variable-value-1>
            - name: <variable-name-2>
              value: <variable-value-2>
            ...
        sendTo: [ "destination 1", "destination 2", ...  ]
        body:
           <body>

The attributes are:

  1. mediation name: the name of the mediation. The URL to the mediator must include the mediation name as a component of the path.

  2. variables: predefined name/value pairs that can be used as predefined variables within the body of the mediation.

  3. sendTo: a list of variable names that represent destinations for the output message.

  4. body: body that contains code based on Common Expression Language (CEL) to process the message.

Two additional implicitly pre-defined variables are also available for a mediation:

  1. body: body of the incoming message

  2. header: HTTP header of the incoming message.

The body of a mediation is an array of JSON objects, where each object may contain one or multiples of:

  1. An assignment

    • Example of assignments. Note that variable name is optional.

      =: 'attrValue = 1"
      =: " sendEvent(dest, body, header)
  2. An if statement

    • Example 1:

      - if : ' attrvalue == "value1" '
        =: "sendEvent(dest1, message)"
    • Example 2:

      - if : ' attrvalue == "value1" '
        body:
          - =: "attr = "value1""
          - =: "sendEvent(dest1, body, header)"
  3. A switch statement

    • Example

      - switch:
        - if : ' attrvalue == "value1" '
          =: "sendEvent(dest1, body, header)"
        - if : 'attrValue == "value2" '
          =: "sendEvent(dest2, body, header)"
        - default:
          =: "sendEvent(dest3, body, header)"
  4. A default statement (if nested in a switch statement)

  5. A nested body

    • A body is an array of JSON objects, where each array element that may contain the attribute names: =, if, switch, and default.

    • The valid combinations of the attribute names in the same JSON object are:

    • =: : a single assignment statement

    • if and =: : The assignment is executed when the condition of the if is true

    • if and body: The body is executed when the condition of the if is true

    • switch and body: The body must be array of JSON objects, where each element of the array is either an if statement, or a default statement.

      For example:

      apiVersion: events.kabanero.io/v1alpha1
      kind: EventMediator
      metadata:
        name: example
      spec:
        createListener: true
        createRoute: true
        mediations:
          - mediation:
              name: mediation1
              sendTo: [ "dest1", "dest2", "dest3"  ]
              body:
                - =: 'attrValue = "" '
                - if: "has(body.attr)"
                  =: "attrValue = body.attr"
                - switch:
                    - if : ' attrValue == "value1" '
                      =: "sendEvent(dest1, body, header)"
                    - if : 'attrValue == "value2" '
                      =: "sendEvent(dest2, body, header)"
                    - default:
                      =: "sendEvent(dest3, body, header)"

Built-in functions

Additional built-in functions are provided to facilitate event processing and routing. These are in addition to standard functions in the Common Expression Language.

sendEvent

The sendEvent function sends an event to a destination.

Input:

  1. destination: destination variable to send the event

  2. body: a JSON compatible message body of message.

  3. header: HTTP header for the message.

Output: empty string if successful, otherwise an error message

Example:

  - =: 'sendEvent(tekton-listener, body, header)'

Event Connections

Event connections map the destinations of mediations to real endpoints. Currently only https endpoints are supported.

The following mediator configuration shows a mediation named webhook:

apiVersion: events.kabanero.io/v1alpha1
kind: EventMediator
metadata:
  name: webhook
spec:
  createListener: true
  createRoute: true
  mediations:
    - mediation:
        name: webhook
        sendTo: [ "dest"  ]
        body:
          - = : 'sendEvent(dest, body, header)'

The connection specification for this configuration might look similar to the following example:

apiVersion: events.kabanero.io/v1alpha1
kind: EventConnections
metadata:
  name: example1
spec:
  connections:
    - from:
        mediator:
            name: webhook
            mediation: webhook
            destination: dest
      to:
        - https:
            - url: https://mediator1/mediation1
              insecure: true
            - urlExpression: cel_expression
              insecure: true

The from attribute specifies:

  1. The name of the mediator

  2. The name of the mediation within the mediator

  3. The name of the destination for the mediation.

The to attribute currently supports only https endpoints. The URL can be any REST endpoint. If pointing to another mediator, the other mediator’s createListener attribute must be set to true, and the URL to use is: https://<service-name>/<mediation_name>;, where <service-name> is the name of the mediator.

You can use the urlExpression to enable dynamically generated destinations. It is a Common Expression Language expression evaluated within the scope of the mediation.

Webhook Processing

The mediator framework provides additional function to facilitate the processing of webhook messages.

Note: Currently, only GitHub webhook messages are supported.

For example:

apiVersion: events.kabanero.io/v1alpha1
kind: EventMediator
metadata:
  name: webhook
spec:
  createListener: true
  createRoute: true
  repositories:
    - github:
        secret: your-github-secret
        webhookSecret: my-webhook-secret
  mediations:
    - mediation:
        name: appsody
        selector:
          - urlPattern: webhook
          - repositoryType:
            file: .type1.yaml
            newVariable: message.body.webhooks-type1
        sendTo: [ "dest"  ]
        variables:
          - name: message.body.webhooks-tekton-service-account
            value: kabanero-pipeline
          body:
              - = : 'sendEvent(dest, body, header)'
    - mediation:
        name: gitops
        selector:
          - urlPattern: webhook
          - repositoryType:
            name: message.body.webhooks-type2
            file: .type2.yaml
        sendTo: [ "dest"  ]
        body:
          - = : 'sendEvent(dest, body, header)'

The repositories attribute defines repository related configuration. For a GitHub repository:

  1. secret: the name of the Kubernetes secret that contains the GitHub API token.

  2. webhookSecret: the name of the Kubernetes secret that contains your webhook secret. The value of the secretToken must match the secret you specified when configuring the webhook on GitHub.

The selector defines which mediation to call based on the specified criteria:

  1. urlPattern: matches the pattern to the incoming URL. Currently only an exact match is supported.

  2. repositoryType: matches the type of the repository. The mediation is called only if the specified file exists in the repository. The content of the file is read and bound to the the variable newVariable.

The variables section creates new variables.

In addition, the mediation automatically adds additional predefined variables to the body of the incoming message after the creation of the repository variables. Although these variables are meant to be used for Tekton event listeners, they are generic enough to be used by other downstream listeners as well.

  1. body.webhooks-tekton-git-server: The name of the incoming git server. For example, github.com.

  2. body.webhooks-tekton-git-org: The GitHub organization.

  3. body.webhooks-tekton-git-repo: The name of the GitHub repository.

  4. body.webhooks-tekton-git-branch: The branch in the GitHub repository.

  5. body.webhooks-tekton-event-type: Valid values are pull_request, push, or tag.

  6. body.webhooks-tekton-monitor: Set to true if the monitor task should be started.

When processing an incoming webhook message, the flow is:

  1. The GitHub secret, if set, is used to authenticate the sender.

  2. The variables body and header are created to store the body and header of the message.

  3. The selector is evaluated to locate the matching mediation.

  4. The pre-defined variables are created.

  5. The variables in the variables section are evaluated in order.

  6. The mediation logic is called.

Edit This Page