stefanprodan / timoni

Timoni is a package manager for Kubernetes, powered by CUE and inspired by Helm.
https://timoni.sh
Apache License 2.0
1.51k stars 67 forks source link

List or object values override fail #297

Closed b4nst closed 8 months ago

b4nst commented 8 months ago

When using a list or object disjunction (I'm pretty sure we can find other examples), the value defined in values.cue cannot be overridden . On top of that, the error message is not really explicit (despite what it says πŸ˜…), which can be confusing for people new to CUE.

Here's a simple and concrete case to understand the issue

timoni mod init my-app --blueprint oci://ghcr.io/stefanprodan/timoni/blueprints/starter

Next add a fail: [...string] property in the #Config definition (my-app/templates/config.cue), as long as this in values.cue

// Code generated by timoni.
// Note that this file must have no imports and all values must be concrete.

@if(!debug)

package main

// Placeholder for user-supplied values.
values: {
    fail: ["single"]
}

Now let's say you wanna use a user supplied value which contains:

fail: ["first", "second", "third"]

Any timoni command (lint, apply) using that value will fail at build stage with:

explicit error (_|_ literal) in source:
    ./values.cue:2:9

I was also able to reproduce the same behaviour with a disjunction of different object definition. I did not investigated the source yet but my first guess is that it comes from CUE directly (those kind of override are not permitted by CUE). However this is confusing since we can already do stuff not allowed by CUE (changing a string concrete value for example).

Btw this reminded me of #252 and what @fionera mentioned there: totally dropping the usage of this values.cue file and directly using CUE default marker to use default values in the #Config definition. I find this default values.cue behaviour quite confusing tbh. You would only have to provide custom values when needed (bundle, apply, etc...).

stefanprodan commented 8 months ago

The role of values.cue in the module root is to allow Helm-like behaviour (overlay/merge instead of unification/immutability). If you don't care about this behaviour, leave the values.cue empty and use the #Config definition to provide defaults. I already moved all things from value.cue into config in the blueprint. I plan to decommission the old init module and change the docs to make it explicit that CUE defaults should go into the #Config definition.

b4nst commented 8 months ago

Perfect, I think that's a pretty good way for new user to slowly adopt CUE patterns. Thanks for your answer!