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

CUE templating advice #253

Open
artemlive opened this issue Nov 24, 2023 · 4 comments
Open

CUE templating advice #253

artemlive opened this issue Nov 24, 2023 · 4 comments

Comments

@artemlive
Copy link

artemlive commented Nov 24, 2023

Hello!
First of all, thanks for such a great tool. I'm enjoying playing around with Timoni.
I'm trying to learn how to work with CUE, and I want to ask for advice. I want to create an abstract package that can create various configmaps/services/deployments, etc.
In my experiments, I have values like this:

values: {
	configMaps: "first": {
		annotations: {
			"test":  "testsstestsssssstestssssssssss"
			"test2": "test2"
		}
		name: "first"
		data: {"1": ""}
	}
	configMaps: "second": {
		annotations: {
			"foo": "bar"
		}
		name: "second"
		data: {
			"1": "2"
			"2": """
                               test
                               test2
                               """
		}
	}
}

And then in the instance:

#CMConfig: {
	// Metadata (common to all resources)
	annotations?: {[string & =~"^(([A-Za-z0-9][-A-Za-z0-9_./]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)]: string}
	name!: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)
	data!: {[string]: string}
}

// Instance takes the config values and outputs the Kubernetes objects.
#Instance: {
	config: #Config
	objects: {
		for c,v in config.configMaps {
				"cm-\(c)":  #ConfigMap & {
						_config: config
						_cm_config: #CMConfig & {
							annotations: v.annotations
							name: v.name
							data: v.data
						}
				}
		}

And it works as I expected:

---
apiVersion: v1
data:
  "1": ""
immutable: true
kind: ConfigMap
metadata:
  annotations:
    test: testsstestsssssstestssssssssss
    test2: test2
  labels:
    app.kubernetes.io/name: backend
    app.kubernetes.io/version: 0.0.0-devel
  name: first
  namespace: default
---
apiVersion: v1
data:
  "1": "2"
  "2": |-
    test
    test2
immutable: true
kind: ConfigMap
metadata:
  annotations:
    foo: bar
  labels:
    app.kubernetes.io/name: backend
    app.kubernetes.io/version: 0.0.0-devel
  name: second
  namespace: default

But I'm curious: am I using the right approach? There are only a few examples of how to work with Timoni, and they are straightforward when values are passed to the statically defined objects. So I wonder whether I'm doing something wrong or it looks fine. :)
In perspective, I want to migrate all our helm charts to Timoni.
Thanks for any advice.

@stefanprodan
Copy link
Owner

stefanprodan commented Nov 24, 2023

Looking at the output I guess your #ConfigMap does uses the corev1 schema and the Timoni #Metadata. One thing I would change is not repeat the name, but use the map key for it.

		for c,v in config.configMaps {
				"cm-\(c)":  #ConfigMap & {
						_config: config
						_cm_config: #CMConfig & {
							annotations: v.annotations
							name: c
							data: v.data
						}
				}
		}

I would also set max length for the data keys in data!: {[string]: string}, and maybe a regex if these keys end up as files inside pods, or env vars.

@artemlive
Copy link
Author

Thanks for the suggestions. I'll make the changes while playing with the syntax. So, is the approach itself idiomatically correct?
It's a little bit difficult to switch from the helm go templates syntax to the complexity of cuelang :)

@stefanprodan
Copy link
Owner

It's definitely more complex than Go text templating, it took me a week or two to get used to it. The most tricky part, coming from Helm and Kustomize, was getting used to CUE's immutability as it requires a diffrent way of thinking about cfg management. For example, once you set a field to a concrete value e.g. replicas: 1, you can no longer change it. At first, I've seen this as major blocker, but later on I realise this is actually a sane way to deal with configs. It forces you to define inputs with a strict schema and defaults. You no longer have to dig into layers of mutations to figure out why some field ended up with a particular value.

@artemlive
Copy link
Author

Thanks for your reply.
It inspires me to gain a more profound knowledge of Timoni and CUE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants