# Official  Helm Chart Template Guide Summary

### Command Cheat sheet

[https://helm.sh/docs/intro/cheatsheet/](https://helm.sh/docs/intro/cheatsheet/)

### Add/Search/Install/Uninstall repo

```bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update bitnami
helm repo list

helm install wordpress bitnami/wordpress
helm list
helm status wordpress
helm get all wordpress
helm get values wordpress
helm uninstall wordpress #--keep-history uninstall while keeping history
```

### Search Repositories

```bash
helm search repo
helm search hub
helm search bitnami
helm search repo wordpress
helm search hub wordpress
```

### Installation Order Helm

* namespace
    

* NetworkPolicy
    
* ResourceQuota
    
* LimitRange
    
* PodSecurityPolicy
    
* PodDisruptionBudget
    
* ServiceAccount
    
* Secret
    
* SecretList
    
* ConfigMap
    
* StorageClass
    
* PersistentVolume
    
* PersistentVolumeClaim
    
* CustomResourceDefinition
    
* ClusterRole
    
* ClusterRoleList
    
* ClusterRoleBinding
    
* ClusterRoleBindingList
    
* Role
    
* RoleList
    
* RoleBinding
    
* RoleBindingList
    
* Service
    
* DaemonSet
    
* Pod
    
* ReplicationController
    
* ReplicaSet
    
* Deployment
    
* HorizontalPodAutoscaler
    
* StatefulSet
    
* Job
    
* CronJob
    
* Ingress
    
* APIService
    

### Customizing Chart before Installing

```bash
helm show values bitnami/wordpress
```

### **More Installation Methods**

The `helm install` command can install from several sources:

* A chart repository (as we've seen above)
    
* A local chart archive (`helm install foo foo-0.1.1.tgz`)
    
* An unpacked chart directory (`helm install foo path/to/foo`)
    
* A full URL (`helm install foo` [`https://example.com/charts/foo-1.2.3.tgz`](https://example.com/charts/foo-1.2.3.tgz))
    

## **'helm upgrade' and 'helm rollback':**

An upgrade takes an existing release and upgrades it according to the information you provide. Because Kubernetes charts can be large and complex, Helm tries to perform the least invasive upgrade.  
  
NOTE: *It will only update things that have changed since the last release.*

To see new upgrade too place:

```bash
helm get values wordpress
```

To rollback:

```bash
helm rollback wordpress 1
```

## **Helpful Options for Install/Upgrade/Rollback**

* `--timeout`
    
* `--wait` It will wait for as long as the `--timeout` value. If timeout is reached, the release will be marked as `FAILED`.
    
* `--no-hooks`: This skips running hooks for the command
    
* `--recreate-pods` (only available for `upgrade` and `rollback`)
    

### Creating your own chart

```bash
helm create webhotel
helm package webhotel
helm install my-hotel ./webhotel

## debugging chart
helm install --debug --dry-run goodly-guppy ./webhotel
```

**NOTES:**

* By virtue of the fact that this file is in the `mychart/templates/` directory, it will be sent through the template engine.
    
* We recommend using the extension `.yaml` for YAML files and `.tpl` for helpers.
    
* The template directive `{{ .`[`Release.Name`](http://Release.Name) `}}` injects the release name into the template.
    
* The `Release` object is one of the built-in objects for Helm
    

# **Built-in Objects**

Objects are passed into a template from the template engine. And your code can pass objects around. There are even a few ways to create new objects within your templates, like with the `tuple` .

Objects can be simple, and have just one value. Or they can contain other objects or functions. For example, the `Release` object contains several objects (like [`Release.Name`](http://Release.Name)) and the `Files` object has a few functions.

NOTE: *The built-in values always begin with a capital letter*.

**Release Object**

This object describes the release itself. It has several objects inside of it:

* [`Release.Name`](http://Release.Name)
    
* `Release.Namespace`
    
* `Release.IsUpgrade`: `true` if the current operation is an upgrade or rollback.
    
* `Release.IsInstall`: `true` if the current operation is an install.
    
* `Release.Revision`: The revision number for this release. On install, this is 1, and it is incremented with each upgrade and rollback.
    
* `Release.Service`: The service that is rendering the present template. On Helm, this is always `Helm`.
    

**Values Object**

Values passed into the template from the `values.yaml` file and from user-supplied files. By default, `Values` is empty.

**Chart Object**

The contents of the `Chart.yaml` file. Any data in `Chart.yaml` will be accessible here. For example `{{ .Chart.Name }}-{{ .Chart.Version }}` will print out the `mychart-0.1.0`.

The available fields are listed in the [Charts Guide](https://helm.sh/docs/topics/charts/#the-chartyaml-file)

**Subchart Object**

This provides access to the scope (.Values, .Charts, .Releases etc.) of subcharts to the parent. For example `.Subcharts.mySubChart.myValue` to access the `myValue` in the `mySubChart` chart.

**Files Object**

This provides access to all non-special files in a chart. While you cannot use it to access templates, you can use it to access other files in the chart. See the section [Accessing Files](https://helm.sh/docs/chart_template_guide/accessing_files/) for more.

* * `Files.Get` is a function for getting a file by name (`.Files.Get config.ini`)
        
    * `Files.GetBytes` is a function for getting the contents of a file as an array of bytes instead of as a string. This is useful for things like images.
        
    * `Files.Glob` is a function that returns a list of files whose names match the given shell glob pattern.
        
    * `Files.Lines` is a function that reads a file line-by-line. This is useful for iterating over each line in a file.
        
    * `Files.AsSecrets` is a function that returns the file bodies as Base 64 encoded strings.
        
    * `Files.AsConfig` is a function that returns file bodies as a YAML map.
        

**Capabilities Object**

This provides information about what capabilities the Kubernetes cluster supports.

* * `Capabilities.APIVersions` is a set of versions.
        
    * `Capabilities.APIVersions.Has $version` indicates whether a version (e.g., `batch/v1`) or resource (e.g., `apps/v1/Deployment`) is available on the cluster.
        
    * `Capabilities.KubeVersion` and `Capabilities.KubeVersion.Version` is the Kubernetes version.
        
    * `Capabilities.KubeVersion.Major` is the Kubernetes major version.
        
    * `Capabilities.KubeVersion.Minor` is the Kubernetes minor version.
        
    * `Capabilities.HelmVersion` is the object containing the Helm Version details, it is the same output of `helm version`.
        
    * `Capabilities.HelmVersion.Version` is the current Helm version in semver format.
        
    * `Capabilities.HelmVersion.GitCommit` is the Helm git sha1.
        
    * `Capabilities.HelmVersion.GitTreeState` is the state of the Helm git tree.
        
    * `Capabilities.HelmVersion.GoVersion` is the version of the Go compiler used.
        

**Template Object**

Contains information about the current template that is being executed

* * [`Template.Name`](http://Template.Name): A namespaced file path to the current template (e.g. `mychart/templates/mytemplate.yaml`)
        
    * `Template.BasePath`: The namespaced path to the templates directory of the current chart (e.g. `mychart/templates`).
        

### Values Files

This object provides access to values passed into the chart. Its contents come from multiple sources:

* The `values.yaml` file in the chart
    
* If this is a subchart, the `values.yaml` file of a parent chart
    
* A values file if passed into `helm install` or `helm upgrade` with the `-f` flag (`helm install -f myvals.yaml ./mychart`)
    
* Individual parameters passed with `--set` (such as `helm install --set foo=bar ./mychart`)
    

NOTE: `values.yaml` is the default, which can be overridden by a parent chart's `values.yaml`, which can in turn be overridden by a user-supplied values file, which can in turn be overridden by `--set` parameters.

**Deleting a default:**

```bash
helm install stable/drupal --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null
```

### Template Functions and Pipelines

So far, we've seen how to place information into a template. But that information is placed into the template unmodified. Sometimes we want to transform the supplied data in a way that makes it more useable to us.

**Template Function**

List of available functions: [https://helm.sh/docs/chart\_template\_guide/function\_list/](https://helm.sh/docs/chart_template_guide/function_list/)

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ quote .Values.favorite.drink }}
  food: {{ quote .Values.favorite.food }}
```

**Template Function syntax**

`functionName arg1 arg2...`

**Pipelines**

Pipelines are an efficient way of getting several things done in sequence. Let's rewrite the above example using a pipeline.

```yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | repeat 5 | quote }}
  food: {{ .Values.favorite.food | upper | quote }}

### above snippet will be translated to below👇 yaml
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: melting-porcup-configmap
data:
  myvalue: "Hello World"
  drink: "coffeecoffeecoffeecoffeecoffee"
  food: "PIZZA"
```

**Using Default Function**

```yaml
drink: {{ .Values.favorite.drink | default "tea" | quote }}
drink: {{ .Values.favorite.drink | default (printf "%s-tea" (include "fullname" .)) }}
```

In some places, an `if` conditional guard may be better suited than `default`.\\

**Using the lookup function**

The `lookup` function can be used to *look up* resources in a running cluster. The synopsis of the lookup function is `lookup apiVersion, kind, namespace, name -> resource or resource list`

| Behavior | Lookup function |
| --- | --- |
| `kubectl get pod mypod -n mynamespace` | `lookup "v1" "Pod" "mynamespace" "mypod"` |
| `kubectl get pods -n mynamespace` | `lookup "v1" "Pod" "mynamespace" ""` |
| `kubectl get pods --all-namespaces` | `lookup "v1" "Pod" "" ""` |
| `kubectl get namespace mynamespace` | `lookup "v1" "Namespace" "" "mynamespace"` |
| `kubectl get namespaces` | `lookup "v1" "Namespace" "" ""` |

Example:

`(lookup "v1" "Namespace" "" "mynamespace").metadata.annotations`

NOTE: To test `lookup` against a running cluster, `helm template|install|upgrade|delete|rollback --dry-run=server` should be used

**Operators are functions**

For templates, the operators (`eq`, `ne`, `lt`, `gt`, `and`, `or` and so on) are all implemented as functions. In pipelines, operations can be grouped with parentheses (`(`, and `)`).

### Flow Control

Helm's template language provides the following control structures:

* `if`/`else` for creating conditional blocks
    
* `with` to specify a scope
    
* `range`, which provides a "for each"-style loop
    

**If/Else**

```yaml
{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

## Example
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{ if eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }}

### Values
apiVersion: v1
kind: ConfigMap
metadata:
  name: eyewitness-elk-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
  mug: "true"
```

**Modifying scope using with**

The next control structure to look at is the `with` action. This controls variable scoping. Recall that `.` is a reference to *the current scope*. So `.Values` tells the template to find the `Values` object in the current scope.

```yaml
###Syntax:
{{ with PIPELINE }}
  # restricted scope
{{ end }}

### Example
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}
  release: {{ .Release.Name }}
```

**Looping with the range action**

```yaml
##Example
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}
  toppings: |-
    {{- range .Values.pizzaToppings }}
    - {{ . | title | quote }}
    {{- end }}   

## Tuple example
sizes: |-
    {{- range tuple "small" "medium" "large" }}
    - {{ . }}
    {{- end }}  
```

In addition to lists and tuples, `range` can be used to iterate over collections that have a key and a value (like a `map` or `dict`).

### Variables

In Helm templates, a variable is a named reference to another object. It follows the form `$name`. Variables are assigned with a special assignment operator: `:=`. We can rewrite the above to use a variable for [`Release.Name`](http://Release.Name).

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- $relname := .Release.Name -}}
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  release: {{ $relname }}
  {{- end }}
```

ariables are particularly useful in `range` loops. They can be used on list-like objects to capture both the index and the value:

```yaml
  toppings: |-
    {{- range $index, $topping := .Values.pizzaToppings }}
      {{ $index }}: {{ $topping }}
    {{- end }}

#result
toppings: |-
      0: mushrooms
      1: cheese
      2: peppers
      3: onions
```

  
For data structures that have both a key and a value, we can use `range` to get both. For example, we can loop through `.Values.favorite` like this:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}

#result
apiVersion: v1
kind: ConfigMap
metadata:
  name: eager-rabbit-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "pizza"
```

Variables are normally not "global". They are scoped to the block in which they are declared. Earlier, we assigned `$relname` in the top level of the template. That variable will be in scope for the entire template. But in our last example, `$key` and `$val` will only be in scope inside of the `{{ range... }}{{ end }}` block.

However, there is one variable that is always global - `$` -this variable will always point to the root context.

### Named Template

It is time to move beyond one template, and begin to create others. In this section, we will see how to define *named templates* in one file, and then use them elsewhere. A *named template* (sometimes called a *partial* or a *subtemplate*) is simply a template defined inside of a file, and given a name. We'll see two ways to create them, and a few different ways to use them.

NOTE: An important detail to keep in mind when naming templates: **template names are global**. If you declare two templates with the same name, whichever one is loaded last will be the one used. Because templates in subcharts are compiled together with top-level templates, you should be careful to name your templates with *chart-specific names*.

**Partials and \_ files**

* Most files in `templates/` are treated as if they contain Kubernetes manifests
    
* The `NOTES.txt` is one exception
    
* But files whose name begins with an underscore (`_`) are assumed to *not* have a manifest inside. These files are not rendered to Kubernetes object definitions, but are available everywhere within other chart templates for use.
    

**Declaring and using templates with define and template**

```yaml
{{- define "MY.NAME" }}
  # body of template here
{{- end }}

### Example
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}
```

Now we can embed this template inside of our existing ConfigMap, and then include it with the `template` action:

```yaml
{{- define "mychart.labels" }}
  labels:
    generator: helm
    date: {{ now | htmlDate }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
  {{- template "mychart.labels" }}
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}

## Result
apiVersion: v1
kind: ConfigMap
metadata:
  name: running-panda-configmap
  labels:
    generator: helm
    date: 2016-11-02
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "pizza"
```

NOTE: Note: a `define` does not produce output unless it is called with a template, as in this example.

Conventionally, Helm charts put these templates inside of a partials file, usually `_helpers.tpl`. Let's move this function there:

**The include function**

Because `template` is an action, and not a function, there is no way to pass the output of a `template` call to other functions; the data is simply inserted inline.

To work around this case, Helm provides an alternative to `template` that will import the contents of a template into the present pipeline where it can be passed along to other functions in the pipeline.

Here's the example above, corrected to use `indent` to indent the [`mychart.app`](http://mychart.app) template correctly

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
  labels:
{{ include "mychart.app" . | indent 4 }}
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}
{{ include "mychart.app" . | indent 2 }}
```

NOTE: It is considered preferable to use `include` over `template` in Helm templates simply so that the output formatting can be handled better for YAML documents.

### Accessing Files Inside Templates

[https://helm.sh/docs/chart\_template\_guide/accessing\_files/](https://helm.sh/docs/chart_template_guide/accessing_files/)

Sometimes it is desirable to import a *file that is not a template* and inject its contents without sending the contents through the template renderer. Helm provides access to files through the `.Files` object.

NOTES

* It is okay to add extra files to your Helm chart. These files will be bundled. Be careful, though. Charts must be smaller than 1M because of the storage limitations of Kubernetes objects.
    
* Some files cannot be accessed through the `.Files` object, usually for security reasons.
    
    * Files in `templates/` cannot be accessed.
        
    * Files excluded using `.helmignore` cannot be accessed.
        
    * Files outside of a Helm application [subchart](https://helm.sh/docs/chart_template_guide/subcharts_and_globals/), including those of the parent, cannot be access
        

**Basic Examples**

`onfig1.toml`:

```toml
message = Hello from config 1
```

`config2.toml`:

```toml
message = This is config 2
```

`config3.toml`:

```toml
message = Goodbye from config 3
```

Each of these is a simple TOML file (think old-school Windows INI files). We know the names of these files, so we can use a `range` function to loop through them and inject their contents into our ConfigMap.

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  {{- $files := .Files }}
  {{- range tuple "config1.toml" "config2.toml" "config3.toml" }}
  {{ . }}: |-
        {{ $files.Get . }}
  {{- end }}

### Result
apiVersion: v1
kind: ConfigMap
metadata:
  name: quieting-giraf-configmap
data:
  config1.toml: |-
        message = Hello from config 1

  config2.toml: |-
        message = This is config 2

  config3.toml: |-
        message = Goodbye from config 3
```

### Creating a NOTES.txt File

[https://helm.sh/docs/chart\_template\_guide/notes\_files/](https://helm.sh/docs/chart_template_guide/notes_files/)

### Subcharts and Global Values

Before we dive into the code, there are a few important details to learn about application subcharts.

1. A subchart is considered "stand-alone", which means a subchart can never explicitly depend on its parent chart.
    
2. For that reason, a subchart cannot access the values of its parent.
    
3. A parent chart can override values for subcharts.
    
4. Helm has a concept of *global values* that can be accessed by all charts.
    

**Creating a Subchart**

For these exercises, we'll start with the `mychart/` chart we created at the beginning of this guide, and we'll add a new chart inside of it.

```console
cd mychart/charts
helm create mysubchart
Creating mysubchart
rm -rf mysubchart/templates/*
```

**Overriding Values from a Parent Values.yaml**

```yaml
favorite:
  drink: coffee
  food: pizza
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

##Chart name
mysubchart:
  dessert: ice cream
```

**Global Chart Values**

Global values are values that can be accessed from any chart or subchart by exactly the same name. Globals require explicit declaration. You can't use an existing non-global as if it were a global.

The Values data type has a reserved section called [`Values.global`](http://Values.global) where global values can be set. Let's set one in our `mychart/values.yaml` file.

```yaml
favorite:
  drink: coffee
  food: pizza
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

mysubchart:
  dessert: ice cream

global:
  salad: caesar
```

Example Config Map

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  salad: {{ .Values.global.salad }}
```

**Sharing Templates with Subcharts**

Parent charts and subcharts can share templates. Any defined block in any chart is available to other charts.

For example, we can define a simple template like this:

```yaml
{{- define "labels" }}from: mychart{{ end }}
```

Recall how the labels on templates are *globally shared*. Thus, the `labels` chart can be included from any other chart.

While chart developers have a choice between `include` and `template`, one advantage of using `include` is that `include` can dynamically reference templates:

```yaml
{{ include $mytemplate }}
```

The above will dereference `$mytemplate`. The `template` function, in contrast, will only accept a string literal.
