Search code examples
kubernetesconditional-statementsargo-workflowsargocd

Argo workflow when a condition for substring match


I want to execute a task in Argo workflow if a string starts with a particular substring. For example, my string is tests/dev-or.yaml and I want to execute task if my string starts with tasks/

Here is my workflow but the condition is not being validated properly

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: conditional-
spec:
  entrypoint: conditional-example
  arguments:
    parameters:
    - name: should-print
      value: "tests/dev-or.yaml"

  templates:
  - name: conditional-example
    inputs:
      parameters:
      - name: should-print
    steps:
    - - name: print-hello
        template: whalesay
        when: "{{inputs.parameters.should-print }} startsWith 'tests/'"

  - name: whalesay
    container:
      image: docker/whalesay:latest
      command: [sh, -c]
      args: ["cowsay hello"]

Below is the error it is giving when I run the workflow

WorkflowFailed 7s workflow-controller  Invalid 'when' expression 'tests/dev-or.yaml startsWith 'tests/'': Unable to access unexported field 'yaml' in token 'or.yaml'

Seems it is not accepting -, .yaml and / while evaluating the when condition.

Any mistake am making in my workflow? What's the right way to use this condition?


Solution

  • tl;dr - use this: when: "'{{inputs.parameters.should-print}}' =~ '^tests/'"

    Parameter substitution happens before the when expression is evaluated. So the when expression is actually tests/dev-or.yaml startsWith 'tests/'. As you can see, the first string needs quotation marks.

    But even if you had when: "'{{inputs.parameters.should-print}}' startsWith 'tests/'" (single quotes added), the expression would fail with this error: Cannot transition token types from STRING [tests/dev-or.yaml] to VARIABLE [startsWith].

    Argo Workflows conditionals are evaluated as govaluate expressions. govaluate does not have any built-in functions, and Argo Workflows does not augment it with any functions. So startsWith is not defined.

    Instead, you should use govaluate's regex comparator. The expression will look like this: when: "'{{inputs.parameters.should-print}}' =~ '^tests/'".

    This is the functional Workflow:

    apiVersion: argoproj.io/v1alpha1
    kind: Workflow
    metadata:
      generateName: conditional-
    spec:
      entrypoint: conditional-example
      arguments:
        parameters:
          - name: should-print
            value: "tests/dev-or.yaml"
      templates:
        - name: conditional-example
          inputs:
            parameters:
              - name: should-print
          steps:
            - - name: print-hello
                template: whalesay
                when: "'{{inputs.parameters.should-print}}' =~ '^tests/'"
        - name: whalesay
          container:
            image: docker/whalesay:latest
            command: [sh, -c]
            args: ["cowsay hello"]