Helm chart: Merge dictionaries, allowing only keys that exist in one of them

20 Views Asked by At

In a helm chart - I have 2 dictionaries, one is static, and the other one is dynamic I want to merge these two dictionaries, so that the dynamic values replace the static ones, but I don't want to allow the dynamic dictionary to add keys that doesn't have a static value to the generate dictionaries

For example - Dictionary 1:

{{ $static := dict "FIRST_NAME" "first" "LAST_NAME" "last" }}
{{ $dynamic := dict "FIRST_NAME" "John" "KEY_TO_REMOVE" "something" }}
...
data:
{{ merge $dynamic $static | toYaml | indent 2}}

Results in:

...
data:
  FIRST_NAME: John
  LAST_NAME: last
  KEY_TO_REMOVE: something

And I want it to result in:

...
data:
  FIRST_NAME: John
  LAST_NAME: last

I can achieve this goal by using a combination of range and index to loop through the merged dict and print only items that exists in $static, but I'm looking for a cleaner "one line" solution

1

There are 1 best solutions below

0
David Maze On

I don't think this is possible without manually iterating through one of the dictionaries.

In this context I might accomplish this by using range to iterate over the static dictionary, and emitting the keys one at a time, without trying to specifically produce the result object as a variable.

data:
{{- range $key, $sv := range $static }}
  {{ $key }}: {{ get $dynamic $key | default $sv | toJson }}
{{- end }}

(There are a lot of practical problems with this as written: empty values in $dynamic will get ignored; this is a shallow merge that considers only the top-level keys; I've avoided some potentially tricky quoting issues.)

Internally Helm uses the Sprig support library for most of its extensions. The problem here is in the available set of dictionary functions. I can get the keys out of $static, and I can pick specific values out of $dynamic, but pick takes a static set of keys as positional parameters; you can't inject a list.

{{/* sadly not an option */}}
{{- $filtered := keys $static | xargs pick $dynamic -}}

If $static is really that static, then you could use pick, but I'm guessing in reality it isn't.

{{/* will work iff you know exactly the keys of $static in code */}}
{{ $static := dict "FIRST_NAME" "first" "LAST_NAME" "last" }}
{{ $dynamic := dict "FIRST_NAME" "John" "KEY_TO_REMOVE" "something" }}
{{ $filtered := pick $dynamic "FIRST_NAME" "LAST_NAME" }}
data:
{{ merge $filtered $static | toYaml | indent 2}}