--- slug: hello-holos title: Hello Holos description: Configure a simple Hello World service with Holos. sidebar_position: 30 --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import RenderingOverview from '@site/src/diagrams/rendering-overview.mdx'; import PlatformSequence from '@site/src/diagrams/render-platform-sequence.mdx'; import ComponentSequence from '@site/src/diagrams/render-component-sequence.mdx'; # Hello Holos ## Overview Like a traditional "Hello World" program, we'll start by configuring the [podinfo Helm chart][podinfo] to output a greeting from a Kubernetes Service. This introduces the core concept of wrapping Helm charts as Holos Components. ## Implementation ### Initialize Platform Structure Create and initialize a minimal platform: ```shell mkdir holos-tutorial && cd holos-tutorial holos init platform v1alpha5 ``` The resulting directory structure: ```text showLineNumbers holos-tutorial/ ├── components/ │   └── podinfo/ │   └── podinfo.cue ├── cue.mod/ ├── platform/ │   ├── platform.gen.cue │   └── podinfo.cue ├── resources.cue ├── schema.cue └── tags.cue ```
```text showLineNumbers holos-tutorial/ ├── components/ │   └── podinfo/ │   └── podinfo.cue ├── cue.mod/ ├── platform/ │   ├── platform.gen.cue │   └── podinfo.cue ├── resources.cue ├── schema.cue └── tags.cue ```
- **Line 1** The platform root is the `holos-tutorial` directory we created. - **Line 2** This tutorial places components in `components/`. They may reside anywhere. - **Line 3** A component is a collection of `*.cue` files at a path. - **Line 4** We'll create this file and configure the podinfo helm chart in the next section. - **Line 5** The CUE module directory. Schema definitions for Kubernetes and Holos resources reside within the `cue.mod` directory. - **Line 6** The platform directory is the **main entrypoint** for the `holos render platform` command. - **Line 7** `platform.gen.cue` is initialized by `holos init platform` and contains the Platform spec. - **Line 8** `podinfo.cue` integrates podinfo with the platform by adding the component to the platform spec. We'll add ths file after the next section. - **Line 9** `resources.cue` Defines the Kubernetes resources available to manage in CUE. - **Line 10** `schema.cue` Defines the configuration common to all component kinds. - **Line 11** `tags.cue` Defines where component parameter values are injected into the overall platform configuration. We don't need to be concerned with this file until we cover component parameters. - **Lines 9-11** Initialized by `holos init platform`, user editable after initialization.
### Create the Component Configure the `podinfo` component: ```bash mkdir -p components/podinfo ``` ```bash cat < components/podinfo/podinfo.cue ``` ```cue showLineNumbers package holos // Produce a helm chart build plan. holos: HelmChart.BuildPlan HelmChart: #Helm & { Name: "podinfo" Chart: { version: "6.6.2" repository: { name: "podinfo" url: "https://stefanprodan.github.io/podinfo" } } // Holos marshals Values into values.yaml for Helm. Values: { // message is a string with a default value. @tag indicates a value may // be injected from the platform spec component parameters. ui: { message: string | *"Hello World" @tag(greeting, type=string) } } } ``` ```bash EOF ``` :::important Like Go packages, CUE loads all `*.cue` files in the component directory to define the component. ::: :::note CUE recursively loads `*.cue` files from the component directory up to the platform root. For example, `#Helm` referenced on line 6 is defined in root-level `schema.cue`. ::: ### Add to Platform Register the `podinfo` component in `platform/podinfo.cue`: ```bash cat < platform/podinfo.cue ``` ```cue showLineNumbers package holos Platform: Components: podinfo: { name: "podinfo" path: "components/podinfo" // Inject a value into the component. parameters: greeting: "Hello Holos!" } ``` ```bash EOF ``` :::tip Parameter names are unrestricted, except for the reserved `holos_` prefix. ::: ## Generate Manifests Render the `podinfo` configuration: ```bash holos render platform ``` ``` cached podinfo 6.6.2 rendered podinfo in 1.938665041s rendered platform in 1.938759417s ``` Holos executes `helm template` with locally cached charts to generate: ```txt deploy/components/podinfo/podinfo.gen.yaml ``` ```yaml showLineNumbers apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: podinfo app.kubernetes.io/version: 6.6.2 helm.sh/chart: podinfo-6.6.2 name: podinfo spec: ports: - name: http port: 9898 protocol: TCP targetPort: http - name: grpc port: 9999 protocol: TCP targetPort: grpc selector: app.kubernetes.io/name: podinfo type: ClusterIP ``` ```yaml showLineNumbers apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: podinfo app.kubernetes.io/version: 6.6.2 helm.sh/chart: podinfo-6.6.2 name: podinfo spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: podinfo strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: prometheus.io/port: "9898" prometheus.io/scrape: "true" labels: app.kubernetes.io/name: podinfo spec: containers: - command: - ./podinfo - --port=9898 - --cert-path=/data/cert - --port-metrics=9797 - --grpc-port=9999 - --grpc-service-name=podinfo - --level=info - --random-delay=false - --random-error=false env: - name: PODINFO_UI_MESSAGE value: Hello Holos! - name: PODINFO_UI_COLOR value: '#34577c' image: ghcr.io/stefanprodan/podinfo:6.6.2 imagePullPolicy: IfNotPresent livenessProbe: exec: command: - podcli - check - http - localhost:9898/healthz failureThreshold: 3 initialDelaySeconds: 1 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 name: podinfo ports: - containerPort: 9898 name: http protocol: TCP - containerPort: 9797 name: http-metrics protocol: TCP - containerPort: 9999 name: grpc protocol: TCP readinessProbe: exec: command: - podcli - check - http - localhost:9898/readyz failureThreshold: 3 initialDelaySeconds: 1 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 resources: limits: null requests: cpu: 1m memory: 16Mi volumeMounts: - mountPath: /data name: data terminationGracePeriodSeconds: 30 volumes: - emptyDir: {} name: data ``` Holos renders the component with the greeting injected from the platform spec. ```shell grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml ``` ```yaml env: - name: PODINFO_UI_MESSAGE value: Hello Holos! ``` ## Breaking it down We run `holos render platform` because the CUE files in the platform directory export a [Platform] resource to `holos`. :::important The `platform/` directory is the default entry point to the platform rendering process. Override with `--platform `. ::: Components are the building blocks of a Platform. The `platform/podinfo.cue` file integrates the `podinfo` component with the Platform. Holos requires two fields to integrate a component with the platform: 1. A unique name for the component. 2. The component path to the directory containing the CUE files that export a `BuildPlan` defining the component. Component parameters are optional and allow re-use of the same component. Take a look at the other tabs for more detailed sequence diagrams. ## Next Steps We've shown how to integrate one Helm chart into the Platform, but we haven't yet covered multiple Helm charts. Continue with the next tutorial to learn how Holos makes it easy to inject values into multiple components safely and efficiently. [podinfo]: https://github.com/stefanprodan/podinfo [CUE Module]: https://cuelang.org/docs/reference/modules/ [CUE Tags]: https://cuelang.org/docs/howto/inject-value-into-evaluation-using-tag-attribute/ [Platform]: ../api/author.md#Platform