Introduce template function `requiredEnv`

The new template function `requiredEnv` ensures that the given env var is set and not empty.
This commit is contained in:
Andreas Bieber 2018-05-04 14:51:55 +02:00
parent 67ddd7f1ae
commit 77204d9a8c
3 changed files with 53 additions and 8 deletions

View File

@ -52,9 +52,11 @@ releases:
- name: address - name: address
value: https://vault.example.com value: https://vault.example.com
- name: db.password - name: db.password
value: {{ env "DB_PASSWORD" }} # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1' value: {{ requiredEnv "DB_PASSWORD" }} # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1'
- name: proxy.domain - name: proxy.domain
value: {{ env "PLATFORM_ID" }}.my-domain.com # Interpolate environment variable with a fixed string value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com # Interpolate environment variable with a fixed string
- name: proxy.scheme
value: {{ env "SCHEME" | default "https" }}
# Local chart example # Local chart example
- name: grafana # name of this release - name: grafana # name of this release
@ -62,10 +64,18 @@ releases:
chart: ../my-charts/grafana # the chart being installed to create this release, referenced by relative path to local chart chart: ../my-charts/grafana # the chart being installed to create this release, referenced by relative path to local chart
values: values:
- "../../my-values/grafana/values.yaml" # Values file (relative path to manifest) - "../../my-values/grafana/values.yaml" # Values file (relative path to manifest)
- ./values/{{ env "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment. - ./values/{{ requiredEnv "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment.
``` ```
## 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 one special template function: `requiredEnv`.
The `required_env` function allows you to declare a particular environment variable as required for template rendering.
If the environment variable is unset or empty, the template rendering will fail with an error message.
## Using environment variables ## 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) and `url` (in repositories). Environment variables can be used in most places for templating the helmfile. Currently this is supported for `name`, `namespace`, `value` (in set) and `url` (in repositories).
@ -75,17 +85,19 @@ Examples:
```yaml ```yaml
respositories: respositories:
- name: your-private-git-repo-hosted-charts - name: your-private-git-repo-hosted-charts
url: https://{{ env "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/ url: https://{{ requiredEnv "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/
``` ```
```yaml ```yaml
releases: releases:
- name: {{ env "NAME" }}-vault - name: {{ requiredEnv "NAME" }}-vault
namespace: {{ env "NAME" }} namespace: {{ requiredEnv "NAME" }}
chart: roboll/vault-secret-manager chart: roboll/vault-secret-manager
set: set:
- name: proxy.domain - name: proxy.domain
value: {{ env "PLATFORM_ID" }}.my-domain.com value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com
- name: proxy.scheme
value: {{ env "SCHEME" | default "https" }}
``` ```
## installation ## installation

View File

@ -107,7 +107,21 @@ func readFromYaml(content []byte, file string) (*HelmState, error) {
} }
func stringTemplate() *template.Template { func stringTemplate() *template.Template {
return template.New("stringTemplate").Funcs(sprig.TxtFuncMap()) funcMap := sprig.TxtFuncMap()
alterFuncMap(&funcMap)
return template.New("stringTemplate").Funcs(funcMap)
}
func alterFuncMap(funcMap *template.FuncMap) {
(*funcMap)["requiredEnv"] = getRequiredEnv
}
func getRequiredEnv(name string) (string, error) {
if val, exists := os.LookupEnv(name); exists && len(val) > 0 {
return val, nil
}
return "", fmt.Errorf("required env var `%s` is not set", name)
} }
func renderTemplateString(s string) (string, error) { func renderTemplateString(s string) (string, error) {

View File

@ -351,6 +351,25 @@ func Test_renderTemplateString(t *testing.T) {
}, },
wantErr: true, wantErr: true,
}, },
{
name: "required env var",
args: args{
s: "{{ requiredEnv \"HF_TEST\" }}",
envs: map[string]string{
"HF_TEST": "value",
},
},
want: "value",
wantErr: false,
},
{
name: "required env var not set",
args: args{
s: "{{ requiredEnv \"HF_TEST_NONE\" }}",
envs: map[string]string{},
},
wantErr: true,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {