如何使用 Go Templates (Helm) 应用递归格式?

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

我正在使用 helm 并给定一个 yaml 对象,我想在应用一些递归格式时将其展平。

鉴于此:

some_map:
  with: different
  indentation:
    levels: and
  nested:
    sub: 
      maps: "42"
    and_more:
      maps: 42

我想(例如)得到这个:

some_map.with="different"
some_map.indentation.levels="and"
some_map.nested.sub.maps="42"
some_map.nested.and_more.maps=42

我没有在 helm 文档中阅读过任何有关递归循环的内容,请记住示例中的递归格式( "%v.%v" if !root else "%v=%v" )可能会有所不同。

go kubernetes kubernetes-helm go-templates
3个回答
4
投票

是的,似乎

{{ define
支持递归使用
{{ include
,尽管不知道深度如何

我制作的 PoC 看看它是否可行

{{- define "bob" -}}
{{- $it := . -}}
{{- $knd := kindOf . -}}
{{- if eq $knd "map" }}
{{- range (keys .) }}
{{- $k := . }}
{{- $v := get $it . }}
{{- $vk := kindOf $v }}
{{- if eq $vk "map" }}
{{-   printf "%s." $k }}
{{-   include "bob" $v }}
{{- else }}
{{-   printf "%s=%s\n" $k (toJson $v) }}
{{- end }}
{{- end }}
{{- else }}
{{ toJson . }}#k({{ $knd }})
{{- end }}
{{- end -}}

调用为

{{ $fred := dict 
    "alpha" (dict "a0" "a0ch0")
    "beta" (dict "beta0" (dict "beta00" 1234))
    "charlie" (list "ch0" "ch1" "ch2") }}
data:
  theData: |
{{ toJson $fred | indent 4 }}
  toml: |
{{ include "bob" $fred | indent 4 }}

已制作

data:
  theData: |
    {"alpha":{"a0":"a0ch0"},"beta":{"beta0":{"beta00":1234}},"charlie":["ch0","ch1","ch2"]}
  toml: |
    alpha.a0="a0ch0"
    beta.beta0.beta00=1234
    charlie=["ch0","ch1","ch2"]

此外,您引用的示例似乎引用了最外层的变量名称,我认为 helm 不知道这一点,因此您需要一个人工包装器

dict
才能获得该行为:
{{ include "toToml" (dict "some_map" .Values.some_map) }}


1
投票

另一种方法

_helpers.tpl:

{{- define "template.flattenFn" -}}
  {{- $ctx := . -}}
  {{- if or (eq (kindOf .data) "map") (eq (kindOf .data) "slice") }}
    {{- range $key, $value := .data }}
      {{- include "template.flattenFn" (dict "prefixes" (append $ctx.prefixes $key) "data" $value ) }}
    {{- end }}
  {{- else if .prefixes }}
    {{- printf "\"%s\":%s,"  (join "__" .prefixes) ( mustToJson ( .data | toString )) }}
  {{- end }}
{{- end -}}

{{- define "template.flatten" -}}
{{- $result := include "template.flattenFn" (dict "prefixes" list "data" . ) -}}
{ {{- trimSuffix "," $result -}} }
{{- end -}}

values.yaml

  environment_map:
    Log:
      Level:
        Default: Debug
      Target:
      - Name: Console
        Args:
          formatter: "JsonFormatter"

用法

{{- range $env, $value := include "template.flatten" .Values.environment_map | fromYaml }}
  - name: {{ $env }}
    value: {{ $value | quote }}
{{- end }}

结果

    - name: Log__Level__Default
      value: "Debug"
    - name: Log__Target__0__Args__formatter
      value: "JsonFormatter"
    - name: Log__Target__0__Name
      value: "Console"

enter image description here


0
投票

感谢@mdaniel 的回答,这帮助/允许我解决我的问题!如果您有具有相同前缀的移动值,他的(很快,我明白了)解决方案就会出现问题。继续他的例子:

{{ $fred := dict
    "alpha" (dict "a0" "a0ch0")
    "beta" (dict "beta0" (dict "beta00" 1234))
    "charlie" (list "ch0" "ch1" "ch2")
    "problem" (dict "beta0" (dict "1" "1" "2" "2" )) }}
data:
  theData: |
{{ toJson $fred | indent 4 }}
  toml: |
{{ include "bob" $fred | indent 4 }}

将产生:

data:
  theData: |
    {"alpha":{"a0":"a0ch0"},"beta":{"beta0":{"beta00":1234}},"charlie":["ch0","ch1","ch2"],"problem":{"beta0":{"1":"1","2":"2"}}}
  toml: |
    problem.beta0.1="1"
    2="2"
    alpha.a0="a0ch0"
    beta.beta0.beta00=1234
    charlie=["ch0","ch1","ch2"]

这是不正确的。还有另一个令人眼花缭乱的问题,即丢失订单,不知道为什么或如何解决它,但这并不是什么大问题。

我的额外要求是,我需要为所有行添加公共前缀。如果没有它,您可以定义另一个模板来简化使用,但这很简单。

免责声明:我对 helm/go 模板完全陌生,因此以下内容可能不是最佳选择,但它应该可以解决这些问题。

再次继续举例:

{{ $fred := dict
    "alpha" (dict "a0" "a0ch0")
    "beta" (dict "beta0" (dict "beta00" 1234))
    "charlie" (list "ch0" "ch1" "ch2")
    "problem" (dict "beta0" (dict "1" "1" "2" "2" )) }}
data:
  theData: |
{{ toJson $fred | indent 4 }}
  toml: |
{{ include "flattenYaml" (dict "prefix" "added_prefix" "data" $fred) | indent 4 }}

将产生:

data:
  theData: |
    {"alpha":{"a0":"a0ch0"},"beta":{"beta0":{"beta00":1234}},"charlie":["ch0","ch1","ch2"],"problem":{"beta0":{"1":"1","2":"2"}}}
  toml: |
    added_prefix.alpha.a0="a0ch0"
    added_prefix.beta.beta0.beta00=1234
    added_prefix.charlie=["ch0","ch1","ch2"]
    added_prefix.problem.beta0.1="1"
    added_prefix.problem.beta0.2="2"

并且 flattenYaml 的模板源看起来像这样:

{{- define "flattenYaml" -}}
{{- $dict := . -}}
{{- $prefix := $dict.prefix -}}
{{- $data := $dict.data -}}
{{- $knd := kindOf $data -}}
    {{- if eq $knd "map" }}
        {{- range (keys $data) }}
            {{- $key := . }}
            {{- $prefixedKey := (printf "%s.%s" $prefix $key) }}
            {{- $value := get $data $key }}
            {{- $valueKind := kindOf $value }}
            {{- if eq $valueKind "map" }}
                {{-   include "flattenYaml" (dict "prefix" ($prefixedKey) "data" $value) }}
            {{- else }}
                {{-   printf "%s=%s\n" $prefixedKey (toJson $value) }}
            {{- end }}
        {{- end }}
    {{- else }}
        {{ toJson . }}#k({{ $knd }})
    {{- end }}
{{- end -}}

免责声明2:我不知道原始解决方案中的

#k ...
中的
{{ toJson . }}#k({{ $knd }})
有什么作用,如果它爆炸到你的脸上,请不要感到惊讶;)

编辑:

    {{ toJson . }}#k({{ $knd }})

实际上吹到了我的脸上,仍然不知道#k应该提供什么,但更换后解决了我的问题:

    {{- if ne $data nil }}
        {{- toJson $data }}
    {{- end }}
© www.soinside.com 2019 - 2024. All rights reserved.