Helm Charts - How do I use `default` on undefined object property values?
Asked Answered
G

3

11

Using Helm, I was under the impression default would be the fallback if a variable is not defined. However, it doesn't appear Helm can get to values in sub-object hashes:

  type: {{ default "NodePort" .Values.fpm.service.type }}

If .Values.fpm.service or service.type is not defined, it should use 9000.

However, attempting to template this throws a nil pointer error:

 <.Values.fpm.service.type>: nil pointer evaluating interface {}.type

Is there a way to simply perform this level of variable testing? Or am I subjected to an if/else test?

The intent of this is to optionally define .fpm.service (and [..].type) within your values.yaml file.

(I'm building a Helm Library chart to handle optional definitions by main charts)

Granulite answered 3/1, 2020 at 0:38 Comment(0)
D
9

According to the official Helm doc (Using Default Function), the syntax is different and you should use it this way:

type: {{ .Values.fpm.service.type | default "NodePort" | quote }}
Dockery answered 3/1, 2020 at 8:31 Comment(5)
That's not it, though. The issue isn't around default. The issue is around Helm trying to go down into a non-existing object: checking for "fpm.service.type" and not just stopping when "fpm.service" doesn't exist.Granulite
PS: The docs to clearly state this is an expected argument approach, too: default DEFAULT_VALUE GIVEN_VALUEGranulite
This answer doesn't answer the question at all.Wavy
.Values.nonexiting | default "a default" will work. .Values.nonexisting.nonexting2 | default "default" will not. Due to the fact that "nonexisting" does not exist and Helm cant then go deeperFerricyanide
There's an option to wrap it with brackets for example: type: {{ ((.Values.fpm).service).type | default "NodePort" | quote }}Milone
G
6

Doesn't look like there's really a good way to stop Helm from trying to dive into non-existing objects. I moved into a single line if condition, and it worked:

  type: {{ if .Values.fpm.service -}} {{ .default "NodePort" .Values.fpm.service.type | quote }} {{- else -}} "NodePort" {{- end }}

This way, I check if fpm.service exists first, before trying .type check. It works, whether .service and .service.type is or is not defined.

Granulite answered 3/1, 2020 at 16:21 Comment(1)
You are correct, non existing objects are being traversed, at least we have to define them with empty values.Urdu
S
5

In Helm we can wrap a value that we might consider optional in brackets.

type: {{ (.Values.fpm.service).type | default "NodePort" }}

Now when we try to run a helm template / install, it will consider .Values.fpm.service to be optional. We would still run into a Nil pointer if .Values.fpm is not set. So you must ensure to encapsulate up until where should be considered optional, as you can see in the example I provided, I did not place brackets around .type otherwise, it would try to find service which may not exist.

Skuld answered 10/12, 2023 at 5:11 Comment(3)
See also https://mcmap.net/q/271951/-how-to-make-nested-variables-optional-in-helmSpagyric
great answer! works like a charm without ugly syntax or overcomplicated statements.Ulysses
This works! stupid helm chartsElurd

© 2022 - 2024 — McMap. All rights reserved.