helm: Wrong interpretation of Zero in templates files when having a default value

Setup

Here is my helm chart (just the relevant part to this issue) values.yaml:

name: failed
MyValue: 0

templates/config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.name }}
data:
  file.conf: |+
    {{ .Values.MyValue | default 10 }}

Expected behaviour

Running helm upgrade --install ... I expect to have a ConfigMap that contains the value “0”.

Actual behaviour

The created ConfigMap contains “10” (the default).

$ kubectl describe cm failed
Name:         failed
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
file.conf:
----
10

Events:  <none>

More fun:

This behaviour is not visible when :

  • there is no default. Changing this line {{ .Values.MyValue | default 10 }} to this {{ .Values.MyValue }}
  • the value is different than Zero (0). Changing this line MyValue: 0 to this MyValue: 7
  • the value is zero by quoted “0” (string not int). Changing this line MyValue: 0 to this MyValue: "0"

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 17
  • Comments: 18 (2 by maintainers)

Commits related to this issue

Most upvoted comments

This is still an issue with helm v3.12.3. Can you please re-open this?

Here’s another option:

{{ if not (kindIs "invalid" .Values.MyValue) }}{{ .Values.MyValue }}{{ else }}{{ 10 }}{{ end }}

Source: https://github.com/Masterminds/sprig/issues/53#issuecomment-483414063

I had to use it because some properties like maxSurge can be an integer or a string.

For anyone looking for another way of doing this, here is how i solved it, where the absence of replica means its not a float kind:

{{ if kindIs "float64" .replicas }}{{ .replicas }}{{ else }}{{ $.Values.defaultReplicas }}{{ end }}

For anyone looking for another way of doing this, here is how i solved it, where the absence of replica means its not a float kind:

{{ if kindIs "float64" .replicas }}{{ .replicas }}{{ else }}{{ $.Values.defaultReplicas }}{{ end }}

This workaround does not work when you pass values from cli

This same thing happens in if statements with 0 values. Because of this, I can’t find a way to differentiate between a null value and a numerical zero. In my use case, the 0 is a valid value, so I need to treat it differently than the null case.

I would be able to work around it if I could explicitly check for a numeric zero value, but the things I’ve tried throw an error or don’t evaluate correctly:

With MyValue: 0:

  • {{- if (eq 0 .Values.MyValue) -}} throws an “incompatible types for comparison” error, even when specifically casting the value as an int in the values file
  • {{- if empty .Values.MyValue -}} evaluates to true
  • {{- if (eq 0 (int .Values.MyValue)) -}} appears to work, but breaks the logic for the null case

Any suggestions?

It looks like isNil would do what I need, so I can work with that. Totally understand that it would be an easier fix than dealing with a breaking change. Thanks!

I’d like to be able to create an optional integer variable that can be explicitly set to zero.

I would usually define it something like this:

{{- if .Values.myVariable }}
option={{ .Values.myVariable }}
{{- end }}

In this case currently, if myVariable: 0 is defined, option will not be added because the if statement is evaluated as false.

Desired: If I set myVariable: 0, I’d like to have option=0. To not add the option, I would set myVariable: null, which should leave it out of the template file.