Search code examples
unmarshallingargo-workflowsargo

Argo Workflow: "Bad Request: json: cannot unmarshal string into Go struct field"


I have a Argo WorkflowTemplate that looks like this:

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: test-container-command
spec:
  entrypoint: main
  templates:
  - name: main
    inputs:
      parameters:
        - name: command
    container:
      image: alpine:latest
      command: "{{ inputs.parameters.command }}"
    env: # some predefined env

What I want to do is to create a WorkflowTemplate that can execute an arbitrary command specified by the input parameter command. That way, users of this WorkflowTemplate can supply the parameter command with an array of strings and then execute it like:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: test-run-
spec:
  workflowTemplateRef:
    name: test-container-command
  entrypoint: main
  arguments:
    parameters:
    - name: command
      value:
        - echo
        - hello

However, when I try to save this WorkflowTemplate, the Argo server gave me this error message:

Bad Request: json: cannot unmarshal string into Go struct field Container.workflow.spec.templates.container.command of type []string

It seems that Argo expects the field .spec.templates.container.command to be an array of strings, but it treat "{{ inputs.parameters.command }}" as a string, even though I'm trying to supply the parameter command with an array of strings.

Is there any way to achieve what I was trying to do as the WorkflowTemplate test-container-command, i.e. provide a WorkflowTemplate for the user to execute arbitrary commands with a predefined container and env?


Solution

  • As it says in error command should be list of strings.

    You need to reformat your template to:

        container:
          image: alpine:latest
          command: ["{{ inputs.parameters.command }}"]
    

    Now argo should create your workflow without any problems

    You could also use

        container:
          image: alpine:latest
          command:
          - "{{ inputs.parameters.command }}"
    

    Edit

    As you want to run some commands within the image it would be much better instead of container use script template

    apiVersion: argoproj.io/v1alpha1
    kind: WorkflowTemplate
    metadata:
      name: test-container-command
    spec:
      entrypoint: main
      templates:
      - name: main
        inputs:
          parameters:
          - name: command
          - name: extraEnv
        script:
          image: alpine:latest
          command: [ "sh" ]
          env:
            - { name: ENV1, value: "foo" }
            - { name: ENV2, value: "{{ inputs.parameters.extraEnv }}" }
          source: |
            {{ inputs.parameters.command }}