Accessing Files Inside Templates

In the previous section we looked at several ways to create and access namedtemplates. This makes it easy to import one template from within anothertemplate. But sometimes it is desirable to import a file that is not atemplate and inject its contents without sending the contents through thetemplate renderer.

Helm provides access to files through the .Files object. Before we get goingwith the template examples, though, there are a few things to note about howthis works:

  • It is okay to add extra files to your Helm chart. These files will be bundled.Be careful, though. Charts must be smaller than 1M because of the storagelimitations of Kubernetes objects.
  • Some files cannot be accessed through the .Files object, usually forsecurity reasons.
    • Files in templates/ cannot be accessed.
    • Files excluded using .helmignore cannot be accessed.
  • Charts do not preserve UNIX mode information, so file-level permissions willhave no impact on the availability of a file when it comes to the .Filesobject.
  • Basic example
  • Path helpers
  • Glob patterns
  • ConfigMap and Secrets utility functions
  • Encoding
  • Lines

Basic example

With those caveats behind, let’s write a template that reads three files intoour ConfigMap. To get started, we will add three files to the chart, putting allthree directly inside of the mychart/ directory.

config1.toml:

  1. message = Hello from config 1

config2.toml:

  1. message = This is config 2

config3.toml:

  1. message = Goodbye from config 3

Each of these is a simple TOML file (think old-school Windows INI files). Weknow the names of these files, so we can use a range function to loop throughthem and inject their contents into our ConfigMap.

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: {{ .Release.Name }}-configmap
  5. data:
  6. {{- $files := .Files }}
  7. {{- range tuple "config1.toml" "config2.toml" "config3.toml" }}
  8. {{ . }}: |-
  9. {{ $files.Get . }}
  10. {{- end }}

This config map uses several of the techniques discussed in previous sections.For example, we create a $files variable to hold a reference to the .Filesobject. We also use the tuple function to create a list of files that we loopthrough. Then we print each file name ({{ . }}: |-) followed by the contentsof the file {{ $files.Get . }}.

Running this template will produce a single ConfigMap with the contents of allthree files:

  1. # Source: mychart/templates/configmap.yaml
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5. name: quieting-giraf-configmap
  6. data:
  7. config1.toml: |-
  8. message = Hello from config 1
  9. config2.toml: |-
  10. message = This is config 2
  11. config3.toml: |-
  12. message = Goodbye from config 3

Path helpers

When working with files, it can be very useful to perform some standardoperations on the file paths themselves. To help with this, Helm imports many ofthe functions from Go’s path package for youruse. They are all accessible with the same names as in the Go package, but witha lowercase first letter. For example, Base becomes base, etc.

The imported functions are:- Base- Dir- Ext- IsAbs- Clean

Glob patterns

As your chart grows, you may find you have a greater need to organize your filesmore, and so we provide a Files.Glob(pattern string) method to assist inextracting certain files with all the flexibility of globpatterns.

.Glob returns a Files type, so you may call any of the Files methods onthe returned object.

For example, imagine the directory structure:

  1. foo/:
  2. foo.txt foo.yaml
  3. bar/:
  4. bar.go bar.conf baz.yaml

You have multiple options with Globs:

  1. {{ range $path := .Files.Glob "**.yaml" }}
  2. {{ $path }}: |
  3. {{ .Files.Get $path }}
  4. {{ end }}

Or

  1. {{ range $path, $bytes := .Files.Glob "foo/*" }}
  2. {{ $path }}: '{{ b64enc $bytes }}'
  3. {{ end }}

ConfigMap and Secrets utility functions

(Available Helm 2.0.2 and after)

It is very common to want to place file content into both ConfigMaps andSecrets, for mounting into your pods at run time. To help with this, we providea couple utility methods on the Files type.

For further organization, it is especially useful to use these methods inconjunction with the Glob method.

Given the directory structure from the Glob example above:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: conf
  5. data:
  6. {{ (.Files.Glob "foo/*").AsConfig | indent 2 }}
  7. ---
  8. apiVersion: v1
  9. kind: Secret
  10. metadata:
  11. name: very-secret
  12. type: Opaque
  13. data:
  14. {{ (.Files.Glob "bar/*").AsSecrets | indent 2 }}

Encoding

You can import a file and have the template base-64 encode it to ensuresuccessful transmission:

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: {{ .Release.Name }}-secret
  5. type: Opaque
  6. data:
  7. token: |-
  8. {{ .Files.Get "config1.toml" | b64enc }}

The above will take the same config1.toml file we used before and encode it:

  1. # Source: mychart/templates/secret.yaml
  2. apiVersion: v1
  3. kind: Secret
  4. metadata:
  5. name: lucky-turkey-secret
  6. type: Opaque
  7. data:
  8. token: |-
  9. bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK

Lines

Sometimes it is desirable to access each line of a file in your template. Weprovide a convenient Lines method for this.

You can loop through Lines using a range function:

  1. data:
  2. some-file.txt: {{ range .Files.Lines "foo/bar.txt" }}
  3. {{ . }}{{ end }}

There is no way to pass files external to the chart during helminstall. So if you are asking users to supply data, it must be loaded usinghelm install -f or helm install —set.

This discussion wraps up our dive into the tools and techniques for writing Helmtemplates. In the next section we will see how you can use one special file,templates/NOTES.txt, to send post-installation instructions to the users ofyour chart.