github.com/koderover/helm@v2.17.0+incompatible/docs/chart_template_guide/functions_and_pipelines.md (about) 1 # Template Functions and Pipelines 2 3 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 usable to us. 4 5 Let's start with a best practice: When injecting strings from the `.Values` object into the template, we ought to quote these strings. We can do that by calling the `quote` function in the template directive: 6 7 ```yaml 8 apiVersion: v1 9 kind: ConfigMap 10 metadata: 11 name: {{ .Release.Name }}-configmap 12 data: 13 myvalue: "Hello World" 14 drink: {{ quote .Values.favorite.drink }} 15 food: {{ quote .Values.favorite.food }} 16 ``` 17 18 Template functions follow the syntax `functionName arg1 arg2...`. In the snippet above, `quote .Values.favorite.drink` calls the `quote` function and passes it a single argument. 19 20 Helm has over 60 available functions. Some of them are defined by the [Go template language](https://godoc.org/text/template) itself. Most of the others are part of the [Sprig template library](https://godoc.org/github.com/Masterminds/sprig). We'll see many of them as we progress through the examples. 21 22 > While we talk about the "Helm template language" as if it is Helm-specific, it is actually a combination of the Go template language, some extra functions, and a variety of wrappers to expose certain objects to the templates. Many resources on Go templates may be helpful as you learn about templating. 23 24 ## Pipelines 25 26 One of the powerful features of the template language is its concept of _pipelines_. Drawing on a concept from UNIX, pipelines are a tool for chaining together a series of template commands to compactly express a series of transformations. In other words, pipelines are an efficient way of getting several things done in sequence. Let's rewrite the above example using a pipeline. 27 28 ```yaml 29 apiVersion: v1 30 kind: ConfigMap 31 metadata: 32 name: {{ .Release.Name }}-configmap 33 data: 34 myvalue: "Hello World" 35 drink: {{ .Values.favorite.drink | quote }} 36 food: {{ .Values.favorite.food | quote }} 37 ``` 38 39 In this example, instead of calling `quote ARGUMENT`, we inverted the order. We "sent" the argument to the function using a pipeline (`|`): `.Values.favorite.drink | quote`. Using pipelines, we can chain several functions together: 40 41 ```yaml 42 apiVersion: v1 43 kind: ConfigMap 44 metadata: 45 name: {{ .Release.Name }}-configmap 46 data: 47 myvalue: "Hello World" 48 drink: {{ .Values.favorite.drink | quote }} 49 food: {{ .Values.favorite.food | upper | quote }} 50 ``` 51 52 > Inverting the order is a common practice in templates. You will see `.val | quote` more often than `quote .val`. Either practice is fine. 53 54 When evaluated, that template will produce this: 55 56 ```yaml 57 # Source: mychart/templates/configmap.yaml 58 apiVersion: v1 59 kind: ConfigMap 60 metadata: 61 name: trendsetting-p-configmap 62 data: 63 myvalue: "Hello World" 64 drink: "coffee" 65 food: "PIZZA" 66 ``` 67 68 Note that our original `pizza` has now been transformed to `"PIZZA"`. 69 70 When pipelining arguments like this, the result of the first evaluation (`.Values.favorite.drink`) is sent as the _last argument to the function_. We can modify the drink example above to illustrate with a function that takes two arguments: `repeat COUNT STRING`: 71 72 ```yaml 73 apiVersion: v1 74 kind: ConfigMap 75 metadata: 76 name: {{ .Release.Name }}-configmap 77 data: 78 myvalue: "Hello World" 79 drink: {{ .Values.favorite.drink | repeat 5 | quote }} 80 food: {{ .Values.favorite.food | upper | quote }} 81 ``` 82 83 The `repeat` function will echo the given string the given number of times, so we will get this for output: 84 85 ```yaml 86 # Source: mychart/templates/configmap.yaml 87 apiVersion: v1 88 kind: ConfigMap 89 metadata: 90 name: melting-porcup-configmap 91 data: 92 myvalue: "Hello World" 93 drink: "coffeecoffeecoffeecoffeecoffee" 94 food: "PIZZA" 95 ``` 96 97 ## Using the `default` function 98 99 One function frequently used in templates is the `default` function: `default DEFAULT_VALUE GIVEN_VALUE`. This function allows you to specify a default value inside of the template, in case the value is omitted. Let's use it to modify the drink example above: 100 101 ```yaml 102 drink: {{ .Values.favorite.drink | default "tea" | quote }} 103 ``` 104 105 If we run this as normal, we'll get our `coffee`: 106 107 ```yaml 108 # Source: mychart/templates/configmap.yaml 109 apiVersion: v1 110 kind: ConfigMap 111 metadata: 112 name: virtuous-mink-configmap 113 data: 114 myvalue: "Hello World" 115 drink: "coffee" 116 food: "PIZZA" 117 ``` 118 119 Now, we will remove the favorite drink setting from `values.yaml`: 120 121 ```yaml 122 favorite: 123 #drink: coffee 124 food: pizza 125 ``` 126 127 Now re-running `helm install --dry-run --debug ./mychart` will produce this YAML: 128 129 ```yaml 130 # Source: mychart/templates/configmap.yaml 131 apiVersion: v1 132 kind: ConfigMap 133 metadata: 134 name: fair-worm-configmap 135 data: 136 myvalue: "Hello World" 137 drink: "tea" 138 food: "PIZZA" 139 ``` 140 141 In an actual chart, all static default values should live in the values.yaml, and should not be repeated using the `default` command (otherwise they would be redundant). However, the `default` command is perfect for computed values, which can not be declared inside values.yaml. For example: 142 143 ```yaml 144 drink: {{ .Values.favorite.drink | default (printf "%s-tea" (include "fullname" .)) }} 145 ``` 146 147 In some places, an `if` conditional guard may be better suited than `default`. We'll see those in the next section. 148 149 Template functions and pipelines are a powerful way to transform information and then insert it into your YAML. But sometimes it's necessary to add some template logic that is a little more sophisticated than just inserting a string. In the next section we will look at the control structures provided by the template language. 150 151 ## Operators are functions 152 153 Operators are implemented as functions that return a boolean value. To use `eq`, `ne`, `lt`, `gt`, `and`, `or`, `not` etcetera place the operator at the front of the statement followed by its parameters just as you would a function. To chain multiple operations together, separate individual functions by surrounding them with parentheses. 154 155 ```yaml 156 {{/* include the body of this if statement when the variable .Values.fooString exists and is set to "foo" */}} 157 {{ if and .Values.fooString (eq .Values.fooString "foo") }} 158 {{ ... }} 159 {{ end }} 160 161 162 {{/* include the body of this if statement when the variable .Values.anUnsetVariable is set or .values.aSetVariable is not set */}} 163 {{ if or .Values.anUnsetVariable (not .Values.aSetVariable) }} 164 {{ ... }} 165 {{ end }} 166 ``` 167 168 Now we can turn from functions and pipelines to flow control with conditions, loops, and scope modifiers.