cue icon indicating copy to clipboard operation
cue copied to clipboard

cmd/cue: add environment to tag variables

Open myitcv opened this issue 9 months ago • 4 comments

What version of CUE are you using (cue version)?

$ cue version
cue version v0.13.0-0.dev.0.20250310212608-931fecbeb96f

go version go1.24.0
      -buildmode exe
       -compiler gc
  DefaultGODEBUG gotestjsonbuildtext=1,multipathtcp=0,randseednop=0,rsa1024min=0,tlsmlkem=0,x509rsacrt=0,x509usepolicies=0
     CGO_ENABLED 1
          GOARCH arm64
            GOOS linux
         GOARM64 v8.0
             vcs git
    vcs.revision 931fecbeb96facac2299e450a79ac1813acfce24
        vcs.time 2025-03-10T21:26:08Z
    vcs.modified false
cue.lang.version v0.13.0

Does this issue reproduce with the latest release?

Yes

What did you do?

Looked at https://cuelang.org/docs/reference/command/cue-help-injection/ for details on how to pass in the current environment (i.e. the set of k=v environment variables for the process in which CUE is evaluating)

What did you expect to see?

Something telling me how to do this.

What did you see instead?

No mention of environment variables. Whilst on https://cuelang.org/docs/reference/command/cue-help-injection/ we can link to an as-yet-not-created page about using -t with individual environment variables, it seems to make sense to me to offer a tag variable for the entire [string]: string environment.

So whilst we could improve the documentation around the -t method of passing in individual values, it seems like it would be a quick and easy win to pass the entire environment as a {[string]: string} as an tag variable. So something like:

v: {[string]: string} @tag(v, var=env)

Such that indexing v would then yield a value for that key/variable.

myitcv avatar Mar 12 '25 09:03 myitcv

Adding comments from a discussion with @rogpeppe - -T is currently fairly benign in terms of the values injected. There is nothing "sensitive" per se.

Environment variables can contain sensitive data, so adding env, say, to the suite of variables enabled by -T, would change the calculus somewhat.

So we need to be clear that the blunt tool that is -T is the "right" balance between convenience and safety.

myitcv avatar Mar 12 '25 11:03 myitcv

Auto-Binding From Environment Variables

What would be wonderful is to go even further by adding an automatic binding between environment variables and CUE fields. In a similar way as Spring Boot does for instance.

If I take this example:

municipality: {
	name:   string
	pop:     int
	capital: bool
}

And I have the following environment variables defined:

MUNICIPALITY_NAME='Kinshasa'
MUNICIPALITY_POP='16.32M'
MUNICIPALITY_CAPITAL=true

Then it would be wonderful to have the following working:

$ cue eval municipality.cue --env
municipality: {
	name:   "Kinshasa"
	pop:     16.32M
	capital: true
}

This is very useful when defining default values and providing a way to override only a subset. Typically when having something like:

municipality: {
	name:   *"Default Municipality" | string
	pop:     *10M | int
	capital: *true | bool
}

Note: the default values in this specific example are very weird, but you get the idea.

Imagine how useful this can be in situations where you may expose hundreds environment variables to users as a configuration interface, with only few of them being overridden in most scenarios.

Handling Sensitive Data In Environment Variables

Environment variables can contain sensitive data

An idea to mitigate this issue is to provide a way to define a prefix for environment variables to be injected.

So if I have that:

CONFIDENTIAL='my-secret-here'
MUNICIPALITY_NAME='Kinshasa'
MUNICIPALITY_POP='16.32M'
MUNICIPALITY_CAPITAL=true

And do that:

$ cue eval municipality.cue --env 'MUNICIPALITY_'

Then the CONFIDENTIAL environment variable will get filtered out since only the ones starting with MUNICIPALITY_ will get injected in the CUE evaluation context.

Flexible Environment Variable Injection

In the cases where the mappings are irrelevant or not enough, then the @myitcv's idea sounds very good and flexible.

Djaytan avatar May 17 '25 11:05 Djaytan

That's an interesting observation, @Djaytan. Please correct me if I'm wrong, but I think what you're proposing could be built on top of my idea?

However, what you're proposing is a more opinionated --env flag that does that lifting for you, automatically?

myitcv avatar May 20 '25 15:05 myitcv

Thank you @myitcv for your feedback!

You're right! Stated differently, I think the highest priority on this topic is to support your idea (i.e., having a way to inject environment variables in CUE through v: {[string]: string} @tag(v, var=env)). That's already a great step forward :) I love your idea because it is generic and flexible thanks to the loose coupling with environment variables.

At least, documenting a way to inject environment variables would be a good starting point.

For instance, here is how I managed to inject the environment variables in the context of my project. This required me to define tags having identifiers matching the environment variables naming convention (upper cases, underscores, etc​). Not that idiomatic to tags naming in CUE in fact, and this implies a quite strong opinion about environment variables usage on top of that 😕. And indeed, such approach caused me some troubles that I had to overcome. By relying instead on your idea, then I would not have faced such issue for instance.

However, what you're proposing is a more opinionated --env flag that does that lifting for you, automatically?

Actually, I already provided a quite comprehensive documentation on the available configuration options of my OCI image (link). This should provide you a great idea about what I'm trying to do concretely speaking. The challenge of the task is to inject environment variable values in predefined YAML files. This implies the need to manually maintain the mapping. It is error prone and time consuming in fact, especially when dealing with hundreds or even thousands of properties.

Hence the fact an automatic binding to environment variables in a similar way as Spring Boot does would be wonderful in my case. Furthermore, since I would expect such thing to be (or become?) a standard usage of CUE lang in containers, then I think having a great support of environment variables would make CUE lang an ideal solution for these use cases.

All of that being said, I saw that complex mappings will be harder to implement (e.g., lists and dynamic objects).

Djaytan avatar May 20 '25 16:05 Djaytan