侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 292 篇文章
  • 累计创建 132 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Helm3入门教程-19:Helm3 的流程控制及控制空格的特殊字符

孔子说JAVA
2022-04-29 / 0 评论 / 0 点赞 / 218 阅读 / 8,105 字 / 正在检测是否收录...

Helm3入门教程全系列,26小时轻松掌握Helm

控制结构(在模板语言中称为"actions")提供给你和模板作者控制模板迭代流的能力。 Helm的模板语言提供了以下控制结构:

  • if/else, 用来创建条件语句
  • with, 用来指定范围
  • range, 提供"for each"类型的循环

除了这些之外,还提供了一些声明和使用命名模板的关键字:

  • define 在模板中声明一个新的命名模板
  • template 导入一个命名模板
  • block 声明一种特殊的可填充的模板块

本教程,我们会讨论关于if,with,和 range。其他部门会在“命名模板”部分说明。

1、If/Else及控制空格

1.1 If/Else

第一个控制结构是在按照条件在一个模板中包含一个块文本。即if/else块。基本的条件结构看起来像这样:

{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

注意,我们讨论的条件 PIPELINE 是 管道 而不是值。这样做的原因是要清楚地说明控制结构可以执行整个管道,而不仅仅是计算一个值。

如果是以下值时,管道会被设置为 false:

  • 布尔false
  • 数字0
  • 空字符串
  • nil (空或null)
  • 空集合(map, slice, tuple, dict, array)

在所有其他条件下,条件都为true。

让我们先在配置映射 ConfigMap 中添加一个简单的条件。如果饮品被设置为咖啡,我们将添加另一个设置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{ if eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }}

注意 .Values.favorite.drink 必须已定义,否则在将它与 “coffee” 进行比较时会抛出错误。由于我们在最后一个例子中注释了drink: coffee,输出中就不会包含 mug: "true"标识。但如果将这行添加到values.yaml 文件中,输入就会是这样:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: eyewitness-elk-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
  mug: "true"

1.2 模板中控制空格的特殊字符

1.2.1 问题出现的方式

模板中包含了控制语句时,如果不进行特殊处理,有时候会出现多余空格/空行的情况,而YAML文件中的空格是非常严格的,如果出现多余的空格或空行,YAML文件就会报错。所以对于空格的管理非常重要,一不小心就会导致你的YAML文件格式错误。

看下面的例子:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{ if eq .Values.favorite.drink "coffee" }}
    mug: true
  {{ end }}

上面的代码看起来好像没什么错误。但是如果我们通过模板引擎运行它,我们会得到一个错误的结果:

$ helm install --dry-run --debug ./mychart
SERVER: "localhost:44134"
CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart
Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: did not find expected key

发生了什么?由于上面的空格,我们生成了不正确的 YAML。

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: eyewitness-elk-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
    mug: true

mug 不正确地缩进。让我们简单地缩进那行,然后重新运行:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{ if eq .Values.favorite.drink "coffee" }}
  mug: true
  {{ end }}

当我们发送该信息时,我们会得到有效的 YAML,但仍然看起来有点意思:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: telling-chimp-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"

  mug: true

请注意,我们在 YAML 中收到了一些空行(mug: true所在行的上一行)。为什么?当模板引擎运行时,它将删除 {{ 和 }} 中的空白内容,但是按原样保留剩余的空白。

1.2.2 处理空格的特殊字符 -

YAML 中的缩进空格是严格的,因此管理空格变得非常重要。幸运的是,Helm 模板有几个工具可以帮助我们。

首先,可以使用特殊字符修改模板声明的大括号语法,以告诉模板引擎填充空白。

  • {{- (添加了破折号和空格)表示去掉左边的空格。
  • -}} 意味着应该删除右空格。
  • 注意!换行符也是空格!
  • 确保 - 和其他指令之间有空格。{{- 3}} 意思是 “删除左空格并打印 3”,而 {{-3}} 意思是 “打印 -3”。

使用这个语法,我们可以修改我们的模板来摆脱这些新行:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}
  {{- if eq .Values.favorite.drink "coffee" }}
  mug: true
  {{- end }}

为了清楚说明这一点,让我们调整上面的内容,将空格替换为 *, 按照此规则将每个空格将被删除。一个在该行的末尾的 * 指示换行符将被移除。

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{ .Values.favorite.drink | default "tea" | quote }}
  food: {{ .Values.favorite.food | upper | quote }}*
**{{- if eq .Values.favorite.drink "coffee"}}
  mug: true*
**{{- end }}

牢记这一点,我们可以通过 Helm 运行我们的模板并查看结果:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: clunky-cat-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
  mug: true

要注意这个删除字符的更改,很容易出现意外地情况:

  food: {{ .Values.favorite.food | upper | quote }}
  {{- if eq .Values.favorite.drink "coffee" -}}
  mug: true
  {{- end -}}

这将会产生 food: "PIZZA"mug:true,因为把两边的新行都删除了。

有时候告诉模板系统如何缩进更容易,而不是试图掌握模板指令的间距。因此,有时可能会发现使用 indent 函数({{ indent 2 "mug:true" }})会很有用。

1.2.3 特殊字符 - 位置不同的差异

1) {{ }} 左右都不包含 - 的情况

如果 {{ }} 上下两边都有元素, 会空一行。效果如下:

template模板部分如下:

split: {{ "=============" }}
{{ if true }}
name: {{ "hello world" }}
{{ end }}
split: {{ "=============" }}

运行 template后:

root@kubernetes:/opt/helm/myapp# helm template . --show-only templates/name.yaml
---
# Source: myapp/templates/name.yaml
split: =============

name: hello world

split: =============

2) {{ }} 左边包含 - 的情况

如果{{ }}上下两边都有元素, 直接输出不会有空行。效果如下:

template模板部分如下:

split: {{ "=============" }}
{{- if true }}
name: {{ "hello world" }}
{{- end }}
split: {{ "=============" }}

运行 template后:

root@kubernetes:/opt/helm/myapp# helm template . --show-only templates/name.yaml
---
# Source: myapp/templates/name.yaml
split: =============
name: hello world
split: =============

3) {{ }} 左右两边都包含 - 的情况

如果{{ }}上下两边都有元素, 会输出到上面一行后面。效果如下:

  • 注: 这种情况会有 mapping values are not allowed in this context 格式的错误, 特别注意 左右都包含 - 的情况.

template模板部分如下:

split: {{ "=============" }}
{{- if true -}}
name
{{- end -}}

运行 template后:

root@kubernetes:/opt/helm/myapp# helm template . --show-only templates/name.yaml
---
# Source: myapp/templates/name.yaml
split: =============name

1.3 特殊字符||-|+> 的区别

1) | 表示每一列转换到 json 后 无论多少个空行有且仅有一个 \n 符。

A: |
  aa
  bb
  cc

转换成 Json后:

{
  "A": "aa\nbb\ncc\n"
}

2) |- 表示每一列转换到 json 后,除最后一行外,每个空行都有一个 \n 符。

A: |-
  aa

  bb
  cc
  
  

转换成 Json后:

{
  "A": "aa\n\nbb\ncc"
}

3) |+ 表示每一列转换到 json 后,每一个空行都有一个 \n 符。

A: |+
  aa
  bb

  cc
  

转换成 Json后:

{
  "A": "aa\nbb\n\ncc\n\n"
}

4) > 表示每一列转换到 json 后,没有 \n 符。

A: >
  aa
  bb
  cc

转换成 Json后:

{
  "A": "aa bb cc"
}

2、使用 with 修改范围

控制结构是 with 控制着变量作用域。回想一下,. 是对当前范围的引用。因此,.Values 告诉模板在当前范围中查找 Values 对象。with语法类似于一个简单的 if 语句:

{{ with PIPELINE }}
  # restricted scope
{{ end }}

范围可以改变。with 可以允许将当前范围(.)设置为特定的对象。例如,我们一直在使用的 .Values.favorites。让我们重写我们的 ConfigMap 来改变 . 范围来指向 .Values.favorites

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}

注意,现在我们可以引用 .drink.food 无需对其进行限定。这是因为该 with 声明设置 . 为指向 .Values.favorite。在 {{ end }} 后 . 复位其先前的范围。

请注意!在受限范围内,此时将无法从父范围访问其他对象。 例如,下面会报错:

  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  release: {{ .Release.Name }}
  {{- end }}

它会产生一个错误,因为 Release.Name 不在 . 限制范围内。但是,如果我们交换最后两行,所有将按预期工作,因为范围在 {{ end }} 之后被重置。

  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}
  release: {{ .Release.Name }}

看下 range,我们看看模板变量,它提供了一个解决上述范围问题的方法。

3、循环 range 动作

许多编程语言都支持使用 for 循环foreach 循环或类似的功能机制进行循环。在 Helm 的模板语言中,遍历集合的方式是使用 range 操作。

首先,让我们在我们的 values.yaml 文件中添加一份披萨配料列表:

favorite:
  drink: coffee
  food: pizza
pizzaToppings:
  - mushrooms
  - cheese
  - peppers
  - onions

现在我们有一个列表(模板中称为 slice)pizzaToppings。我们可以修改我们的模板,将这个列表打印到我们的 ConfigMap 中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  {{- end }}
  toppings: |-
    {{- range .Values.pizzaToppings }}
    - {{ . | title | quote }}
    {{- end }}

让我们仔细看看 toppings:list。该 range 函数将遍历 pizzaToppings 列表。但现在发生了一些有趣的事. 就像 withsets 的范围 .,range 操作子也是一样。每次通过循环时,. 都设置为当前比萨饼顶部。也就是第一次 . 设定 mushrooms。第二个迭代它设置为 cheese,依此类推。

我们可以直接向管道发送 . 的值,所以当我们这样做时 {{ . | title | quote }},它会发送 . 到 title(标题 case 函数),然后发送到 quote。如果我们运行这个模板,输出将是:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: edgy-dragonfly-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
  toppings: |-
    - "Mushrooms"
    - "Cheese"
    - "Peppers"
    - "Onions"

现在,在这个例子中,我们碰到了一些棘手的事情。该 toppings: |- 行声明了一个多行字符串。所以我们的 toppings list 实际上不是 YAML 清单。这是一个很大的字符串。我们为什么要这样做?因为 ConfigMaps 中的数据 data 由键 / 值对组成,其中键和值都是简单的字符串。要理解这种情况,请查看 Kubernetes ConfigMap 文档.。但对我们来说,这个细节并不重要。

YAML 中的 |- 标记表示一个多行字符串。这可以是一种有用的技术,用于在清单中嵌入大块数据,如此处所示。

有时能快速在模板中创建一个列表,然后遍历该列表是很有用的。Helm 模板有一个功能可以使这个变得简单:tuple。在计算机科学中,元组是类固定大小的列表类集合,但是具有任意数据类型。这粗略地表达了 tuple 的使用方式。

  sizes: |-
    {{- range tuple "small" "medium" "large" }}
    - {{ . }}
    {{- end }}
  sizes: |-
    - small
    - medium
    - large

除了list和tuple之外,range还可以用于遍历具有键和值的集合(如map 或 dict)。

0

评论区