Helm: 模板无法读取外部文件

huangapple go评论57阅读模式
英文:

Helm: Template unable to read external files

问题

以下是翻译好的部分:

有一些外部文件(例如 - "panels/pods/memory.txt"),需要根据configMap.yaml文件内的参数动态读取。

=> cat templates/configMap.yaml
fileContent_via_template: {{ include "readfile" (dict "metrics" "panels/pods/memory.txt") }}
=> cat panels/pods/memory.txt
这是从memory.txt文件中显示的虚拟内容

为了读取外部文件,定义了一个模板 -

=> templates/_helpers.tpl
{{- define "readfile" -}}
  {{- $content := .Files.Get .metrics -}}
  {{ $content }}
{{- end -}}

它抛出以下错误 -

错误: 模板: grafana/templates/configMap.yaml:2:22: 在执行“grafana/templates/configMap.yaml”时发生错误,位置在<include &quot;readfile&quot; (dict &quot;metrics&quot; &quot;panels/pods/memory.txt&quot;)>: 调用 include 时出错: 模板: grafana/templates/_helpers.tpl:42:24: 在执行“readfile”时出错,位置在<.Files.Get>: 评估接口 {} 的 nil 指针

如果从configMap.yaml直接读取相同的外部文件,那么它可以工作 -

=&gt; cat templates/configMap.yaml
fileContent: {{ .Files.Get &quot;panels/pods/memory.txt&quot; }}

它返回以下输出:

---
# Source: grafana/templates/configMap.yaml
fileContent: 这是从memory.txt文件中显示的虚拟内容
英文:

There are some external files (e.g - "panels/pods/memory.txt") which is needed to read dynamically based on parameters inside configMap.yaml file

=&gt; cat templates/configMap.yaml
fileContent_via_template: {{ include &quot;readfile&quot; (dict &quot;metrics&quot; &quot;panels/pods/memory.txt&quot;) }}

=&gt; cat panels/pods/memory.txt
This is dummy content which is displayed from memory.txt file

To read external file, defined a template -

=&gt; templates/_helpers.tpl
{{- define &quot;readfile&quot; -}}
  {{- $content := .Files.Get .metrics -}}
  {{ $content }}
{{- end -}

It throws below error -

Error: template: grafana/templates/configMap.yaml:2:22: executing &quot;grafana/templates/configMap.yaml&quot; at &lt;include &quot;readfile&quot; (dict &quot;metrics&quot; &quot;panels/pods/memory.txt&quot;)&gt;: error calling include: template: grafana/templates/_helpers.tpl:42:24: executing &quot;readfile&quot; at &lt;.Files.Get&gt;: nil pointer evaluating interface {}.Get

If same external file is read from configMap.yaml directly, then it works -

=&gt; cat templates/configMap.yaml
fileContent: {{ .Files.Get &quot;panels/pods/memory.txt&quot; }}

It returns the below output:

---
# Source: grafana/templates/configMap.yaml
fileContent: This is dummy content which is displayed from memory.txt file


答案1

得分: 1

Inside the readfile template, you refer to .Files.Get. 这是正常的 Go 模板语法:从对象 . 中获取字段 Files,然后在该对象内获取字段 Get。然而,. 不再是顶级 Helm 对象,而是模板的参数。

你可以通过将 .Files 明确传递为参数来修复这个问题

{{ include &quot;readfile&quot; (dict &quot;Files&quot; .Files &quot;metrics&quot; &quot;panels/pods/memory&quot;) }}
{{/*                        ^^^^^^^^^^^^^^                               */}}

如果你还需要其他特性,比如 .Values,或者如果你需要将整个顶级对象传递给其他模板,你可能需要将顶级对象作为参数传递。在我的模板中,我喜欢称之为 top,但我不认为我在野外见过一个具体的约定。

在这种情况下,你需要同时更改模板以从 top 对象中引用 .Files

{{/* Reads a file as in .Files.Get and ....  Takes a dictionary with two
     fields.  `metrics` is the name of the file to read, and `top` is the
     top-level Helm object. */}
{{ define &quot;readfile&quot; }}
  {{- $content := .top.Files.Get .metrics -}}
  {{/*-           ^^^^                  -*/}}
  {{ $content }}
{{- end }}

在调用站点上,同样,你需要添加该参数。

{{ include &quot;readfile&quot; (dict &quot;top&quot; . &quot;metrics&quot; &quot;panels/pods/memory&quot;) }}
{{/*                        ^^^^^^^                               */}}
英文:

Inside the readfile template, you refer to .Files.Get. This is normal Go template syntax: from the object ., get the field Files, and within that object, get the field Get. However, . is no longer the top-level Helm object but rather the parameter to the template.

You could fix this without changing the inner template code by explicitly passing .Files as a parameter

{{ include &quot;readfile&quot; (dict &quot;Files&quot; .Files &quot;metrics&quot; &quot;panels/pods/memory&quot;) }}
{{/*                        ^^^^^^^^^^^^^^                               */}}

If you also needed other characterictics like .Values, or if you needed to pass the whole top-level object on to some other template, you may need to pass the top-level object as a parameter. In my templates I like to call this top but I don't think I've seen a specific convention for this in the wild.

In this case, you'd need to both change the template to refer to .Files out of the top object

{{/* Reads a file as in .Files.Get and ....  Takes a dictionary with two
     fields.  `metrics` is the name of the file to read, and `top` is the
     top-level Helm object. */}}
{{ define &quot;readfile&quot; }}
  {{- $content := .top.Files.Get .metrics -}}
  {{/*-           ^^^^                  -*/}}
  {{ $content }}
{{- end }}

At the call site, again, you need to add the parameter.

{{ include &quot;readfile&quot; (dict &quot;top&quot; . &quot;metrics&quot; &quot;panels/pods/memory&quot;) }}
{{/*                        ^^^^^^^                               */}}

huangapple
  • 本文由 发表于 2023年5月21日 11:39:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298195.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定