26

I'd like to allow our developers to pass dynamic arguments to a helm template (Kubernetes job). Currently my arguments in the helm template are somewhat static (apart from certain values) and look like this

      Args:
        --arg1
        value1
        --arg2
        value2
        --sql-cmd
        select * from db

If I were run a task using the docker container without Kubernetes, I would pass parameters like so:

docker run my-image --arg1 value1 --arg2 value2 --sql-cmd "select * from db"

Is there any way to templatize arguments in a helm chart in such way that any number of arguments could be passed to a template.

For example.

cat values.yaml
...
arguments: --arg1 value1 --arg2 value2 --sql-cmd "select * from db"
...

or

cat values.yaml
...
arguments: --arg3 value3
...

I've tried a few approaches but was not successful. Here is one example:

     Args:          
      {{  range .Values.arguments }}
        {{ . }}
      {{ end }}
Aaron Bandelli
  • 1,238
  • 2
  • 14
  • 16

8 Answers8

19

Yes. In values.yaml you need to give it an array instead of a space delimited string.

cat values.yaml
...
arguments: ['--arg3', 'value3', '--arg2', 'value2']
...

or

cat values.yaml
...
arguments:
- --arg3
- value3
- --arg2
- value2
...

and then you like you mentioned in the template should do it:

     args:          
      {{  range .Values.arguments }}
        - {{ . }}
      {{ end }}

If you want to override the arguments on the command line you can pass an array with --set like this:

--set arguments={--arg1, value1, --arg2, value2, --arg3, value3, ....}
Rico
  • 58,485
  • 12
  • 111
  • 141
  • How does this work if you call `helm install` with `--set`? Can you now set an arbitrary number of arguments with arbitrary names? – Dan Jul 15 '19 at 12:54
  • If you do `--set` it basically overrides what's in the `values.yaml` – Rico Jul 15 '19 at 17:34
  • So you can do `--set arg1=val1 --set arg2=val2` etc? – Dan Jul 15 '19 at 22:43
  • 1
    In this case `arguments` is an array so it would have to be passed like this: `--set arguments={--arg1, value1, --arg2, value2, --arg3, value3, ....}. Passing arrays: https://github.com/helm/helm/issues/1987 – Rico Jul 16 '19 at 00:12
7

In your values file define arguments as:

extraArgs:
  argument1: value1
  argument2: value2
  booleanArg1:

In your template do:

    args:
{{- range $key, $value := .Values.extraArgs }}
    {{- if $value }}
    - --{{ $key }}={{ $value }}
    {{- else }}
    - --{{ $key }}
    {{- end }}
{{- end }}
030
  • 10,842
  • 12
  • 78
  • 123
Acid R
  • 71
  • 1
  • 1
3

The arguments format needs to be kept consistent in such cases. Here is my case and it works fine.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.app.name }}
  labels:
    app: {{ .Values.app.name }}
    instance: test
spec:
  replicas: {{ .Values.master.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.app.name }}
      instance: test
  template:
    metadata:
      labels:
        app: {{ .Values.app.name }}
        instance: test
    spec:
      imagePullSecrets:
        - name: gcr-pull-secret
      containers:
        - name: {{ .Values.app.name }}
          image: {{ .Values.app.image }}
          env:
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
          args:
              [
               "--users={{int .Values.cmd.users}}",
               "--spawn-rate={{int .Values.cmd.rate}}",
               "--host={{.Values.cmd.host}}",
               "--logfile={{.Values.cmd.logfile}}",
               "--{{.Values.cmd.role}}"]
          ports:
            - containerPort: {{ .Values.container.port }}
          resources:
            requests:
              memory: {{ .Values.container.requests.memory }}
              cpu: {{ .Values.container.requests.cpu }}
            limits:
              memory: {{ .Values.container.limits.memory }}
              cpu: {{ .Values.container.limits.cpu }}

Unfortunately following mixed args format does not work within container construct -

mycommand -ArgA valA --ArgB valB --ArgBool1 -ArgBool2 --ArgC=valC

The correct format of above command expected is -

mycommand --ArgA=valA --ArgB=valB --ArgC=valC --ArgBool1 --ArgBool2

This can be achieved by following constructs -

#Dockerfile last line 
ENTRYPOINT [mycommand]

#deployment.yaml
containers:
  - name: {{ .Values.app.name }}
    image: {{ .Values.app.image }}
    args: [
      "--ArgA={{ .Values.cmd.ArgA }}",
      "--ArgB={{ .Values.cmd.ArgB }}",
      "--ArgC={{ .Values.cmd.ArgC }}",
      "--{{ .Values.cmd.ArgBool1 }}",
      "--{{ .Values.cmd.ArgBool2 }}" ]

#values.yaml
cmd:
   ArgA: valA
   ArgB: valB
   ArgC: valC
   ArgBool1: "ArgBool1"
   ArgBool2: "ArgBool2"
Abhishek Kulkarni
  • 3,693
  • 8
  • 35
  • 42
2

Rico's answer needed to be improved. Using the previous example I've received errors like:

templates/deployment.yaml: error converting YAML to JSON: yaml or

failed to get versionedObject: unable to convert unstructured object to apps/v1beta2, Kind=Deployment: cannot restore slice from string

This is my working setup with coma in elements: ( the vertical format for the list is more readable )

cat values.yaml
...
arguments: [
    "--arg3,", 
    "value3,",
    "--arg2,",
    "value2,",
]
...

in the template should do it:

          args: [
{{  range .Values.arguments }}
{{ . }}
{{ end }}
          ]
Jake Sylvestre
  • 936
  • 3
  • 14
  • 39
2

because of some limitations, I had to work with split and to use a delimiter, so in my case:

deployment.yaml :

        {{- if .Values.deployment.args }}
        args:
        {{- range (split " " .Values.deployment.args) }}
        - {{ . }}
        {{- end }}
        {{- end }}

when use --set:

helm install --set deployment.args="--inspect server.js" ...

results with:

  - args:
    - --inspect
    - server.js
renemadsen
  • 161
  • 1
  • 9
dsaydon
  • 4,421
  • 6
  • 48
  • 52
0

helm install --name "airflow" stable/airflow --set secrets.database=mydatabase,secrets.password=mypassword

So this is the helm chart in question: https://github.com/helm/charts/tree/master/stable/airflow Now I want to overwrite the default values in the helm chart secrets.database and secrets.password so I use --set argument and then it is key=value pairs separated by commas.
helm install --name "<name for your chart>" <chart> --set key0=value0,key1=value1,key2=value2,key3=value3

Gajendra D Ambi
  • 3,832
  • 26
  • 30
0

Did you try this?

{{  range .Values.arguments }}
{{ . | quote }}
{{ end }}
Rui Martins
  • 3,337
  • 5
  • 35
  • 40
0

Acid R's key/value solution was the only thing that worked for me.

I ended up with this:

values.yaml

arguments: 
  url1: 'http://something1.example.com'
  url2: 'http://something2.example.com'
  url3: 'http://something3.example.com'
  url4: 'http://something3.example.com'

And in my template:

          args: 
          {{- range $key, $value := .Values.arguments }}
            - --url={{ $value }}
          {{- end }}

stratus
  • 101
  • 2