Helm模板嵌套值防空指针及default函数使用问题求助
我有一个设计复杂的values文件,用来集中存储多个部署的通用配置,里面有大量嵌套值,比如:
app1: environment: staging: replicas: 3
我用下面的方式获取这个值:
{{ index .Values (.Values.app) "environment" (.Values.env) "replicas" }}
值存在时能正常工作,但我想在值不存在时设置默认值,这就需要遍历配置树的每一步都做判断。
我试了常规写法,但没用:
{{ if index .Values (.Values.app) "environment" (.Values.env) "replicas" }} replicas: {{ index .Values (.Values.app) "environment" (.Values.env) "replicas" }} {{ else }} replicas: 1 {{ end }}
之前看到过关于text/template继承的双括号用法,但完全搞不定。
额外问题:
- 怎么让内置的
default函数和index配合使用?试了好几次都失败了。 - 有没有更简洁的方式处理重复出现的
(.Values.app)和(.Values.env)?
编辑1
我尝试用default给每一步加空字典,但还是不行,代码如下:
{{- $app := index .Values (.Values.appName) -}} {{- $env := index $app "environment" | default dict -}} {{- $replicas := index $env (.Values.env) | default dict -}} {{- if $replicas "replicas" -}} replicas: {{ index .Values (.Values.appName) "environment" (.Values.env) "replicas" }} {{- else -}} replicas: 1 {{- end -}}
编辑2
我发现按当前思路走太繁琐,换了个思路但没成功:
{{- if hasKey index .Values (.Values.appName) "environment" -}} {{- if hasKey index .Values (.Values.appName) "environment" (.Values.env) -}} replicas: {{ index .Values (.Values.appName) "environment" (.Values.env) "replicas" }} {{- end -}} {{- else -}} replicas: 1 {{- end -}}
本来想用hasKey判断每一步的键是否存在,只在前一个键存在时继续,但hasKey只接受两个参数,没法把index的结果直接传进去,试了各种括号组合都没用。
编辑3
现在不再报空指针错误了,但渲染后的manifest里完全没有replicas字段:
{{ $app := index .Values (.Values.appName) }} {{ if hasKey $app "environment" }} {{ $env := index $app "environment" (.Values.env) }} {{ if hasKey $env "replicas" and not empty $env "replicas" }} {{ $replicas := index .Values (.Values.appName) "environment" (.Values.env) "replicas" }} replicas: {{ default "1" $replicas }} {{ end }} {{ end }}
编辑4
找到问题了!{{ if hasKey $env "replicas" and not empty $env "replicas" }}这个条件不匹配,所以replicas字段根本没生成,这个逻辑是对的,调试起来会更容易。
1. 分步取值+每层兜底(兼容所有Helm版本)
核心是每一步取值都用default返回空字典避免空指针,最后给目标值设默认:
{{- $targetApp := .Values.appName -}} {{- $targetEnv := .Values.env -}} {{- $app := index .Values $targetApp | default dict -}} {{- $envs := index $app "environment" | default dict -}} {{- $envConfig := index $envs $targetEnv | default dict -}} {{- $replicas := index $envConfig "replicas" | default 1 -}} replicas: {{ $replicas }}
不管前面哪一层配置缺失,最终都会返回默认值1,同时提前把重复变量赋值,减少冗余代码。
2. 修复条件判断的写法
你第三次编辑里的条件语法错误,Go模板中and需要将两个条件分别用括号包裹,且empty需要传入具体值:
{{ $targetApp := .Values.appName }} {{ $targetEnv := .Values.env }} {{ $app := index .Values $targetApp | default dict }} {{ if hasKey $app "environment" }} {{ $envs := index $app "environment" | default dict }} {{ $env := index $envs $targetEnv | default dict }} {{ if and (hasKey $env "replicas") (not (empty (index $env "replicas"))) }} replicas: {{ index $env "replicas" }} {{ else }} replicas: 1 {{ end }} {{ else }} replicas: 1 {{ end }}
3. 最简洁写法:用dig函数(Helm 3.5+支持)
Helm 3.5及以上版本内置dig函数,可直接链式取值并设置默认值,一步到位:
replicas: {{ dig .Values.appName "environment" .Values.env "replicas" 1 .Values }}
参数格式为:dig 键1 键2 ... 默认值 根对象,完美解决嵌套取值加默认的需求。
内容的提问来源于stack exchange,提问作者jonnybinthemix

