Helm 可选的嵌套变量
Helm optional nested variables
如何在值文件中创建一个可选块,然后在模板中引用它?
例如,假设我有一个如下所示的值文件:
# values.yaml
foo:
bar: "something"
然后我有一个如下所示的 helm 模板:
{{ .Values.foo.bar }}
如果我想让值文件中的 foo.bar 成为可选的怎么办?如果值中不存在 foo
键,则会引发错误。
我试过添加为 if 条件。但是,如果缺少 foo
键,这仍然会失败:
{{ if .Values.foo.bar }}
{{ .Values.foo.bar }}
{{ end }}
非常感谢任何想法。
大多数图表会将父对象默认为 values.yaml
中的空地图,因此它始终存在。
foo: {}
然后 {{ if .Values.foo.bar }}
有效。
如果不可能,请测试两个键:
{{ if .Values.foo }}
{{ if .Values.foo.bar }}
{{ .Values.foo.bar }}
{{ end }}
{{ end }}
使用 and
函数在这种情况下不起作用,因为 and
评估所有参数,即使第一个参数是假的。
如果您需要检查是否存在虚假值或空值,sprig 中还包含 hasKey
函数:
{{ if hasKey .Values.foo "bar" }}
我成功使用的一项技术是使用变量来保存外部块的值,然后它可以使用模板构造,如 default
和 Sprig 的 dict 助手。
{{- $foo := .Values.foo | default dict -}}
Bar is {{ $foo.bar | default "not in the values file" }}
如果 foo
不在文件中,这会提供备用字典,因此 $foo
始终已定义,您可以在其中查找 $foo.bar
。
我四处寻找同一个问题的答案,但找不到任何答案。看来你必须使用自定义函数,所以我写了一个。这是我想出的。它适用于我的用例,欢迎 feedback/improvements。
_helpers.tpl
{{- define "hasDeepKey" -}}
{{- $mapToCheck := index . "mapToCheck" -}}
{{- $keyToFind := index . "keyToFind" -}}
{{- $keySet := (splitList "." $keyToFind) -}}
{{- $firstKey := first $keySet -}}
{{- if index $mapToCheck $firstKey -}}{{*/ The key was found */}}
{{- if eq 1 (len $keySet) -}}{{*/ The final key in the set implies we're done */}}
true
{{- else }}{{*/ More keys to check, recurse */}}
{{- include "hasDeepKey" (dict "mapToCheck" (index $mapToCheck $firstKey) "keyToFind" (join "." (rest $keySet))) }}
{{- end }}
{{- else }}{{/* The key was not found */}}
false
{{- end }}
{{- end }}
values.yaml:
{{- if eq "true" (include "hasDeepKey" (dict "mapToCheck" .Values "keyToFind" "foo.bar")) }}
bar: {{- .Values.foo.bar }}
{{- end }}
使用with
看看with
operator。这将当前范围限制在 .Values.foo
级别,如果 .foo
缺失,该块将被忽略:
{{- with .Values.foo }}
{{- .bar }}
{{- end }}
在 sprig 中实现了一个名为 dig
的新功能,它确实解决了这个问题,请参阅此处 http://masterminds.github.io/sprig/dicts.html。
尚未发布,因此更不可能很快掌舵。
与此同时,我修改了@Samuel 解决方案以模仿新的挖掘功能。
{{- define "dig" -}}
{{- $mapToCheck := index . "map" -}}
{{- $keyToFind := index . "key" -}}
{{- $default := index . "default" -}}
{{- $keySet := (splitList "." $keyToFind) -}}
{{- $firstKey := first $keySet -}}
{{- if index $mapToCheck $firstKey -}} {{/* The key was found */}}
{{- if eq 1 (len $keySet) -}}{{/* The final key in the set implies we're done */}}
{{- index $mapToCheck $firstKey -}}
{{- else }}{{/* More keys to check, recurse */}}
{{- include "dig" (dict "map" (index $mapToCheck $firstKey) "key" (join "." (rest $keySet)) "default" $default) }}
{{- end }}
{{- else }}{{/* The key was not found */}}
{{- $default -}}
{{- end }}
{{- end }}
你可以这样称呼它
$regKey := include "dig" (dict "map" .Values "key" "global.registryKey" "default" "")
简单的解决方法
用圆括号 ()
.
包裹 每个可为 null 的级别
{{ ((.Values.foo).bar) }}
或
{{ if ((.Values.foo).bar) }}
{{ .Values.foo.bar }}
{{ end }}
它是如何工作的?
Helm 使用 go text/template
并从那里继承行为。
每一对括号()
都可以认为是一个pipeline
.
来自文档 (https://pkg.go.dev/text/template#hdr-Actions)
是:
The default textual representation (the same as would be printed by fmt.Print)...
行为:
If the value of the pipeline is empty, no output is generated... The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.
因此,通过用括号包裹每个可为空的级别,当它们被链接时,前导nil指针优雅地不产生输出给后继者等等,实现嵌套的可为空字段解决方法。
如何在值文件中创建一个可选块,然后在模板中引用它?
例如,假设我有一个如下所示的值文件:
# values.yaml
foo:
bar: "something"
然后我有一个如下所示的 helm 模板:
{{ .Values.foo.bar }}
如果我想让值文件中的 foo.bar 成为可选的怎么办?如果值中不存在 foo
键,则会引发错误。
我试过添加为 if 条件。但是,如果缺少 foo
键,这仍然会失败:
{{ if .Values.foo.bar }}
{{ .Values.foo.bar }}
{{ end }}
非常感谢任何想法。
大多数图表会将父对象默认为 values.yaml
中的空地图,因此它始终存在。
foo: {}
然后 {{ if .Values.foo.bar }}
有效。
如果不可能,请测试两个键:
{{ if .Values.foo }}
{{ if .Values.foo.bar }}
{{ .Values.foo.bar }}
{{ end }}
{{ end }}
使用 and
函数在这种情况下不起作用,因为 and
评估所有参数,即使第一个参数是假的。
如果您需要检查是否存在虚假值或空值,sprig 中还包含 hasKey
函数:
{{ if hasKey .Values.foo "bar" }}
我成功使用的一项技术是使用变量来保存外部块的值,然后它可以使用模板构造,如 default
和 Sprig 的 dict 助手。
{{- $foo := .Values.foo | default dict -}}
Bar is {{ $foo.bar | default "not in the values file" }}
如果 foo
不在文件中,这会提供备用字典,因此 $foo
始终已定义,您可以在其中查找 $foo.bar
。
我四处寻找同一个问题的答案,但找不到任何答案。看来你必须使用自定义函数,所以我写了一个。这是我想出的。它适用于我的用例,欢迎 feedback/improvements。
_helpers.tpl
{{- define "hasDeepKey" -}}
{{- $mapToCheck := index . "mapToCheck" -}}
{{- $keyToFind := index . "keyToFind" -}}
{{- $keySet := (splitList "." $keyToFind) -}}
{{- $firstKey := first $keySet -}}
{{- if index $mapToCheck $firstKey -}}{{*/ The key was found */}}
{{- if eq 1 (len $keySet) -}}{{*/ The final key in the set implies we're done */}}
true
{{- else }}{{*/ More keys to check, recurse */}}
{{- include "hasDeepKey" (dict "mapToCheck" (index $mapToCheck $firstKey) "keyToFind" (join "." (rest $keySet))) }}
{{- end }}
{{- else }}{{/* The key was not found */}}
false
{{- end }}
{{- end }}
values.yaml:
{{- if eq "true" (include "hasDeepKey" (dict "mapToCheck" .Values "keyToFind" "foo.bar")) }}
bar: {{- .Values.foo.bar }}
{{- end }}
使用with
看看with
operator。这将当前范围限制在 .Values.foo
级别,如果 .foo
缺失,该块将被忽略:
{{- with .Values.foo }}
{{- .bar }}
{{- end }}
在 sprig 中实现了一个名为 dig
的新功能,它确实解决了这个问题,请参阅此处 http://masterminds.github.io/sprig/dicts.html。
尚未发布,因此更不可能很快掌舵。
与此同时,我修改了@Samuel 解决方案以模仿新的挖掘功能。
{{- define "dig" -}}
{{- $mapToCheck := index . "map" -}}
{{- $keyToFind := index . "key" -}}
{{- $default := index . "default" -}}
{{- $keySet := (splitList "." $keyToFind) -}}
{{- $firstKey := first $keySet -}}
{{- if index $mapToCheck $firstKey -}} {{/* The key was found */}}
{{- if eq 1 (len $keySet) -}}{{/* The final key in the set implies we're done */}}
{{- index $mapToCheck $firstKey -}}
{{- else }}{{/* More keys to check, recurse */}}
{{- include "dig" (dict "map" (index $mapToCheck $firstKey) "key" (join "." (rest $keySet)) "default" $default) }}
{{- end }}
{{- else }}{{/* The key was not found */}}
{{- $default -}}
{{- end }}
{{- end }}
你可以这样称呼它
$regKey := include "dig" (dict "map" .Values "key" "global.registryKey" "default" "")
简单的解决方法
用圆括号 ()
.
{{ ((.Values.foo).bar) }}
或
{{ if ((.Values.foo).bar) }}
{{ .Values.foo.bar }}
{{ end }}
它是如何工作的?
Helm 使用 go text/template
并从那里继承行为。
每一对括号()
都可以认为是一个pipeline
.
来自文档 (https://pkg.go.dev/text/template#hdr-Actions)
是:
The default textual representation (the same as would be printed by fmt.Print)...
行为:
If the value of the pipeline is empty, no output is generated... The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.
因此,通过用括号包裹每个可为空的级别,当它们被链接时,前导nil指针优雅地不产生输出给后继者等等,实现嵌套的可为空字段解决方法。