Helm Named Templates: Difference between revisions
(→block) |
|||
(76 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
=Internal= | =Internal= | ||
* [[Helm_Templates#Named_Template_Actions|Helm Templates]] | * [[Helm_Templates#Named_Template_Actions|Helm Templates]] | ||
=Overview= | |||
A named template, also known as a partial, sub-template or embedded template, is a fragment of text that is declared in one file and then rendered in-line into another template, usually defined in a different file, every time it is invoked with the [[#template|template]] action or the [[#include_Function|include]] function. A sub-template is declared with the [[#define|define]] action. A sub-template name has a [[#Sub-Template_Name|name]], declared when the sub-template is defined. The sub-template body may contain action and function declarations, which will be rendered when the enclosing template is rendered. When the template engine reads the sub-template declaration, it will store away the reference to the sub-template, keyed by its name, until it encounters a [[#template|template]] action or a [[#include_Function|include]] function that specify the sub-template name. At that time, it will render the sub-template inline. | |||
=Sub-Template Elements= | |||
==Sub-Template Name== | |||
Sub-template names, including those declared in [[Helm_Dependencies#Subcharts|subcharts]], are global. This means that if two sub-templates have the same name, whichever is loaded last will be the one to be used. For this reason, is a good practice to name the sub-templates with chart-specific names, and prefix the name of the sub-template with the name of the chart: | |||
<syntaxhighlight lang='yaml'> | |||
{{ define "mychart.mysubtemplate" }} | |||
</syntaxhighlight> | |||
Using the chart name as a prefix, chart-specific sub-templates get their own namespace and that decreases the probability of conflict that may arise due to two different charts that implement templates with the same name. | |||
==Sub-Template Files== | |||
Sub-templates can be declared inside other template files, in helper files, for example <code>[[Helm_Chart_helpers.tpl|_helpers.tpl]]</code>, inside the chart's <code>[[Helm_Templates#The_templates.2F_Directory|templates/]]</code> directory. <code>[[Helm Chart _helpers.tpl|_helpers.tpl]]</code> is the default location for small sub-templates. If a sub-template is large enough, it can be stored in its own '_'-prefixed file. For more details on templates/ directory and template file conventions, see: | |||
{{Internal|Helm_Templates#The_templates.2F_Directory|<tt>templates/</tt>}} | |||
==Sub-Template Scope== | |||
If a sub-template includes references to [[Helm_Templates#Built-in_Objects|built-in objects]], those objects need to be reachable from the [[Helm_Templates#Scopes|scope]] ([[sprig_dict#Overview|dict]] instance) the sub-template is invoked with. The scope ([[sprig_dict#Overview|dict]] instance) is specified as the second argument of [[#template|template]] or [[#include_Function|include]] invocation, after the sub-template name: | |||
<syntaxhighlight lang='yaml'> | |||
{{ include "<sub-template-name>" <scope> }} | |||
{{ template "<sub-template-name>" <scope> }} | |||
</syntaxhighlight> | |||
The scope can be "." or any other known scope. | |||
<syntaxhighlight lang='yaml'> | |||
{{ include "mychart.mysubtemplate" . }} | |||
{{ template "mychart.mysubtemplate" .Values }} | |||
</syntaxhighlight> | |||
=Actions= | |||
==define== | |||
{{External|https://helm.sh/docs/chart_template_guide/named_templates/#declaring-and-using-templates-with-define-and-template}} | |||
The 'define' action is used to declare the name and the content of the sub-template: | |||
<syntaxhighlight lang='yaml'> | |||
{{/* | |||
Generate basic labels. | |||
This is a multi-line comment. | |||
*/}} | |||
{{- define "mychart.mysubtemplate" }} | |||
labels: | |||
color: blue | |||
date: {{ now | htmlDate }} | |||
{{- end }} | |||
</syntaxhighlight> | |||
Note that the indentation of the sub-template body is important. The [[#template|template]] action will render the body as is, honoring the existing white space and indentation. The [[#include_Function|include]] function can be used to indent the body, by piping it through the [[Helm_Template_Function_indent|indent]] function. However, the indent function will only add extra indentation to the already existing one. | |||
By convention, a "define" declaration should be preceded by a documentation block that describes what it does. The body of the sub-template may include directive. "define" declaration does not produce output, until the sub-template is rendered with [[#template|template]] or [[#include_Function|include]]. | |||
==template== | |||
The 'template' action renders the specified sub-template, with the given scope, in the enclosing template. | |||
<syntaxhighlight lang='yaml'> | |||
... | |||
kind: ConfigMap | |||
metadata: | |||
name: test-cm | |||
{{- template "mychart.mysubtemplate" . }} | |||
... | |||
</syntaxhighlight> | |||
Note that "template" renders the sub-template body as is, reflecting the original indentation. The action output cannot be passed to other functions, and that is why the [[#input_Function|input]] function is almost always a better option to embed a sub-template. | |||
=include Function= | |||
The <code>include</code> function is the preferred alternative to embed a template. The output of the function can be processed by a pipeline before embedding, hence the indentation can be controlled, unlike in <code>[[#template|template]]</code> case. | |||
<syntaxhighlight lang='yaml'> | |||
... | |||
kind: ConfigMap | |||
metadata: | |||
name: test-cm | |||
{{- include "mychart.mysubtemplate" . | indent 2 }} | |||
... | |||
</syntaxhighlight> | |||
{{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.}} | |||
=Passing Arguments to Sub-templates= | |||
{{External|http://masterminds.github.io/sprig/dicts.html}} | |||
Arguments can be passed to sub-templates using [[sprig_dict#Overview|dict]]: | |||
<syntaxhighlight lang='yaml'> | |||
{{- include "mychart.mysubtemplate" (dict "color" "green" "shape" "square") -}} | |||
</syntaxhighlight> | |||
The dict keys can be accessed inside the sub-template as such: | |||
<syntaxhighlight lang='yaml'> | |||
{{- define "mychart.mysubtemplate" -}} | |||
apiVersion: v1 | |||
kind: ConfigMap | |||
metadata: | |||
name: {{ .name }} | |||
data: | |||
color: {{ .color }} | |||
{{- end -}} | |||
</syntaxhighlight> | |||
This pattern works only if the template does not need to access built-in objects via the [[Helm_Templates#Scope|root scope]]. If access to the root scope is required, the extra arguments can be passed using a child [[sprig_dict#Overview|dict]] instance: | |||
<syntaxhighlight lang='yaml'> | |||
{{- $SubTemplateArgs := dict "Name" "example" -}} | |||
{{- $_ := set . "SubTemplateArgs" $SubTemplateArgs -}} | |||
{{- include "mychart.mysubtemplate" . }} | |||
</syntaxhighlight> | |||
<syntaxhighlight lang='yaml'> | |||
{{- define "mychart.mysubtemplate" -}} | |||
apiVersion: v1 | |||
kind: ConfigMap | |||
metadata: | |||
name: {{ .SubTemplateArgs.Name }} | |||
labels: | |||
release: {{ .Release.Name }} | |||
{{- end -}} | |||
</syntaxhighlight> | |||
For more dict patterns, see: {{Internal|sprig_dict#Overview|dict}} | |||
=Sub-templates as Variables= | |||
Sub-templates may be used instead of variables, by declaring a template that acts like a variable: | |||
<syntaxhighlight lang='yaml'> | |||
{{/* | |||
Compute the service name that depends on the release name. This partial should be inlined every time the service name is needed. | |||
*/}} | |||
{{- define "myChart.postgresqlServiceName" -}} | |||
{{- printf "%s-postgresql" .Release.Name -}} | |||
{{- end -}} | |||
</syntaxhighlight> | |||
When we need the service name in a template, we render it as such: | |||
<syntaxhighlight lang='yaml'> | |||
... {{ template "myChart.postgresqlServiceName" . }} ... | |||
</syntaxhighlight> | |||
=Recipes= | |||
{{Internal|Helm Named Template Recipes|Named Template Recipes}} | |||
=block= | |||
<code>block</code> declares a special kind of fillable template area. | |||
=Named Templates and Whitespace Handling= | |||
Also see: {{Internal|Helm_Templates#Directives_and_Whitespace_Handling|Directives and Whitespace Handling}} |
Latest revision as of 07:38, 9 February 2022
External
Internal
Overview
A named template, also known as a partial, sub-template or embedded template, is a fragment of text that is declared in one file and then rendered in-line into another template, usually defined in a different file, every time it is invoked with the template action or the include function. A sub-template is declared with the define action. A sub-template name has a name, declared when the sub-template is defined. The sub-template body may contain action and function declarations, which will be rendered when the enclosing template is rendered. When the template engine reads the sub-template declaration, it will store away the reference to the sub-template, keyed by its name, until it encounters a template action or a include function that specify the sub-template name. At that time, it will render the sub-template inline.
Sub-Template Elements
Sub-Template Name
Sub-template names, including those declared in subcharts, are global. This means that if two sub-templates have the same name, whichever is loaded last will be the one to be used. For this reason, is a good practice to name the sub-templates with chart-specific names, and prefix the name of the sub-template with the name of the chart:
{{ define "mychart.mysubtemplate" }}
Using the chart name as a prefix, chart-specific sub-templates get their own namespace and that decreases the probability of conflict that may arise due to two different charts that implement templates with the same name.
Sub-Template Files
Sub-templates can be declared inside other template files, in helper files, for example _helpers.tpl
, inside the chart's templates/
directory. _helpers.tpl
is the default location for small sub-templates. If a sub-template is large enough, it can be stored in its own '_'-prefixed file. For more details on templates/ directory and template file conventions, see:
Sub-Template Scope
If a sub-template includes references to built-in objects, those objects need to be reachable from the scope (dict instance) the sub-template is invoked with. The scope (dict instance) is specified as the second argument of template or include invocation, after the sub-template name:
{{ include "<sub-template-name>" <scope> }}
{{ template "<sub-template-name>" <scope> }}
The scope can be "." or any other known scope.
{{ include "mychart.mysubtemplate" . }}
{{ template "mychart.mysubtemplate" .Values }}
Actions
define
The 'define' action is used to declare the name and the content of the sub-template:
{{/*
Generate basic labels.
This is a multi-line comment.
*/}}
{{- define "mychart.mysubtemplate" }}
labels:
color: blue
date: {{ now | htmlDate }}
{{- end }}
Note that the indentation of the sub-template body is important. The template action will render the body as is, honoring the existing white space and indentation. The include function can be used to indent the body, by piping it through the indent function. However, the indent function will only add extra indentation to the already existing one.
By convention, a "define" declaration should be preceded by a documentation block that describes what it does. The body of the sub-template may include directive. "define" declaration does not produce output, until the sub-template is rendered with template or include.
template
The 'template' action renders the specified sub-template, with the given scope, in the enclosing template.
...
kind: ConfigMap
metadata:
name: test-cm
{{- template "mychart.mysubtemplate" . }}
...
Note that "template" renders the sub-template body as is, reflecting the original indentation. The action output cannot be passed to other functions, and that is why the input function is almost always a better option to embed a sub-template.
include Function
The include
function is the preferred alternative to embed a template. The output of the function can be processed by a pipeline before embedding, hence the indentation can be controlled, unlike in template
case.
...
kind: ConfigMap
metadata:
name: test-cm
{{- include "mychart.mysubtemplate" . | indent 2 }}
...
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.
Passing Arguments to Sub-templates
Arguments can be passed to sub-templates using dict:
{{- include "mychart.mysubtemplate" (dict "color" "green" "shape" "square") -}}
The dict keys can be accessed inside the sub-template as such:
{{- define "mychart.mysubtemplate" -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .name }}
data:
color: {{ .color }}
{{- end -}}
This pattern works only if the template does not need to access built-in objects via the root scope. If access to the root scope is required, the extra arguments can be passed using a child dict instance:
{{- $SubTemplateArgs := dict "Name" "example" -}}
{{- $_ := set . "SubTemplateArgs" $SubTemplateArgs -}}
{{- include "mychart.mysubtemplate" . }}
{{- define "mychart.mysubtemplate" -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .SubTemplateArgs.Name }}
labels:
release: {{ .Release.Name }}
{{- end -}}
For more dict patterns, see:
Sub-templates as Variables
Sub-templates may be used instead of variables, by declaring a template that acts like a variable:
{{/*
Compute the service name that depends on the release name. This partial should be inlined every time the service name is needed.
*/}}
{{- define "myChart.postgresqlServiceName" -}}
{{- printf "%s-postgresql" .Release.Name -}}
{{- end -}}
When we need the service name in a template, we render it as such:
... {{ template "myChart.postgresqlServiceName" . }} ...
Recipes
block
block
declares a special kind of fillable template area.
Named Templates and Whitespace Handling
Also see: