How to parameterize a workflowTempateRef?
Asked Answered
S

2

6

I have a WorkflowTemplate "nyc-test-template" which I trigger via Argo Events and PubSub. So, if I publish a message {} into the PubSub topic "argo-events-nyc" the template specified via a workflowTempateRef is started. That does work just fine. Now I want to parameterize the to be started template.

My not-working draft looks as follows:

apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: pubsub-event-source-nyc
spec:
  template:
    serviceAccountName: argo-events
  pubSub:
    examplex:
      jsonBody: true
      topic: argo-events-nyc
      subscriptionID: argo-events-nyc-sub

---

apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: pubsub-sensor-nyc
spec:
  template:
    serviceAccountName: argo-events-sa
  dependencies:
    - name: pubsub-event-source-dep
      eventSourceName: pubsub-event-source-nyc
      eventName: examplex
  triggers:
    - template:
        name: argo-workflow-trigger
        argoWorkflow:
          group: argoproj.io
          version: v1alpha1
          resource: workflows
          operation: submit
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: nyc-test-template-
                namespace: argo
              spec:
                arguments:
                  parameters:
                    - name: wft
                      value: nyc-test-template
                workflowTemplateRef:
                  # I'm pretty sure this inputs block is useless. But leaving it out 
                  # and instead referencing arguments.parameters.wft won't work either.
                  inputs:
                    parameters:
                      - name: wft
                  name: "{{inputs.parameters.wft}}"
          parameters:
            - src:
                dependencyName: pubsub-event-source-dep
                dataKey: body.wft
              dest: spec.arguments.parameters.0.value

What I would like to happen is this:

  • an empty message {} would trigger "nyc-test-template"
  • the message {"wft": "my-template"} would trigger "my-template"

Instead publishing an empty message will cause the Sensor to throw an error:

2021-03-29T15:31:16.386441528Z2021/03/29 15:31:16 Failed to parse workflow: error unmarshaling JSON: while decoding JSON: json: unknown field "inputs"

Frankly speaking - above yaml took crude inspiration from this example. It's not really the result of an educated guess as I still don't understand the mechanics of how parameters, arguments and inputs are interacting.

Serpentine answered 29/3, 2021 at 15:32 Comment(0)
S
3

Credits go to Derek Wang.

apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: pubsub-sensor-nyc
spec:
  template:
    serviceAccountName: argo-events-sa
  dependencies:
    - name: pubsub-event-source-dep
      eventSourceName: pubsub-event-source-nyc
      eventName: examplex
  triggers:
    - template:
        name: argo-workflow-trigger
        argoWorkflow:
          group: argoproj.io
          version: v1alpha1
          resource: workflows
          operation: submit
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: nyc-test-template-
                namespace: argo
              spec:
                workflowTemplateRef:
                  name: nyc-test-template
          parameters:
            - src:
                dependencyName: pubsub-event-source-dep
                dataKey: body.wft
                value: nyc-test-template # default value
              dest: spec.workflowTemplateRef.name # <- this
Serpentine answered 29/3, 2021 at 18:32 Comment(0)
C
3

You can use when to toggle which template to use depending on a parameter.

Suppose I have two simple WorkflowTemplates like these:

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: t1
spec:
  templates:
    - name: whalesay-template
      container:
        image: docker/whalesay
        command: [cowsay]
        args: [t1]

---

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: t2
spec:
  templates:
    - name: whalesay-template
      container:
        image: docker/whalesay
        command: [cowsay]
        args: [t2]

I can choose to execute one or another template from the WorkflowTemplates depending on an argument passed to a Workflow (either manually or from an argo-events setup).

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: switch-
spec:
  entrypoint: pick
  arguments:
    parameters:
      - name: which
  templates:
    - name: pick
      steps:
        - - name: t1
            when: "{{workflow.parameters.which}} == t1"
            templateRef:
              name: t1
              template: whalesay-template
          - name: t2
            when: "{{workflow.parameters.which}} == t2"
            templateRef:
              name: t2
              template: whalesay-template

For top-level arguments to a Workflow, you can use workflow.parameters.SOMETHING.

Building on the above, you can use a JSON parsing tool like jq to retrieve toggle value and then choose your template based on that value.

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: switch-
spec:
  entrypoint: pick
  arguments:
    parameters:
      - name: json
  templates:
    - name: pick
      steps:
        - - name: parse
            template: parse
        - - name: t1
            when: "{{steps.parse.outputs.result}} == a"
            templateRef:
              name: t1
              template: whalesay-template
          - name: t2
            when: "{{steps.parse.outputs.result}} == b"
            templateRef:
              name: t2
              template: whalesay-template
    - name: parse
      container:
        image: jorgeandrada/alpine-jq
        command: [sh, -c]
        env:
          - name: JSON
            value: "{{workflow.parameters.json}}"
        args: [echo "$JSON" | jq -j '.test']

I should mention that using jq is a bit heavy-handed. In future versions of Argo (3.1+) there will be tools to inspect JSON more directly. But this solution is nicely reverse-compatible.

Combustor answered 29/3, 2021 at 17:47 Comment(2)
Thanks a lot - that is a fascinating solution! +1 But I just got hold of a more simple and direct solution.Serpentine
@Serpentine Sweet! Hope you'll post the better solution. :-)Combustor
S
3

Credits go to Derek Wang.

apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: pubsub-sensor-nyc
spec:
  template:
    serviceAccountName: argo-events-sa
  dependencies:
    - name: pubsub-event-source-dep
      eventSourceName: pubsub-event-source-nyc
      eventName: examplex
  triggers:
    - template:
        name: argo-workflow-trigger
        argoWorkflow:
          group: argoproj.io
          version: v1alpha1
          resource: workflows
          operation: submit
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: nyc-test-template-
                namespace: argo
              spec:
                workflowTemplateRef:
                  name: nyc-test-template
          parameters:
            - src:
                dependencyName: pubsub-event-source-dep
                dataKey: body.wft
                value: nyc-test-template # default value
              dest: spec.workflowTemplateRef.name # <- this
Serpentine answered 29/3, 2021 at 18:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.