TT Lab
Get started
Learn Learning paths Courses

Authoring and Shipping Helm Charts

How You Write the Same Value Changes Its Type

Continue in TT Lab

Goal

You check the syntax of the --set family of options one at a time with a value dump, and compare, down to the JSON types, how the result differs between giving the same value in a values file and giving it with --set.

Why it matters

--set looks like a convenience option for when you are in a hurry, but it is actually a small language. A dot digs into depth, a comma splits values, braces make a list, brackets pick an element, and a backslash turns those rules off for a moment. Accidents from not knowing the types are more frequent than accidents from not knowing the syntax. --set image.tag=8 puts in the number 8, and tag: "8" in a values file puts in a string. If the chart has | quote applied, both look the same, but in a chart that does not, the manifest quietly changes. Deleting a value with null differs from leaving it as an empty string, and putting the body of a file in as a value needs a dedicated option. This lab makes all of these differences visible and checks them one by one.

Steps

  1. Create a /root/hc-set/dumper chart (name dumper, version 0.1.0). values.yaml holds image (repository registry.local/api, tag "1.10"), replicas: 2, nodeSelector: {}, args: [], and config: {}. templates/dump.yaml is a ConfigMap named <릴리스이름>-dump (release name) with a single dump.json key in data, whose value is the whole of .Values converted to JSON and wrapped in quotes. After rendering, extract only that JSON and save it to /root/hc-set/out/base.json.
  2. Without editing the defaults, using only --set, change image.repository to registry.local/web, replicas to 5, and args to a list of three elements alpha, beta, and gamma, render it, and save that JSON to /root/hc-set/out/basics.json.
  3. With --set, put kubernetes.io/os: linux in nodeSelector and feature.flag: beta in config, render, and save the JSON to /root/hc-set/out/escape.json. Both keys have a dot inside the name.
  4. Put in the same tag in three ways, render, and save each — --set image.tag=8 to /root/hc-set/out/num-set.json, --set-string image.tag=8 to /root/hc-set/out/num-setstring.json, and --set image.tag=1.10 to /root/hc-set/out/num-float.json. Check how the JSON type of image.tag diverges across the three files.
  5. With --set-json, put config as {"retries": 3, "mode": "strict"} and args as ["--a", "--b"], render, and save the JSON to /root/hc-set/out/setjson.json. retries must be a number.
  6. Create a three-line certificate-looking file at /root/hc-set/ca.pem (-----BEGIN CERTIFICATE-----, MIIBkTCB+wIJAKt, -----END CERTIFICATE-----). Put the content of this file in as the value of config.ca, render, and save the JSON to /root/hc-set/out/setfile.json. The content must go in, not the path.
  7. Using --set, delete image.tag (the key itself must disappear) and save the rendered JSON to /root/hc-set/out/null.json, and put name: first and value: 1 into element 0 of args, render, and save the JSON to /root/hc-set/out/index.json. value must be a number.
  8. Write image.tag: "8" and replicas: 5 in /root/hc-set/override.yaml and save the JSON rendered with that file to /root/hc-set/out/via-file.json. Save the result of giving the same two values as --set image.tag=8 --set replicas=5 to /root/hc-set/out/via-set.json, and the result of giving them as --set-string image.tag=8 --set replicas=5 to /root/hc-set/out/via-setstring.json. Take the difference between the file version and the set version with diff and leave it in /root/hc-set/out/compare.txt (since there is a difference, diff ends with a non-zero code).

Notes

A chart that exports the received values exactly as they are

Create a /root/hc-set/dumper chart (name dumper, version 0.1.0). values.yaml holds image (repository registry.local/api, tag "1.10"), replicas: 2, nodeSelector: {}, args: [], and config: {}. templates/dump.yaml is a ConfigMap named <릴리스이름>-dump (release name) with a single dump.json key in data, whose value is the whole of .Values converted to JSON and wrapped in quotes. After rendering, extract only that JSON and save it to /root/hc-set/out/base.json.

A single line {{ .Values | toJson | quote }} is enough. To pull only that string out of the render result, use yq -r '.data."dump.json"'. If you set it up this way, you can check even the types of values with your own eyes — if you dump as YAML, whether something is a string or a number is hidden behind the quoting rules.

Dots, commas, braces — the syntax of set

Without editing the defaults, using only --set, change image.repository to registry.local/web, replicas to 5, and args to a list of three elements alpha, beta, and gamma, render it, and save that JSON to /root/hc-set/out/basics.json.

A dot digs into depth, and a comma splits several values within one option. To give a whole list, use a list wrapped in braces ({a,b,c}) — wrap it in quotes so the shell does not expand the braces first. You can also use --set several times.

When there is a dot inside the key

With --set, put kubernetes.io/os: linux in nodeSelector and feature.flag: beta in config, render, and save the JSON to /root/hc-set/out/escape.json. Both keys have a dot inside the name.

If you write it without any handling, the dot is read as a symbol that digs into depth, and a nested map called io/os under kubernetes is created. Escape a dot that is part of the key with a backslash (\.). The shell also eats backslashes, so it is safer to wrap the whole option in single quotes.

Values that are read as numbers and values that are not

Put in the same tag in three ways, render, and save each — --set image.tag=8 to /root/hc-set/out/num-set.json, --set-string image.tag=8 to /root/hc-set/out/num-setstring.json, and --set image.tag=1.10 to /root/hc-set/out/num-float.json. Check how the JSON type of image.tag diverges across the three files.

--set puts in a number if the value is read as an integer. A value with a decimal point or one that starts with 0 is not read as an integer and stays a string — render it yourself to check. You can see the type with jq -r '.image.tag | type'. This is exactly where strings that look like numbers, such as image tags, cause trouble.

Put in a list and an object whole

With --set-json, put config as {"retries": 3, "mode": "strict"} and args as ["--a", "--b"], render, and save the JSON to /root/hc-set/out/setjson.json. retries must be a number.

To make a nested object with --set, you have to write it out flat like config.retries=3,config.mode=strict, and once an object goes inside a list it quickly becomes hard to read. --set-json takes the value as JSON as it is, so the types also go in as intended. Wrap it in single quotes so the shell does not touch the braces and quotes.

Put in the content of a file as a value

Create a three-line certificate-looking file at /root/hc-set/ca.pem (-----BEGIN CERTIFICATE-----, MIIBkTCB+wIJAKt, -----END CERTIFICATE-----). Put the content of this file in as the value of config.ca, render, and save the JSON to /root/hc-set/out/setfile.json. The content must go in, not the path.

If you give --set config.ca=/root/..., the path string becomes the value as it is. There is a separate dedicated option that reads a file and puts it in (skim the options starting with set in helm template --help). It is used when putting in multi-line values such as the body of a certificate or a configuration file.

Delete a value, and pick and change a list element

Using --set, delete image.tag (the key itself must disappear) and save the rendered JSON to /root/hc-set/out/null.json, and put name: first and value: 1 into element 0 of args, render, and save the JSON to /root/hc-set/out/index.json. value must be a number.

--set key=null does not empty that key but removes it. The result differs from an empty string (key=) — if the chart branches with if .Values.image.tag, the two cases behave the same, but they diverge in places that look with hasKey. You pick a list element's place with brackets, like args[0].name=....

When giving the same value in a file and with set

Write image.tag: "8" and replicas: 5 in /root/hc-set/override.yaml and save the JSON rendered with that file to /root/hc-set/out/via-file.json. Save the result of giving the same two values as --set image.tag=8 --set replicas=5 to /root/hc-set/out/via-set.json, and the result of giving them as --set-string image.tag=8 --set replicas=5 to /root/hc-set/out/via-setstring.json. Take the difference between the file version and the set version with diff and leave it in /root/hc-set/out/compare.txt (since there is a difference, diff ends with a non-zero code).

Of the three files, two are exactly the same and only one differs. First predict which two, and then check. If you sort the key order with jq -S . <파일> (with the file in the placeholder), comparison is easy. Since diff ends with a non-zero code, write it with || true or in a way that ignores the exit code.