Compare commits

..

15 Commits

Author SHA1 Message Date
Gary Larizza
488f7ae985 Start Hello Holos
This is a very, very minimal framework using the Tokyo docs as a guide.
This code is going to have to change when `v1alpha5` is published, so
I'm just dropping it in here as a placeholder.

Like the Tokyo docs, I was intening to setup the code and commands at the
start, and then have a "Breaking it down" section later explaining all
the moving parts.
2024-11-05 16:27:10 -08:00
Gary Larizza
4817491aab Update groupId for uniqueness 2024-11-05 16:26:40 -08:00
Gary Larizza
30ce72a9b7 Add the Local Cluster guide 2024-11-05 14:50:16 -08:00
Gary Larizza
958f65ddcf Setup page first draft 2024-11-05 14:47:12 -08:00
Gary Larizza
a1c9111a05 Overview initial draft 2024-11-05 13:30:35 -08:00
Jeff McCune
ee30c52673 docs: generate version specific api docs (#303)
Without this patch each version of the core and author schemas are
duplicated into each docs version.  This is unnecessary and difficult to
maintain now that we have docusaurus versioned docs enabled.

This patch updates the schema generation script to check if the docs
version has been released, and if so write into a markdown file in the
versioned docs folder.  If not, the version is written into the next
version folder.

This patch also updates some, but not all, document links to the md or
mdx relative file paths.  This is necessary to generate the correct
versioned links.

A nice outcome of this change is that technical docs no longer need to
link to version specific pages.  For example, `[Core Schema]:
./api/core.md` will always refer to the correct auto generated docs
associated with the docs version.
2024-11-05 07:20:53 -08:00
Jeff McCune
117a00334f docs: restructure docs into tutorial and topics (#301)
The docs for v1alpha4 have the right information, but in the wrong
places.  The most important bits are tucked away in the Core API docs.
One of our first users entirely missed the `holos generate platform`
command mentioned in the Helm guide.

We'll fix this by organizing the docs into two distinct categories.
First, a tutorial written as a series progressively building up the
minimum knowledge to use holos effectively and gain the benefits.  Think
of it as a tour of the essential bits.

The second category are focused topics which stand alone.  They're the
things most people using holos will need to know eventually, but aren't
essential for everyone to know.  For example, Clusters and Fleets will
move from the Author API to stand alone examples of how to implement
these features if necessary.

Then there's a Glossary which serves as the place to describe our
concepts and domain specific language.

Finally there's the API documentation which should be cut down to the
specific version.  The next release version will be v1alpha5.

Attribution: We're copying the Tokio docs structure, it's concise and a
similar size and complexity to our own project.

The Go docs are also an inspiration, but the project is much larger so
not directly comparable.  The organization of https://go.dev/doc/ feels
complete at first glance, despite the size and age of the project.  The
site also makes clear who each section is for without needing to come
right out and say it. Getting started, Using and understanding Go,
Writing modules, using databases, etc...
2024-11-04 20:25:04 -08:00
Jeff McCune
1e03debfac tests: add make unity target
For https://cuelabs.dev/unity/
2024-11-04 19:08:44 -08:00
Jeff McCune
72137b2fa9 docs: upgrade docusaurus to 3.6.0
npm i @docusaurus/core@latest @docusaurus/plugin-client-redirects@latest \
  @docusaurus/preset-classic@latest @docusaurus/theme-mermaid@latest \
  @docusaurus/module-type-aliases@latest @docusaurus/tsconfig@latest \
  @docusaurus/types@latest
2024-11-04 06:47:48 -08:00
Jeff McCune
5abf967116 docs: npm run docusaurus docs:version v1alpha4 (#299)
Tag version v1alpha4 so we can start working on v1alpha5 as the next
version in main.
2024-11-04 06:43:15 -08:00
Jeff McCune
5d882f465d website: fix resources.yaml tab in helm guide (#293)
We switched from using a kustomize remote base to a local file so the
tests don't need to make a network round trip to github.  It's also
better practice to use local files for this sort of thing.

In doing so I botched the location of the file, putting it in the
platform registration section.  This patch claifies how `resources.yaml`
is linked to `httpbin.cue` through the `KustomizeConfig: Files:
"resources.yaml": _` field.
2024-11-03 10:57:52 -08:00
Jeff McCune
45bdaac833 main: cue v0.10.1 and add e2e test for helm guide (#293)
Previously there was no test coverage of the
https://holos.run/docs/guides/helm/ guide.  This patch uses Roger's
testscript package, which the CUE folks also use to add comprehensive
test coverage of each step in the guide.  Ideally we would execute these
commands directly from the guide itself, but for now we'll duplicate the
commands into the test script.  This could be enhanced by generating the
test script from the document itself in some way.

When updating the script, use the `holos txtar` command to embed entire
helm charts into the test script.  It's not super fast, but it's better
than network access and it's not terribly slow either.  A few seconds to
unpack.

---

txtar: quote files for testscript unquote

For the helm guide test script we want to include the entire helm chart
which may have files that need to be quoted.  This patch changes the
default behavior of the holos txtar command to quote files if necessary
and list them in an unquote script command in the comment of the
archive.

The purpose is for testscript authors to copy and paste the entire thing
into a test script and include the unquote command at the top.

---

This change also updates CUE to v0.10.1
2024-11-03 10:27:46 -08:00
Jeff McCune
7ae1f990ef website: update quickstart diagram to match helm
Avoid confusion, got a question about this in discord.
2024-11-03 08:53:43 -08:00
Jeff McCune
b526fd1669 testdata: clean up old v1alpha1 tests (#292)
No longer necessary now that we're on v1alpha4.  Test coverage for
v1alpha4 and the user facing guides will be added back soon for use both
in the holos repo and in Unity.
2024-11-01 15:22:13 -07:00
Jeff McCune
5e07655f35 website: fix port in helm guide
Should be 9115 not 6115.
2024-11-01 06:39:48 -07:00
201 changed files with 32051 additions and 2224 deletions

View File

@@ -34,12 +34,14 @@
"blackbox",
"buildplan",
"builtinpluginloadingoptions",
"cachedir",
"cadvisor",
"cainjector",
"CAROOT",
"certificaterequest",
"certificaterequests",
"certificatesigningrequests",
"clientset",
"clsx",
"clusterexternalsecret",
"clusterexternalsecrets",
@@ -50,8 +52,10 @@
"clustersecretstore",
"clustersecretstores",
"clusterwide",
"Cmds",
"CNCF",
"CODEOWNERS",
"configdir",
"configmap",
"configmapargs",
"connectrpc",
@@ -101,6 +105,7 @@
"ghaction",
"githubaccesstokens",
"gitops",
"GOBIN",
"godoc",
"golangci",
"gomarkdoc",
@@ -170,6 +175,7 @@
"Multicluster",
"mutatingwebhookconfiguration",
"mutatingwebhookconfigurations",
"mvdan",
"mxcl",
"myhostname",
"myRegistrKeySecretName",
@@ -187,6 +193,7 @@
"organizationconnect",
"orgid",
"otelconnect",
"outfile",
"overriden",
"Parentspanid",
"patchstrategicmerge",
@@ -238,6 +245,7 @@
"requestauthentications",
"resourcequotas",
"retryable",
"rogpeppe",
"rolebinding",
"rootfs",
"ropc",
@@ -274,6 +282,7 @@
"systemconnect",
"tablewriter",
"templatable",
"testscript",
"thanos",
"Tiltfile",
"timestamppb",
@@ -306,6 +315,7 @@
"volumeattachments",
"wasmplugin",
"wasmplugins",
"workdir",
"workloadentries",
"workloadentry",
"workloadgroup",

View File

@@ -13,7 +13,7 @@ permissions:
jobs:
test:
runs-on: gha-rs
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -35,7 +35,7 @@ jobs:
uses: azure/setup-helm@v4
- name: Set up Kubectl
uses: azure/setup-kubectl@v3
uses: azure/setup-kubectl@v4
- name: Install Tools
run: |

View File

@@ -150,6 +150,10 @@ dev-deploy: install image ## deploy to dev
website: ## Build website
./hack/build-website
.PHONY: unity
unity: ## https://cuelabs.dev/unity/
./scripts/unity
.PHONY: help
help: ## Display this help menu.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

View File

@@ -1,4 +1,4 @@
---
description: Core v1alpha2 schema for advanced use cases.
sidebar_position: 996
description: Core schema for holos to render a component BuildPlan.
sidebar_position: 100
---

View File

@@ -2,8 +2,10 @@ package main
import (
"os"
"path/filepath"
"testing"
cue "cuelang.org/go/cmd/cue/cmd"
"github.com/holos-run/holos/internal/cli"
"github.com/rogpeppe/go-internal/testscript"
)
@@ -11,11 +13,29 @@ import (
func TestMain(m *testing.M) {
os.Exit(testscript.RunMain(m, map[string]func() int{
"holos": cli.MakeMain(),
"cue": cue.Main,
}))
}
func TestGetSecrets(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata",
})
func TestGuides(t *testing.T) {
testscript.Run(t, params(filepath.Join("v1alpha4", "guides")))
}
func TestCLI(t *testing.T) {
testscript.Run(t, params("cli"))
}
func params(dir string) testscript.Params {
return testscript.Params{
Dir: filepath.Join("tests", dir),
RequireExplicitExec: true,
RequireUniqueNames: true,
Setup: func(env *testscript.Env) error {
// Just like cmd/cue/cmd.TestScript, set up separate cache and config dirs per test.
env.Setenv("CUE_CACHE_DIR", filepath.Join(env.WorkDir, "tmp/cachedir"))
configDir := filepath.Join(env.WorkDir, "tmp/configdir")
env.Setenv("CUE_CONFIG_DIR", configDir)
return nil
},
}
}

View File

@@ -1,34 +0,0 @@
# Want support for intermediary constraints
exec holos build ./foo/... --log-level debug
stdout '^bf2bc7f9-9ba0-4f9e-9bd2-9a205627eb0b$'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- foo/constraints.cue --
package holos
metadata: name: "jeff"
-- foo/bar/bar.cue --
package holos
spec: components: KubernetesObjectsList: [
#KubernetesObjects & {
apiObjectMap: foo: bar: "bf2bc7f9-9ba0-4f9e-9bd2-9a205627eb0b"
}
]
-- schema.cue --
package holos
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
#KubernetesObjects: {
apiVersion: "holos.run/v1alpha1"
kind: "KubernetesObjects"
apiObjectMap: {...}
}
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"

View File

@@ -1,20 +0,0 @@
# Want cue errors to show files and lines
! exec holos build .
stderr 'apiObjectMap.foo.bar: cannot convert incomplete value'
stderr '/component.cue:\d+:\d+$'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: KubernetesObjectsList: [{apiObjectMap: foo: bar: _baz}]
_baz: string

View File

@@ -1,61 +0,0 @@
# Want kube api objects in the apiObjects output.
exec holos build .
stdout '^kind: SecretStore$'
stdout '# Source: CUE apiObjects.SecretStore.default'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: KubernetesObjectsList: [{apiObjectMap: #APIObjects.apiObjectMap}]
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
#SecretStore: {
kind: string
metadata: name: string
}
#APIObjects: {
apiObjects: {
SecretStore: {
default: #SecretStore & { metadata: name: "default" }
}
}
}
-- schema.cue --
package holos
// #APIObjects is the output type for api objects produced by cue. A map is used to aid debugging and clarity.
import "encoding/yaml"
#APIObjects: {
// apiObjects holds each the api objects produced by cue.
apiObjects: {
[Kind=_]: {
[Name=_]: {
kind: Kind
metadata: name: Name
}
}
}
// apiObjectsContent holds the marshalled representation of apiObjects
apiObjectMap: {
for kind, v in apiObjects {
"\(kind)": {
for name, obj in v {
"\(name)": yaml.Marshal(obj)
}
}
}
}
}

View File

@@ -1,62 +0,0 @@
# Want kube api objects in the apiObjects output.
exec holos build .
stdout '^kind: SecretStore$'
stdout '# Source: CUE apiObjects.SecretStore.default'
stderr 'skipping helm: no chart name specified'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: HelmChartList: [{apiObjectMap: #APIObjects.apiObjectMap}]
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
#SecretStore: {
kind: string
metadata: name: string
}
#APIObjects: {
apiObjects: {
SecretStore: {
default: #SecretStore & { metadata: name: "default" }
}
}
}
-- schema.cue --
package holos
// #APIObjects is the output type for api objects produced by cue. A map is used to aid debugging and clarity.
import "encoding/yaml"
#APIObjects: {
// apiObjects holds each the api objects produced by cue.
apiObjects: {
[Kind=_]: {
[Name=_]: {
kind: Kind
metadata: name: Name
}
}
}
// apiObjectsContent holds the marshalled representation of apiObjects
apiObjectMap: {
for kind, v in apiObjects {
"\(kind)": {
for name, obj in v {
"\(name)": yaml.Marshal(obj)
}
}
}
}
}

View File

@@ -1,25 +0,0 @@
# Want api object kind and name in errors
! exec holos build .
stderr 'apiObjects.secretstore.default.foo: field not allowed'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
apiVersion: "holos.run/v1alpha1"
kind: "KubernetesObjects"
cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
#SecretStore: {
metadata: name: string
}
apiObjects: {
secretstore: {
default: #SecretStore & { foo: "not allowed" }
}
}

View File

@@ -1,289 +0,0 @@
# Want helm errors to show up
! exec holos build .
stderr 'Error: execution error at \(zitadel/templates/secret_zitadel-masterkey.yaml:2:4\): Either set .Values.zitadel.masterkey xor .Values.zitadel.masterkeySecretName'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- zitadel.cue --
package holos
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: HelmChartList: [_HelmChart]
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
_HelmChart: {
apiVersion: "holos.run/v1alpha1"
kind: "HelmChart"
metadata: name: "zitadel"
namespace: "zitadel"
chart: {
name: "zitadel"
version: "7.9.0"
release: name
repository: {
name: "zitadel"
url: "https://charts.zitadel.com"
}
}
}
-- vendor/zitadel/templates/secret_zitadel-masterkey.yaml --
{{- if (or (and .Values.zitadel.masterkey .Values.zitadel.masterkeySecretName) (and (not .Values.zitadel.masterkey) (not .Values.zitadel.masterkeySecretName)) ) }}
{{- fail "Either set .Values.zitadel.masterkey xor .Values.zitadel.masterkeySecretName" }}
{{- end }}
{{- if .Values.zitadel.masterkey -}}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: zitadel-masterkey
{{- with .Values.zitadel.masterkeyAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
{{- include "zitadel.labels" . | nindent 4 }}
stringData:
masterkey: {{ .Values.zitadel.masterkey }}
{{- end -}}
-- vendor/zitadel/Chart.yaml --
apiVersion: v2
appVersion: v2.46.0
description: A Helm chart for ZITADEL
icon: https://zitadel.com/zitadel-logo-dark.svg
kubeVersion: '>= 1.21.0-0'
maintainers:
- email: support@zitadel.com
name: zitadel
url: https://zitadel.com
name: zitadel
type: application
version: 7.9.0
-- vendor/zitadel/values.yaml --
# Default values for zitadel.
zitadel:
# The ZITADEL config under configmapConfig is written to a Kubernetes ConfigMap
# See all defaults here:
# https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
configmapConfig:
ExternalSecure: true
Machine:
Identification:
Hostname:
Enabled: true
Webhook:
Enabled: false
# The ZITADEL config under secretConfig is written to a Kubernetes Secret
# See all defaults here:
# https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml
secretConfig:
# Annotations set on secretConfig secret
secretConfigAnnotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# Reference the name of a secret that contains ZITADEL configuration.
configSecretName:
# The key under which the ZITADEL configuration is located in the secret.
configSecretKey: config-yaml
# ZITADEL uses the masterkey for symmetric encryption.
# You can generate it for example with tr -dc A-Za-z0-9 </dev/urandom | head -c 32
masterkey: ""
# Reference the name of the secret that contains the masterkey. The key should be named "masterkey".
# Note: Either zitadel.masterkey or zitadel.masterkeySecretName must be set
masterkeySecretName: ""
# Annotations set on masterkey secret
masterkeyAnnotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# The CA Certificate needed for establishing secure database connections
dbSslCaCrt: ""
# The Secret containing the CA certificate at key ca.crt needed for establishing secure database connections
dbSslCaCrtSecret: ""
# The db admins secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslAdminCrtSecret: ""
# The db users secret containing the client certificate and key at tls.crt and tls.key needed for establishing secure database connections
dbSslUserCrtSecret: ""
# Generate a self-signed certificate using an init container
# This will also mount the generated files to /etc/tls/ so that you can reference them in the pod.
# E.G. KeyPath: /etc/tls/tls.key CertPath: /etc/tls/tls.crt
# By default, the SAN DNS names include, localhost, the POD IP address and the POD name. You may include one more by using additionalDnsName like "my.zitadel.fqdn".
selfSignedCert:
enabled: false
additionalDnsName:
replicaCount: 3
image:
repository: ghcr.io/zitadel/zitadel
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
chownImage:
repository: alpine
pullPolicy: IfNotPresent
tag: "3.19"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
# Annotations to add to the deployment
annotations: {}
# Annotations to add to the configMap
configMap:
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "0"
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podAdditionalLabels: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
securityContext: {}
# Additional environment variables
env:
[]
# - name: ZITADEL_DATABASE_POSTGRES_HOST
# valueFrom:
# secretKeyRef:
# name: postgres-pguser-postgres
# key: host
service:
type: ClusterIP
# If service type is "ClusterIP", this can optionally be set to a fixed IP address.
clusterIP: ""
port: 8080
protocol: http2
annotations: {}
scheme: HTTP
ingress:
enabled: false
className: ""
annotations: {}
hosts:
- host: localhost
paths:
- path: /
pathType: Prefix
tls: []
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
initJob:
# Once ZITADEL is installed, the initJob can be disabled.
enabled: true
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "1"
resources: {}
backoffLimit: 5
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
# Available init commands :
# "": initialize ZITADEL instance (without skip anything)
# database: initialize only the database
# grant: set ALL grant to user
# user: initialize only the database user
# zitadel: initialize ZITADEL internals (skip "create user" and "create database")
command: ""
setupJob:
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "2"
resources: {}
activeDeadlineSeconds: 300
extraContainers: []
podAnnotations: {}
additionalArgs:
- "--init-projections=true"
machinekeyWriter:
image:
repository: bitnami/kubectl
tag: ""
resources: {}
readinessProbe:
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
livenessProbe:
enabled: true
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
startupProbe:
enabled: true
periodSeconds: 1
failureThreshold: 30
metrics:
enabled: false
serviceMonitor:
# If true, the chart creates a ServiceMonitor that is compatible with Prometheus Operator
# https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.ServiceMonitor.
# The Prometheus community Helm chart installs this operator
# https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack#kube-prometheus-stack
enabled: false
honorLabels: false
honorTimestamps: true
pdb:
enabled: false
# these values are used for the PDB and are mutally exclusive
minAvailable: 1
# maxUnavailable: 1
annotations: {}

View File

@@ -1,39 +0,0 @@
# Kustomize is a supported holos component kind
exec holos render component --cluster-name=mycluster . --log-level=debug
# Want generated output
cmp want.yaml deploy/clusters/mycluster/components/kstest/kstest.gen.yaml
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: KustomizeBuildList: [{metadata: name: "kstest"}]
-- kustomization.yaml --
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mynamespace
resources:
- serviceaccount.yaml
-- serviceaccount.yaml --
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
-- want.yaml --
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
namespace: mynamespace

View File

@@ -1,17 +0,0 @@
# https://github.com/holos-run/holos/issues/72
# Want holos to fail on unknown fields to catch typos and aid refactors
! exec holos build .
stderr 'unknown field \\"TypoKubernetesObjectsList\\"'
-- platform.config.json --
{}
-- cue.mod --
package holos
-- component.cue --
package holos
_cluster: string @tag(cluster, string)
_platform_config: string @tag(platform_config, string)
apiVersion: "holos.run/v1alpha1"
kind: "BuildPlan"
spec: components: TypoKubernetesObjectsList: []

File diff suppressed because it is too large Load Diff

View File

@@ -2291,9 +2291,10 @@ First for prometheus.
<Tabs groupId="5062EB93-F5AA-4038-9CF8-67A5ECA085FD">
<TabItem value="command" label="Command">
```bash
cue import -p holos -o- -l '_Helm: Values:' \
projects/platform/components/prometheus/vendor/25.27.0/prometheus/values.yaml \
> projects/platform/components/prometheus/values.cue
cue import --package holos \
--path '_Helm: Values:' \
--outfile projects/platform/components/prometheus/values.cue \
projects/platform/components/prometheus/vendor/25.27.0/prometheus/values.yaml
```
</TabItem>
<TabItem value="output" label="values.cue">
@@ -3647,9 +3648,10 @@ Then for blackbox.
<Tabs groupId="843D706B-5BE0-46FE-978F-EA17BC1AD932">
<TabItem value="command" label="Command">
```bash
cue import -p holos -o- -l '_Helm: Values:' \
projects/platform/components/blackbox/vendor/9.0.1/prometheus-blackbox-exporter/values.yaml \
> projects/platform/components/blackbox/values.cue
cue import --package holos \
--path '_Helm: Values:' \
--outfile projects/platform/components/blackbox/values.cue
projects/platform/components/blackbox/vendor/9.0.1/prometheus-blackbox-exporter/values.yaml
```
</TabItem>
<TabItem value="output" label="values.cue">
@@ -4310,11 +4312,10 @@ git diff
- __address__
target_label: __param_target
- - replacement: blackbox
+ - replacement: blackbox:6115
+ - replacement: blackbox:9115
target_label: __address__
- source_labels:
- __param_target
```
</TabItem>
</Tabs>
@@ -4578,9 +4579,10 @@ _Kustomize.BuildPlan
// https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/README.md
_Kustomize: #Kustomize & {
KustomizeConfig: Resources: "github.com/mccutchen/go-httpbin/kustomize": _
KustomizeConfig: Files: "resources.yaml": _
KustomizeConfig: Kustomization: {
commonLabels: "app.kubernetes.io/name": "httpbin"
images: [{name: "mccutchen/go-httpbin"}]
_patches: probe: {
target: kind: "Service"
target: name: "httpbin"
@@ -4593,6 +4595,55 @@ _Kustomize: #Kustomize & {
patches: [for x in _patches {x}]
}
}
```
</TabItem>
<TabItem value="projects/platform/components/httpbin/resources.yaml" label="resources.yaml">
Add a plain `resources.yaml` file containing resources for kustomize to process.
:::important
Holos knows this file is part of the BuildPlan from the `KustomizeConfig:
Files: "resources.yaml": _` line in the Component.
:::
```bash
mkdir -p projects/platform/components/httpbin
touch projects/platform/components/httpbin/resources.yaml
```
```yaml showLineNumbers
# https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
template:
spec:
containers:
- name: httpbin
image: mccutchen/go-httpbin
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /status/200
port: http
readinessProbe:
httpGet:
path: /status/200
port: http
resources: {}
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
appProtocol: http
```
</TabItem>
</Tabs>

View File

Before

Width:  |  Height:  |  Size: 690 KiB

After

Width:  |  Height:  |  Size: 690 KiB

View File

Before

Width:  |  Height:  |  Size: 997 KiB

After

Width:  |  Height:  |  Size: 997 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 287 KiB

After

Width:  |  Height:  |  Size: 287 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1009 KiB

After

Width:  |  Height:  |  Size: 1009 KiB

View File

Before

Width:  |  Height:  |  Size: 617 KiB

After

Width:  |  Height:  |  Size: 617 KiB

View File

Before

Width:  |  Height:  |  Size: 706 KiB

After

Width:  |  Height:  |  Size: 706 KiB

View File

Before

Width:  |  Height:  |  Size: 794 KiB

After

Width:  |  Height:  |  Size: 794 KiB

View File

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 248 KiB

View File

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -326,35 +326,34 @@ like this.
```mermaid
---
title: Figure 1 - Render Pipeline
title: Figure 1 - v1alpha4 Rendered Manifest Pipeline
---
graph LR
PS[<a href="/docs/api/author/v1alpha3/#Platform">Platform</a>]
HC[<a href="/docs/api/author/v1alpha3/#ComponentFields">Components</a>]
BP[<a href="/docs/api/core/v1alpha3#BuildPlan">BuildPlan</a>]
Platform[<a href="/docs/api/author/v1alpha4/#Platform">Platform</a>]
Component[<a href="/docs/api/author/v1alpha4/#ComponentConfig">Components</a>]
H[<a href="/docs/api/author/v1alpha3/#Helm">Helm</a>]
K[<a href="/docs/api/author/v1alpha3/#Kustomize">Kustomize</a>]
O[<a href="/docs/api/author/v1alpha3/#Kubernetes">Kubernetes</a>]
Helm[<a href="/docs/api/author/v1alpha4/#Helm">Helm</a>]
Kustomize[<a href="/docs/api/author/v1alpha4/#Kustomize">Kustomize</a>]
Kubernetes[<a href="/docs/api/author/v1alpha4/#Kubernetes">Kubernetes</a>]
P[<a href="/docs/api/core/v1alpha3#Kustomize">Kustomize</a>]
Y[Kubernetes <br/>Resources]
G[GitOps <br/>Resource]
FS[Local Files]
BuildPlan[<a href="/docs/api/core/v1alpha4/#buildplan">BuildPlan</a>]
C[Kube API Server]
ResourcesArtifact[<a href="/docs/api/core/v1alpha4/#artifact">Resources<br/>Artifact</a>]
GitOpsArtifact[<a href="/docs/api/core/v1alpha4/#artifact">GitOps<br/>Artifact</a>]
PS --> HC --> BP
BP --> H --> P
BP --> K --> P
BP --> O --> P
Generators[<a href="/docs/api/core/v1alpha4/#generators">Generators</a>]
Transformers[<a href="/docs/api/core/v1alpha4/#transformer">Transformers</a>]
Files[Manifest<br/>Files]
P --> Y --> FS
P --> G --> FS
Platform --> Component
Component --> Helm --> BuildPlan
Component --> Kubernetes --> BuildPlan
Component --> Kustomize --> BuildPlan
FS --> ArgoCD --> C
FS --> Flux --> C
FS --> kubectl --> C
BuildPlan --> ResourcesArtifact --> Generators
BuildPlan --> GitOpsArtifact --> Generators
Generators --> Transformers --> Files
```
### Why do we render the platform? {#why-render-the-platform}

View File

Before

Width:  |  Height:  |  Size: 934 KiB

After

Width:  |  Height:  |  Size: 934 KiB

View File

Before

Width:  |  Height:  |  Size: 703 KiB

After

Width:  |  Height:  |  Size: 703 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1014 KiB

After

Width:  |  Height:  |  Size: 1014 KiB

View File

Before

Width:  |  Height:  |  Size: 728 KiB

After

Width:  |  Height:  |  Size: 728 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1014 KiB

After

Width:  |  Height:  |  Size: 1014 KiB

View File

Before

Width:  |  Height:  |  Size: 854 KiB

After

Width:  |  Height:  |  Size: 854 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 624 KiB

After

Width:  |  Height:  |  Size: 624 KiB

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

View File

@@ -0,0 +1,52 @@
---
description: Introduction
---
# Introduction
Welcome to Holos. Holos is an open source tool to manage software development
platforms safely, easily, and consistently. We built Holos to help engineering
teams work more efficiently together by empowering them to build golden paths
and paved roads for other teams to leverage for quicker delivery.
## Documentation
- [Guides] are organized into example use-cases of how Holos helps engineering
teams at the fictional Bank of Holos deliver business value on the bank's
platform.
- The [API Reference] is a technical reference for when you're writing CUE code to define your platform.
## Backstory
At [Open Infrastructure Services], we've each helped dozens of companies build and operate their software development platforms. During the U.S. presidential election just before the pandemic, our second-largest client, Twitter, experienced a global outage that lasted nearly a full day. We were managing their production configuration system, allowing the core infrastructure team to focus on business-critical objectives. This gave us a front-row seat to the incident.
A close friend and engineer on the team made a trivial one-line change to the firewall configuration. Less than 30 minutes later, everything was down. That change, which passed code review, caused the host firewall to revert to its default state on hundreds of thousands of servers, blocking all connections globally—except for SSH, thankfully. Even a Presidential candidate complained loudly.
This incident forced us to reconsider key issues with Twitter's platform:
1. **Lack of Visibility** - Engineers couldn't foresee the impact of even a small change, making it difficult to assess risks.
2. **Large Blast Radius** - Small changes affected the entire global fleet in under 30 minutes. There was no way to limit the impact of a single change.
3. **Incomplete Tooling** - The right processes were in place, but the tooling didn't fully support them. The change was tested and reviewed, but critical information wasn't surfaced in time.
Over the next few years, we built features to address these issues. Meanwhile, I began exploring how these solutions could work in the Kubernetes and cloud-native space.
As Google Cloud partners, we worked with large customers to understand how they built their platforms on Kubernetes. During the pandemic, we built a platform using CNCF projects like ArgoCD, Prometheus Stack, Istio, Cert Manager, and External Secrets Operator, integrating them into a cohesive platform. We started with upstream recommendations—primarily Helm charts—and wrote scripts to integrate each piece into the platform. For example, we passed Helm outputs to Kustomize to add labels or fix bugs, and wrote umbrella charts to add Ingress, HTTPRoute, and ExternalSecret resources.
These scripts served as necessary glue to hold everything together but became difficult to manage across multiple environments, regions, and cloud providers. YAML templates and nested loops created friction, making them hard to troubleshoot. The scripts themselves made it difficult to see what was happening and to fix issues affecting the entire platform.
Still, the scripts had a key advantage: they produced fully rendered manifests in plain text, committed to version control, and applied via ArgoCD. This clarity made troubleshooting easier and reduced errors in production.
Despite the makeshift nature of the scripts, I kept thinking about the "[Why are we templating YAML]?" post on Hacker News. I wanted to replace our scripts and charts with something more robust and easier to maintain—something that addressed Twitter's issues head-on.
I rewrote our scripts and charts using CUE and Go, replacing the glue layer. The result is **Holos**—a tool designed to complement Helm, Kustomize, and Jsonnet, making it easier and safer to define golden paths and paved roads without bespoke scripts or templates.
Thanks for reading. Take Holos for a spin on your local machine with our [Quickstart] guide.
[Guides]: /docs/guides/
[API Reference]: /docs/api/
[Quickstart]: /docs/quickstart/
[CUE]: https://cuelang.org/
[Author API]: /docs/api/author/
[Core API]: /docs/api/core/
[Open Infrastructure Services]: https://openinfrastructure.co/
[Why are we templating YAML]: https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=https%3A%2F%2Fleebriggs.co.uk%2Fblog%2F2019%2F02%2F07%2Fwhy-are-we-templating-yaml&sort=byDate&type=story

View File

@@ -1,5 +1,3 @@
import DocCardList from '@theme/DocCardList';
# Author Schema
# Author API
<DocCardList />
v1alpha5

View File

@@ -1,5 +1,3 @@
import DocCardList from '@theme/DocCardList';
# Core Schema
# Core API
<DocCardList />
v1alpha5

15
doc/md/topics.mdx Normal file
View File

@@ -0,0 +1,15 @@
---
slug: /topics
title: Topics
description: Stand alone topics that often come up when using Holos.
---
import DocCardList from '@theme/DocCardList';
# Topics
This section has self-contained articles related to various topics that come up
when writing platform configuration code with Holos.
---
<DocCardList />

View File

@@ -0,0 +1 @@
# Multi Cluster

View File

View File

View File

@@ -0,0 +1,272 @@
---
description: Build a local Cluster to use with these guides.
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
# Local Cluster
In this guide we'll set up a local k3d cluster to apply and explore the
configuration described in our other guides. After completing this guide you'll
have a standard Kubernetes API server with proper DNS and TLS certificates.
You'll be able to easily reset the cluster to a known good state to iterate on
your own Platform.
## Reset the Cluster
If you've already followed this guide, reset the cluster by running the
following commands. Skip this section if you're creating a cluster for the
first time.
First, delete the cluster.
<Tabs groupId="k3d-cluster-delete">
<TabItem value="command" label="Command">
```bash
k3d cluster delete workload
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
INFO[0000] Deleting cluster 'workload'
INFO[0000] Deleting cluster network 'k3d-workload'
INFO[0000] Deleting 1 attached volumes...
INFO[0000] Removing cluster details from default kubeconfig...
INFO[0000] Removing standalone kubeconfig file (if there is one)...
INFO[0000] Successfully deleted cluster workload!
```
</TabItem>
</Tabs>
Then create the cluster again.
<Tabs groupId="k3d-cluster-create">
<TabItem value="command" label="Command">
```bash
k3d cluster create workload \
--registry-use k3d-registry.holos.localhost:5100 \
--port "443:443@loadbalancer" \
--k3s-arg "--disable=traefik@server:0"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
INFO[0000] portmapping '443:443' targets the loadbalancer: defaulting to [servers:*:proxy agents:*:proxy]
INFO[0000] Prep: Network
INFO[0000] Created network 'k3d-workload'
INFO[0000] Created image volume k3d-workload-images
INFO[0000] Starting new tools node...
INFO[0000] Starting node 'k3d-workload-tools'
INFO[0001] Creating node 'k3d-workload-server-0'
INFO[0001] Creating LoadBalancer 'k3d-workload-serverlb'
INFO[0001] Using the k3d-tools node to gather environment information
INFO[0001] HostIP: using network gateway 172.17.0.1 address
INFO[0001] Starting cluster 'workload'
INFO[0001] Starting servers...
INFO[0001] Starting node 'k3d-workload-server-0'
INFO[0003] All agents already running.
INFO[0003] Starting helpers...
INFO[0003] Starting node 'k3d-workload-serverlb'
INFO[0009] Injecting records for hostAliases (incl. host.k3d.internal) and for 3 network members into CoreDNS configmap...
INFO[0012] Cluster 'workload' created successfully!
INFO[0012] You can now use it like this:
kubectl cluster-info
```
</TabItem>
</Tabs>
Finally, add your trusted certificate authority.
<Tabs groupId="apply-local-ca">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f "$(mkcert -CAROOT)/namespace.yaml"
kubectl apply --server-side=true -n cert-manager -f "$(mkcert -CAROOT)/local-ca.yaml"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
namespace/cert-manager serverside-applied
secret/local-ca serverside-applied
```
</TabItem>
</Tabs>
You're back to the same state as the first time you completed this guide.
## What you'll need {#requirements}
You'll need the following tools installed to complete this guide.
1. [holos](/docs/install) - to build the platform.
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos components that wrap upstream Helm charts.
3. [k3d](https://k3d.io/#installation) - to provide a k8s api server.
4. [OrbStack](https://docs.orbstack.dev/install) or [Docker](https://docs.docker.com/get-docker/) - to use k3d.
5. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to interact with the k8s api server.
6. [mkcert](https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installation) - to make trusted TLS certificates.
7. [jq](https://jqlang.github.io/jq/download/) - to fiddle with JSON output.
## Configure DNS {#configure-dns}
Configure your machine to resolve `*.holos.localhost` to your loopback
interface. This is necessary for requests to reach the workload cluster. Save
this script to a file and execute it.
```bash showLineNumbers
#! /bin/bash
#
set -euo pipefail
tmpdir="$(mktemp -d)"
finish() {
[[ -d "$tmpdir" ]] && rm -rf "$tmpdir"
}
trap finish EXIT
cd "$tmpdir"
brew install dnsmasq
cat <<EOF >"$(brew --prefix)/etc/dnsmasq.d/holos.localhost.conf"
# Refer to https://holos.run/docs/tutorial/local/k3d/
address=/holos.localhost/127.0.0.1
EOF
if [[ -r /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist ]]; then
echo "dnsmasq already configured"
else
sudo cp "$(brew list dnsmasq | grep 'dnsmasq.plist$')" \
/Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
dscacheutil -flushcache
echo "dnsmasq configured"
fi
sudo mkdir -p /etc/resolver
sudo tee /etc/resolver/holos.localhost <<EOF
domain holos.localhost
nameserver 127.0.0.1
EOF
sudo killall -HUP mDNSResponder
echo "all done."
```
## Create the Cluster {#create-the-cluster}
The Workload Cluster is where your applications and services will be deployed.
In production this is usually an EKS, GKE, or AKS cluster.
:::tip
Holos supports all compliant Kubernetes clusters. Holos was developed and tested
on GKE, EKS, Talos, k3s, and Kubeadm clusters.
:::
Create a local registry to speed up image builds and pulls.
```bash
k3d registry create registry.holos.localhost --port 5100
```
Create the workload cluster configured to use the local registry.
```bash
k3d cluster create workload \
--registry-use k3d-registry.holos.localhost:5100 \
--port "443:443@loadbalancer" \
--k3s-arg "--disable=traefik@server:0"
```
Traefik is disabled because Istio provides the same functionality.
## Setup Root CA {#setup-root-ca}
Platforms most often use cert-manager to issue tls certificates. The browser
and tools we're using need to trust these certificates to work together.
Generate a local, trusted root certificate authority with the following script.
Admin access is necessary for `mkcert` to manage the certificate into your trust
stores.
```bash
sudo -v
```
Manage the local CA and copy the CA key to the workload cluster so that cert
manager can manage trusted certificates.
Save this script to a file and execute it to configure a trusted certificate
authority.
```bash showLineNumbers
#! /bin/bash
#
set -euo pipefail
mkcert --install
tmpdir="$(mktemp -d)"
finish() {
[[ -d "$tmpdir" ]] && rm -rf "$tmpdir"
}
trap finish EXIT
cd "$tmpdir"
# Create the local CA Secret with ca.crt, tls.crt, tls.key
mkdir local-ca
cd local-ca
CAROOT="$(mkcert -CAROOT)"
cp -p "${CAROOT}/rootCA.pem" ca.crt
cp -p "${CAROOT}/rootCA.pem" tls.crt
cp -p "${CAROOT}/rootCA-key.pem" tls.key
kubectl create secret generic --from-file=. --dry-run=client -o yaml local-ca > ../local-ca.yaml
echo 'type: kubernetes.io/tls' >> ../local-ca.yaml
cd ..
cat <<EOF > namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
labels:
kubernetes.io/metadata.name: cert-manager
name: cert-manager
spec:
finalizers:
- kubernetes
EOF
kubectl apply --server-side=true -f namespace.yaml
kubectl apply -n cert-manager --server-side=true -f local-ca.yaml
# Save the Secret to easily reset the cluster later.
install -m 0644 namespace.yaml "${CAROOT}/namespace.yaml"
install -m 0600 local-ca.yaml "${CAROOT}/local-ca.yaml"
```
:::warning
Take care to run the local-ca script each time you create the workload cluster
so that Certificates are issued correctly.
:::
## Clean Up {#clean-up}
If you'd like to clean up the resources you created in this guide, remove them
with:
```bash
k3d cluster delete workload
```
## Next Steps
Now that you have a real cluster, continue your Holos journey by following the
[Tutorial](../tutorial/1-overview.mdx) and setting up your own Platform.

17
doc/md/tutorial.mdx Normal file
View File

@@ -0,0 +1,17 @@
---
slug: /
title: Tutorial
description: Take a guided tour of Holos features with our tutorial.
---
import DocCardList from '@theme/DocCardList';
# Tutorial
Our tutorial starts with a technical overview of Holos and then progresses
through each of the main features and concepts. Upon completing the tutorial
you'll have a solid understanding of the primary features and advantages of
Holos.
---
<DocCardList />

View File

@@ -0,0 +1,94 @@
# Overview
Holos is an open-source tool that simplifies software integration for platform
teams. While most Kubernetes tools focus on application management, Holos takes
a holistic infrastructure-as-code (IaC) approach, targeting the integration
layer where applications and organizational data converge. By providing
well-defined, typed structures for consistent validation, Holos reduces errors,
streamlines integration, and creates clear pathways for teams to easily
integrate their services.
# How Holos works
Holos implements the [rendered manifests pattern][rmp], generating fully
rendered Kubernetes manifests from [CUE language][CUE] abstractions called
Components. These Components can model [Helm charts][Helm], [Kustomize
bases][Kustomize], or native Kubernetes resources. A Holos Platform consists of
one or more Components and is applied to one or more Kubernetes clusters.
```mermaid
graph BT
Platform[Platform]
Cluster[Cluster]
Component[Component]
Helm[Helm]
Kustomize[Kustomize]
CUE[CUE]
Platform --> Cluster
Component --> Platform
Helm --> Component
Kustomize --> Component
CUE --> Component
```
# Holos' role in your workflow
Holos generates, but does not apply, rendered manifests, allowing teams to use
`git diff` to clearly see changes and assess the impact on clusters and services
before deploying. Instead, Holos manages the GitOps configuration for tools like
ArgoCD and Flux CD, enabling continuous deployment of resource changes with the
full visibility and control that these tools provide. As a result, expect Holos
to sit at the very end of a CI pipeline.
# Advantages of using Holos
### Safety
* CUE constraints on Holos Components surface validation errors early in the
development process, reducing the number of failed deployments and the time
spent troubleshooting them.
* Holos natively provides a "blast radius" to code
changes by identifying the rendered manifests across your fleet of Kubernetes
clusters that will be affected by the change.
* CUE's unification strategy allows multiples teams to contribute to the desired
state of a service:
* The Platform team provides definitions for shared resources.
* Engineering teams populate definitions with service-specific data.
* The Security team provides concrete values that cannot be changed to harden the company's security posture.
### Flexibility
* CUE is adept at modeling variation and organizational complexity at scale,
while Holos enables seamless integration of CUE data with native Kubernetes
tools such as [Helm][Helm] and [Kustomize][Kustomize].
* Holos is extensible, allowing Holos Components to be modeled from any tool that
generates (e.g. `helm`) or transforms (e.g. `kustomize`) manifest data.
### Consistency
* Holos manages the execution context for Helm and Kustomize, ensuring that
rendered manifests are consistently and reliably reproducible, no matter where
Holos is run.
* CUE constraints ensure that data abstractions include the required information
in the expected format, triggering early failures if any required data is
missing.
# When not to use Holos
Holos excels at configuration management and is most effective when integrated
into a broader Kubernetes deployment strategy. If you need a single tool to
manage the entire lifecycle of a Kubernetes cluster, Holos may not fully meet
your needs on its own.
# Next Steps
Now that you have a base understanding of how Holos works, continue
to the [Setup page](./2-setup.mdx) that guides you through installing Holos and
initializing your first Platform.
[rmp]: https://akuity.io/blog/the-rendered-manifests-pattern
[Helm]: https://helm.sh/
[Kustomize]: https://kustomize.io/
[CUE]: https://cuelang.org/

View File

@@ -0,0 +1,85 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Setup
This tutorial will guide you through the installation of Holos and its
dependencies, as well as the initialization of a minimal Platform that you can
extend to meet your specific needs.
# Prerequisites
Holos integrates with the following tools that should be installed to enable
their functionality.
* [Helm][helm] to fetch and render Helm chart Components
* [Kubectl][kubectl] to [kustomize][kustomize] components.
# Install Holos
Holos is distributed as a single file executable that can be installed in a couple of ways.
### Releases
Download `holos` from the [releases](https://github.com/holos-run/holos/releases) page and place the executable into your shell path.
### Go install
Alternatively, install directly into your go bin path using:
```shell
go install github.com/holos-run/holos/cmd/holos@latest
```
# Do I need a Kubernetes cluster?
Holos only generates rendered Kubernetes manifests, so you don't need a
Kubernetes cluster to start using the tool or understand its workflow. However,
you will need a cluster eventually to apply the rendered manifests and verify
that they achieve the desired end state.
We recommend using [k3d](https://k3d.io/) to set up a minimal Kubernetes cluster with
[Orbstack](https://docs.orbstack.dev/install) or
[Docker](https://docs.docker.com/get-started/get-docker/). To simplify this,
we've created [the Local Cluster guide](../topics/4-local-cluster.mdx) which
automates the process, ensuring proper DNS and TLS certificates, and includes a
script to reset the cluster to a known good state.
When you're ready to experiment with a live Kubernetes cluster, refer to [the
Local Cluster guide](../topics/4-local-cluster.mdx).
# Initialize a new Platform
Use Holos to generate a minimal platform using the recommended directory structure
by creating an empty directory and then using the `holos generate platform` subcommand:
<Tabs groupId="tutorial-setup-generate-platform">
<TabItem value="command" label="Command">
```bash
mkdir holos_platform
cd holos_platform
holos generate platform v1alpha4
```
</TabItem>
<TabItem value="output" label="Output">
```txt
no output
```
</TabItem>
</Tabs>
Holos creates a `platform` directory with a `platform.gen.cue` file that serves
as the foundation for your newly initialized Holos Platform. For each Holos
Component you model, you'll add a new CUE file to the platform directory,
mapping it to the location of the Component's CUE code, and extending the
capabilities of your platform.
# Next Steps
Now that you've got Holos and its prerequisites installed, continue on to the
[Hello Holos page](./3-hello-holos.mdx) where we will guide you through the
process of creating your first Component and modeling a Helm chart.
[helm]: https://github.com/helm/helm/releases
[kubectl]: https://kubernetes.io/docs/tasks/tools/
[kustomize]: https://kustomize.io/

View File

@@ -0,0 +1,74 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Hello Holos
One of the first exercises you perform when learning a new programming language
is to print out the "Hello World!" greeting. For Holos, our "Hello Holos"
exercise involves modeling the [podinfo Helm chart][podinfo] that produces a
similar greeting message from a Kubernetes Pod.
By the end of this tutorial you will gain the understanding of how to model
an individual Holos Component using a Helm chart as its source.
# The code
### Podinfo Helm Chart
Let's start by creating a directory for `podinfo`, touching an empty CUE file,
and then populating it with the CUE code below:
<Tabs groupId="tutorial-hello-podinfo-helm-cue-code">
<TabItem value="projects/tutorial/components/podinfo/podinfo.cue" label="Podinfo Helm Chart">
```bash
mkdir -p projects/tutorial/components/podinfo
touch projects/tutorial/components/podinfo/podinfo.cue
```
```cue showLineNumbers
package holos
// Produce a helm chart build plan.
_HelmChart.BuildPlan
_HelmChart: #Helm & {
Name: "podinfo"
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
}
```
</TabItem>
</Tabs>
### Register the podinfo component
Now let's register the code modeling the `podinfo` Helm chart as a Holos
Component and assign it to a cluser. For this we will need a create new file in
the `platform` directory with the following contents:
<Tabs groupId="tutorial-hello-register-podinfo-component">
<TabItem value="platform/podinfo.cue" label="Register Podinfo">
```bash
touch plaform/podinfo.cue
```
```cue showLineNumbers
_Platform: Components: podinfo: {
name: "podinfo"
component: "projects/tutorial/components/podinfo"
cluster: "local"
}
```
</TabItem>
</Tabs>
[podinfo]: https://github.com/stefanprodan/podinfo

View File

@@ -0,0 +1 @@
# Helm

View File

@@ -0,0 +1 @@
# Kustomize

Some files were not shown because too many files have changed in this diff Show More