YAML Techniques

Most of this guide has been focused on writing the template language. Here,we’ll look at the YAML format. YAML has some useful features that we, astemplate authors, can use to make our templates less error prone and easier toread.

Scalars and Collections

According to the YAML spec, there are twotypes of collections, and many scalar types.

The two types of collections are maps and sequences:

  1. map:
  2. one: 1
  3. two: 2
  4. three: 3
  5. sequence:
  6. - one
  7. - two
  8. - three

Scalar values are individual values (as opposed to collections)

Scalar Types in YAML

In Helm’s dialect of YAML, the scalar data type of a value is determined by acomplex set of rules, including the Kubernetes schema for resource definitions.But when inferring types, the following rules tend to hold true.

If an integer or float is an unquoted bare word, it is typically treated as anumeric type:

  1. count: 1
  2. size: 2.34

But if they are quoted, they are treated as strings:

  1. count: "1" # <-- string, not int
  2. size: '2.34' # <-- string, not float

The same is true of booleans:

  1. isGood: true # bool
  2. answer: "true" # string

The word for an empty value is null (not nil).

Note that port: "80" is valid YAML, and will pass through both the templateengine and the YAML parser, but will fail if Kubernetes expects port to be aninteger.

In some cases, you can force a particular type inference using YAML node tags:

  1. coffee: "yes, please"
  2. age: !!str 21
  3. port: !!int "80"

In the above, !!str tells the parser that age is a string, even if it lookslike an int. And port is treated as an int, even though it is quoted.

Strings in YAML

Much of the data that we place in YAML documents are strings. YAML has more thanone way to represent a string. This section explains the ways and demonstrateshow to use some of them.

There are three “inline” ways of declaring a string:

  1. way1: bare words
  2. way2: "double-quoted strings"
  3. way3: 'single-quoted strings'

All inline styles must be on one line.

  • Bare words are unquoted, and are not escaped. For this reason, you have to becareful what characters you use.
  • Double-quoted strings can have specific characters escaped with \. Forexample "\"Hello\", she said". You can escape line breaks with \n.
  • Single-quoted strings are “literal” strings, and do not use the \ to escapecharacters. The only escape sequence is '', which is decoded as a single'.

In addition to the one-line strings, you can declare multi-line strings:

  1. coffee: |
  2. Latte
  3. Cappuccino
  4. Espresso

The above will treat the value of coffee as a single string equivalent toLatte\nCappuccino\nEspresso\n.

Note that the first line after the | must be correctly indented. So we couldbreak the example above by doing this:

  1. coffee: |
  2. Latte
  3. Cappuccino
  4. Espresso

Because Latte is incorrectly indented, we’d get an error like this:

  1. Error parsing file: error converting YAML to JSON: yaml: line 7: did not find expected key

In templates, it is sometimes safer to put a fake “first line” of content in amulti-line document just for protection from the above error:

  1. coffee: |
  2. # Commented first line
  3. Latte
  4. Cappuccino
  5. Espresso

Note that whatever that first line is, it will be preserved in the output of thestring. So if you are, for example, using this technique to inject a file’scontents into a ConfigMap, the comment should be of the type expected bywhatever is reading that entry.

Controlling Spaces in Multi-line Strings

In the example above, we used | to indicate a multi-line string. But noticethat the content of our string was followed with a trailing \n. If we want theYAML processor to strip off the trailing newline, we can add a - after the|:

  1. coffee: |-
  2. Latte
  3. Cappuccino
  4. Espresso

Now the coffee value will be: Latte\nCappuccino\nEspresso (with no trailing\n).

Other times, we might want all trailing whitespace to be preserved. We can dothis with the |+ notation:

  1. coffee: |+
  2. Latte
  3. Cappuccino
  4. Espresso
  5. another: value

Now the value of coffee will be Latte\nCappuccino\nEspresso\n\n\n.

Indentation inside of a text block is preserved, and results in the preservationof line breaks, too:

  1. coffee: |-
  2. Latte
  3. 12 oz
  4. 16 oz
  5. Cappuccino
  6. Espresso

In the above case, coffee will be Latte\n 12 oz\n 16 oz\nCappuccino\nEspresso.

Indenting and Templates

When writing templates, you may find yourself wanting to inject the contents ofa file into the template. As we saw in previous chapters, there are two ways ofdoing this:

  • Use {{ .Files.Get "FILENAME" }} to get the contents of a file in the chart.
  • Use {{ include "TEMPLATE" . }} to render a template and then place itscontents into the chart.

When inserting files into YAML, it’s good to understand the multi-line rulesabove. Often times, the easiest way to insert a static file is to do somethinglike this:

  1. myfile: |
  2. {{ .Files.Get "myfile.txt" | indent 2 }}

Note how we do the indentation above: indent 2 tells the template engine toindent every line in “myfile.txt” with two spaces. Note that we do not indentthat template line. That’s because if we did, the file content of the first linewould be indented twice.

Folded Multi-line Strings

Sometimes you want to represent a string in your YAML with multiple lines, butwant it to be treated as one long line when it is interpreted. This is called“folding”. To declare a folded block, use > instead of |:

  1. coffee: >
  2. Latte
  3. Cappuccino
  4. Espresso

The value of coffee above will be Latte Cappuccino Espresso\n. Note that allbut the last line feed will be converted to spaces. You can combine thewhitespace controls with the folded text marker, so >- will replace or trimall newlines.

Note that in the folded syntax, indenting text will cause lines to be preserved.

  1. coffee: >-
  2. Latte
  3. 12 oz
  4. 16 oz
  5. Cappuccino
  6. Espresso

The above will produce Latte\n 12 oz\n 16 oz\nCappuccino Espresso. Note thatboth the spacing and the newlines are still there.

Embedding Multiple Documents in One File

It is possible to place more than one YAML documents into a single file. This isdone by prefixing a new document with —- and ending the document with

document:1

document: 2 …

In many cases, either the —- or the may be omitted.

Some files in Helm cannot contain more than one doc. If, for example, more thanone document is provided inside of a values.yaml file, only the first will beused.

Template files, however, may have more than one document. When this happens, thefile (and all of its documents) is treated as one object during templaterendering. But then the resulting YAML is split into multiple documents beforeit is fed to Kubernetes.

We recommend only using multiple documents per file when it is absolutelynecessary. Having multiple documents in a file can be difficult to debug.

YAML is a Superset of JSON

Because YAML is a superset of JSON, any valid JSON document should be validYAML.

  1. {
  2. "coffee": "yes, please",
  3. "coffees": [
  4. "Latte", "Cappuccino", "Espresso"
  5. ]
  6. }

The above is another way of representing this:

  1. coffee: yes, please
  2. coffees:
  3. - Latte
  4. - Cappuccino
  5. - Espresso

And the two can be mixed (with care):

  1. coffee: "yes, please"
  2. coffees: [ "Latte", "Cappuccino", "Espresso"]

All three of these should parse into the same internal representation.

While this means that files such as values.yaml may contain JSON data, Helmdoes not treat the file extension .json as a valid suffix.

YAML Anchors

The YAML spec provides a way to store a reference to a value, and later refer tothat value by reference. YAML refers to this as “anchoring”:

  1. coffee: "yes, please"
  2. favorite: &favoriteCoffee "Cappucino"
  3. coffees:
  4. - Latte
  5. - *favoriteCoffee
  6. - Espresso

In the above, &favoriteCoffee sets a reference to Cappuccino. Later, thatreference is used as *favoriteCoffee. So coffees becomes Latte, Cappuccino, Espresso.

While there are a few cases where anchors are useful, there is one aspect ofthem that can cause subtle bugs: The first time the YAML is consumed, thereference is expanded and then discarded.

So if we were to decode and then re-encode the example above, the resulting YAMLwould be:

  1. coffee: yes, please
  2. favorite: Cappucino
  3. coffees:
  4. - Latte
  5. - Cappucino
  6. - Espresso

Because Helm and Kubernetes often read, modify, and then rewrite YAML files, theanchors will be lost.