mirror of
https://github.com/holos-run/holos.git
synced 2026-03-20 09:15:02 +00:00
Version doesn't make as much sense since we're doing a hello world tutorial. Also consolidate the values information into one step, and consolidate the breaking it down section to make it shorter and clearer.
391 lines
10 KiB
Plaintext
391 lines
10 KiB
Plaintext
---
|
|
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
|
|
|
|
One of the first exercises we do when learning a new programming language is
|
|
printing out a "Hello World!" greeting. Hello Holos configures the [podinfo Helm
|
|
chart][podinfo] producing a similar greeting from a Kubernetes Service.
|
|
|
|
By the end of this tutorial you have an understanding of how to wrap a Helm
|
|
Chart as a Holos Component.
|
|
|
|
## The Code
|
|
|
|
### Generating the structure
|
|
|
|
Use `holos` to generate a minimal platform directory structure. Start by
|
|
creating a blank directory to hold the platform configuration.
|
|
|
|
```shell
|
|
mkdir holos-tutorial && cd holos-tutorial
|
|
```
|
|
|
|
Use the `holos init platform` command to initialize a minimal platform in the
|
|
blank directory.
|
|
|
|
```shell
|
|
holos init platform v1alpha5
|
|
```
|
|
|
|
Here's the filesystem tree we'll build in this tutorial.
|
|
|
|
<Tabs groupId="80D04C6A-BC83-44D0-95CC-CE01B439B159">
|
|
<TabItem value="tree" label="Tree">
|
|
```text showLineNumbers
|
|
holos-tutorial/
|
|
├── components/
|
|
│ └── podinfo/
|
|
│ └── podinfo.cue
|
|
├── cue.mod/
|
|
├── platform/
|
|
│ ├── platform.gen.cue
|
|
│ └── podinfo.cue
|
|
├── resources.cue
|
|
├── schema.cue
|
|
└── tags.cue
|
|
```
|
|
</TabItem>
|
|
<TabItem value="details" label="Details">
|
|
<div style={{display: "flex"}}>
|
|
<div>
|
|
```text showLineNumbers
|
|
holos-tutorial/
|
|
├── components/
|
|
│ └── podinfo/
|
|
│ └── podinfo.cue
|
|
├── cue.mod/
|
|
├── platform/
|
|
│ ├── platform.gen.cue
|
|
│ └── podinfo.cue
|
|
├── resources.cue
|
|
├── schema.cue
|
|
└── tags.cue
|
|
```
|
|
</div>
|
|
<div>
|
|
- **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.
|
|
</div>
|
|
</div>
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
### Creating a component
|
|
|
|
Start by creating a directory for the `podinfo` component. Create an empty file
|
|
and then add the following CUE configuration to it.
|
|
|
|
<Tabs groupId="tutorial-hello-podinfo-helm-cue-code">
|
|
<TabItem value="components/podinfo/podinfo.cue" label="Podinfo Helm Chart">
|
|
```bash
|
|
mkdir -p components/podinfo
|
|
touch 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)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::important
|
|
CUE loads all of `*.cue` files in the component directory to define component,
|
|
similar to Go packages.
|
|
:::
|
|
|
|
:::note
|
|
CUE _also_ loads all `*.cue` files from the component leaf directory to the
|
|
platform root directory. In this example, `#Helm` on line 6 is defined in
|
|
`schema.cue` at the root.
|
|
:::
|
|
|
|
### Integrating the component
|
|
|
|
Integrate the `podinfo` component into the platform by creating a new cue file
|
|
in the `platform` directory with the following content.
|
|
|
|
<Tabs groupId="tutorial-hello-register-podinfo-component">
|
|
<TabItem value="platform/podinfo.cue" label="Register Podinfo">
|
|
```bash
|
|
touch 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!"
|
|
}
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::tip
|
|
Component parameters may have any name as long as they don't start with
|
|
`holos_`.
|
|
:::
|
|
|
|
## Rendering manifests
|
|
|
|
Render a manifest for `podinfo` using the `holos render platform ./platform`
|
|
command. The `platform/` directory is the main entrypoint for this command.
|
|
|
|
<Tabs groupId="E150C802-7162-4FBF-82A7-77D9ADAEE847">
|
|
<TabItem value="command" label="Command">
|
|
```bash
|
|
holos render platform ./platform
|
|
```
|
|
</TabItem>
|
|
<TabItem value="output" label="Output">
|
|
```
|
|
cached podinfo 6.6.2
|
|
rendered podinfo in 1.938665041s
|
|
rendered platform in 1.938759417s
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::important
|
|
Holos rendered the following manifest file by executing `helm template` after
|
|
caching `podinfo` locally.
|
|
:::
|
|
|
|
```txt
|
|
deploy/components/podinfo/podinfo.gen.yaml
|
|
```
|
|
|
|
<Tabs groupId="0E9C231D-D0E8-410A-A4A0-601842A086A6">
|
|
<TabItem value="service" label="Service">
|
|
```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
|
|
```
|
|
</TabItem>
|
|
<TabItem value="deployment" label="Deployment">
|
|
```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
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
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 ./platform` because the cue files in the platform
|
|
directory export a [Platform] resource to `holos`. The platform directory is
|
|
the entrypoint to the platform rendering process.
|
|
|
|
Components are the building blocks for 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 exporting a
|
|
`BuildPlan` defining the component.
|
|
|
|
Component parameters are optional. They allow re-use of the same component.
|
|
Refer to the [Component Parameters] topic for more information.
|
|
|
|
<Tabs groupId="67C1EE71-3EA8-4568-9F6D-0072BA09FF12">
|
|
<TabItem value="overview" label="Rendering Overview">
|
|
Take a look at the other tabs for more detailed sequence diagrams.
|
|
<RenderingOverview />
|
|
</TabItem>
|
|
<TabItem value="platform" label="Platform Sequence">
|
|
<PlatformSequence />
|
|
</TabItem>
|
|
<TabItem value="component" label="Component Sequence">
|
|
<ComponentSequence />
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
## Next Steps
|
|
|
|
We've shown how to integrate one Helm chart to the Platform, but we haven't yet
|
|
covered multiple Helm charts. Continue on with the next tutorial to learn how
|
|
Holos makes it easy to inject values into multiple components safely and easily.
|
|
|
|
[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
|
|
[Component Parameters]: ../topics/component-parameters.mdx
|