mirror of
https://github.com/holos-run/holos.git
synced 2026-03-20 09:15:02 +00:00
278 lines
8.0 KiB
Plaintext
278 lines
8.0 KiB
Plaintext
---
|
|
slug: cue
|
|
title: CUE
|
|
description: Render component manifests directly from CUE.
|
|
sidebar_position: 50
|
|
---
|
|
|
|
import Tabs from '@theme/Tabs';
|
|
import TabItem from '@theme/TabItem';
|
|
|
|
# CUE
|
|
|
|
## Overview
|
|
|
|
This tutorial demonstrates how to add additional resources to a component using
|
|
CUE. Holos components often mix in resources, eliminating the need to modify
|
|
existing charts or manifests. In this tutorial, we'll add an [ExternalSecret]
|
|
resource to the podinfo Helm chart 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 using Timoni.
|
|
3. Helm, Kustomize, and CUE can be mixed together within the same component.
|
|
|
|
## The Code
|
|
|
|
### Generating the Structure
|
|
|
|
Use `holos` to generate a minimal platform directory structure. First, create
|
|
and navigate into a blank directory. Then, use the `holos generate platform`
|
|
command to generate a minimal platform.
|
|
|
|
```shell
|
|
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, then add
|
|
the following CUE configuration to it.
|
|
|
|
```bash
|
|
mkdir -p components/podinfo
|
|
```
|
|
```bash
|
|
cat <<EOF > components/podinfo/podinfo.cue
|
|
```
|
|
```cue showLineNumbers
|
|
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"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
```bash
|
|
EOF
|
|
```
|
|
|
|
Register the component with the platform.
|
|
|
|
```bash
|
|
cat <<EOF > platform/podinfo.cue
|
|
```
|
|
```cue showLineNumbers
|
|
package holos
|
|
|
|
Platform: Components: podinfo: {
|
|
name: "podinfo"
|
|
path: "components/podinfo"
|
|
}
|
|
```
|
|
```bash
|
|
EOF
|
|
```
|
|
|
|
Render the platform.
|
|
|
|
<Tabs groupId="tutorial-hello-render-manifests">
|
|
<TabItem value="command" label="Command">
|
|
```bash
|
|
holos render platform
|
|
```
|
|
</TabItem>
|
|
<TabItem value="output" label="Output">
|
|
```
|
|
cached podinfo 6.6.2
|
|
rendered podinfo in 1.938665041s
|
|
rendered platform in 1.938759417s
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
Add and commit the initial configuration.
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
cat <<EOF > components/podinfo/mixins.cue
|
|
```
|
|
```cue showLineNumbers
|
|
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"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
```bash
|
|
EOF
|
|
```
|
|
|
|
:::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 for the ExternalSecret Custom Resource
|
|
Definition (CRD). These schemas are located in the `cue.mod` directory,
|
|
generated by the `holos init platform` command executed at the start of this
|
|
tutorial.
|
|
|
|
To import your own custom resource definitions, use [Timoni]. We imported the
|
|
ExternalSecret CRDs embedded in `holos` using the following command.
|
|
|
|
<Tabs groupId="35B1A1A1-D7DF-4D27-A575-28556E182096">
|
|
<TabItem value="command" label="Command">
|
|
```bash
|
|
timoni mod vendor crds -f https://raw.githubusercontent.com/external-secrets/external-secrets/v0.10.5/deploy/crds/bundle.yaml
|
|
```
|
|
</TabItem>
|
|
<TabItem value="output" label="Output">
|
|
```txt
|
|
2:22PM INF schemas vendored: external-secrets.io/clusterexternalsecret/v1beta1
|
|
2:22PM INF schemas vendored: external-secrets.io/clustersecretstore/v1alpha1
|
|
2:22PM INF schemas vendored: external-secrets.io/clustersecretstore/v1beta1
|
|
2:22PM INF schemas vendored: external-secrets.io/externalsecret/v1alpha1
|
|
2:22PM INF schemas vendored: external-secrets.io/externalsecret/v1beta1
|
|
2:22PM INF schemas vendored: external-secrets.io/pushsecret/v1alpha1
|
|
2:22PM INF schemas vendored: external-secrets.io/secretstore/v1alpha1
|
|
2:22PM INF schemas vendored: external-secrets.io/secretstore/v1beta1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/acraccesstoken/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/ecrauthorizationtoken/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/fake/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/gcraccesstoken/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/githubaccesstoken/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/password/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/uuid/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/vaultdynamicsecret/v1alpha1
|
|
2:22PM INF schemas vendored: generators.external-secrets.io/webhook/v1alpha1
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::tip
|
|
Take a look at
|
|
[cue.mod/gen/external-secrets.io/externalsecret/v1beta1/types_gen.cue] to see
|
|
the imported definitions.
|
|
:::
|
|
|
|
Once imported, the final step is to add the resource kind to the `#Resources`
|
|
struct. Typically, this is done by creating a new file that CUE unifies with the
|
|
existing [resources.cue] file.
|
|
|
|
## Reviewing Changes
|
|
|
|
Render the platform with the `ExternalSecret` mixed into the podinfo component.
|
|
|
|
```shell
|
|
holos render platform
|
|
```
|
|
|
|
Take a look at the diff to see the mixed in `ExternalSecret`.
|
|
|
|
```shell
|
|
git diff deploy
|
|
```
|
|
|
|
```diff
|
|
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 approach works for every kind of component in Holos,
|
|
allowing seamless integration without needing to fork the upstream Helm chart.
|
|
This way, we can easily update to new podinfo versions as they're released.
|
|
|
|
## Trying Locally
|
|
|
|
Optionally, apply the manifests rendered by Holos to a [Local Cluster] for
|
|
testing.
|
|
|
|
## 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.
|
|
|
|
[Local Cluster]: ../topics/local-cluster.mdx
|
|
[ExternalSecret]: https://external-secrets.io/latest/api/externalsecret/
|
|
[Artifact]: ../api/core.md#Artifact
|
|
[Resources]: ../api/core.md#Resources
|
|
[Generator]: ../api/core.md#Generator
|
|
[Hello Holos]: ./hello-holos.mdx
|
|
[cue.mod/gen/external-secrets.io/externalsecret/v1beta1/types_gen.cue]: https://github.com/holos-run/holos/blob/main/internal/generate/platforms/cue.mod/gen/external-secrets.io/externalsecret/v1beta1/types_gen.cue#L13
|
|
[ComponentConfig]: ../api/author.md#ComponentConfig
|
|
[timoni]: https://timoni.sh/install/
|
|
[resources.cue]: https://github.com/holos-run/holos/blob/main/internal/generate/platforms/v1alpha5/resources.cue#L33
|