Helm dig using dynamic list of values

477 views Asked by At

I am trying to use the dig function in helm to check if a value exists in my dictionary, I have a space delimited string that I want to use as each key to check in the dictionary.

For example without adding a values file it should like this:

{{- $mydict := (dict "A" (dict "B" ( dict "C" "Present"))) -}}
{{- $string := "\"A\" \"B\" \"C\"" -}}
{{- $vals := dig $string "not present" $mydict -}}
{{- if eq $vals "not present" }}
{{- fail (printf "Failed to find value") }}
{{- end }}

Is there a way to expand the string to be read by dig? I tried to change the string into a list but that also doesn't seem to help.

1

There are 1 answers

0
David Maze On

I don't think there's a good way to do this.

The core problem here is that dig takes its path as a sequence of positional parameters, but there's no "apply" function that could inject a variable number of parameters.

{{- $s1 := "A" -}}
{{- $l1 := splitList " " $s1 -}}
{{- dig (index $l1 0) "not present" $mydict }}

{{ $s2 := "A B" -}}
{{- $l2 := splitList " " $s2 -}}
{{- dig (index $l2 0) (index $l2 1) "not present" $mydict }}

Note that the two dig calls have different numbers of parameters, and we need to manually expand the list. This would be possible in other languages (Python for example has a way to construct a list of parameters, then invoke a function with it) but not in the Go template language.

I've generally approached this problem with a recursive template function. Let the template parameter be a list, where the first value is the data structure you're traversing and the remaining values are the path. Then you can walk down it.

{{- define "find" -}}
  {{- if eq (len .) 1 -}}
    {{- if (index . 0) -}}
      present
    {{- else -}}
      not present
    {{- end -}}
  {{- else -}}
    {{- $d := index (index . 0) (index . 1) | default dict -}}
    {{- $l := slice . 2 -}}
    {{- include "find" (prepend $l $d) -}}
  {{- end -}}
{{- end -}}

This still has problems; for example, the template function can only return a string, so if you want to pick out part of a nested map this can't return it.