Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Shell variables in yq 4 using env()

I want to build a pipeline function that replaces a value in a yaml file. For that I want to make both the
pattern and the replacement value variable. I have seen the env-variables-operators article in the yq docs, however I cannot find the relevant section.

I have a yaml file with the following content:

---
spec:
  source:
    helm:
      parameters:
        - name: "image.tag"
          value: "1.0.0"

I now want to build a pipeline function that will replace the value of the value key in the yaml.
I can do so with:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

$ yq '.spec.source.helm.parameters[0].value = "2.0.0"' myyaml.yml
---
spec:
  source:
    helm:
      parameters:
        - name: "image.tag"
          value: "2.0.0"

Now I want to make this command customizable.
What works:

$ VALUE=3.0.0
$ replacement=$VALUE yq '.spec.source.helm.parameters[0].value = env(replacement)' myyaml.yml
---
spec:
  source:
    helm:
      parameters:
        - name: "image.tag"
          value: "3.0.0"

What doesn’t work

$ VALUE=3.0.0
$ PATTERN=.spec.source.helm.parameters[0].value
$ replacement=$VALUE pattern=$PATTERN yq 'env(pattern) = env(replacement)'
spec:
  source:
    helm:
      parameters:
        - name: "image.tag"
          value: "1.0.0"

I have also tried to use strenv and wrapping the replacement pattern in quotes, but it is not working.
Can anyone help me with the correct syntax?

>Solution :

You can import data with env but not code. You could inject it (note the changes in the quoting), but this is bad practice as it makes your script very vulnerable:

VALUE='3.0.0'
PATTERN='.spec.source.helm.parameters[0].value'
replacement="$VALUE" yq "${PATTERN} = env(replacement)" myyaml.yml
---
spec:
  source:
    helm:
      parameters:
        - name: "image.tag"
          value: "3.0.0"

Better practice would be to import the path in a form that is interpretable by yq, e.g. as an array and using setpath:

VALUE='3.0.0'
PATTERN='["spec","source","helm","parameters",0,"value"]'
replacement="$VALUE" pattern="$PATTERN" yq 'setpath(env(pattern); env(replacement))' myyaml.yml
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading