# Common: The Helm Helper Chart

This chart is designed to make it easier for you to build and maintain Helm
charts.

It provides utilities that reflect best practices of Kubernetes chart development,
making it faster for you to write charts.

## Tips

A few tips for working with Common:

- Be careful when using functions that generate random data (like `common.fullname.unique`).
  They may trigger unwanted upgrades or have other side effects.

In this document, we use `release-name` as the name of the release.

## Resource Kinds

Kubernetes defines a variety of resource kinds, from `Secret` to `StatefulSet`.
We define some of the most common kinds in a way that lets you easily work with
them.

The resource kind templates are designed to make it much faster for you to
define _basic_ versions of these resources. They allow you to extend and modify
just what you need, without having to copy around lots of boilerplate.

To make use of these templates you must define a template that will extend the
base template (though it can be empty). The name of this template is then passed
to the base template, for example:

```yaml
{{- template "common.service" (list . "mychart.service") -}}
{{- define "mychart.service" -}}
## Define overrides for your Service resource here, e.g.
# metadata:
#   labels:
#     custom: label
# spec:
#   ports:
#   - port: 8080
{{- end -}}
```

Note that the `common.service` template defines two parameters:

  - The root context (usually `.`)
  - A template name containing the service definition overrides

A limitation of the Go template library is that a template can only take a
single argument. The `list` function is used to work around this by constructing
a list or array of arguments that is passed to the template.

The `common.service` template is responsible for rendering the templates with
the root context and merging any overrides. As you can see, this makes it very
easy to create a basic `Service` resource without having to copy around the
standard metadata and labels.

Each implemented base resource is described in greater detail below.

### `common.service`

The `common.service` template creates a basic `Service` resource with the
following defaults:

- Service type (ClusterIP, NodePort, LoadBalancer) made configurable by `.Values.service.type`
- Named port `http` configured on port 80
- Selector set to `app.kubernetes.io/name: {{ template "common.name" }}, app.kubernetes.io/instance: {{ .Release.Name | quote }}` to match the default used in the `Deployment` resource

Example template:

```yaml
{{- template "common.service" (list . "mychart.mail.service") -}}
{{- define "mychart.mail.service" -}}
metadata:
  name: {{ template "common.fullname" . }}-mail # overrides the default name to add a suffix
  labels:                                       # appended to the labels section
    protocol: mail
spec:
  ports:                                        # composes the `ports` section of the service definition.
  - name: smtp
    port: 25
    targetPort: 25
  - name: imaps
    port: 993
    targetPort: 993
  selector:                                     # this is appended to the default selector
    protocol: mail
{{- end -}}
---
{{ template "common.service" (list . "mychart.web.service") -}}
{{- define "mychart.web.service" -}}
metadata:
  name: {{ template "common.fullname" . }}-www  # overrides the default name to add a suffix
  labels:                                       # appended to the labels section
    protocol: www
spec:
  ports:                                        # composes the `ports` section of the service definition.
  - name: www
    port: 80
    targetPort: 8080
{{- end -}}
```

The above template defines _two_ services: a web service and a mail service.

The most important part of a service definition is the `ports` object, which
defines the ports that this service will listen on. Most of the time,
`selector` is computed for you. But you can replace it or add to it.

The output of the example above is:

```yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: service
    helm.sh/chart: service-0.1.0
    app.kubernetes.io/managed-by: Helm
    protocol: mail
    app.kubernetes.io/instance: release-name
  name: release-name-service-mail
spec:
  ports:
  - name: smtp
    port: 25
    targetPort: 25
  - name: imaps
    port: 993
    targetPort: 993
  selector:
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name
    protocol: mail
  type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: service
    helm.sh/chart: service-0.1.0
    app.kubernetes.io/managed-by: Helm
    protocol: www
    app.kubernetes.io/instance: release-name
  name: release-name-service-www
spec:
  ports:
  - name: www
    port: 80
    targetPort: 8080
  type: ClusterIP
```

## `common.deployment`

The `common.deployment` template defines a basic `Deployment`. Underneath the
hood, it uses `common.container` (see next section).

By default, the pod template within the deployment defines the labels `app: {{ template "common.name" . }}`
and `release: {{ .Release.Name | quote }` as this is also used as the selector. The
standard set of labels are not used as some of these can change during upgrades,
which causes the replica sets and pods to not correctly match.

Example use:

```yaml
{{- template "common.deployment" (list . "mychart.deployment") -}}
{{- define "mychart.deployment" -}}
## Define overrides for your Deployment resource here, e.g.
spec:
  replicas: {{ .Values.replicaCount }}
{{- end -}}
```

## `common.container`

The `common.container` template creates a basic `Container` spec to be used
within a `Deployment` or `ReplicaSet`. It holds the following defaults:

- The name is set to the chart name
- Uses `.Values.image` to describe the image to run, with the following spec:
  ```yaml
  image:
    repository: nginx
    tag: stable
    pullPolicy: IfNotPresent
  ```
- Exposes the named port `http` as port 80
- Lays out the compute resources using `.Values.resources`

Example use:

```yaml
{{- template "common.deployment" (list . "mychart.deployment") -}}
{{- define "mychart.deployment" -}}
## Define overrides for your Deployment resource here, e.g.
spec:
  template:
    spec:
      containers:
      - {{ template "common.container" (list . "mychart.deployment.container") }}
{{- end -}}
{{- define "mychart.deployment.container" -}}
## Define overrides for your Container here, e.g.
livenessProbe:
  httpGet:
    path: /
    port: 80
readinessProbe:
  httpGet:
    path: /
    port: 80
{{- end -}}
```

The above example creates a `Deployment` resource which makes use of the
`common.container` template to populate the PodSpec's container list. The usage
of this template is similar to the other resources, you must define and
reference a template that contains overrides for the container object.

The most important part of a container definition is the image you want to run.
As mentioned above, this is derived from `.Values.image` by default. It is a
best practice to define the image, tag and pull policy in your charts' values as
this makes it easy for an operator to change the image registry, or use a
specific tag or version. Another example of configuration that should be exposed
to chart operators is the container's required compute resources, as this is
also very specific to an operators environment. An example `values.yaml` for
your chart could look like:

```yaml
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent
resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi
```

The output of running the above values through the earlier template is:

```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: deployment
    helm.sh/chart: deployment-0.1.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/instance: release-name
  name: release-name-deployment
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: deployment
    spec:
      containers:
      - image: nginx:stable
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /
            port: 80
        name: deployment
        ports:
        - containerPort: 80
          name: http
        readinessProbe:
          httpGet:
            path: /
            port: 80
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
          requests:
            cpu: 100m
            memory: 128Mi
```

## `common.configmap`

The `common.configmap` template creates an empty `ConfigMap` resource that you
can override with your configuration.

Example use:

```yaml
{{- template "common.configmap" (list . "mychart.configmap") -}}
{{- define "mychart.configmap" -}}
data:
  zeus: cat
  athena: cat
  julius: cat
  one: |-
    {{ .Files.Get "file1.txt" }}
{{- end -}}
```

Output:

```yaml
apiVersion: v1
data:
  athena: cat
  julius: cat
  one: This is a file.
  zeus: cat
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: configmap
    helm.sh/chart: configmap-0.1.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/instance: release-name
  name: release-name-configmap
```

## `common.secret`

The `common.secret` template creates an empty `Secret` resource that you
can override with your secrets.

Example use:

```yaml
{{- template "common.secret" (list . "mychart.secret") -}}
{{- define "mychart.secret" -}}
data:
  zeus: {{ print "cat" | b64enc }}
  athena: {{ print "cat" | b64enc }}
  julius: {{ print "cat" | b64enc }}
  one: |-
    {{ .Files.Get "file1.txt" | b64enc }}
{{- end -}}
```

Output:

```yaml
apiVersion: v1
data:
  athena: Y2F0
  julius: Y2F0
  one: VGhpcyBpcyBhIGZpbGUuCg==
  zeus: Y2F0
kind: Secret
metadata:
  labels:
    app.kubernetes.io/name: secret
    helm.sh/chart: secret-0.1.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/instance: release-name
  name: release-name-secret
type: Opaque
```

## `common.ingress`

The `common.ingress` template is designed to give you a well-defined `Ingress`
resource, that can be configured using `.Values.ingress`. An example values file
that can be used to configure the `Ingress` resource is:

```yaml
ingress:
  hosts:
  - chart-example.local
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  tls:
  - secretName: chart-example-tls
    hosts:
    - chart-example.local
```

Example use:

```yaml
{{- template "common.ingress" (list . "mychart.ingress") -}}
{{- define "mychart.ingress" -}}
{{- end -}}
```

Output:

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  labels:
    app.kubernetes.io/name: ingress
    helm.sh/chart: ingress-0.1.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/instance: release-name
  name: release-name-ingress
spec:
  rules:
  - host: chart-example.local
    http:
      paths:
      - backend:
          serviceName: release-name-ingress
          servicePort: 80
        path: /
  tls:
  - hosts:
    - chart-example.local
    secretName: chart-example-tls
```

## `common.persistentvolumeclaim`

`common.persistentvolumeclaim` can be used to easily add a
`PersistentVolumeClaim` resource to your chart that can be configured using
`.Values.persistence`:

|           Value           |                                               Description                                               |
| ------------------------- | ------------------------------------------------------------------------------------------------------- |
| persistence.enabled       | Whether or not to claim a persistent volume. If false, `common.volume.pvc` will use an emptyDir instead |
| persistence.storageClass  | `StorageClass` name                                                                                     |
| persistence.accessMode    | Access mode for persistent volume                                                                       |
| persistence.size          | Size of persistent volume                                                                               |
| persistence.existingClaim | If defined, `PersistentVolumeClaim` is not created and `common.volume.pvc` helper uses this claim       |

An example values file that can be used to configure the
`PersistentVolumeClaim` resource is:

```yaml
persistence:
  enabled: true
  storageClass: fast
  accessMode: ReadWriteOnce
  size: 8Gi
```

Example use:

```yaml
{{- template "common.persistentvolumeclaim" (list . "mychart.persistentvolumeclaim") -}}
{{- define "mychart.persistentvolumeclaim" -}}
{{- end -}}
```

Output:

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app.kubernetes.io/name: persistentvolumeclaim
    helm.sh/chart: persistentvolumeclaim-0.1.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/instance: release-name
  name: release-name-persistentvolumeclaim
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: "fast"
```

## Partial API Objects

When writing Kubernetes resources, you may find the following helpers useful to
construct parts of the spec.

### EnvVar

Use the EnvVar helpers within a container spec to simplify specifying key-value
environment variables or referencing secrets as values.

Example Use:

```yaml
{{- template "common.deployment" (list . "mychart.deployment") -}}
{{- define "mychart.deployment" -}}
spec:
  template:
    spec:
      containers:
      - {{ template "common.container" (list . "mychart.deployment.container") }}
{{- end -}}
{{- define "mychart.deployment.container" -}}
{{- $fullname := include "common.fullname" . -}}
env:
- {{ template "common.envvar.value" (list "ZEUS" "cat") }}
- {{ template "common.envvar.secret" (list "ATHENA" "secret-name" "athena") }}
{{- end -}}
```

Output:

```yaml
...
    spec:
      containers:
      - env:
        - name: ZEUS
          value: cat
        - name: ATHENA
          valueFrom:
            secretKeyRef:
              key: athena
              name: secret-name
...
```

### Volume

Use the Volume helpers within a `Deployment` spec to help define ConfigMap and
PersistentVolumeClaim volumes.

Example Use:

```yaml
{{- template "common.deployment" (list . "mychart.deployment") -}}
{{- define "mychart.deployment" -}}
spec:
  template:
    spec:
      volumes:
      - {{ template "common.volume.configMap" (list "config" "configmap-name") }}
      - {{ template "common.volume.pvc" (list "data" "pvc-name" .Values.persistence) }}
{{- end -}}
```

Output:

```yaml
...
    spec:
      volumes:
      - configMap:
          name: configmap-name
        name: config
      - name: data
        persistentVolumeClaim:
          claimName: pvc-name
...
```

The `common.volume.pvc` helper uses the following configuration from the `.Values.persistence` object:

|           Value           |                      Description                      |
| ------------------------- | ----------------------------------------------------- |
| persistence.enabled       | If false, creates an `emptyDir` instead               |
| persistence.existingClaim | If set, uses this instead of the passed in claim name |

## Utilities

### `common.fullname`

The `common.fullname` template generates a name suitable for the `name:` field
in Kubernetes metadata. It is used like this:

```yaml
name: {{ template "common.fullname" . }}
```

The following different values can influence it:

```yaml
# By default, fullname uses '{{ .Release.Name }}-{{ .Chart.Name }}'. This
# overrides that and uses the given string instead.
fullnameOverride: "some-name"

# This adds a prefix
fullnamePrefix: "pre-"
# This appends a suffix
fullnameSuffix: "-suf"

# Global versions of the above
global:
  fullnamePrefix: "pp-"
  fullnameSuffix: "-ps"
```

Example output:

```yaml
---
# with the values above
name: pp-pre-some-name-suf-ps

---
# the default, for release "happy-panda" and chart "wordpress"
name: happy-panda-wordpress
```

Output of this function is truncated at 54 characters, which leaves 9 additional
characters for customized overriding. Thus you can easily extend this name
in your own charts:

```yaml
{{- define "my.fullname" -}}
  {{ template "common.fullname" . }}-my-stuff
{{- end -}}
```

### `common.fullname.unique`

The `common.fullname.unique` variant of fullname appends a unique seven-character
sequence to the end of the common name field.

This takes all of the same parameters as `common.fullname`

Example template:

```yaml
uniqueName: {{ template "common.fullname.unique" . }}
```

Example output:

```yaml
uniqueName: release-name-fullname-jl0dbwx
```

It is also impacted by the prefix and suffix definitions, as well as by
`.Values.fullnameOverride`

Note that the effective maximum length of this function is 63 characters, not 54.

### `common.name`

The `common.name` template generates a name suitable for the `app` label. It is used like this:

```yaml
app: {{ template "common.name" . }}
```

The following different values can influence it:

```yaml
# By default, name uses '{{ .Chart.Name }}'. This
# overrides that and uses the given string instead.
nameOverride: "some-name"

# This adds a prefix
namePrefix: "pre-"
# This appends a suffix
nameSuffix: "-suf"

# Global versions of the above
global:
  namePrefix: "pp-"
  nameSuffix: "-ps"
```

Example output:

```yaml
---
# with the values above
name: pp-pre-some-name-suf-ps

---
# the default, for chart "wordpress"
name: wordpress
```

Output of this function is truncated at 54 characters, which leaves 9 additional
characters for customized overriding. Thus you can easily extend this name
in your own charts:

```yaml
{{- define "my.name" -}}
  {{ template "common.name" . }}-my-stuff
{{- end -}}
```

### `common.metadata`

The `common.metadata` helper generates the `metadata:` section of a Kubernetes
resource.

This takes three objects:
  - .top: top context
  - .fullnameOverride: override the fullname with this name
  - .metadata
    - .labels: key/value list of labels
    - .annotations: key/value list of annotations
    - .hook: name(s) of hook(s)

It generates standard labels, annotations, hooks, and a name field.

Example template:

```yaml
{{ template "common.metadata" (dict "top" . "metadata" .Values.bio) }}
---
{{ template "common.metadata" (dict "top" . "metadata" .Values.pet "fullnameOverride" .Values.pet.fullnameOverride) }}
```

Example values:

```yaml
bio:
  name: example
  labels:
    first: matt
    last: butcher
    nick: technosophos
  annotations:
    format: bio
    destination: archive
  hook: pre-install

pet:
  fullnameOverride: Zeus

```

Example output:

```yaml
metadata:
  name: release-name-metadata
  labels:
    app.kubernetes.io/name: metadata
    app.kubernetes.io/managed-by: "Helm"
    app.kubernetes.io/instance: "release-name"
    helm.sh/chart: metadata-0.1.0
    first: "matt"
    last: "butcher"
    nick: "technosophos"
  annotations:
    "destination": "archive"
    "format": "bio"
    "helm.sh/hook": "pre-install"
---
metadata:
  name: Zeus
  labels:
    app.kubernetes.io/name: metadata
    app.kubernetes.io/managed-by: "Helm"
    app.kubernetes.io/instance: "release-name"
    helm.sh/chart: metadata-0.1.0
  annotations:
```

Most of the common templates that define a resource type (e.g. `common.configmap`
or `common.job`) use this to generate the metadata, which means they inherit
the same `labels`, `annotations`, `nameOverride`, and `hook` fields.

### `common.labelize`

`common.labelize` turns a map into a set of labels.

Example template:

```yaml
{{- $map := dict "first" "1" "second" "2" "third" "3" -}}
{{- template "common.labelize" $map -}}
```

Example output:

```yaml
first: "1"
second: "2"
third: "3"
```

### `common.labels.standard`

`common.labels.standard` prints the standard set of labels.

Example usage:

```
{{ template "common.labels.standard" . }}
```

Example output:

```yaml
app.kubernetes.io/name: labelizer
app.kubernetes.io/managed-by: "Tiller"
app.kubernetes.io/instance: "release-name"
helm.sh/chart: labelizer-0.1.0
```

### `common.hook`

The `common.hook` template is a convenience for defining hooks.

Example template:

```yaml
{{ template "common.hook" "pre-install,post-install" }}
```

Example output:

```yaml
"helm.sh/hook": "pre-install,post-install"
```

### `common.chartref`

The `common.chartref` helper prints the chart name and version, escaped to be
legal in a Kubernetes label field.

Example template:

```yaml
chartref: {{ template "common.chartref" . }}
```

For the chart `foo` with version `1.2.3-beta.55+1234`, this will render:

```yaml
chartref: foo-1.2.3-beta.55_1234
```

(Note that `+` is an illegal character in label values)
