Reputation: 2246
Is there a way to provide an image name for the container template dynamically based on its input parameters?
We have more than 30 different tasks each with its own image and that should be invoked identically in a workflow. The number may vary each run depending on the output of a previous task. So we don't want to or even can't just hardcode them inside workflow YAML.
An easy solution would be to provide the image field for the container depending on the input parameter and have the same template for each of these tasks. But looks like it's impossible. This workflow doesn't work:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: hello-world-
spec:
entrypoint: whalesay
templates:
- name: whalesay
inputs:
parameters:
- name: image
default: whalesay:latest
container:
image: "docker/{{image}}"
command: [cowsay]
args: ["hello world"]
Is there some workaround for this particular case?
Also is there a document somewhere describing in which fields one can use workflow variables? Documentation page says only:
Some fields in a workflow specification allow for variable references which are automatically substituted by Argo.
Upvotes: 3
Views: 2727
Reputation: 8392
What you’re trying to do is definitely supported. Just change {{image}}
to the fully qualified variable name {{inputs.parameters.image}}
.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: hello-world-
spec:
entrypoint: whalesay
templates:
- name: whalesay
inputs:
parameters:
- name: image
default: whalesay:latest
container:
image: "docker/{{inputs.parameters.image}}"
command: [cowsay]
args: ["hello world"]
There is currently no documentation listing template-able fields. But there is an open issue for adding that documentation.
Upvotes: 5
Reputation: 2246
This is a possible workaround: to use when
and conditional run of a task. We need to list of all possible tasks with their container images though:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: test-dynamic-image-
spec:
entrypoint: main
templates:
- name: main
steps:
- - name: fanout-step
template: fanout
- - name: loop-step
template: options
arguments:
parameters:
- name: code
value: "{{item}}"
withParam: "{{steps.code-step.outputs.parameters.codes}}"
- name: fanout
script:
image: python:alpine3.6
command: [python]
source: |
import json
with open("/tmp/codes.json", 'w') as wf:
json.dump(["foo", "bar", "buz"], wf)
outputs:
parameters:
- name: codes
valueFrom:
path: /tmp/codes.json
- name: foo-code
script:
image: python:alpine3.6
command: [ python ]
source: |
print("foo-code")
- name: bar-code
script:
image: python:alpine3.6
command: [ python ]
source: |
print("bar-code")
- name: buz-code
script:
image: python:alpine3.6
command: [ python ]
source: |
print("buz-code")
- name: missed-code
script:
image: python:alpine3.6
command: [ python ]
source: |
print("THIS SHOULD NOT BE PRINTED")
- name: options
inputs:
parameters:
- name: code
steps:
- - name: foo-code-option
template: foo-code
when: "{{inputs.parameters.code}} == foo"
- name: bar-code-option
template: bar-code
when: "{{inputs.parameters.code}} == bar"
- name: buz-code-option
template: buz-code
when: "{{inputs.parameters.code}} == buz"
- name: missed-code-option
template: missed-code
when: "{{inputs.parameters.code}} == missed"
Upvotes: 0