Add chart type

The chart type is added to differentiaite between an application chart
and a library chart. Library charts can be used as dependencies but are
not installable.

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>
pull/5295/head
Martin Hickey 5 years ago
parent e51a9b90c9
commit abdaf3ce1b

@ -78,6 +78,7 @@ func (o *createOptions) run(out io.Writer) error {
cfile := &chart.Metadata{
Name: chartname,
Description: "A Helm chart for Kubernetes",
Type: "application",
Version: "0.1.0",
AppVersion: "1.0",
APIVersion: chart.APIVersionv1,

@ -231,6 +231,14 @@ func (o *installOptions) run(out io.Writer) error {
return err
}
chartType := chartRequested.Metadata.Type
if strings.EqualFold(chartType, "library") {
return errors.New("Library charts are not installable")
}
if chartType != "" && !strings.EqualFold(chartType, "application") {
return errors.New("Invalid chart type. Valid types are: application or library")
}
if req := chartRequested.Metadata.Dependencies; req != nil {
// If checkDependencies returns an error, we have unfulfilled dependencies.
// As of Helm 2.4.0, this is treated as a stopping condition:

@ -119,6 +119,25 @@ func TestInstall(t *testing.T) {
cmd: "install badreq testdata/testcharts/chart-bad-requirements",
wantError: true,
},
// Install, chart with library chart dependency
{
name: "install chart with library chart dependency",
cmd: "install withlibchartp testdata/testcharts/chart-with-lib-dep",
},
// Install, library chart
{
name: "install library chart",
cmd: "install libchart testdata/testcharts/lib-chart",
wantError: true,
golden: "output/template-lib-chart.txt",
},
// Install, chart with bad type
{
name: "install chart with bad type",
cmd: "install badtype testdata/testcharts/chart-bad-type",
wantError: true,
golden: "output/template-chart-bad-type.txt",
},
}
runTestActionCmd(t, tests)

@ -22,6 +22,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"syscall"
"github.com/Masterminds/semver"
@ -134,6 +135,12 @@ func (o *packageOptions) run(out io.Writer) error {
return err
}
chartType := ch.Metadata.Type
if chartType != "" && !strings.EqualFold(chartType, "library") &&
!strings.EqualFold(chartType, "application") {
return errors.New("Invalid chart type. Valid types are: application or library")
}
overrideVals, err := o.mergedValues()
if err != nil {
return err

@ -147,6 +147,11 @@ func TestPackage(t *testing.T) {
expect: fmt.Sprintf("does-not-exist: %s", statFileMsg),
err: true,
},
{
name: "package testdata/testcharts/chart-bad-type",
args: []string{"testdata/testcharts/chart-bad-type"},
err: true,
},
}
origDir, err := os.Getwd()

@ -157,6 +157,14 @@ func (o *templateOptions) run(out io.Writer) error {
return err
}
chartType := c.Metadata.Type
if strings.EqualFold(chartType, "library") {
return errors.New("Library charts are not installable")
}
if chartType != "" && !strings.EqualFold(chartType, "application") {
return errors.New("Invalid chart type. Valid types are: application or library")
}
if req := c.Metadata.Dependencies; req != nil {
if err := checkDependencies(c, req); err != nil {
return err

@ -76,6 +76,18 @@ func TestTemplateCmd(t *testing.T) {
wantError: true,
golden: "output/template-no-args.txt",
},
{
name: "check library chart",
cmd: fmt.Sprintf("template '%s'", "testdata/testcharts/lib-chart"),
wantError: true,
golden: "output/template-lib-chart.txt",
},
{
name: "check chart bad type",
cmd: fmt.Sprintf("template '%s'", "testdata/testcharts/chart-bad-type"),
wantError: true,
golden: "output/template-chart-bad-type.txt",
},
}
runTestCmd(t, tests)
}

@ -0,0 +1 @@
Error: Invalid chart type. Valid types are: application or library

@ -0,0 +1 @@
Error: Library charts are not installable

@ -0,0 +1,7 @@
description: Deploy a basic Alpine Linux pod
home: https://k8s.io/helm
name: chart-bad-type
sources:
- https://github.com/helm/helm
version: 0.1.0
type: foobar

@ -0,0 +1,13 @@
#Alpine: A simple Helm chart
Run a single pod of Alpine Linux.
This example was generated using the command `helm create alpine`.
The `templates/` directory contains a very simple pod resource with a
couple of parameters.
The `values.yaml` file contains the default values for the
`alpine-pod.yaml` template.
You can install this example using `helm install docs/examples/alpine`.

@ -0,0 +1,25 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{.Release.Name}}-{{.Values.Name}}"
labels:
# The "heritage" label is used to track which tool deployed a given chart.
# It is useful for admins who want to see what releases a particular tool
# is responsible for.
heritage: {{.Release.Service | quote }}
# The "release" convention makes it easy to tie a release to all of the
# Kubernetes resources that were created as part of that release.
release: {{.Release.Name | quote }}
# This makes it easy to audit chart usage.
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
values: {{.Values.test.Name}}
spec:
# This shows how to use a simple value. This will look for a passed-in value
# called restartPolicy. If it is not found, it will use the default value.
# {{default "Never" .restartPolicy}} is a slightly optimized version of the
# more conventional syntax: {{.restartPolicy | default "Never"}}
restartPolicy: {{default "Never" .Values.restartPolicy}}
containers:
- name: waiter
image: "alpine:3.3"
command: ["/bin/sleep","9000"]

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

@ -0,0 +1,6 @@
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: chart-with-lib-dep
type: application
version: 0.1.0

@ -0,0 +1,19 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range .Values.ingress.hosts }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "chart-with-lib-dep.fullname" . }})
export NODE_IP=$(kubectl get nodes -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc -w {{ template "chart-with-lib-dep.fullname" . }}'
export SERVICE_IP=$(kubectl get svc {{ template "chart-with-lib-dep.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods -l "app={{ template "chart-with-lib-dep.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl port-forward $POD_NAME 8080:80
{{- end }}

@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "chart-with-lib-dep.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "chart-with-lib-dep.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "chart-with-lib-dep.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

@ -0,0 +1,51 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ template "chart-with-lib-dep.fullname" . }}
labels:
app: {{ template "chart-with-lib-dep.name" . }}
chart: {{ template "chart-with-lib-dep.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ template "chart-with-lib-dep.name" . }}
release: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ template "chart-with-lib-dep.name" . }}
release: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}

@ -0,0 +1,38 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "chart-with-lib-dep.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
app: {{ template "chart-with-lib-dep.name" . }}
chart: {{ template "chart-with-lib-dep.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- with .Values.ingress.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ $fullName }}
servicePort: http
{{- end }}
{{- end }}

@ -0,0 +1,10 @@
{{- 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 -}}

@ -0,0 +1,48 @@
# Default values for chart-with-lib-dep.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
tag: stable
pullPolicy: IfNotPresent
nameOverride: ""
fullnameOverride: ""
service:
type: ClusterIP
port: 80
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
path: /
hosts:
- chart-example.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

@ -0,0 +1,12 @@
apiVersion: v1
description: Common chartbuilding components and helpers
name: lib-chart
version: 0.0.5
appVersion: 0.0.5
home: https://helm.sh
maintainers:
- name: technosophos
email: technosophos@gmail.com
- name: prydonius
email: adnan@bitnami.com
type: Library

@ -0,0 +1,831 @@
# 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 workaround 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: {{ template "common.name" }}, release: {{ .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: service
chart: service-0.1.0
heritage: Tiller
protocol: mail
release: release-name
name: release-name-service-mail
spec:
ports:
- name: smtp
port: 25
targetPort: 25
- name: imaps
port: 993
targetPort: 993
selector:
app: service
release: release-name
protocol: mail
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
labels:
app: service
chart: service-0.1.0
heritage: Tiller
protocol: www
release: 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: deployment
chart: deployment-0.1.0
heritage: Tiller
release: release-name
name: release-name-deployment
spec:
template:
metadata:
labels:
app: 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: configmap
chart: configmap-0.1.0
heritage: Tiller
release: 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: secret
chart: secret-0.1.0
heritage: Tiller
release: 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: ingress
chart: ingress-0.1.0
heritage: Tiller
release: 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: persistentvolumeclaim
chart: persistentvolumeclaim-0.1.0
heritage: Tiller
release: 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: metadata
heritage: "Tiller"
release: "RELEASE-NAME"
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: metadata
heritage: "Tiller"
release: "RELEASE-NAME"
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: labelizer
heritage: "Tiller"
release: "RELEASE-NAME"
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)

@ -0,0 +1,14 @@
{{- /*
common.chartref prints a chart name and version.
It does minimal escaping for use in Kubernetes labels.
Example output:
zookeeper-1.2.3
wordpress-3.2.1_20170219
*/ -}}
{{- define "common.chartref" -}}
{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}}
{{- end -}}

@ -0,0 +1,9 @@
{{- define "common.configmap.tpl" -}}
apiVersion: v1
kind: ConfigMap
{{ template "common.metadata" . }}
data: {}
{{- end -}}
{{- define "common.configmap" -}}
{{- template "common.util.merge" (append . "common.configmap.tpl") -}}
{{- end -}}

@ -0,0 +1,15 @@
{{- define "common.container.tpl" -}}
name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
resources:
{{ toYaml .Values.resources | indent 2 }}
{{- end -}}
{{- define "common.container" -}}
{{- /* clear new line so indentation works correctly */ -}}
{{- println "" -}}
{{- include "common.util.merge" (append . "common.container.tpl") | indent 8 -}}
{{- end -}}

@ -0,0 +1,18 @@
{{- define "common.deployment.tpl" -}}
apiVersion: extensions/v1beta1
kind: Deployment
{{ template "common.metadata" . }}
spec:
template:
metadata:
labels:
app: {{ template "common.name" . }}
release: {{ .Release.Name | quote }}
spec:
containers:
-
{{ include "common.container.tpl" . | indent 8 }}
{{- end -}}
{{- define "common.deployment" -}}
{{- template "common.util.merge" (append . "common.deployment.tpl") -}}
{{- end -}}

@ -0,0 +1,31 @@
{{- define "common.envvar.value" -}}
{{- $name := index . 0 -}}
{{- $value := index . 1 -}}
name: {{ $name }}
value: {{ default "" $value | quote }}
{{- end -}}
{{- define "common.envvar.configmap" -}}
{{- $name := index . 0 -}}
{{- $configMapName := index . 1 -}}
{{- $configMapKey := index . 2 -}}
name: {{ $name }}
valueFrom:
configMapKeyRef:
name: {{ $configMapName }}
key: {{ $configMapKey }}
{{- end -}}
{{- define "common.envvar.secret" -}}
{{- $name := index . 0 -}}
{{- $secretName := index . 1 -}}
{{- $secretKey := index . 2 -}}
name: {{ $name }}
valueFrom:
secretKeyRef:
name: {{ $secretName }}
key: {{ $secretKey }}
{{- end -}}

@ -0,0 +1,39 @@
{{- /*
fullname defines a suitably unique name for a resource by combining
the release name and the chart name.
The prevailing wisdom is that names should only contain a-z, 0-9 plus dot (.) and dash (-), and should
not exceed 63 characters.
Parameters:
- .Values.fullnameOverride: Replaces the computed name with this given name
- .Values.fullnamePrefix: Prefix
- .Values.global.fullnamePrefix: Global prefix
- .Values.fullnameSuffix: Suffix
- .Values.global.fullnameSuffix: Global suffix
The applied order is: "global prefix + prefix + name + suffix + global suffix"
Usage: 'name: "{{- template "common.fullname" . -}}"'
*/ -}}
{{- define "common.fullname"}}
{{- $global := default (dict) .Values.global -}}
{{- $base := default (printf "%s-%s" .Release.Name .Chart.Name) .Values.fullnameOverride -}}
{{- $gpre := default "" $global.fullnamePrefix -}}
{{- $pre := default "" .Values.fullnamePrefix -}}
{{- $suf := default "" .Values.fullnameSuffix -}}
{{- $gsuf := default "" $global.fullnameSuffix -}}
{{- $name := print $gpre $pre $base $suf $gsuf -}}
{{- $name | lower | trunc 54 | trimSuffix "-" -}}
{{- end -}}
{{- /*
common.fullname.unique adds a random suffix to the unique name.
This takes the same parameters as common.fullname
*/ -}}
{{- define "common.fullname.unique" -}}
{{ template "common.fullname" . }}-{{ randAlphaNum 7 | lower }}
{{- end }}

@ -0,0 +1,27 @@
{{- define "common.ingress.tpl" -}}
apiVersion: extensions/v1beta1
kind: Ingress
{{ template "common.metadata" . }}
{{- if .Values.ingress.annotations }}
annotations:
{{ include "common.annote" .Values.ingress.annotations | indent 4 }}
{{- end }}
spec:
rules:
{{- range $host := .Values.ingress.hosts }}
- host: {{ $host }}
http:
paths:
- path: /
backend:
serviceName: {{ template "common.fullname" $ }}
servicePort: 80
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
{{- end -}}
{{- end -}}
{{- define "common.ingress" -}}
{{- template "common.util.merge" (append . "common.ingress.tpl") -}}
{{- end -}}

@ -0,0 +1,10 @@
{{- /*
common.metadata creates a standard metadata header.
It creates a 'metadata:' section with name and labels.
*/ -}}
{{ define "common.metadata" -}}
metadata:
name: {{ template "common.fullname" . }}
labels:
{{ include "common.labels.standard" . | indent 4 -}}
{{- end -}}

@ -0,0 +1,18 @@
{{- /*
common.hook defines a hook.
This is to be used in a 'metadata.annotations' section.
This should be called as 'template "common.metadata.hook" "post-install"'
Any valid hook may be passed in. Separate multiple hooks with a ",".
*/ -}}
{{- define "common.hook" -}}
"helm.sh/hook": {{printf "%s" . | quote}}
{{- end -}}
{{- define "common.annote" -}}
{{- range $k, $v := . }}
{{ $k | quote }}: {{ $v | quote }}
{{- end -}}
{{- end -}}

@ -0,0 +1,28 @@
{{- /*
common.labelize takes a dict or map and generates labels.
Values will be quoted. Keys will not.
Example output:
first: "Matt"
last: "Butcher"
*/ -}}
{{- define "common.labelize" -}}
{{- range $k, $v := . }}
{{ $k }}: {{ $v | quote }}
{{- end -}}
{{- end -}}
{{- /*
common.labels.standard prints the standard Helm labels.
The standard labels are frequently used in metadata.
*/ -}}
{{- define "common.labels.standard" -}}
app: {{ template "common.name" . }}
chart: {{ template "common.chartref" . }}
heritage: {{ .Release.Service | quote }}
release: {{ .Release.Name | quote }}
{{- end -}}

@ -0,0 +1,29 @@
{{- /*
name defines a template for the name of the chart. It should be used for the `app` label.
This is common practice in many Kubernetes manifests, and is not Helm-specific.
The prevailing wisdom is that names should only contain a-z, 0-9 plus dot (.) and dash (-), and should
not exceed 63 characters.
Parameters:
- .Values.nameOverride: Replaces the computed name with this given name
- .Values.namePrefix: Prefix
- .Values.global.namePrefix: Global prefix
- .Values.nameSuffix: Suffix
- .Values.global.nameSuffix: Global suffix
The applied order is: "global prefix + prefix + name + suffix + global suffix"
Usage: 'name: "{{- template "common.name" . -}}"'
*/ -}}
{{- define "common.name"}}
{{- $global := default (dict) .Values.global -}}
{{- $base := default .Chart.Name .Values.nameOverride -}}
{{- $gpre := default "" $global.namePrefix -}}
{{- $pre := default "" .Values.namePrefix -}}
{{- $suf := default "" .Values.nameSuffix -}}
{{- $gsuf := default "" $global.nameSuffix -}}
{{- $name := print $gpre $pre $base $suf $gsuf -}}
{{- $name | lower | trunc 54 | trimSuffix "-" -}}
{{- end -}}

@ -0,0 +1,24 @@
{{- define "common.persistentvolumeclaim.tpl" -}}
apiVersion: v1
kind: PersistentVolumeClaim
{{ template "common.metadata" . }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end -}}
{{- define "common.persistentvolumeclaim" -}}
{{- $top := first . -}}
{{- if and $top.Values.persistence.enabled (not $top.Values.persistence.existingClaim) -}}
{{- template "common.util.merge" (append . "common.persistentvolumeclaim.tpl") -}}
{{- end -}}
{{- end -}}

@ -0,0 +1,10 @@
{{- define "common.secret.tpl" -}}
apiVersion: v1
kind: Secret
{{ template "common.metadata" . }}
type: Opaque
data: {}
{{- end -}}
{{- define "common.secret" -}}
{{- template "common.util.merge" (append . "common.secret.tpl") -}}
{{- end -}}

@ -0,0 +1,17 @@
{{- define "common.service.tpl" -}}
apiVersion: v1
kind: Service
{{ template "common.metadata" . }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: 80
targetPort: http
selector:
app: {{ template "common.name" . }}
release: {{ .Release.Name | quote }}
{{- end -}}
{{- define "common.service" -}}
{{- template "common.util.merge" (append . "common.service.tpl") -}}
{{- end -}}

@ -0,0 +1,15 @@
{{- /*
common.util.merge will merge two YAML templates and output the result.
This takes an array of three values:
- the top context
- the template name of the overrides (destination)
- the template name of the base (source)
*/ -}}
{{- define "common.util.merge" -}}
{{- $top := first . -}}
{{- $overrides := fromYaml (include (index . 1) $top) | default (dict ) -}}
{{- $tpl := fromYaml (include (index . 2) $top) | default (dict ) -}}
{{- toYaml (merge $overrides $tpl) -}}
{{- end -}}

@ -0,0 +1,22 @@
{{- define "common.volume.configMap" -}}
{{- $name := index . 0 -}}
{{- $configMapName := index . 1 -}}
name: {{ $name }}
configMap:
name: {{ $configMapName }}
{{- end -}}
{{- define "common.volume.pvc" -}}
{{- $name := index . 0 -}}
{{- $claimName := index . 1 -}}
{{- $persistence := index . 2 -}}
name: {{ $name }}
{{- if $persistence.enabled }}
persistentVolumeClaim:
claimName: {{ $persistence.existingClaim | default $claimName }}
{{- else }}
emptyDir: {}
{{- end -}}
{{- end -}}

@ -0,0 +1,4 @@
# Default values for commons.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value

@ -62,4 +62,6 @@ type Metadata struct {
KubeVersion string `json:"kubeVersion,omitempty"`
// Dependencies are a list of dependencies for a chart.
Dependencies []*Dependency `json:"dependencies,omitempty"`
// Specifies the chart type: application or library
Type string `json:"type,omitempty"`
}

Loading…
Cancel
Save