Compare commits
15 Commits
v0.97.3
...
301-docs-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488f7ae985 | ||
|
|
4817491aab | ||
|
|
30ce72a9b7 | ||
|
|
958f65ddcf | ||
|
|
a1c9111a05 | ||
|
|
ee30c52673 | ||
|
|
117a00334f | ||
|
|
1e03debfac | ||
|
|
72137b2fa9 | ||
|
|
5abf967116 | ||
|
|
5d882f465d | ||
|
|
45bdaac833 | ||
|
|
7ae1f990ef | ||
|
|
b526fd1669 | ||
|
|
5e07655f35 |
10
.cspell.json
@@ -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",
|
||||
|
||||
@@ -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: |
|
||||
4
Makefile
@@ -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)
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
34
cmd/holos/testdata/constraints.txt
vendored
@@ -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"
|
||||
20
cmd/holos/testdata/issue15_cue_errors.txt
vendored
@@ -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
|
||||
61
cmd/holos/testdata/issue25_apiobjects_cue.txt
vendored
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
cmd/holos/testdata/issue25_apiobjects_helm.txt
vendored
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
cmd/holos/testdata/issue25_show_object_names.txt
vendored
@@ -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" }
|
||||
}
|
||||
}
|
||||
289
cmd/holos/testdata/issue33_helm_stderr.txt
vendored
@@ -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: {}
|
||||
@@ -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
|
||||
@@ -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: []
|
||||
15042
cmd/holos/tests/v1alpha4/guides/helm.txt
Normal 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>
|
||||
|
Before Width: | Height: | Size: 690 KiB After Width: | Height: | Size: 690 KiB |
|
Before Width: | Height: | Size: 997 KiB After Width: | Height: | Size: 997 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1009 KiB After Width: | Height: | Size: 1009 KiB |
|
Before Width: | Height: | Size: 617 KiB After Width: | Height: | Size: 617 KiB |
|
Before Width: | Height: | Size: 706 KiB After Width: | Height: | Size: 706 KiB |
|
Before Width: | Height: | Size: 794 KiB After Width: | Height: | Size: 794 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
@@ -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}
|
||||
|
Before Width: | Height: | Size: 934 KiB After Width: | Height: | Size: 934 KiB |
|
Before Width: | Height: | Size: 703 KiB After Width: | Height: | Size: 703 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1014 KiB After Width: | Height: | Size: 1014 KiB |
|
Before Width: | Height: | Size: 728 KiB After Width: | Height: | Size: 728 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1014 KiB After Width: | Height: | Size: 1014 KiB |
|
Before Width: | Height: | Size: 854 KiB After Width: | Height: | Size: 854 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 624 KiB After Width: | Height: | Size: 624 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
52
doc/md.archive/introduction.md
Normal 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
|
||||
@@ -1,5 +1,3 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
# Author Schema
|
||||
|
||||
# Author API
|
||||
|
||||
<DocCardList />
|
||||
v1alpha5
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
# Core Schema
|
||||
|
||||
# Core API
|
||||
|
||||
<DocCardList />
|
||||
v1alpha5
|
||||
|
||||
15
doc/md/topics.mdx
Normal 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 />
|
||||
1
doc/md/topics/1-multiple-clusters.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Multi Cluster
|
||||
0
doc/md/topics/2-multiple-fleets.mdx
Normal file
0
doc/md/topics/3-platform-wide-data.mdx
Normal file
272
doc/md/topics/4-local-cluster.mdx
Normal 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
@@ -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 />
|
||||
94
doc/md/tutorial/1-overview.mdx
Normal 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/
|
||||
85
doc/md/tutorial/2-setup.mdx
Normal 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/
|
||||
74
doc/md/tutorial/3-hello-holos.mdx
Normal 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
|
||||
1
doc/md/tutorial/4-helm.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Helm
|
||||
1
doc/md/tutorial/5-kustomize.mdx
Normal file
@@ -0,0 +1 @@
|
||||
# Kustomize
|
||||