Helm使用Go模板 Go Template 来生成模板和资源文件。虽然Go提供了几个内置函数,但是Helm还添加了其他的函数。
在 Sprig库 中添加了几乎所有的函数。出于安全考虑,删除了env
和expandenv
这两个函数,这两个函数让chart作者能访问Tiller的环境变量,同时新增两个特殊的模板函数:include
和required
。
模板函数遵循语法functionName arg1 arg2 ...
,调用函数并将参数传递给它。常用的函数包括:
命名模板(也称为子模板)是限定在一个文件内部的模板,并给它起一个名称。
命名模板的模板名称是全局的。如果声明两个具有相同名称的模板,则最后加载的那个模板是起作用的模板。由于子 chart 中的模板与顶级模板一起编译,因此注意小心地使用特定 chart 的名称来命名模板。
通用的命名约定是为每个定义的模板添加 chart 名称:{{define "mychart.labels"}}
。通过使用特定 chart 名称作为前缀,可以避免由于同名模板的两个不同 chart 而可能出现的任何冲突。
该 define 操作允许我们在模板文件内创建一个命名模板。它的语法如下所示:
{{ define "MY.NAME" }}
# body of template here
{{ end }}
# 例如,可以定义一个模板来封装一个 Kubernetes 标签块
{{- define "mychart.labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}
{{- end }}
Helm chart 通常将define创建的这些命名模板放入 partials 文件中,通常是helpers.tpl
。按照惯例,define 函数应该有一个简单的文档块({{/* ... */}})
来描述它所做的事情。
上面定义的命名模板中,没有使用任何对象,只是使用函数。现在将命名模板修改为如下形式,以包含 chart 名称和 chart 版本:
{{/* Generate basic labels */}}
{{- define "mychart.labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}
chart: {{ .Chart.Name }}
version: {{ .Chart.Version }}
{{- end }}
# 这将不会得到我们所期望的结果
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: moldy-jaguar-configmap
labels:
generator: helm
date: 2016-11-02
chart: # 未获取到Chart.Name
version: # 未获取到Chart.Version
# 上述两个值,不在我们定义的模板的范围内
当一个命名模板被渲染时,它将接收由该template调用传入的作用域。
{{- template "mychart.labels" }}
# 没有范围被传入,因此在模板中无法访问任何内容
# 将范围传递给模板
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "mychart.labels" . }} # 在template末尾传递了`.`
# `.`表示顶级范围,`.Values`范围,`.Values.favorite`范围
添加范围后,就可以得到正确的值。
{{template "name"}}
// 执行名为name的模板,提供给模板的参数为nil,如模板不存在输出为""
{{template "name" pipeline}}
// 执行名为name的模板,提供给模板的参数为pipeline的值
# 调用上述define中定义的命名模板
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 }}
即使这个定义在_helpers.tpl
,它仍然可以在 configmap.yaml 以下位置访问,因为模板名称是全局的 。
虽然Go提供了template函数,能够将一个模板包含在另一个模板中,但是Go的template函数中不能使用管道来传递值到其他内置的函数中。
为了能够引入模板,然后对该模板的输出执行操作,Helm提供了include函数允许引入另一个模板,然后将结果传递给其他函数模板。
// 调用模板 mysql.labels,然后将结果缩进四个空格(在函数中使用管道来进行值的传递),其中 `.` 表示渲染的根对象
{{ include "mysql.labels" . | indent 4 }}
// 调用模板 toYaml,渲染$value的内容,然后将渲染的输出传递给 indent 函数
{{- include "toYaml" $value | nindent 2}}
因为YAML的缩进级别和空白很重要,所以使用indent函数是包含代码片段的好方法,并在相关的上下文中处理缩进。
required 函数允许根据模板渲染的要求声明特定的值条目。如果values.yaml中该条目值为空,则模板渲染将失败并显示用户提交的错误消息。
// 声明 .Values.who 条目是必需的,并且在缺少该条目(即未定义Values.who)时将显示错误消息
value: {{required "A valid .Values.who entry required!" .Values.who}}
tpl 函数允许开发人员将字符串计算为模板内的模板。 这对于将模板字符串作为值传递给 chart 或渲染外部配置文件很有用。
语法: {{tpl TEMPLATE_STRING VALUES}}
// 模板字符串 values.yaml文件
template: "{{.Values.name}}"
name: "Tom"
// template
{{tpl .Values.template .}}
// output
Tom
// 外部配置文件 conf/app.conf
firstName={{.Values.firstName}}
lastName={{.Values.lastName}}
// values.yaml文件
firstName: Peter
lastName: Parkerk
// template
{{tpl (.Files.Get "conf/app.conf") . }}
// output
firstName=Peter
lastName=Parker
default函数,如:default DEFAULT_VALUE GIVEN_VALUE
。该功能允许在模板内部指定默认值,以防该值被省略。
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
在实际的 chart 中:
values.yaml
中,不应该使用 default 命令重复(否则它们将是重复多余的)。对于模板,运算符(eq,ne,lt,gt,and,or 等等)都是已实现的功能。在管道中,运算符可以用圆括号((
和))
分组。
将运算符放到声明的前面,后面跟着它的参数,就像使用函数一样。要多个运算符一起使用,将每个函数通过圆括号分隔。