## 1. 模板函數
比如我們需要從`.Values`中讀取的值變成字符串的時候就可以通過調用`quote`模板函數來實現:(`templates/configmap.yaml`)
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
k8s: {{ quote .Values.course.k8s }}
python: {{ .Values.course.python }}
```
模板函數遵循調用的語法為:`functionName arg1 arg2...`。在上面的模板文件中,`quote .Values.course.k8s`調用quote函數并將后面的值作為一個參數傳遞給它。最終被渲染為:
```bash
$ helm install --dry-run --debug .
[debug] Created tunnel using local port: '39405'
......
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: masked-saola-configmap
data:
myvalue: "Hello World"
k8s: "devops"
python: django
```
我們可以看到`.Values.course.k8s`被渲染成了字符串`devops`。上節課我們也提到過 Helm 是一種 [Go 模板語言](https://pkg.go.dev/text/template),擁有超過60多種可用的內置函數,一部分是由Go 模板語言本身定義的,其他大部分都是Sprig模板庫提供的一部分,我們可以前往這兩個文檔中查看這些函數的用法。
比如我們這里使用的**quote函數**就是Sprig 模板庫提供的一種字符串函數,用途就是用雙引號將字符串括起來,如果需要雙引號",則需要添加\來進行轉義,而squote函數的用途則是用雙引號將字符串括起來,而不會對內容進行轉義。
所以在我們遇到一些需求的時候,首先要想到的是去查看下上面的兩個模板文檔中是否提供了對應的模板函數,這些模板函數可以很好的解決我們的需求。
## 2. 輔助模板
有時您想在圖表中創建一些可重復使用的部分,無論它們是塊還是模板部分。通常,將它們保存在自己的文件中會更干凈。
在該`templates/`目錄中,任何以下劃線 ( _) 開頭的文件都不會輸出 `Kubernetes` 清單文件。所以按照慣例,輔助模板和部分被放置在一個`_helpers.tpl`文件中。
## 2. 管道
模板語言除了提供了豐富的內置函數之外,其另一個強大的功能就是管道的概念。和UNIX中一樣,管道我們通常稱為Pipeline,是一個鏈在一起的一系列模板命令的工具,以緊湊地表達一系列轉換。簡單來說,管道是可以按順序完成一系列事情的一種方法。比如我們用管道來重寫上面的 ConfigMap 模板:(`templates/configmap.yaml`)
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
k8s: {{ .Values.course.k8s | quote }}
python: {{ .Values.course.python }}
```
這里我們直接調用quote函數,而是調換了一個順序,使用一個管道符|將前面的參數發送給后面的模板函數:`{{ .Values.course.k8s | quote }}`,使用管道我們可以將幾個功能順序的連接在一起,比如我們希望上面的 ConfigMap 模板中的 k8s 的 value 值被渲染后是大寫的字符串,則我們就可以使用管道來修改:`(templates/configmap.yaml)`
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
k8s: {{ .Values.course.k8s | upper | quote }}
python: {{ .Values.course.python }}
```
這里我們在管道中增加了一個`upper`函數,該函數同樣是Sprig 模板庫提供的,表示將字符串每一個字母都變成大寫。然后我們用`debug`模式來查看下上面的模板最終會被渲染成什么樣子:
```bash
$ helm install --dry-run --debug .
[debug] Created tunnel using local port: '46651'
......
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: maudlin-labradoodle-configmap
data:
myvalue: "Hello World"
k8s: "DEVOPS"
python: django
```
我們可以看到之前我們的devops已經被渲染成了`"DEVOPS"`了,要注意的是使用管道操作的時候,前面的操作結果會作為參數傳遞給后面的模板函數,比如我們這里希望將上面模板中的 python 的值渲染為重復出現3次的字符串,則我們就可以使用到Sprig 模板庫提供的`repeat`函數,不過該函數需要傳入一個參數`repeat COUNT STRING`表示重復的次數:(`templates/configmap.yaml`)
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
k8s: {{ .Values.course.k8s | upper | quote }}
python: {{ .Values.course.python | quote | repeat 3 }}
```
該repeat函數會將給定的字符串重復3次返回,所以我們將得到這個輸出:
```bash
helm install --dry-run --debug .
[debug] Created tunnel using local port: '39712'
......
Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 7: did not find expected key
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: piquant-butterfly-configmap
data:
myvalue: "Hello World"
k8s: "DEVOPS"
python: "django""django""django"
```
我們可以看到上面的輸出中 python 對應的值變成了3個相同的字符串,這顯然是不符合我們預期的,我們的預期是形成一個字符串,而現在是3個字符串了,而且上面還有錯誤信息,根據管道處理的順序,我們將`quote`函數放到`repeat`函數后面去是不是就可以解決這個問題了:(`templates/configmap.yaml`)
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
k8s: {{ .Values.course.k8s | upper | quote }}
python: {{ .Values.course.python | repeat 3 | quote }}
```
現在是不是就是先重復3次`.Values.course.python`的值,然后調用`quote`函數:
```bash
helm install --dry-run --debug .
[debug] Created tunnel using local port: '33837'
......
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: braided-manatee-configmap
data:
myvalue: "Hello World"
k8s: "DEVOPS"
python: "djangodjangodjango"
```
現在是不是就正常了,也得到了我們的預期結果,所以我們在使用管道操作的時候一定要注意是按照從前到后一步一步順序處理的。
## 3. default 函數
另外一個我們會經常使用的一個函數是`default` 函數:`default DEFAULT_VALUE GIVEN_VALUE`。該函數允許我們在模板內部指定默認值,以防止該值被忽略掉了。比如我們來修改上面的 ConfigMap 的模板:(`templates/configmap.yaml`)
```bash
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: {{ .Values.hello | default "Hello World" | quote }}
k8s: {{ .Values.course.k8s | upper | quote }}
python: {{ .Values.course.python | repeat 5 | quote }}
```
由于我們的`values.yaml`文件中只定義了 course 結構的信息,并沒有定義 hello 的值,所以如果沒有設置默認值的話是得不到`{{ .Values.hello }}`的值的,這里我們為該值定義了一個默認值:`Hello World`,所以現在如果在`values.yaml`文件中沒有定義這個值,則我們也可以得到默認值:
```bash
$ helm install --dry-run --debug .
[debug] Created tunnel using local port: '42670'
......
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: orbiting-hog-configmap
data:
myvalue: "Hello World"
k8s: "DEVOPS"
python: "djangodjangodjangodjangodjango"
```
我們可以看到`myvalue`值被渲染成了`Hello World`,證明我們的默認值生效了。
## 4. lookup 函數
該lookup函數可用于查找正在運行的集群中的資源。查找函數的概要是`lookup apiVersion, kind, namespace, name -> resource or resource list`。
| parameter | apiVersion | kind | namespace | name |
|-----------|------------|--------|-----------|--------|
| type | string | string | string | string |
`name`和都是`namespace`可選的,可以作為空字符串 ( `""`) 傳遞。
以下參數組合是可能的:
| 行為 | 查找功能 |
|--------------------------------------|------------------------------------------|
| Kubectl Get Pod Mypod -N Mynamespace | Lookup “v1” “Pod” “mynamespace” “mypod” |
| Kubectl Get Pods -N Mynamespace | Lookup “v1” “Pod” “mynamespace” “” |
| Kubectl Get Pods —all-Namespaces | Lookup “v1” “Pod” “” “” |
| Kubectl Get Namespace Mynamespace | Lookup “v1” “Namespace” “” “mynamespace” |
| Kubectl Get Namespaces | Lookup “v1” “Namespace” “” “” |
當`lookup`返回一個對象時,它會返回一個字典。可以進一步導航此字典以提取特定值。
以下示例將返回`mynamespace`對象的注釋:
```bash
(lookup "v1" "Namespace" "" "mynamespace").metadata.annotations
```
返回對象列表時`lookup`,可以通過以下`items`字段訪問對象列表:
```bash
{{ range $index, $service := (lookup "v1" "Service" "mynamespace" "").items }}
{{/* do something with each service */}}
{{ end }}
```
當沒有找到對象時,返回一個空值。這可用于檢查對象是否存在。
該`lookup`函數使用 `Helm` 現有的 `Kubernetes` 連接配置來查詢 Kubernetes。如果與調用 API 服務器交互時返回任何錯誤(例如由于缺少訪問資源的權限),則 `helm` 的模板處理將失敗。
請記住,Helm 不應該在 `a helm template`或 a期間聯系 `Kubernetes API` 服務器`helm install|update|delete|rollback --dry-run`,因此lookup在這種情況下,該函數將返回一個空列表(即 dict)。
## 5. 運算符
對于模板,運算符(eq、ne、lt、gt、and等or)都實現為函數。在管道中,操作可以用括號((和))分組。
現在我們可以從函數和管道轉向[帶有條件、循環和范圍修飾符的流控制](https://ghostwritten.blog.csdn.net/article/details/120305974)。