Helm 模板:子键索引

问题描述 投票:0回答:1

我想实现以下场景。

全局变量

global:
  env:
    name: prod

图表特定变量

env:
  name: dev

我想要优先于图表特定>全局变量

例如:在我的图表中,我想使用类似的东西

      containers:
          - name: "{{- include "tester.getValueWithPrecedence" (list . "env.name") -}}"

这是 _helpers.tpl 函数

{{- define "tester.getValueWithPrecedence" -}}
{{- $top := index . 0 }}
{{- $var := index . 1 }}
{{- if hasKey $top.Values $var -}}
{{- index $top.Values $var -}}
{{- else if hasKey $top.Values.global $var -}}
{{- index $top.Values.global $var -}}
{{- end -}}
{{- end -}}

我认为问题是

env.name
键不被解释为子键,而是一个字符串。

有什么办法可以实现这个目标吗?

非常感谢任何帮助。

kubernetes kubernetes-helm sprig-template-functions
1个回答
0
投票

按照您描述的方式很难做到这一点。

正如您所注意到的,核心问题是

hasKey

index
 都希望它们的参数作为映射中的单个键而不是点分隔的字符串。 
index
 可以接受多个参数 - 
index .Values "env" "name"
 - 但不能接受单个列表类型的参数,并且没有一个好方法将列表扩展为多个参数。 (否则 
dig
 模板函数可能是答案的一部分。)


您仍然可以编写一个模板函数来执行此操作,但会有点复杂。您可以编写一个递归模板,逐步遍历路径组件列表,并使用首选字典和后备调用它。

{{- include "f" (list .Values .Values.global (list "env" "name")) }} {{- include "f" (list .Values.env .Values.global.env (list "name")) }}
有帮助的实现技巧是 

pluck

 将采用单个路径步骤和多个字典(同样,作为位置参数而不是列表),并将该步骤返回到包含它的所有字典中。这意味着pluck
的返回值有三种情况:

    它什么也没返回,我们在两个字典中都错过了;
  1. 它只返回一本字典;或
  2. 它从两个字典中返回一个子键。
一旦我们弄清楚我们处于哪种情况,类似地,我们要么处于列表的末尾,要么不处于列表的末尾,我们就可以相应地递归或返回值。

所以我可能会写(未经测试):

{{- define "f" -}} {{- $first := index . 0 }} {{- $second := index . 1 }} {{- $path := index . 2 }} {{- $result := pluck (first $path) $first $second }} {{- if eq 0 (len $result) }} {{- "" }} {{- else if eq 1 (len $path) }} {{- first $result }} {{- else if eq 1 (len $result) }} {{- include "f" (list (first $result) dict (rest $path) }} {{- else }} {{- include "f" (list (index $result 0) (index $result 1) (rest $path) }} {{- end }} {{- end }}
这里要注意的另一件重要事情是,无论 

.Values

 中的内容是什么,
define
d 函数只会生成一个字符串作为其结果。在此示例中,我为“未找到”情况返回一个空字符串。


根据您使用此功能的频率,可能不值得花精力编写这个非常通用的函数。

env: - name: ENVIRONMENT value: {{ dig "env" "name" (dig "global" "env" "name" .Values) .Values }}
根据您的使用案例,它还可以帮助您了解每个部署的 

helm install -f

 值会覆盖图表的 
values.yaml
 文件。所以你不需要在 
values.yaml
 中写入默认值,而是检查用户是否在不同的路径上提供了覆盖;您可以使用相同的 
.Values.env.name
 并且用户覆盖将优先。 
global
 名称暗示了父子图表关系,并且父图表值将优先于子图表 
values.yaml
 中的默认值。不过,还有其他合理的设置,您确实需要您所询问的更通用的方法。

© www.soinside.com 2019 - 2024. All rights reserved.