helmfile/docs/templating.md

237 lines
9.4 KiB
Markdown

# Templating
Helmfile uses [Go templates](https://godoc.org/text/template) for templating your helmfile.yaml. While go ships several built-in functions, we have added all of the functions in the [Sprig library](https://godoc.org/github.com/Masterminds/sprig).
We also added the following functions:
* [`env`](templating_funcs.md#env)
* [`requiredEnv`](templating_funcs.md#requiredenv)
* [`exec`](templating_funcs.md#exec)
* [`envExec`](templating_funcs.md#envexec)
* [`readFile`](templating_funcs.md#readfile)
* [`readDir`](templating_funcs.md#readdir)
* [`readDirEntries`](templating_funcs.md#readdirentries)
* [`toYaml`](templating_funcs.md#toyaml)
* [`fromYaml`](templating_funcs.md#fromyaml)
* [`setValueAtPath`](templating_funcs.md#setvalueatpath)
* [`get`](templating_funcs.md#get) (Sprig's original `get` is available as `sprigGet`)
* [`getOrNil`](templating_funcs.md#getornil)
* [`tpl`](templating_funcs.md#tpl)
* [`required`](templating_funcs.md#required)
* [`fetchSecretValue`](templating_funcs.md#fetchsecretvalue)
* [`expandSecretRefs`](templating_funcs.md#expandsecretrefs)
* [`include`](templating_funcs.md#include)
More details on each function can be found at the ["Template Functions" page in our documentation](templating_funcs.md).
## 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:
```yaml
repositories:
- name: your-private-git-repo-hosted-charts
url: https://{{ requiredEnv "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/
```
```yaml
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](environments.md), 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](cli.md#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](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:
```yaml
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:
```yaml
{{ readFile "values.yaml" | fromYaml | setValueAtPath "foo.bar" "FOO_BAR" | toYaml }}
```
And `values.yaml` was:
```yaml
foo:
bar: ""
```
The resulting, temporary values.yaml that is generated from `values.yaml.gotmpl` would become:
```yaml
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:
```yaml
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`:
```yaml
releases:
- name: {{ requiredEnv "NAME" }}-vault
namespace: {{ requiredEnv "NAME" }}
chart: roboll/vault-secret-manager
values:
- values.yaml.gotmpl
```
`values.yaml.gotmpl`:
```yaml
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:
```yaml
mysetting: |
{{ exec "./mycmd" (list "arg1" "arg2" "--flag1") | indent 2 }}
```
Or even with a pipeline:
```yaml
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:
```yaml
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:
```console
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