【问题标题】:helm filter over range舵过滤器超出范围
【发布时间】:2021-04-27 12:00:22
【问题描述】:

是否可以在 helm 中过滤范围的结果? 例如,值文件包含一个地图列表,如:

clients:
  - name: clientA
    id: id001
    user: usernameA
    pass: passwordA
  - name: clientB
    id: id002
    user: usernameB
    pass: passwordB
  - name: clientA
    id: id003
    user: usernameA
    pass: passwordA

在我的模板中,我只需要提取用户的唯一值并通过。 我有这样的事情:

{{- range .Values.clients }}
- name: {{ .name | printf "user_%s" }}
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: {{ .user | quote }}
- name: {{ .name | printf "pass_%s" }}
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: {{ .pass | quote }}
{{- end }}  

最终结果应该是这样的:

- name: user_clientA
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: usernameA
- name: pass_clientA
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: passwordA
- name: user_clientB
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: usernameB
- name: pass_clientB
  valueFrom:
    secretKeyRef:
      name: somesecret
      key: passwordB

我试过 {{- range .Values.clients |选择“用户”“通过”| uniq }} 但似乎不起作用。我不知道怎么写,所以我可以只过滤“user”和“pass”键并丢弃重复项。

【问题讨论】:

    标签: go range kubernetes-helm uniq


    【解决方案1】:

    即使有了扩展,Helm 也不支持像您建议的那样对列表进行深度过滤。说“将此列表过滤到此地图项的唯一值”或“给定一个项目,它是否是列表中具有某些属性的第一个项目”并不是一个好方法。在更实用的语言中,我可以想象在这里使用 mapfilter 之类的结构,而 Helm 没有这些结构。

    实际上,我最有可能做的事情是声明这是一个无效配置。只执行您展示的模板会很懒惰,但并非不合理。 (如果这是在 pod 规范的 env: 块中,我相信这会产生一个有效的对象,并且每个环境变量的最后一个设置都会生效。)

    可以在 Helm 模板中进行检查;但它有很多代码,用一种不熟悉的语言编写,很难测试。还要考虑像 operator 这样的东西是否对你来说是一个更好的实现选择,因为它可以用更标准的语言编写。


    如果您认为列表的长度会相当短,您可以编写一个递归模板来处理它。它将接收剩余项目的列表和它已经看到的名称列表。如果项目列表为空,则停止;如果当前项目已被看到,则用列表的其余部分和相同的已看到列表调用我们自己;否则发出该项目,将其添加到“已看到”列表中,然后调用我们自己。在 Python 伪代码中,这可能如下所示:

    def helper(remaining, seen):
      if len(remaining) == 0:
        # do nothing if the list is empty
        return
      else:
        first = remaining[0]
        name = first['name']
        rest = remaining[1:]
        if name in seen:
          # we have already seen this item; skip it and go to the next one
          return helper(rest, seen)
        else:
          # this is a new item; emit it and remember its name
          emit(first)
          new_seen = seen + [name]
          return helper(rest, new_seen)
    
    def process(the_list):
      helper(the_list, [])
    

    您可以将该逻辑转换为 Helm 模板,并附加将多个参数打包到一个列表中的技巧,因为 Go text/template 模板只接受一个参数。 (如果您需要 .Values.Release.Files等的顶级 Helm 对​​象。您也需要明确地传递它。)

    {{- define "helper" -}}
      {{- $remaining = index . 0 -}}
      {{- $seen := index . 1 -}}
      {{- if empty $remaining -}}
        {{-/* do nothing */-}}
      {{- else -}}
        {{- $first := first $remaining -}}
        {{- $name := $first.name -}}
        {{- $rest := rest $remaining -}}
        {{- if has $name $seen -}}
          {{-/* recurse without emitting anything */-}}
          {{- template "helper" (list $rest $seen) -}}
        {{- else -}}
          {{-/* emit the item */-}}
    - name: user_{{ $first.name  }}
      valueFrom:
        secretKeyRef:
          name: somesecret
          key: {{ quote $first.user }}
    - name: pass_{{ $first.name }}
      valueFrom:
        secretKeyRef:
          name: somesecret
          key: {{ quote $first.pass }}
    {{/* ...then move on to the next item */-}}
          {{- $new_seen := append $seen $first.name -}}
          {{- template "helper" (list $first $new_seen) -}}
        {{- end -}}
      {{- end -}}
    {{- end -}}
    
    env:
    {{ include "helper" (list .Values.clients list) | indent 2 }}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-07
      • 2013-02-12
      • 2013-04-19
      • 1970-01-01
      • 2023-03-27
      • 2017-02-12
      相关资源
      最近更新 更多