Argo workflow when a condition for substring match

12/10/2021

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?

-- Biru
argo-workflows
argocd
conditional-statements
kubernetes

1 Answer

12/10/2021

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

Parameter substitution happens before 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"]
-- crenshaw-dev
Source: StackOverflow