Skip to main content
Version: v1alpha5

CUE

Overview

This tutorial demonstrates mixing additional resources into a component using CUE. Holos components frequently mix in resources so we don't need to modify existing charts or manifests. We'll add an ExternalSecret resource to the podinfo Helm chart we configured in the Hello Holos tutorial.

Key concepts:

  1. Resources are validated against #Resources defined at the root.
  2. Custom Resource Definitions need to be imported with timoni.
  3. Helm, Kustomize, and CUE can be mixed in together in the same component.

The Code

Generating the structure

Use holos to generate a minimal platform directory structure. First, create and cd into a blank directory. Then use the holos generate platform command to generate a minimal platform.

mkdir holos-cue-tutorial && cd holos-cue-tutorial
holos init platform v1alpha5

Creating the component

Create the directory for the podinfo component. Create an empty file and then add the following CUE configuration to it.

mkdir -p components/podinfo
touch components/podinfo/podinfo.cue
package holos

// export the component build plan to holos
holos: Component.BuildPlan

// Component is a Helm chart
Component: #Helm & {
Name: "podinfo"
Namespace: "default"
// Add metadata.namespace to all resources with kustomize.
KustomizeConfig: Kustomization: namespace: Namespace
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
}

Integrate the component with the platform.

touch platform/podinfo.cue
package holos

Platform: Components: podinfo: {
name: "podinfo"
path: "components/podinfo"
}

Render the platform.

holos render platform ./platform

Add and commit the initial configuration.

git init . && git add . && git commit -m initial

Mixing in Resources

We use the ComponentConfig Resources field to mix in resources to any component kind. This field is a convenient wrapper around the core [BuildPlan] Resources Generator.

Create the mixins.cue file.

touch components/podinfo/mixins.cue
package holos

// Component fields are unified with podinfo.cue
Component: {
// Concrete values are defined in podinfo.cue
Name: string
Namespace: string

// Resources represents mix-in resources organized as a struct.
Resources: ExternalSecret: (Name): {
// Name is consistent with the component name.
metadata: name: Name
// Namespace is consistent with the component namespace.
metadata: namespace: Namespace
spec: {
// Ensure the target secret name is consistent.
target: name: metadata.name
// Ensure the name in the SecretStore is consistent.
dataFrom: [{extract: {key: metadata.name}}]
refreshInterval: "30s"
secretStoreRef: kind: "SecretStore"
secretStoreRef: name: "default"
}
}
}
important

Holos uses CUE to validate mixed in resources against a schema. The Resources field validates against the #Resources definition in resources.cue.

Importing CRDs

Holos includes CUE schema definitions of the ExternalSecret custom resource definition (CRD). These schemas are located in the cue.mod directory, written by the holos init platform command we executed at the start of this tutorial.

Import your own custom resource definitions using timoni. We imported the ExternalSecret CRDs embedded into holos with the following command.

timoni mod vendor crds -f https://raw.githubusercontent.com/external-secrets/external-secrets/v0.10.5/deploy/crds/bundle.yaml
tip

Take a look at cue.mod/gen/external-secrets.io/externalsecret/v1beta1/types_gen.cue to see the imported definitions.

Once imported, the last step is to add the resource kind to the #Resources struct. This is most often accomplished by adding a new file which cue unifies with the existing resources.cue file.

Reviewing Changes

Render the platform with the ExternalSecret mixed into the podinfo component.

holos render platform ./platform

Take a look at the diff to see the mixed in ExternalSecret.

git diff deploy
diff --git a/deploy/components/podinfo/podinfo.gen.yaml b/deploy/components/podinfo/podinfo.gen.yaml
index 6e4aec0..f79e9d0 100644
--- a/deploy/components/podinfo/podinfo.gen.yaml
+++ b/deploy/components/podinfo/podinfo.gen.yaml
@@ -112,3 +112,19 @@ spec:
volumes:
- emptyDir: {}
name: data
+---
+apiVersion: external-secrets.io/v1beta1
+kind: ExternalSecret
+metadata:
+ name: podinfo
+ namespace: default
+spec:
+ dataFrom:
+ - extract:
+ key: podinfo
+ refreshInterval: 30s
+ secretStoreRef:
+ kind: SecretStore
+ name: default
+ target:
+ name: podinfo

We saw how to mix in resources using the Resources field of the ComponentConfig. This technique approach works for every kind of component in Holos. We did this without needing to fork the upstream Helm chart so we can easily update to new podinfo versions as they're released.

Trying Locally

Optionally apply the manifests Holos rendered to a Local Cluster.

Next Steps

This tutorial uses the #Resources structure to map resource kinds to their schema definitions in CUE. This structure is defined in resources.cue at the root of the tree. Take a look at resources.cue to see this mapping structure.

Continue to the next tutorial to learn how to define your own data structures similar to this #Resources structure.