【问题标题】:Helm optional nested variablesHelm 可选嵌套变量
【发布时间】:2020-05-04 19:52:27
【问题描述】:

如何在值文件中创建一个可选块,然后在模板中引用它?

例如,假设我有一个如下所示的值文件:

# values.yaml
foo:
   bar: "something"

然后我有一个如下所示的 helm 模板:

{{ .Values.foo.bar }}

如果我想将值文件中的 foo.bar 设为可选怎么办?如果值中不存在 foo 键,则会引发错误。

我尝试添加为 if 条件。但是,如果缺少 foo 键,这仍然会失败:

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

非常感谢任何想法。

【问题讨论】:

    标签: kubernetes kubernetes-helm go-templates


    【解决方案1】:

    大多数图表会将父对象默认为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" }}
    

    【讨论】:

    • 感谢您的回复。我之前尝试过 hasKey 方法,但没有设置默认的foo: {}。我再试一次。
    • 是否可以以更干净的方式清理/重写以下内容? {{ if hasKey .Values.global "rabbitmq" }} {{ .Values.global.rabbitmq.password | b64enc | quote }} {{ else }} {{ $def.RABBITMQ_PASSWORD | b64enc | quote }} {{ end }}
    • @Justin 我不确定这如何适用于嵌套键问题?您可以将其作为一个单独的问题
    【解决方案2】:

    简单的解决方法

    用括号()包裹每个可为空的级别

    {{ ((.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指针或接口值,任意长度为零的数组、切片、映射或字符串。

    因此,通过用括号包裹每个可为空的级别,当它们被链接时,前驱的 nil 指针优雅地不向后继的生成任何输出等等,从而实现嵌套的可为空字段的解决方法。 p>

    【讨论】:

    • 干杯;这似乎很好用。你在哪里找到的?我正在努力为它找到任何文档
    • 它对我不起作用,您使用哪个 helm 版本?
    • 可以确认它在我们的用例上工作,但很高兴知道它为什么工作?我也没有找到任何关于括号为什么/如何改变 nil 行为的文档。
    • @JameelA。感谢您的确认。不幸的是,Helm 中没有记录该用法。这是 go text/template 中隐式记录的语法。我添加了一些参考资料和简要说明。希望这会有所帮助。
    • @ZimbiX 谢谢!我最初是从 Github issue 中读到这个用法的,然后就记住了。找不到原来的线程了:(。我已经添加了一些参考。希望这会有所帮助。
    【解决方案3】:

    我成功使用的一种技术是使用一个变量来保存外部块的值,然后可以使用 default 和 Sprig 的 dict 帮助器等模板构造。

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

    如果文件中没有foo,这将提供一个备用字典,因此始终定义$foo,您可以在其中查找$foo.bar

    【讨论】:

      【解决方案4】:

      使用with

      查看with operator。这将当前范围限制在.Values.foo 的级别,如果缺少.foo,该块将被静默忽略:

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

      【讨论】:

      • 可以确认,如宣传的那样工作。我会接受这是真正的答案。
      【解决方案5】:

      在 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" "") 
      

      【讨论】:

      • 在我看来,dig 功能可能会在 1 月份登陆 helm(新的 sprig 已经发布,并且 helm 的 merge request 已经被接受;helm 的下一个功能版本是 @987654323 @)
      【解决方案6】:

      我四处寻找同一问题的答案,但找不到任何东西。看来你必须使用自定义函数,所以我写了一个。这是我想出的。它适用于我的用例,欢迎提供反馈/改进。

      _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 }}
      

      【讨论】:

        猜你喜欢
        • 2019-11-16
        • 2019-02-25
        • 2018-11-15
        • 1970-01-01
        • 2018-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多