kubernetes Helm可选嵌套变量

mfuanj7w  于 2023-03-07  发布在  Kubernetes
关注(0)|答案(6)|浏览(133)

如何在值文件中创建一个可选块,然后在模板中引用它?
例如,假设我有一个如下所示的值文件:

# values.yaml
foo:
   bar: "something"

然后我有一个 Helm 模板,看起来像这样:

{{ .Values.foo.bar }}

如果我想让foo.barvalues文件中的www.example.com成为可选的,那么如果foo键在values中不存在,就会引发一个错误。
我试过添加if条件,但是如果缺少foo键,仍然会失败:

{{ if .Values.foo.bar }}
{{ .Values.foo.bar }}
{{ end }}

任何想法都不胜感激。

r3i60tvu

r3i60tvu1#

简单的变通方案

用圆括号()每个可为空的级别括起来。

{{ ((.Values.foo).bar) }}

或者

{{ if ((.Values.foo).bar) }}
{{ .Values.foo.bar }}
{{ end }}

它是如何工作的?

Helm使用go text/template并从那里继承行为。
每一对括号()都可以看作是一个pipeline
来自文档(https://pkg.go.dev/text/template#hdr-Actions)
它是:
默认的文本表示形式(与fmt.print打印的相同)...
行为:
如果管道的值为空,则不生成输出...空值为false、0、任何nil指针或接口值以及长度为零的任何数组、切片、Map或字符串。
因此,通过用圆括号将每个可空级别 Package 起来,当它们被链接时,前趋nil指针优雅地不向后继nil指针生成输出,以此类推,实现嵌套可空字段的解决方案。

e4eetjau

e4eetjau2#

大多数图表将默认父对象为values.yaml中的空Map,因此它始终存在。

foo: {}

然后第一级检查{{ if .Values.foo.bar }}工作。
如果不可能,请按顺序测试每个键,并加上括号(添加自Torrey's better solution):

{{ if ((.Values.foo).bar) }}
{{ .Values.foo.bar }}
{{ end }}

在这种情况下,使用and函数不起作用,因为and会计算所有参数,即使第一个参数为falsey。
如果您需要检查是否存在错误值或空值,sprig中还包含hasKey函数:

{{ if hasKey .Values.foo "bar" }}
r1zk6ea1

r1zk6ea13#

我成功使用的一项技术是使用变量保存外部块的值,然后外部块可以使用模板构造,如default和Sprig的dict helper。

{{- $foo := .Values.foo | default dict -}}
Bar is {{ $foo.bar | default "not in the values file" }}

如果foo不在文件中,那么它提供了一个后备字典,因此$foo总是被定义的,您可以在其中查找$foo.bar

yvt65v4c

yvt65v4c4#

使用with

看一下with操作符,它将当前作用域限制在.Values.foo级别,如果.foo丢失,则该块将自动忽略:

{{- with .Values.foo }}
  {{- .bar }}
{{- end }}
mjqavswn

mjqavswn5#

在sprig中实现了一个新函数dig,它确实解决了这个问题,请参见此处http://masterminds.github.io/sprig/dicts.html
还没有被释放,所以更不可能很快掌舵。
同时,我修改了@Samuel solution来模拟新的dig函数。

{{- 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" "")
vc9ivgsu

vc9ivgsu6#

我四处寻找这个问题的答案,但没有找到任何答案。看起来你必须使用一个自定义函数,所以我写了一个。下面是我的想法。它适合我的用例,欢迎反馈/改进。
_助手. 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 }}

相关问题