Khary Mendez
Khary Mendez

Reputation: 1848

How to check for a non-existent dictionary value within a helm template?

In my values config file, I have an array of dictionaries as follows:

    connects_to
     - name: myname
       release: optional release
     - name: another name

Note that name will always be provided but release may or may not be. In my template, I have:

    {{- if .Values.connects_to }}
        app.openshift.io/connects-to: '
    {{- range .Values.connects_to -}}
    {{- if .release -}}  
        {{- .release -}}-{{- .name -}},
    {{- else -}}
        {{- $.Release.Name -}}-{{- .name -}},
    {{- end -}}
    {{- end -}}
    '
    {{- end }}

which gives the error:

    can't evaluate field release in type interface {}

I have also tried using "hasKey" as follows:

    {{- if .Values.connects_to }}
        app.openshift.io/connects-to: '
    {{- range .Values.connects_to -}}
    {{- if hasKey . "release" -}}  
        {{- .release -}}-{{- .name -}},
    {{- else -}}
        {{- $.Release.Name -}}-{{- .name -}},
    {{- end -}}
    {{- end -}}
    '
    {{- end }}

which gives the error:

    wrong type for value; expected map[string]interface {}; got string

How would I accomplish this check without having to specify a value for "release" every time? My helm version:

    version.BuildInfo{Version:"v3.2.3+4.el8", GitCommit:"2160a65177049990d1b76efc67cb1a9fd21909b1", GitTreeState:"clean", GoVersion:"go1.13.4"}

Upvotes: 2

Views: 8104

Answers (3)

Itai B
Itai B

Reputation: 41

Regarding @DieterDP 's response https://stackoverflow.com/a/72360797/17143221

I am getting the same issue when using this template. This can be solved by using parentheses around the optional dict as a mean of null-safety.

template:

# Fails when somedict doesn't exist
{{- if hasKey .Values.somedict "valueX" -}}
    {{- .Values.somedict.valueX -}}
{{- end -}}

# Works when somedict doesn't exist
{{- if hasKey (.Values.somedict) "valueX" -}}
    {{- .Values.somedict.valueX -}}
{{- end -}}

values.yaml:

# without "somedict"

Upvotes: 3

DieterDP
DieterDP

Reputation: 4347

For people looking for a possible cause for the error (wrong type for value; expected map[string]interface {}; got string).

Given the template

{{- if hasKey .Values.somedict "valueX" -}}
    {{- .Values.somedict.valueX -}}
{{- end -}}

And using 2 values.yaml (eg: helm template . --values Values1.yaml --values Values2.yaml).

Values1.yaml:

somedict:
  valueA: 1

Values2.yaml:

# Causes error
somedict:

# Works
somedict: {}

# Leaving out "somedict" also work

Upvotes: 2

Khary Mendez
Khary Mendez

Reputation: 1848

This actually works with the "hasKey" approach, there was an error in the values definition.

Upvotes: 2

Related Questions