Update documentation and tests for .Values (#839)

Resolves #816
This commit is contained in:
eddycharly 2019-09-14 05:35:16 +02:00 committed by KUOKA Yusuke
parent 9d851cda3b
commit fd0133e10a
4 changed files with 51 additions and 22 deletions

View File

@ -212,17 +212,17 @@ helmfiles:
# The default is `environments: {"default": {}}` which implies: # The default is `environments: {"default": {}}` which implies:
# #
# - `{{ .Environment.Name }}` evaluates to "default" # - `{{ .Environment.Name }}` evaluates to "default"
# - `{{ .Environment.Values }}` being empty # - `{{ .Values }}` being empty
environments: environments:
# The "default" environment is available and used when `helmfile` is run without `--environment NAME`. # The "default" environment is available and used when `helmfile` is run without `--environment NAME`.
default: default:
# Everything from the values.yaml is available via `{{ .Environment.Values.KEY }}`. # Everything from the values.yaml is available via `{{ .Values.KEY }}`.
# Suppose `{"foo": {"bar": 1}}` contained in the values.yaml below, # Suppose `{"foo": {"bar": 1}}` contained in the values.yaml below,
# `{{ .Environment.Values.foo.bar }}` is evaluated to `1`. # `{{ .Values.foo.bar }}` is evaluated to `1`.
values: values:
- environments/default/values.yaml - environments/default/values.yaml
# Each entry in values can be either a file path or inline values. # Each entry in values can be either a file path or inline values.
# The below is an example of inline values, which is merged to the `.Environment.Values` # The below is an example of inline values, which is merged to the `.Values`
- myChartVer: 1.0.0-dev - myChartVer: 1.0.0-dev
# Any environment other than `default` is used only when `helmfile` is run with `--environment NAME`. # Any environment other than `default` is used only when `helmfile` is run with `--environment NAME`.
# That is, the "production" env below is used when and only when it is run like `helmfile --environment production sync`. # That is, the "production" env below is used when and only when it is run like `helmfile --environment production sync`.
@ -625,7 +625,7 @@ releaseName: prod
`values.yaml.gotmpl` `values.yaml.gotmpl`
```yaml ```yaml
domain: {{ .Environment.Values | getOrNil "my.domain" | default "dev.example.com" }} domain: {{ .Values | getOrNil "my.domain" | default "dev.example.com" }}
``` ```
`helmfile sync` installs `myapp` with the value `domain=dev.example.com`, `helmfile sync` installs `myapp` with the value `domain=dev.example.com`,
@ -652,17 +652,26 @@ environments:
- other.yaml.gotmpl # template directives with potential side-effects like `exec` and `readFile` will be honoured - other.yaml.gotmpl # template directives with potential side-effects like `exec` and `readFile` will be honoured
releases: releases:
- name: myapp-{{ .Environment.Values.releaseName }} # release name will be one of `dev` or `prod` depending on selected environment - name: myapp-{{ .Values.releaseName }} # release name will be one of `dev` or `prod` depending on selected environment
values: values:
- values.yaml.gotmpl - values.yaml.gotmpl
{{ if eq (.Environment.Values.releaseName "prod" ) }} {{ if eq (.Values.releaseName "prod" ) }}
# this release would be installed only if selected environment is `production` # this release would be installed only if selected environment is `production`
- name: production-specific-release - name: production-specific-release
... ...
{{ end }} {{ end }}
``` ```
### Note
The `{{ .Values.foo }}` syntax is the recommended way of using environment values.
Prior to this [pull request](https://github.com/roboll/helmfile/pull/647), environment values were made available through the `{{ .Environment.Values.foo }}` syntax.
This is still working but is **deprecated** and the new `{{ .Values.foo }}` syntax should be used instead.
You can read more infos about the feature proposal [here](https://github.com/roboll/helmfile/issues/640).
## Environment Secrets ## Environment Secrets
Environment Secrets (not to be confused with Kubernetes Secrets) are encrypted versions of `Environment Values`. Environment Secrets (not to be confused with Kubernetes Secrets) are encrypted versions of `Environment Values`.
@ -697,7 +706,7 @@ releases:
Then the environment secret `foo.bar` can be referenced by the below template expression in your `values.yaml.gotmpl`: Then the environment secret `foo.bar` can be referenced by the below template expression in your `values.yaml.gotmpl`:
```yaml ```yaml
{{ .Environment.Values.foo.bar }} {{ .Values.foo.bar }}
``` ```
## Tillerless ## Tillerless

View File

@ -11,13 +11,13 @@ One example of how helmfile achieves it is that, `helmfile` fails when you tried
That is, the following example let `helmfile` fail when you have no `eventApi.replicas` defined in environment values. That is, the following example let `helmfile` fail when you have no `eventApi.replicas` defined in environment values.
``` ```
{{ .Environment.Values.eventApi.replicas | default 1 }} {{ .Values.eventApi.replicas | default 1 }}
``` ```
In case it isn't a mistake and you do want to allow missing keys, use the `getOrNil` template function: In case it isn't a mistake and you do want to allow missing keys, use the `getOrNil` template function:
``` ```
{{ .Environment.Values | getOrNil "eventApi.replicas" }} {{ .Values | getOrNil "eventApi.replicas" }}
``` ```
This result in printing `<no value` in your template, that may or may not result in a failure. This result in printing `<no value` in your template, that may or may not result in a failure.
@ -25,7 +25,7 @@ This result in printing `<no value` in your template, that may or may not result
If you want a kind of default values that is used when a missing key was referenced, use `default` like: If you want a kind of default values that is used when a missing key was referenced, use `default` like:
``` ```
{{ .Environment.Values | getOrNil "eventApi.replicas" | default 1 }} {{ .Values | getOrNil "eventApi.replicas" | default 1 }}
``` ```
Now, you get `1` when there is no `eventApi.replicas` defined in environment values. Now, you get `1` when there is no `eventApi.replicas` defined in environment values.
@ -267,7 +267,7 @@ bases:
# Part 3: Dynamic Releases # Part 3: Dynamic Releases
releases: releases:
- name: test1 - name: test1
chart: mychart-{{ .Environment.Values.myname }} chart: mychart-{{ .Values.myname }}
values: values:
replicaCount: 1 replicaCount: 1
image: image:
@ -302,9 +302,9 @@ Where the gotmpl file loaded in the second part looks like:
```yaml ```yaml
helmDefaults: helmDefaults:
tillerNamespace: kube-system tillerNamespace: kube-system
kubeContext: {{ .Environment.Values.kubeContext }} kubeContext: {{ .Values.kubeContext }}
verify: false verify: false
{{ if .Environment.Values.wait }} {{ if .Values.wait }}
wait: true wait: true
{{ else }} {{ else }}
wait: false wait: false
@ -314,9 +314,9 @@ helmDefaults:
force: true force: true
``` ```
Each go template is rendered in the context where `.Environment.Values` is inherited from the previous part. Each go template is rendered in the context where `.Values` is inherited from the previous part.
So in `mydefaults.yaml.gotmpl`, both `.Environment.Values.kubeContext` and `.Environment.Values.wait` are valid as they do exist in the environment values inherited from the previous part(=the first part) of your `helmfile.yaml.gotmpl`, and therefore the template is rendered to: So in `mydefaults.yaml.gotmpl`, both `.Values.kubeContext` and `.Values.wait` are valid as they do exist in the environment values inherited from the previous part(=the first part) of your `helmfile.yaml.gotmpl`, and therefore the template is rendered to:
```yaml ```yaml
helmDefaults: helmDefaults:
@ -329,13 +329,13 @@ helmDefaults:
force: true force: true
``` ```
Similarly, the third part of the top-level `helmfile.yaml.gotmpl`, `.Environment.Values.myname` is valid as it is included in the environment values inherited from the previous parts: Similarly, the third part of the top-level `helmfile.yaml.gotmpl`, `.Values.myname` is valid as it is included in the environment values inherited from the previous parts:
```yaml ```yaml
# Part 3: Dynamic Releases # Part 3: Dynamic Releases
releases: releases:
- name: test1 - name: test1
chart: mychart-{{ .Environment.Values.myname }} chart: mychart-{{ .Values.myname }}
values: values:
replicaCount: 1 replicaCount: 1
image: image:

View File

@ -3,7 +3,6 @@ package app
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"gotest.tools/assert"
"io" "io"
"log" "log"
"os" "os"
@ -14,6 +13,8 @@ import (
"sync" "sync"
"testing" "testing"
"gotest.tools/assert"
"github.com/roboll/helmfile/pkg/helmexec" "github.com/roboll/helmfile/pkg/helmexec"
"github.com/roboll/helmfile/pkg/state" "github.com/roboll/helmfile/pkg/state"
"github.com/roboll/helmfile/pkg/testhelper" "github.com/roboll/helmfile/pkg/testhelper"
@ -1755,6 +1756,24 @@ releases:
{stateExternal, `{{ if (keys .Environment.Values | has "bar") }}{{ if (keys .Environment.Values.bar | has "baz") }}{{ .Environment.Values.bar.baz }}{{ end }}{{ end }}`, `BAZ`}, {stateExternal, `{{ if (keys .Environment.Values | has "bar") }}{{ if (keys .Environment.Values.bar | has "baz") }}{{ .Environment.Values.bar.baz }}{{ end }}{{ end }}`, `BAZ`},
// See https://github.com/roboll/helmfile/issues/643 // See https://github.com/roboll/helmfile/issues/643
{stateExternal, `{{ range $service := .Environment.Values.services }}{{ $service.name }}{{ if hasKey $service "something" }}{{ $service.something }}{{ end }}{{ end }}`, `xyfalse`}, {stateExternal, `{{ range $service := .Environment.Values.services }}{{ $service.name }}{{ if hasKey $service "something" }}{{ $service.something }}{{ end }}{{ end }}`, `xyfalse`},
// Same test with .Values
{stateInline, `{{ getOrNil "foo" .Values }}`, `FOO`},
{stateInline, `{{ getOrNil "baz" (getOrNil "bar" .Values) }}`, `BAZ`},
{stateInline, `{{ if hasKey .Values "foo" }}{{ .Values.foo }}{{ end }}`, `FOO`},
{stateInline, `{{ if hasKey .Values "bar" }}{{ .Values.bar.baz }}{{ end }}`, `BAZ`},
{stateInline, `{{ if (keys .Values | has "foo") }}{{ .Values.foo }}{{ end }}`, `FOO`},
// See https://github.com/roboll/helmfile/issues/624
// This fails when .Values.bar is not map[string]interface{}. At the time of #624 it was map[interface{}]interface{}, which sprig's dict funcs don't support.
{stateInline, `{{ if (keys .Values | has "bar") }}{{ if (keys .Values.bar | has "baz") }}{{ .Values.bar.baz }}{{ end }}{{ end }}`, `BAZ`},
{stateExternal, `{{ getOrNil "foo" .Values }}`, `FOO`},
{stateExternal, `{{ getOrNil "baz" (getOrNil "bar" .Values) }}`, `BAZ`},
{stateExternal, `{{ if hasKey .Values "foo" }}{{ .Values.foo }}{{ end }}`, `FOO`},
{stateExternal, `{{ if hasKey .Values "bar" }}{{ .Values.bar.baz }}{{ end }}`, `BAZ`},
{stateExternal, `{{ if (keys .Values | has "foo") }}{{ .Values.foo }}{{ end }}`, `FOO`},
// See https://github.com/roboll/helmfile/issues/624
{stateExternal, `{{ if (keys .Values | has "bar") }}{{ if (keys .Values.bar | has "baz") }}{{ .Values.bar.baz }}{{ end }}{{ end }}`, `BAZ`},
// See https://github.com/roboll/helmfile/issues/643
{stateExternal, `{{ range $service := .Values.services }}{{ $service.name }}{{ if hasKey $service "something" }}{{ $service.something }}{{ end }}{{ end }}`, `xyfalse`},
} }
for i := range testcases { for i := range testcases {
tc := testcases[i] tc := testcases[i]

View File

@ -1,13 +1,14 @@
package app package app
import ( import (
"github.com/roboll/helmfile/pkg/helmexec"
"github.com/roboll/helmfile/pkg/state"
"github.com/roboll/helmfile/pkg/testhelper"
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/roboll/helmfile/pkg/helmexec"
"github.com/roboll/helmfile/pkg/state"
"github.com/roboll/helmfile/pkg/testhelper"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )