Parameterization basics

The contents of the $.Values dictionary can be used to parameterize templates. Each chart has its own $.Values dictionary. The dictionary is compiled by merging parameters obtained from parameter files, command line options and other sources.

Below is a quick example of parameterization using values.yaml:

# values.yaml:
myparam: myvalue
# templates/example.yaml:
{{ $.Values.myparam }}

Output:

myvalue

And here is a more complex example:

# values.yaml:
myparams:
- value: original
# templates/example.yaml:
{{ (index $.Values.myparams 0).value }}
werf render --set myparams[0].value=overriden

Output:

overriden

Parameter sources and their priority

The $.Values dictionary is compiled by combining the parameters from the parameter sources in the following order, from the lowest priority to the highest:

  1. values.yaml of the current chart.
  2. secret-values.yaml of the current chart (werf only).
  3. The dictionary in values.yaml of the parent chart, whose key is the alias or name of the current chart.
  4. The dictionary in secret-values.yaml of the parent chart (werf only), whose key is the alias or name of the current chart.
  5. Parameter files stored in the WERF_VALUES_* variable.
  6. Parameter files set by the --values option.
  7. Secret parameter files stored in the WERF_SECRET_VALUES_* variable (werf only).
  8. Secret parameter files set by the --secret-values option (werf only).
  9. Parameters stored in the WERF_SET_JSON_* variable.
  10. Parameters set by the --set-json option.
  11. Parameters stored in the WERF_SET_* variable.
  12. Parameters set by the --set option.
  13. Parameters stored in the WERF_SET_STRING_* variable.
  14. Parameters set by the --set-string option.
  15. Parameters in the set files stored in the WERF_SET_FILE_* variable.
  16. Parameters in the set files set by the --set-file option.
  17. Parameters stored in the WERF_SET_LITERAL_* variable.
  18. Parameters set by the --set-literal option.
  19. werf auxiliary parameters.

Sources 5–19 are passed to the main chart. The parameters of a dependent chart are taken from the dictionary whose key is the alias or name of the dependent chart, so --set mychild.myparam=value overrides myparam from values.yaml and secret-values.yaml of the mychild chart and from the mychild dictionary of the parent chart.

The rules for combining parameters:

  • basic data types are overwritten;

  • lists are overwritten;

  • dictionaries are merged;

  • in case of a conflict, the parameters from the sources located higher in the list are overwritten by the parameters from the sources located lower in the list;

  • null set by the --values, --secret-values or --set* options removes the value of the parameter with the same key that comes from the sources located higher in the list.

  • null set for the whole dictionary of a dependent chart, e.g. --set mychild=null, removes only the parameters of this chart that come from the --values, --secret-values and --set* options: the chart keeps the parameters from its own values.yaml and secret-values.yaml, from the dictionary in values.yaml and secret-values.yaml of the parent chart, and the parameters exported to it from values.yaml of the parent chart, from the --set* options and from werf auxiliary parameters. If a parameter from the --set* options is exported to this chart, the null has no effect.

The export-values and import-values directives copy parameters between the parent chart and its dependent charts (see below) and do not form sources of their own: the copy is made within each of the following sources, and the priority of the copied parameter is the priority of the source it came from (from the lowest to the highest):

  1. values.yaml of all charts and secret-values.yaml of the dependent charts.
  2. secret-values.yaml of the main chart.
  3. Parameter files (WERF_VALUES_* and --values).
  4. Secret parameter files (WERF_SECRET_VALUES_* and --secret-values).
  5. All WERF_SET_* variables and --set* options.
  6. werf auxiliary parameters.

For example, with --set g.repo=A --set-string mychild.image.repository=B and g.repo exported to mychild.image.repository, the result is A: both options are in one source, where the exported parameter wins.

  • export-values copies a parameter of the parent chart to a dependent chart. Within one source, the exported parameter overrides the parameter of the dependent chart with the same key. Across sources, the parameter from the source located lower in the list wins. For example, --set mychild.myparam=value overrides a parameter that is exported to mychild.myparam from values.yaml of the parent chart, and a werf auxiliary parameter exported to mychild.image.repository overrides mychild.image.repository from --values.

  • import-values copies a dictionary of a dependent chart to the parent chart. Within one source, the parent chart’s own parameter overrides the imported one with the same key. Across sources, the parameter from the source located lower in the list wins. For example, a dictionary imported from --set mychild.mydict.myparam=value overrides mydict.myparam from values.yaml of the parent chart.

A parameter that cannot be copied is skipped with a warning: a value other than a dictionary exported to the root of a dependent chart, or a value other than a dictionary or null imported from a dependent chart. An imported null is copied as null.

Parameterizing the chart

The chart can be parameterized using its parameter file:

# values.yaml:
myparam: myvalue
# templates/example.yaml:
{{ $.Values.myparam }}

Output:

myvalue

You can also add/override the chart parameters using command line arguments:

werf render --set myparam=overriden  # or WERF_SET_MYPARAM=myparam=overriden werf render
werf render --set-string myparam=overriden  # or WERF_SET_STRING_MYPARAM=myparam=overriden werf render

… as well as by additional parameter files:

# .helm/values-production.yaml:
myparam: overriden
werf render --values .helm/values-production.yaml  # or WERF_VALUES_PROD=.helm/values-production.yaml werf render

… or by a secret parameter file of the main chart (werf only):

# .helm/secret-values.yaml:
myparam: <encrypted>
werf render

… or by additional secret parameter files of the main chart (werf only):

# .helm/secret-values-production.yaml:
myparam: <encrypted>
werf render --secret-values .helm/secret-values-production.yaml  # or WERF_SECRET_VALUES_PROD=.helm/secret-values-production.yaml werf render

… or by set files:

# myparam.txt:
overriden
werf render --set-file myparam=myparam.txt  # or WERF_SET_FILE_PROD=myparam=myparam.txt werf render

The output is the same:

overriden

Parameterizing dependent charts

A dependent chart can be parameterized both using its own parameter file and the parameter file of the parent chart.

In the example below, the parameters from the mychild dictionary in the values.yaml file of the myparent chart override the parameters in the values.yaml file of the mychild chart:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
# values.yaml:
mychild:
  myparam: overriden
# charts/mychild/values.yaml:
myparam: original
# charts/mychild/templates/example.yaml:
{{ $.Values.myparam }}

Output:

overriden

Note that the dictionary in values.yaml of the parent chart that contains parameters for the dependent chart must have alias (if any) or name of the dependent chart as its name.

You can also add/override parameters of a dependent chart using command line arguments:

werf render --set mychild.myparam=overriden  # or WERF_SET_MYPARAM=mychild.myparam=overriden werf render
werf render --set-string mychild.myparam=overriden  # or WERF_SET_STRING_MYPARAM=mychild.myparam=overriden werf render

… as well as by additional parameter files:

# .helm/values-production.yaml:
mychild:
  myparam: overriden
werf render --values .helm/values-production.yaml  # or WERF_VALUES_PROD=.helm/values-production.yaml werf render

… or by a secret parameter file of the main chart (werf only):

# .helm/secret-values.yaml:
mychild:
  myparam: <encrypted>
werf render

or by additional secret parameter files of the main chart (werf only):

# .helm/secret-values-production.yaml:
mychild:
  myparam: <encrypted>
werf render --secret-values .helm/secret-values-production.yaml  # or WERF_SECRET_VALUES_PROD=.helm/secret-values-production.yaml werf render

… or using set files:

# mychild-myparam.txt:
overriden
werf render --set-file mychild.myparam=mychild-myparam.txt  # or WERF_SET_FILE_PROD=mychild.myparam=mychild-myparam.txt werf render

… or vie the export-values directive (werf only):

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
  export-values:
  - parent: myparam
    child: myparam
# values.yaml:
myparam: overriden
werf render

The output will be the same:

overriden

Using the dependent chart parameters in the parent chart

You can use the import-values directive in the parent chart to pass the parameters of the dependent chart to the parent one. Only dictionaries (or null) can be imported, and the parent chart’s own parameters override the imported ones:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild
  import-values:
  - child: mydict
    parent: mydict
# values.yaml:
mydict:
  myparam1: original
# charts/mychild/values.yaml:
mydict:
  myparam1: imported
  myparam2: imported
# templates/example.yaml:
{{ $.Values.mydict.myparam1 }} {{ $.Values.mydict.myparam2 }}

Output:

original imported

Global parameters

Chart parameters are only accessible in that chart (and have limited availability in the dependent charts). One easy way to access the parameters of one chart in other linked charts is to use global parameters.

A global parameter has global scope — a parameter declared in a parent, child, or other linked chart becomes available in all linked charts at the same path:

# Chart.yaml:
name: myparent
dependencies:
- name: mychild1
- name: mychild2
# charts/mychild1/values.yaml:
global:
  myparam: myvalue
# templates/example.yaml:
myparent: {{ $.Values.global.myparam }}
# charts/mychild1/templates/example.yaml:
mychild1: {{ $.Values.global.myparam }}
# charts/mychild2/templates/example.yaml:
mychild2: {{ $.Values.global.myparam }}

Output:

myparent: myvalue
---
mychild1: myvalue
---
mychild2: myvalue

Secret parameters (werf only)

You can use secret parameter files to store secret parameters. These files are encrypted and stored in the Git repository.

By default, werf tries to locate the .helm/secret-values.yaml file containing the encrypted parameters. When werf finds the file, it decrypts it and merges the decrypted parameters with the others:

# .helm/values.yaml:
plainParam: plainValue
# .helm/secret-values.yaml:
secretParam: 1000625c4f1d874f0ab853bf1db4e438ad6f054526e5dcf4fc8c10e551174904e6d0
{{ $.Values.plainParam }}
{{ $.Values.secretParam }}

Output:

plainValue
secretValue

Working with secret parameter files

The order in which the secret parameters files are processed:

  1. Use an existing secret key or create a new one by running werf helm secret generate-secret-key.

  2. Save the secret key to the WERF_SECRET_KEY environment variable, or to <Git repository root>/.werf_secret_key or <home directory>/.werf/global_secret_key.

  3. Use the werf helm secret values edit .helm/secret-values.yaml command to open the secret parameters file and add the decrypted parameters to it or modify them.

  4. Save the file — it will be encrypted and saved in an encrypted form.

  5. Commit the added/modified file .helm/secret-values.yaml to Git.

  6. On subsequent werf invocations, the secret key must be present in the aforementioned environment variable or files, or werf will not be able to decrypt the secret parameter file.

Note that someone with access to the secret key can decrypt the contents of the secret settings file, so keep the secret key in a safe place!

When using the <Git repository root>/.werf_secret_key file, be sure to add it to .gitignore to avoid unintentionally saving it to the Git repository.

Many werf commands can also be run without a secret key (the --ignore-secret-key flag enables this), in which case the parameters will be available for use in an encrypted rather than decrypted form.

Additional secret parameter files

You can create and use extra secret files in addition to the .helm/secret-values.yaml file:

# .helm/secret-values-production.yaml:
secret: 1000625c4f1d874f0ab853bf1db4e438ad6f054526e5dcf4fc8c10e551174904e6d0
werf --secret-values .helm/secret-values-production.yaml

Secret parameters in the release

werf saves the parameters from the --values, --secret-values and --set* options in the release, together with the parameters that export-values copies from them, and the parameters from --secret-values are saved in decrypted form. werf release get --print-values shows them, anyone who can read the release Secret in the cluster can read them, and changing only --secret-values creates a new release revision. Releases deployed with --secret-values by an earlier werf version get one new revision on the first deployment after the update. The parameters from secret-values.yaml of the charts are not saved among these parameters, but if Chart.yaml of the chart lists dependent charts in dependencies, the chart saved in the release contains them in decrypted form, and werf release get --print-values shows them too.

werf bundle publish saves the --secret-values files in secret-values.yaml of the bundle, encrypted, so werf bundle apply does not save them in the release among the parameters of the options; as with any secret-values.yaml, they are saved decrypted in the chart in the release if the bundle lists dependent charts in dependencies.

Information about the built images (werf only)

werf stores detailed information about the built images in $.Values.global.werf.images, available in all charts (main and dependent):

global:
  werf:
    images:
      backend:
        # Container registry address:
        registry: example.org
        # Repository namespace:
        namespace: apps
        # Image short name:
        name: myapp
        # Image tag:
        tag: a243949601ddc3d4133c4d5269ba23ed58cb8b18bf2b64047f35abd2-1598024377816
        # Image digest:
        digest: sha256:ece15c4a8e7e04dd0afa25b85a51e3fba35eb31e0e1489a2f3e916da77e4e865
        # Tag and digest combined:
        tag_digest: "a243949...816@sha256:ece15c4a..."
        # Full image name without tag (registry + repository):
        image: example.org/apps/myapp
        # Full repository path (namespace + name):
        repository: apps/myapp
        # Full image reference with digest:
        ref: "example.org/apps/myapp:a243949...816@sha256:ece15c4a..."
        # Full image reference with tag:
        ref_tag: "example.org/apps/myapp:a243949...816"
        # Repository path with tag and digest:
        repository_ref: "apps/myapp:a243949...816@sha256:ece15c4a..."
        # Repository path with tag:
        repository_tag: "apps/myapp:a243949...816"
        # Short name with tag and digest:
        name_ref: "myapp:a243949...816@sha256:ece15c4a..."
        # Short name with tag:
        name_tag: "myapp:a243949...816"

This structured format allows you to use individual image components, which is useful when working with external charts that expect image values in a structured format:

image:
  registry: {{ $.Values.global.werf.images.backend.registry }}
  repository: {{ $.Values.global.werf.images.backend.repository }}
  tag: {{ $.Values.global.werf.images.backend.tag }}

Since $.Values.global.werf has global scope, images is available in all dependent charts. You can also use export-values to map individual image fields to the format expected by an external chart:

# .helm/Chart.yaml:
dependencies:
- name: postgres-operator
  export-values:
  - parent: global.werf.images.pg.registry
    child: image.registry
  - parent: global.werf.images.pg.repository
    child: image.repository
  - parent: global.werf.images.pg.tag
    child: image.tag

The postgres-operator chart will receive:

image:
  registry: example.org
  repository: apps/pg
  tag: a243949601ddc3d4133c4d5269ba23ed58cb8b18bf2b64047f35abd2-1598024377816

Release information

werf stores release information in the properties of the $.Release object:

# Is the release being installed for the first time?
IsInstall: true
# Is the existing release being updated?
IsUpgrade: false
# Release name:
Name: myapp-production
# Kubernetes Namespace name:
Namespace: myapp-production
# Release revision:
Revision: 1

… and in $.Values.global.werf, available in all charts (werf only):

global:
  werf:
    # Name of the werf project:
    name: myapp
    # Environment:
    env: production
    # Kubernetes Namespace:
    namespace: myapp-production

For backward compatibility, the same values are also available in $.Values.werf.

Example of use:

{{ $.Release.Namespace }}
{{ $.Values.global.werf.env }}

Output:

myapp-production
production

Chart information

werf stores information about the current chart in the $.Chart object:

# Is the chart the main one?
IsRoot: true

# Contents of the Chart.yaml:
Name: mychart
Version: 1.0.0
Type: library
KubeVersion: "~1.20.3"
AppVersion: "1.0"
Deprecated: false
Icon: https://example.org/mychart-icon.svg
Description: This is My Chart
Home: https://example.org
Sources:
  - https://github.com/my/chart
Keywords:
  - apps
Annotations:
  anyAdditionalInfo: here
Dependencies:
- Name: redis
  Condition: redis.enabled

Example of use:

{{ $.Chart.Name }}

Output:

mychart

Template information

werf stores information about the current template in the properties of the $.Template object:

# The relative path to the chart's templates directory:
BasePath: mychart/templates
# The relative path to the current template file:
Name: mychart/templates/example.yaml

Example of use:

{{ $.Template.Name }}

Output:

mychart/templates/example.yaml

Git commit information (werf only)

werf stores information about the Git commit that triggered its run in $.Values.global.werf.commit, available in all charts:

global:
  werf:
    commit:
      date:
        # The date of the Git commit that triggered werf (the human-readable form):
        human: 2022-01-21 18:51:39 +0300 +0300
        # The date of the Git commit that triggered werf (Unix time):
        unix: 1642780299
      # The hash of the Git commit that triggered werf:
      hash: 1b28e6843a963c5bdb3579f6fc93317cc028051c

For backward compatibility, the same values are also available in $.Values.werf.commit.

Example of use:

{{ $.Values.global.werf.commit.hash }}

Output:

1b28e6843a963c5bdb3579f6fc93317cc028051c

Information about the Kubernetes cluster

werf provides information about the capabilities of the target Kubernetes cluster via the properties of the $.Capabilities object:

KubeVersion:
  # The full version of the Kubernetes cluster:
  Version: v1.20.0
  # The major version of the Kubernetes cluster:
  Major: "1"
  # The minor version of the Kubernetes cluster:
  Minor: "20"
# A list of APIs supported by the Kubernetes cluster:
APIVersions:
- apps/v1
- batch/v1
- # ...

… as well as methods of the $.Capabilities object:

  • APIVersions.Has <arg> — tells whether the Kubernetes cluster supports the API (e.g., apps/v1) or resource (e.g., apps/v1/Deployment) specified by the argument.

Example of use:

{{ $.Capabilities.KubeVersion.Version }}
{{ $.Capabilities.APIVersions.Has "apps/v1" }}

Output:

v1.20.0
true