Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default function treats boolean false as not defined, and applies default #3308

Closed
Stono opened this issue Dec 31, 2017 · 50 comments
Closed

Comments

@Stono
Copy link

Stono commented Dec 31, 2017

values.yaml:

someKey: false

in template:

{{ default true .Values.someKey }}

I would expect this to return false, as someKey is defined, and its value is false, however it returns true.

@bacongobbler
Copy link
Member

You have the arguments flipped in the wrong direction. It should be {{ default .Values.somekey false }}. default takes its first argument as the value to check if it exists, then defaults to the second argument if it's not defined.

@Stono
Copy link
Author

Stono commented Dec 31, 2017

@bacongobbler apologies, i noticed this too but it's still incorrect the other way.... I also tried {{ $deployment.enabled | default true }} just for the hell of it

values.yaml
screen shot 2017-12-31 at 20 02 25

template:
screen shot 2017-12-31 at 20 02 07

You would expect that to be false however:

screen shot 2017-12-31 at 20 01 47

@bacongobbler
Copy link
Member

Ah, I forgot that "empty value" is false when in reference to booleans, so I don't think you can use default in the way you want to.

https://github.com/Masterminds/sprig/blob/ecbec66c2936b6503e7c9e29123e343be03ac8eb/docs/defaults.md#default

It's probably better to use {{ if $deployment.enabled }}{{ $deployment.enabled }}{{ else }}true{{ end }} instead.

@Stono
Copy link
Author

Stono commented Dec 31, 2017

Ahh that clarifies, how annoying!
Thanks dude.

@tw0517tw
Copy link

Hi @bacongobbler ,

What if I'd like to use this in a block if in my template? Something like:

{{- if (default $foo true) }}
someSetting: "bar"
{{- end }}

and I want the someSetting to not render only when $foo is explicitly set to false.

@max-tet
Copy link

max-tet commented Aug 28, 2018

This is still open, istn't it?
The workaround provided by @bacongobbler does not seem to work.
There must be some way to distinguish null from false? How else can you set a default to true and make it overridable by a false value?

@atombender
Copy link

atombender commented Sep 6, 2018

This is the workaround I use:

{{ if or (not (hasKey . "enabled")) (eq (coalesce .enabled false) true) }}
...
{{ end }}

Obviously, if the dictionary you're checking is something like $foo:

{{ if or (not (hasKey $foo "enabled")) (eq (coalesce $foo.enabled false) true) }}
...
{{ end }}

The reason I'm using coalesce is because eq .enabled true fails (error calling eq: invalid type for comparison) with null errors for some dastardly reason.

Obviously, the only works if enabled is either a boolean, or absent. If it's actually null, then the above won't work.

@marcinma
Copy link

Why this is closed? Issue still exists

@bacongobbler
Copy link
Member

What issue are you seeing @marcinma? What's your recommendation for a fix?

@atombender
Copy link

You have the arguments flipped in the wrong direction. It should be {{ default .Values.somekey false }}

That's wrong. default takes the default value as its first argument, and the value to be tested as the second. I use this all the time. Yes, the order is weird, but the OP is right.

There's a bug here and this needs to reopened.

@atombender
Copy link

The issue has been reported in Sprig.

@marcinma
Copy link

What issue are you seeing @marcinma? What's your recommendation for a fix?

Lets start with obvious test:

$> cat values.yaml

bugExists: false

$> cat templates/bug.yaml

defaul result oposite: {{ default .Values.bugExists true }}
default result normal: {{ default  true .Values.bugExists }}
real value: {{ .Values.bugExists }}

$> helm template --output-dir=out .
wrote out/test/templates/bug.yaml

$> cat out/test/templates/bug.yaml
---
# Source: test/templates/bug.yaml
defaul result oposite: true
default result normal: true
real value: false

Although false is defined it is not used in any case.
At lest helm documentation should describe this behavior until fixed here:
https://github.com/helm/helm/blob/master/docs/chart_template_guide/functions_and_pipelines.md#using-the-default-function

Not sure how this can be fixed yet this bug shouldn't be closed.

@gabordk
Copy link

gabordk commented Jul 31, 2019

What if I'd like to use this in a block if in my template? Something like:

{{- if (default $foo true) }}
someSetting: "bar"
{{- end }}

and I want the someSetting to not render only when $foo is explicitly set to false.

@tw0517tw Did you found any solution to this?

@tw0517tw
Copy link

tw0517tw commented Aug 1, 2019

@gabordk No I didn't find any.

@andyliuliming
Copy link

sad to see this does not work:
{{ $ba := and (.Values.global.oneBool) (default true .Values.global.anotherbool) }}

@mentos1386
Copy link
Contributor

@bacongobbler If this is working as intended (that you cannot use default with booleans). Can it be added to documentation, as a warning? Or reopen the issue if it isn't working as intended.

@cjmaloof
Copy link

Similarly, an integer value of 0 is always replaced by the default.

@cosimps
Copy link

cosimps commented Feb 12, 2020

Hi @bacongobbler ,

What if I'd like to use this in a block if in my template? Something like:

{{- if (default $foo true) }}
someSetting: "bar"
{{- end }}

and I want the someSetting to not render only when $foo is explicitly set to false.

@gabordk and anyone else that my encounter this issue, this is my workaround that I am using is a few templates:

{{- if or (.Values.enabled) (eq (.Values.enabled | toString) "<nil>") }}
someSetting: bar
{{- end }}

in action:

$> cat chart/values.yaml

enabled: true

$> helm template chart/

---
someSetting: bar
otherSetting: foo
$> cat chart/values.yaml

$> helm template chart/

---
someSetting: bar
otherSetting: foo
$> cat chart/values.yaml

enabled: false

$> helm template chart/

---
otherSetting: foo

lawliet89 added a commit to aicadium-archive/helm-charts that referenced this issue May 14, 2020
cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
k8s-ci-robot pushed a commit to helm/charts that referenced this issue May 14, 2020
…2391)

cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
iwilltry42 pushed a commit to iwilltry42/charts that referenced this issue May 19, 2020
…lm#22391)

cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
irlevesque pushed a commit to quantopian/charts that referenced this issue Jul 13, 2020
…lm#22391)

cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
includerandom pushed a commit to includerandom/helm_charts that referenced this issue Jul 19, 2020
…lm#22391)

cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
li-adrienloiseau pushed a commit to li-adrienloiseau/charts that referenced this issue Jul 29, 2020
…lm#22391)

cf. helm/helm#3308

Signed-off-by: Yong Wen Chua <lawliet89@users.noreply.github.com>
Signed-off-by: Adrien Loiseau <adrien.loiseau@logic-immo.com>
@prashant-shahi
Copy link

I had same issue with "false" and "true" i.e. Boolean as string being set in the pod ENVs.
default assumed the string to be boolean.

I solved it by using and explicit quote on top of .Values.insecure being a string "false" itself..

{{- define "app.isInsecure" -}}
{{- default "true" (.Values.insecure | quote) }}
{{- end }}

@whatthefrog
Copy link

whatthefrog commented Nov 10, 2022

kcasas
simplest workaround I've come up is this

list nil true | has .Values.vaultEnabled

In some cases it may be useful to also add the "true" string to the checked list

list nil true "true" | has .Values.vaultEnabled

@joejulian
Copy link
Contributor

Hi @bacongobbler ,

What if I'd like to use this in a block if in my template? Something like:

{{- if (default $foo true) }}
someSetting: "bar"
{{- end }}

and I want the someSetting to not render only when $foo is explicitly set to false.

I do:

{{- if (dig "somekey" true .Values) }}
someSetting: bar
{{- end }}

Which looks in .Values for the key, "somekey". If it's there, it uses that value. If it's not, it uses (in the above example) true as the default.

mvisonneau pushed a commit to mvisonneau/helm-charts that referenced this issue Nov 24, 2022
…e details please see: helm/helm#3308 (#55)

Co-authored-by: Eugene Furmanyk <eugene.furmanyk@ringcentral.com>
@jbilliau-rcd
Copy link

Hi @bacongobbler ,
What if I'd like to use this in a block if in my template? Something like:

{{- if (default $foo true) }}
someSetting: "bar"
{{- end }}

and I want the someSetting to not render only when $foo is explicitly set to false.

@gabordk and anyone else that my encounter this issue, this is my workaround that I am using is a few templates:

{{- if or (.Values.enabled) (eq (.Values.enabled | toString) "<nil>") }}
someSetting: bar
{{- end }}

in action:

$> cat chart/values.yaml

enabled: true

$> helm template chart/

---
someSetting: bar
otherSetting: foo
$> cat chart/values.yaml

$> helm template chart/

---
someSetting: bar
otherSetting: foo
$> cat chart/values.yaml

enabled: false

$> helm template chart/

---
otherSetting: foo

For anyone stumbling here from doing a google search on this issue, it is indeed still an issue but the real hero is @cosimps whose workaround works beautifully. Much appreciated!

@dicky-yuen
Copy link

dicky-yuen commented Apr 18, 2023

{{if ((.Values.health).enabled)}}

This works well for me, in case anyone still cares about this.

It works. But can you explain why the bracket can work it?

@Mo0rBy
Copy link

Mo0rBy commented Aug 14, 2023

How is this not re-opened or fixed? This is a really helpful thread with some workarounds, but we shouldn't need it. This functionality with default and Booleans seems really simple and should work straight away

@Mo0rBy
Copy link

Mo0rBy commented Aug 14, 2023

I'm going to put this solution to my problem here in case it helps anyone:

I wanted to render part of a template (a deployment label) by default unless the values.yaml explicitly stated that a value was false:

      labels:
        {{- if ne false ((.Values.security).label).enabled }}
        myLabel: "this-section-is-rendered-unless-the-value-is-explicitly-false"
        {{- end }}

Here is the explanation of using the parenthesis on my evaluated value > https://stackoverflow.com/questions/59795596/how-to-make-nested-variables-optional-in-helm/68807258#68807258

And I am simply use a "not equals" which fits the logic very nicely. The users of my chart will have to explicitly state the specific value as false in order to not include this label in the deployment.

@vincentor
Copy link

five years later and i fall into the same hole now, this issue should be fixed

@Cajga
Copy link

Cajga commented Aug 31, 2023

IMO the solution from @joejulian that is using the "dig" function is the most elegant, readable and simple solution.

Update: it is indeed mentioned in the documentation

jbeard6 added a commit to ezcater/tonic_helm_charts that referenced this issue Sep 25, 2023
The use of the `default` function had the unintended side-effect of
never allowing the value to be `false`.

See the following for more details:
- [helm/helm#3308](helm/helm#3308)
- [Masterminds/sprig#111](Masterminds/sprig#111)
- [Default Functions](http://masterminds.github.io/sprig/defaults.html)
jbeard6 added a commit to ezcater/tonic_helm_charts that referenced this issue Sep 25, 2023
* Allow services to be exposed via HTTP.

The use of the `default` function had the unintended side-effect of
never allowing the value to be `false`.

See the following for more details:
- [helm/helm#3308](helm/helm#3308)
- [Masterminds/sprig#111](Masterminds/sprig#111)
- [Default Functions](http://masterminds.github.io/sprig/defaults.html)

* Release info: v1.0.2-r6
jbeard6 added a commit to ezcater/tonic_helm_charts that referenced this issue Sep 25, 2023
The use of the `default` function had the unintended side-effect of
never allowing the value to be `false`.

See the following for more details:
- [helm/helm#3308](helm/helm#3308)
- [Masterminds/sprig#111](Masterminds/sprig#111)
- [Default Functions](http://masterminds.github.io/sprig/defaults.html)
@glebsts
Copy link

glebsts commented Oct 11, 2023

Almost six years and it is still an issue. I want to explicitly change default-true in subchart in my values, and I cannot use false.

@tgolly
Copy link

tgolly commented Dec 29, 2023

What I'm trying to do is: if my enabled boolean is not defined, have it default to true (which I realise is unusual but I have a use case for it).

So:

  • enabled == true -> true
  • enabled == false -> false
  • enabled "not defined" -> true

It thought either of these would work:

{{- if .enabled | default true }}
{{- if default true .enabled }}

...but they don't.

After a lot of trial and error, this is the simplest workaround I could find:

{{- if ne (toString .enabled) "false" }}

This works because "toString" on an undefined boolean returns <nil>.

But still, having an undefined boolean always return false instead of not defined means you cannot use the "default" function to set the default for a boolean. It can only ever default to false.

Please re-open this issue, until the "default" function can be used with boolean values without these workarounds.

@cesium147
Copy link

I not found simple way to resolve case with set False when default value is True.
But share my working version with next conditions:

  • flag has value > value
  • flag == true > true
  • flag == false > false
  • flag is empty > true
  • flag is absent > true

template.yaml

---
flag1: {{ .Values.flag1 | default (eq (toString .Values.flag1) "<nil>" | ternary true false) }}
flag2: {{ .Values.flag2 | default (eq (toString .Values.flag2) "<nil>" | ternary true false) }}
flag3: {{ .Values.flag3 | default (eq (toString .Values.flag3) "<nil>" | ternary true false) }}
flag4: {{ .Values.flag4 | default (eq (toString .Values.flag4) "<nil>" | ternary true false) }}
flag5: {{ .Values.flag5 | default (eq (toString .Values.flag5) "<nil>" | ternary true false) }}

values.yaml

---
flag1: test
flag2: true
flag3: false
flag4: 
# flag5:

output

---
flag1: test
flag2: true
flag3: false
flag4: true
flag5: true

@michelefa1988
Copy link

What I'm trying to do is: if my enabled boolean is not defined, have it default to true (which I realise is unusual but I have a use case for it).

So:

  • enabled == true -> true
  • enabled == false -> false
  • enabled "not defined" -> true

It thought either of these would work:

{{- if .enabled | default true }}
{{- if default true .enabled }}

...but they don't.

After a lot of trial and error, this is the simplest workaround I could find:

{{- if ne (toString .enabled) "false" }}

This works because "toString" on an undefined boolean returns <nil>.

But still, having an undefined boolean always return false instead of not defined means you cannot use the "default" function to set the default for a boolean. It can only ever default to false.

Please re-open this issue, until the "default" function can be used with boolean values without these workarounds.

@tgolly I have exactly your used case and I have not been able to workaround it. Did you manage to find a workaround at the end?

@tgolly
Copy link

tgolly commented Apr 8, 2024

@tgolly I have exactly your used case and I have not been able to workaround it. Did you manage to find a workaround at the end?

@michelefa1988 No. 😢

This issue really needs to be re-opened.

@detro
Copy link

detro commented Apr 26, 2024

The issue has to be reopened. The root of the issue boils down to the coalescing of absence of boolean to false.

Given that making a change to the default function would break an entire ecosystem (and have probably a swarm of ppl descend on Helm with pitchforks), my advice is to go for an additional function. A default_boolean that offers a way to control the coalescence better.

And for ppl that go around down-voting comments: please grow up.

@pawamoy
Copy link

pawamoy commented Apr 26, 2024

I suspect some comments are downvoted because they either don't bring anything to the discussion, or are not respectful. I've just unsubscribed 🙂 Good luck everybody!

@tgolly
Copy link

tgolly commented Apr 27, 2024

I think you are right @pawamoy .

@FahadBSyed
Copy link

We just hit this too, kind of silly that this hasn't been fixed yet

FahadBSyed added a commit to pachyderm/pachyderm that referenced this issue May 2, 2024
It turns out that the `default` function in Helm doesn't work as
expected for `boolean` types (which you would expect it to work for at
the bare minimum), but this is because of a technicality in Helm's
design: helm/helm#3308

Also, we had to add code to handle legacy storage configuration in the
new StorageEnv code for the storage service.
FahadBSyed added a commit to pachyderm/pachyderm that referenced this issue May 2, 2024
It turns out that the `default` function in Helm doesn't work as
expected for `boolean` types (which you would expect it to work for at
the bare minimum), but this is because of a technicality in Helm's
design: helm/helm#3308

Also, we had to add code to handle legacy storage configuration in the
new StorageEnv code for the storage service.
FahadBSyed added a commit to pachyderm/pachyderm that referenced this issue May 2, 2024
It turns out that the `default` function in Helm doesn't work as
expected for `boolean` types (which you would expect it to work for at
the bare minimum), but this is because of a technicality in Helm's
design: helm/helm#3308

Also, we had to add code to handle legacy storage configuration in the
new StorageEnv code for the storage service.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests