helmfile/docs/templating.md

9.4 KiB

Templating

Helmfile uses Go templates for templating your helmfile.yaml. While go ships several built-in functions, we have added all of the functions in the Sprig library.

We also added the following functions:

More details on each function can be found at the "Template Functions" page in our documentation.

Using environment variables

Environment variables can be used in most places for templating the helmfile. Currently this is supported for name, namespace, value (in set), values and url (in repositories).

Examples:

repositories:
- name: your-private-git-repo-hosted-charts
  url: https://{{ requiredEnv "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/
releases:
  - name: {{ requiredEnv "NAME" }}-vault
    namespace: {{ requiredEnv "NAME" }}
    chart: roboll/vault-secret-manager
    values:
      - db:
          username: {{ requiredEnv "DB_USERNAME" }}
          password: {{ requiredEnv "DB_PASSWORD" }}
    set:
      - name: proxy.domain
        value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
      - name: proxy.scheme
        value: {{ env "SCHEME" | default "https" }}

Note

If you wish to treat your enviroment variables as strings always, even if they are boolean or numeric values you can use {{ env "ENV_NAME" | quote }} or "{{ env "ENV_NAME" }}". These approaches also work with requiredEnv.

Useful internal Helmfile environment variables

Helmfile uses some OS environment variables to override default behaviour:

  • HELMFILE_DISABLE_INSECURE_FEATURES - disable insecure features, expecting true lower case
  • HELMFILE_DISABLE_RUNNER_UNIQUE_ID - disable unique logging ID, expecting any non-empty value
  • HELMFILE_SKIP_INSECURE_TEMPLATE_FUNCTIONS - disable insecure template functions, expecting true lower case
  • HELMFILE_USE_HELM_STATUS_TO_CHECK_RELEASE_EXISTENCE - expecting non-empty value to use helm status to check release existence, instead of helm list which is the default behaviour
  • HELMFILE_EXPERIMENTAL - enable experimental features, expecting true lower case
  • HELMFILE_ENVIRONMENT - specify Helmfile environment, it has lower priority than CLI argument --environment
  • HELMFILE_TEMPDIR - specify directory to store temporary files
  • HELMFILE_UPGRADE_NOTICE_DISABLED - expecting any non-empty value to skip the check for the latest version of Helmfile in helmfile version
  • HELMFILE_GO_YAML_V3 - use go.yaml.in/yaml/v3 instead of go.yaml.in/yaml/v2. It's false by default in Helmfile v0.x, and true in Helmfile v1.x.
  • HELMFILE_CACHE_HOME - specify directory to store cached files for remote operations
  • HELMFILE_FILE_PATH - specify the path to the helmfile.yaml file
  • HELMFILE_INTERACTIVE - enable interactive mode, expecting true lower case. The same as --interactive CLI flag
  • HELMFILE_RENDER_YAML - force helmfile.yaml to be rendered as a Go template regardless of file extension, expecting true lower case. Useful for migrating from v0 to v1 without renaming files to .gotmpl
  • HELMFILE_AWS_SDK_LOG_LEVEL - configure AWS SDK logging level for vals library. Valid values: off (default, secure, case-insensitive), minimal, standard, verbose, or custom comma-separated values like request,response. See issue #2270 for details
  • HELMFILE_VALS_FAIL_ON_MISSING_KEY_IN_MAP - enable strict mode for vals secret references. When set to true (or any value accepted by Go's strconv.ParseBool like TRUE, 1), vals will fail when a referenced key does not exist in the secret map. Invalid values will cause an error when vals is initialized (when secret refs are first evaluated). Default is false (when unset or empty) for backward compatibility. See issue #1563 for details

Templates

You can use go's text/template expressions in helmfile.yaml and values.yaml.gotmpl (templated helm values files). values.yaml references will be used verbatim. In other words:

  • for value files ending with .gotmpl, template expressions will be rendered
  • for plain value files (ending in .yaml), content will be used as-is

In addition to built-in ones, the following custom template functions are available:

  • readFile reads the specified local file and generate a golang string
  • readDir reads the files within provided directory path. (folders are excluded)
  • readDirEntries Returns a list of https://pkg.go.dev/os#DirEntry within provided directory path
  • fromYaml reads a golang string and generates a map
  • setValueAtPath PATH NEW_VALUE traverses a golang map, replaces the value at the PATH with NEW_VALUE
  • toYaml marshals a map into a string
  • get returns the value of the specified key if present in the .Values object, otherwise will return the default value defined in the function

Values Files Templates

You can reference a template of values file in your helmfile.yaml like below:

releases:
- name: myapp
  chart: mychart
  values:
  - values.yaml.gotmpl

Every values file whose file extension is .gotmpl is considered as a template file.

Suppose values.yaml.gotmpl was something like:

{{ readFile "values.yaml" | fromYaml | setValueAtPath "foo.bar" "FOO_BAR" | toYaml }}

And values.yaml was:

foo:
  bar: ""

The resulting, temporary values.yaml that is generated from values.yaml.gotmpl would become:

foo:
  # Notice `setValueAtPath "foo.bar" "FOO_BAR"` in the template above
  bar: FOO_BAR

Refactoring helmfile.yaml with values files templates

One of expected use-cases of values files templates is to keep helmfile.yaml small and concise.

See the example helmfile.yaml below:

releases:
  - name: {{ requiredEnv "NAME" }}-vault
    namespace: {{ requiredEnv "NAME" }}
    chart: roboll/vault-secret-manager
    values:
      - db:
          username: {{ requiredEnv "DB_USERNAME" }}
          password: {{ requiredEnv "DB_PASSWORD" }}
    set:
      - name: proxy.domain
        value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
      - name: proxy.scheme
        value: {{ env "SCHEME" | default "https" }}

The values and set sections of the config file can be separated out into a template:

helmfile.yaml:

releases:
  - name: {{ requiredEnv "NAME" }}-vault
    namespace: {{ requiredEnv "NAME" }}
    chart: roboll/vault-secret-manager
    values:
    - values.yaml.gotmpl

values.yaml.gotmpl:

db:
  username: {{ requiredEnv "DB_USERNAME" }}
  password: {{ requiredEnv "DB_PASSWORD" }}
proxy:
  domain: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
  scheme: {{ env "SCHEME" | default "https" }}

Importing values from any source

The exec template function that is available in values.yaml.gotmpl is useful for importing values from any source that is accessible by running a command:

A usual usage of exec would look like this:

mysetting: |
{{ exec "./mycmd" (list "arg1" "arg2" "--flag1") | indent 2 }}

Or even with a pipeline:

mysetting: |
{{ yourinput | exec "./mycmd-consume-stdin" (list "arg1" "arg2") | indent 2 }}

The possibility is endless. Try importing values from your golang app, bash script, jsonnet, or anything!

Then envExec same as exec, but it can receive a dict as the envs.

A usual usage of envExec would look like this:

mysetting: |
{{ envExec (dict "envkey" "envValue") "./mycmd" (list "arg1" "arg2" "--flag1") | indent 2 }}

Using .env files

Helmfile itself doesn't have an ability to load .env files. But you can write some bash script to achieve the goal:

set -a; . .env; set +a; helmfile sync

Please see #203 for more context.

Running Helmfile interactively

helmfile --interactive [apply|destroy|delete|sync] requests confirmation from you before actually modifying your cluster.

Use it when you're running helmfile manually on your local machine or a kind of secure administrative hosts.

For your local use-case, aliasing it like alias hi='helmfile --interactive' would be convenient.

Another way to use it is to set the environment variable HELMFILE_INTERACTIVE=true to enable the interactive mode by default. Anything other than true will disable the interactive mode. The precedence has the --interactive flag.

Running Helmfile without an Internet connection

Once you download all required charts into your machine, you can run helmfile sync --skip-deps to deploy your apps. With the --skip-deps option, you can skip running "helm repo update" and "helm dependency build".

bash and zsh completion

helmfile completion --help