Search code examples
kubernetesyamlkubernetes-helmhelmfileyq

Update nested array value in yaml with yq


Given a yaml file (helmfile) like the following

releases:
  - chart: ../charts/foo
    name: foo
    namespace: '{{ .Values.stack }}'
    values:
      - ../config/templates/foo-values.yaml.gotmpl
    set:
      - name: image.tag
        value: 22
      - name: replicas
        value: 1
  - chart: ../charts/bar
    name: bar
    namespace: '{{ .Values.stack }}'
    values:
      - ../config/templates/bar-values.yaml.gotmpl
    set:
      - name: image.bar_proxy.tag
        value: 46
      - name: image.bar.tag
        value: 29
      - name: replicas
        value: 1

I'm trying to figure out a clean way to update a specific image tag. For example, I'd like to update image.bar_proxy.tag from 46 to 51.

I have the following, which does the job, but it requires that you know the exact index of the array item:

yq -y '.releases[] |= if .name=="bar" then .set[0].value |= 51 else . end' helmfile-example.yaml

So if the array order were to change at some point this would break.

A preferred solution would be: "update image.bar_proxy.tag value from 46 to 51 where set[].name==image.bar_proxy.tag". Any ideas on how to achieve a more specific conditional selection like this?

FYI our yq version:

$ yq --version
yq 2.10.0

Solution

  • You can use the following filter to make it work. It works by dynamically selecting the index of the object where your tag exists. On the selected object .value=51 will update the value as you wanted. You can also use the -i flag to do in-place modification of the original file.

    yq -y '.releases[].set |= map(select(.name == "image.bar_proxy.tag").value=51)' yaml
    

    See the underlying jq filter acting on the JSON object at jq-playground