carvel-dev / ytt

YAML templating tool that works on YAML structure instead of text
https://carvel.dev/ytt
Apache License 2.0
1.65k stars 135 forks source link

Support default value for `any` type #883

Open LittleWat opened 8 months ago

LittleWat commented 8 months ago

Describe the problem/challenge you have

I want set the default value for any type but I can't.

Here is the example.

#@data/values-schema
---
test:
  #@schema/type any=True
  optional_config:
    param1: "a"
    param2: "b"
#@ load("@ytt:data", "data")

conf: #@ data.values.test.optional_config
#@data/values
---
test:
  optional_config:
    param3: "c"
$  ytt -f value.yaml -f schema.yaml -f template.yaml
ytt: Error: Overlaying data values (in following order: value.yaml):
  Document on line value.yaml:2:
    Map item (key 'test') on line value.yaml:3:
      Map item (key 'optional_config') on line value.yaml:4:
        Map item (key 'param3') on line value.yaml:5:
          Expected number of matched nodes to be 1, but was 0

Describe the solution you'd like

In the example, the expected output is:

conf:
    param1: a
    param2: b
    param3: c

I hope this is supported 🙏

Or I would be glad if you could share the workarounds for this 🙇‍♂️


Vote on this request

This is an invitation to the community to vote on issues, to help us prioritize our backlog. Use the "smiley face" up to the right of this comment to vote.

👍 "I would like to see this addressed as soon as possible" 👎 "There are other more important things to focus on right now"

We are also happy to receive and review Pull Requests if you want to help working on this issue.

LittleWat commented 8 months ago

I found the workaround for this. It was necessary to write the Starlark code, though.

#@data/values-schema
---
test:
  #@schema/type any=True
  optional_config: null

_default_optional_config:
  param1: a
  param2: b
#@ load("@ytt:data", "data")
#@ load("@ytt:struct", "struct")

#@ def combine_with_default(user_config, default_config):
#@  result = struct.decode(default_config)
#@  if user_config:
#@      result.update(struct.decode(user_config))
#@  end
#@  return result
#@ end

conf: #@ combine_with_default(data.values.test.optional_config, data.values._default_optional_config)
#@data/values
---
test:
  optional_config:
    param1: "aaa"
    param3: "c"
    parma4:
      param4_4: "ddd"

and here is the execution result:

$  ytt -f schema.yaml -f template.yaml -f value.yaml
conf:
  param1: aaa
  param2: b
  param3: c
  parma4:
    param4_4: ddd
prembhaskal commented 8 months ago

@LittleWat What you are trying to achieve can be easily done using an overlay

conf: #@ data.values.test.optional_config

- default-schema.yml
```yaml
#@data/values-schema
---
test:
  #@schema/type any=True
  optional_config:
    param1: a
    param2: b

@overlay/match by=overlay.all


conf:

@overlay/match missing_ok=True

param3: c
prembhaskal commented 8 months ago

you can even overlay data values instead of overlaying final results using below variant of val.yml

@overlay/match by=overlay.all


test: optional_config:

@overlay/match missing_ok=True

param3: c
prembhaskal commented 8 months ago

Also feel free to use / explore carvel channel on kubernetes slack. A question similar to yours is here - https://kubernetes.slack.com/archives/CH8KCCKA5/p1675159628085549

LittleWat commented 6 months ago

@prembhaskal Hi, thank you for your quick replies!

I see! #@overlay function can be used here. However, in our use-case, we want to let our customers configure just #@data/values file to abstract(simplify) the k8s configuration. It would be necessary to let our customers understand the logic behind it when using the #@overlay function, which is not so ideal. But it might be necessary. Thanks anyway!!

prembhaskal commented 6 months ago

hmm understood, so you want to hide the complexity of overlay from end user, but still allow them to pass in the extra configurations. I think we can do that by making overlay to read from another data values file. something like below (a pseudo code btw)

#@ load("@ytt:overlay", "overlay")
#@load("@ytt:data", "data")
#@data/values

#@overlay/match by=overlay.all
---
test:
  optional_config:
  #@overlay/match missing_ok=True
    #@ data.other_optional_config

I can give it a try later today.