如何从Helm Helper函数返回列表变量并实现模板迭代?
问题:Helm模板Helper函数如何返回列表供遍历?
在Helm模板中,为了减少重复代码,需要合并values.yaml中的两个字段:单个对象schema和对象列表schemas,统一成一个列表后遍历。原本的合并逻辑如下:
{{- $schemas := list -}} {{- if .Values.schema -}} {{- $schemas = list .Values.schema -}} {{- end -}} {{- if .Values.schemas -}} {{- $schemas = .Values.schemas -}} {{- end -}}
为了避免在多个模板中复制这段代码,将其封装成Helper函数:
{{- define "helper.schemas" -}} {{- $schemas := list -}} {{- if .Values.postgres.database.schema -}} {{- $schemas = list .Values.postgres.database.schema -}} {{- end -}} {{- if .Values.postgres.database.schemas -}} {{- $schemas = .Values.postgres.database.schemas -}} {{- end -}} {{- $schemas }} {{- end -}}
但在主模板中调用时:
{{- range $indx, $schema := include "helper.schemas" . }} ... {{- end }}
出现错误:range can't iterate over [map[.. ..]]。
解决方案
问题根源
include函数会将Helper模板的输出转换成字符串,而非直接返回Go模板的变量(列表/映射类型)。因此range尝试遍历字符串而非真正的列表,导致报错。
可行解决方法
方法1:使用tpl函数解析Helper输出
tpl函数可将字符串形式的YAML/模板解析为Helm能识别的变量类型。修改主模板的调用方式:
{{- /* 用tpl解析Helper返回的字符串为列表 */ -}} {{- range $indx, $schema := tpl (include "helper.schemas" .) . }} # 这里编写遍历逻辑 {{- end }}
注意:Helper中输出的$schemas必须是合法的YAML格式,确保tpl能正确解析。
方法2:合并逻辑与渲染逻辑分离(推荐)
更清晰的做法是先在主模板中完成列表合并,再调用Helper渲染单个列表项:
- 定义渲染单个schema的Helper:
{{- define "helper.schema.render" -}} # 单个schema的渲染逻辑示例 apiVersion: v1 kind: ConfigMap metadata: name: schema-{{ .name }} data: schema.sql: | {{ .sqlContent }} {{- end }}
- 在主模板中合并列表并遍历:
{{- /* 合并schema和schemas为统一列表 */ -}} {{- $schemas := list -}} {{- if .Values.postgres.database.schema -}} {{- $schemas = append $schemas .Values.postgres.database.schema -}} {{- end -}} {{- if .Values.postgres.database.schemas -}} {{- $schemas = concat $schemas .Values.postgres.database.schemas -}} {{- end -}} {{- /* 遍历列表,调用Helper渲染每个项 */ -}} {{- range $indx, $schema := $schemas }} {{ include "helper.schema.render" $schema }} {{- end }}
注:若需求是优先使用schemas列表(存在时忽略单个schema),可将合并逻辑改回原来的覆盖方式,而非append/concat。
方法3:通过上下文传递变量
在Helper中将合并后的列表存入当前上下文,供主模板直接使用:
- 定义初始化Helper:
{{- define "helper.schemas.init" -}} {{- $schemas := list -}} {{- if .Values.postgres.database.schema -}} {{- $schemas = list .Values.postgres.database.schema -}} {{- end -}} {{- if .Values.postgres.database.schemas -}} {{- $schemas = .Values.postgres.database.schemas -}} {{- end -}} {{- /* 将合并后的列表存入上下文的schemas字段 */ -}} {{- $_ := set . "schemas" $schemas -}} {{- end -}}
- 在主模板中调用Helper并遍历:
{{- /* 先初始化上下文里的schemas变量 */ -}} {{- include "helper.schemas.init" . -}} {{- /* 直接遍历上下文里的schemas */ -}} {{- range $indx, $schema := .schemas }} # 编写遍历逻辑 {{- end }}
内容的提问来源于stack exchange,提问作者Herr Derb
相关产品推荐
相关产品推荐

