Compare commits
226 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bf0cb8d8e | ||
|
|
766c8912b7 | ||
|
|
be1dee5f1c | ||
|
|
6ad56525ac | ||
|
|
791ec5ee71 | ||
|
|
638ac7473c | ||
|
|
ee24b5ce13 | ||
|
|
fa2fdbe4e8 | ||
|
|
63e1df1d4c | ||
|
|
2ad0c2a93e | ||
|
|
3a6a04f318 | ||
|
|
8afeece890 | ||
|
|
bc9c43a0b9 | ||
|
|
5a98c77e4c | ||
|
|
b3f7de39ec | ||
|
|
ca4ecf1b28 | ||
|
|
9ce28660ce | ||
|
|
728e8ba06e | ||
|
|
e4b07dad6d | ||
|
|
b7c0bba2b9 | ||
|
|
847ab8441c | ||
|
|
5f72af3d53 | ||
|
|
33eed43fd1 | ||
|
|
d2fbbdd1cc | ||
|
|
e42da118dc | ||
|
|
7d36567dcf | ||
|
|
bee698bebe | ||
|
|
58df0626d0 | ||
|
|
c817a24704 | ||
|
|
bd56f3118c | ||
|
|
d3aa748e92 | ||
|
|
6738248756 | ||
|
|
011b488775 | ||
|
|
c8d89f3291 | ||
|
|
a44ebe5171 | ||
|
|
66a3b6a874 | ||
|
|
0886788238 | ||
|
|
4fd6785a10 | ||
|
|
e4695fa204 | ||
|
|
4cd9395e6c | ||
|
|
6f4f355ee0 | ||
|
|
0fde16f477 | ||
|
|
426b4323f7 | ||
|
|
ee1e4988a6 | ||
|
|
5c391e8444 | ||
|
|
aba1b44f4d | ||
|
|
44f9615a93 | ||
|
|
69a6d2acad | ||
|
|
d2c94dc8df | ||
|
|
01720b38fc | ||
|
|
632e3c2725 | ||
|
|
18e0b48012 | ||
|
|
7dfa9dcb93 | ||
|
|
3dedd857ea | ||
|
|
cd379167cc | ||
|
|
52a5348f82 | ||
|
|
7c5c8fe692 | ||
|
|
ec371ed688 | ||
|
|
1984410577 | ||
|
|
438e01fbad | ||
|
|
d122cadae6 | ||
|
|
53fcdf307b | ||
|
|
5e6bb96147 | ||
|
|
94d03f9c59 | ||
|
|
0c01c9177d | ||
|
|
36f542da7a | ||
|
|
e41f0aa70c | ||
|
|
351c8ba74a | ||
|
|
a0e0b5bb75 | ||
|
|
7bc94e314c | ||
|
|
9681ce02e7 | ||
|
|
07e8e9f5f3 | ||
|
|
437d8a7824 | ||
|
|
6cc8214636 | ||
|
|
7d8f324014 | ||
|
|
8555d56f8c | ||
|
|
5884d720f2 | ||
|
|
92d274ced1 | ||
|
|
4dd78bd826 | ||
|
|
aeb8fd8e72 | ||
|
|
1e9744f748 | ||
|
|
a95abe65f6 | ||
|
|
c58510b92c | ||
|
|
302a7bfcf0 | ||
|
|
decbbaab0f | ||
|
|
822f599202 | ||
|
|
6a47edbc3d | ||
|
|
67d00f1dd4 | ||
|
|
bfa02cd6ed | ||
|
|
2d8ca474f3 | ||
|
|
c7cd6f5190 | ||
|
|
21e3e6f5e4 | ||
|
|
16a4f89c2f | ||
|
|
f15dea5ee7 | ||
|
|
a3bbadd1f5 | ||
|
|
30cbb0d537 | ||
|
|
6041fd4d76 | ||
|
|
fec1de0004 | ||
|
|
6ad24a6eec | ||
|
|
57dedc6450 | ||
|
|
8d2a9dd659 | ||
|
|
e3c53f5655 | ||
|
|
3b833cdacd | ||
|
|
31d1086345 | ||
|
|
b737543c13 | ||
|
|
8e150ee0d7 | ||
|
|
117a2a886d | ||
|
|
79b41dfbf5 | ||
|
|
55562f9d83 | ||
|
|
e0a636f183 | ||
|
|
1fa74214cf | ||
|
|
e5851cac57 | ||
|
|
4a26662b92 | ||
|
|
6bc6888ffc | ||
|
|
dab1f305e1 | ||
|
|
fbe79dd0af | ||
|
|
6d6829b149 | ||
|
|
971a3fa280 | ||
|
|
7632344cd1 | ||
|
|
42067748ad | ||
|
|
340c3484e5 | ||
|
|
250238c286 | ||
|
|
a223e2b426 | ||
|
|
63a7da02e7 | ||
|
|
569f827e30 | ||
|
|
4a656db2ec | ||
|
|
77b0933961 | ||
|
|
3b796cfbbd | ||
|
|
8a7a010b94 | ||
|
|
2454f6e9ee | ||
|
|
63d00bfddf | ||
|
|
f34da6c24e | ||
|
|
1d98069b73 | ||
|
|
e956b64d04 | ||
|
|
054d33b498 | ||
|
|
f2f75a4e00 | ||
|
|
a0cf73faf9 | ||
|
|
d74655c632 | ||
|
|
b8019429b8 | ||
|
|
9c08214118 | ||
|
|
f58d791e03 | ||
|
|
836033e16a | ||
|
|
77279d9baf | ||
|
|
bf19aee1a7 | ||
|
|
4de88b3155 | ||
|
|
6f39cc6fdc | ||
|
|
e410563f82 | ||
|
|
0a53bef72a | ||
|
|
02a450e597 | ||
|
|
e1222cf367 | ||
|
|
740a3d21a1 | ||
|
|
1114b65a47 | ||
|
|
c9d892eee3 | ||
|
|
4c77eba72b | ||
|
|
a8ae56b08b | ||
|
|
b04837ede2 | ||
|
|
559c8bc79f | ||
|
|
a30335b171 | ||
|
|
108831747a | ||
|
|
c714a2b61e | ||
|
|
1cba383dc1 | ||
|
|
265d5773b8 | ||
|
|
44f8779136 | ||
|
|
4127804092 | ||
|
|
8f424cfabe | ||
|
|
699148abdd | ||
|
|
73f777759e | ||
|
|
8b9070f185 | ||
|
|
1e8861c8b7 | ||
|
|
bdc182f4eb | ||
|
|
4db3fb4ead | ||
|
|
1911c7fe01 | ||
|
|
5e582ec5c6 | ||
|
|
e3c3ab6799 | ||
|
|
f3a1aeaf3f | ||
|
|
1be7d5597b | ||
|
|
2dc492dba8 | ||
|
|
1364467853 | ||
|
|
7f37ac6721 | ||
|
|
3f3a3e5bb0 | ||
|
|
4dc923f540 | ||
|
|
963ca0e6a7 | ||
|
|
ce875e6c18 | ||
|
|
ef016948b7 | ||
|
|
df65f103e6 | ||
|
|
98d9831167 | ||
|
|
fcb0f7d27a | ||
|
|
5f3c6a1cc4 | ||
|
|
3ab6ccd864 | ||
|
|
fe168a1a3f | ||
|
|
4c0d0dd18b | ||
|
|
9d0a0b1ed5 | ||
|
|
b6c6e9bc2f | ||
|
|
44b560194a | ||
|
|
b545df9641 | ||
|
|
e335541c6c | ||
|
|
3c1fcd9d6e | ||
|
|
4fca94d863 | ||
|
|
a3d49f0d6e | ||
|
|
f432a445a0 | ||
|
|
effaa9badf | ||
|
|
ac6be04859 | ||
|
|
c0ca7e7392 | ||
|
|
2f0b883724 | ||
|
|
7b8eed0347 | ||
|
|
230a2f18b8 | ||
|
|
89578d891f | ||
|
|
8995af06fa | ||
|
|
55752aee1c | ||
|
|
a90ba17904 | ||
|
|
6f78984561 | ||
|
|
b927caed96 | ||
|
|
e4e8a5e217 | ||
|
|
804bafd4e6 | ||
|
|
f2a9508aba | ||
|
|
392b9f711b | ||
|
|
2d9f35067f | ||
|
|
a0fd53deaa | ||
|
|
e346e10c07 | ||
|
|
f1dc54650e | ||
|
|
9ed5d588d0 | ||
|
|
6eb24faf63 | ||
|
|
daa13906b5 | ||
|
|
b2ce455aa2 | ||
|
|
90629b84b5 | ||
|
|
7f077f5347 |
140
.cspell.json
@@ -5,56 +5,194 @@
|
||||
"mdx"
|
||||
],
|
||||
"words": [
|
||||
"acraccesstokens",
|
||||
"admissionregistration",
|
||||
"anthos",
|
||||
"apiextensions",
|
||||
"applicationset",
|
||||
"applicationsets",
|
||||
"appproject",
|
||||
"appprojects",
|
||||
"argoproj",
|
||||
"authcode",
|
||||
"authorizationpolicies",
|
||||
"authpolicy",
|
||||
"authproxy",
|
||||
"authroutes",
|
||||
"balancereader",
|
||||
"buildplan",
|
||||
"cainjector",
|
||||
"CAROOT",
|
||||
"certificaterequests",
|
||||
"certificatesigningrequests",
|
||||
"clsx",
|
||||
"clusterexternalsecrets",
|
||||
"clusterissuer",
|
||||
"clusterissuers",
|
||||
"clusterrole",
|
||||
"clusterrolebinding",
|
||||
"clustersecretstores",
|
||||
"CNCF",
|
||||
"CODEOWNERS",
|
||||
"configmap",
|
||||
"cookiesecret",
|
||||
"coredns",
|
||||
"corev",
|
||||
"CRD's",
|
||||
"crds",
|
||||
"creds",
|
||||
"crossplane",
|
||||
"cuecontext",
|
||||
"cuelang",
|
||||
"customresourcedefinition",
|
||||
"daemonset",
|
||||
"destinationrules",
|
||||
"devicecode",
|
||||
"dnsmasq",
|
||||
"dscacheutil",
|
||||
"ecrauthorizationtokens",
|
||||
"entgo",
|
||||
"envoyfilters",
|
||||
"errgroup",
|
||||
"etcdsnapshotfiles",
|
||||
"externalsecret",
|
||||
"externalsecrets",
|
||||
"fctr",
|
||||
"fieldmaskpb",
|
||||
"flushcache",
|
||||
"gatewayclasses",
|
||||
"gcraccesstokens",
|
||||
"gendoc",
|
||||
"ggnpl",
|
||||
"ghaction",
|
||||
"githubaccesstokens",
|
||||
"gitops",
|
||||
"godoc",
|
||||
"golangci",
|
||||
"goreleaser",
|
||||
"grpcreflect",
|
||||
"grpcroutes",
|
||||
"grpcurl",
|
||||
"healthz",
|
||||
"helmchartconfigs",
|
||||
"helmcharts",
|
||||
"Hiera",
|
||||
"holos",
|
||||
"holoslogger",
|
||||
"horizontalpodautoscaler",
|
||||
"Hostnames",
|
||||
"httpbin",
|
||||
"httproute",
|
||||
"httproutes",
|
||||
"Infima",
|
||||
"isatty",
|
||||
"istiod",
|
||||
"jbrx",
|
||||
"jeffmccune",
|
||||
"jetstack",
|
||||
"Jsonnet",
|
||||
"kfbh",
|
||||
"killall",
|
||||
"kubeadm",
|
||||
"kubeconfig",
|
||||
"kubelogin",
|
||||
"Kustomization",
|
||||
"Kustomizations",
|
||||
"kustomize",
|
||||
"ldflags",
|
||||
"leaderelection",
|
||||
"ledgerwriter",
|
||||
"libnss",
|
||||
"loadbalancer",
|
||||
"mattn",
|
||||
"mccutchen",
|
||||
"mindmap",
|
||||
"mktemp",
|
||||
"msqbn",
|
||||
"mtls",
|
||||
"Multicluster",
|
||||
"mutatingwebhookconfiguration",
|
||||
"mxcl",
|
||||
"myhostname",
|
||||
"nameserver",
|
||||
"nolint",
|
||||
"organizationconnect",
|
||||
"orgid",
|
||||
"otelconnect",
|
||||
"Parentspanid",
|
||||
"pcjc",
|
||||
"peerauthentications",
|
||||
"pflag",
|
||||
"pipefail",
|
||||
"PKCE",
|
||||
"platformconnect",
|
||||
"podcli",
|
||||
"poddisruptionbudget",
|
||||
"podinfo",
|
||||
"portmapping",
|
||||
"promhttp",
|
||||
"protobuf",
|
||||
"protojson",
|
||||
"proxyconfigs",
|
||||
"Pulumi",
|
||||
"pushsecrets",
|
||||
"putenv",
|
||||
"qjbp",
|
||||
"quickstart",
|
||||
"QVRFLS",
|
||||
"readyz",
|
||||
"referencegrant",
|
||||
"referencegrants",
|
||||
"requestauthentications",
|
||||
"retryable",
|
||||
"rolebinding",
|
||||
"ropc",
|
||||
"seccomp",
|
||||
"SECRETKEY",
|
||||
"secretstore",
|
||||
"secretstores",
|
||||
"serverlb",
|
||||
"serverside",
|
||||
"serviceaccount",
|
||||
"servicebindings",
|
||||
"serviceentries",
|
||||
"spanid",
|
||||
"spiffe",
|
||||
"startupapicheck",
|
||||
"statefulset",
|
||||
"stefanprodan",
|
||||
"struct",
|
||||
"structpb",
|
||||
"subjectaccessreviews",
|
||||
"svclb",
|
||||
"systemconnect",
|
||||
"tablewriter",
|
||||
"Tiltfile",
|
||||
"timestamppb",
|
||||
"Timoni",
|
||||
"tlsclientconfig",
|
||||
"tokencache",
|
||||
"Tokener",
|
||||
"Traceid",
|
||||
"traefik",
|
||||
"transactionhistory",
|
||||
"uibutton",
|
||||
"unstage",
|
||||
"untar",
|
||||
"Upsert",
|
||||
"urandom",
|
||||
"usecases",
|
||||
"userconnect",
|
||||
"zitadel"
|
||||
"userdata",
|
||||
"userservice",
|
||||
"validatingwebhookconfiguration",
|
||||
"vaultdynamicsecrets",
|
||||
"virtualservices",
|
||||
"wasmplugins",
|
||||
"workloadentries",
|
||||
"workloadgroups",
|
||||
"zerolog",
|
||||
"zitadel",
|
||||
"ztunnel"
|
||||
]
|
||||
}
|
||||
|
||||
57
.github/workflows/dev-deploy.yaml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Dev Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['main', 'dev-deploy']
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
## Not needed on ubuntu-latest
|
||||
# - name: Provide GPG and Git
|
||||
# run: sudo apt update && sudo apt -qq -y install gnupg git curl zip unzip tar bzip2 make jq
|
||||
|
||||
## Not needed on ubuntu-latest
|
||||
# - name: Provide Holos Dependencies
|
||||
# run: |
|
||||
# sudo mkdir -p -m 755 /etc/apt/keyrings
|
||||
# curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
# sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
# echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
|
||||
# sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
|
||||
# sudo apt update
|
||||
# sudo apt install -qq -y kubectl
|
||||
# curl -fsSL -o- https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
|
||||
# Must come after git executable is provided
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
|
||||
- uses: ko-build/setup-ko@v0.7
|
||||
env:
|
||||
KO_DOCKER_REPO: quay.io/holos-run/holos
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: make dev-deploy
|
||||
env:
|
||||
auth_user: holos-run+pusher
|
||||
auth_token: ${{ secrets.QUAY_TOKEN }}
|
||||
run: |
|
||||
echo "${auth_token}" | ko login quay.io --username "${auth_user}" --password-stdin
|
||||
make dev-deploy
|
||||
30
.github/workflows/golangci-lint.yaml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: golangci-lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- test
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
permissions:
|
||||
# Required: allow read access to the content for analysis.
|
||||
contents: read
|
||||
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
||||
pull-requests: read
|
||||
# Optional: allow write access to checks to allow the action to annotate code in the PR.
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: stable
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v1.60
|
||||
21
.github/workflows/lint.yaml
vendored
@@ -13,9 +13,9 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
lint:
|
||||
name: lint
|
||||
runs-on: gha-rs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -30,16 +30,13 @@ jobs:
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
- name: Install Packages
|
||||
run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
## Not needed on ubuntu-latest
|
||||
# - name: Install Packages
|
||||
# run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
|
||||
- name: Install Tools
|
||||
run: |
|
||||
set -x
|
||||
make tools
|
||||
run: make tools
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
version: latest
|
||||
skip-pkg-cache: true
|
||||
- name: Lint
|
||||
# golangci-lint runs in a separate workflow.
|
||||
run: make lint -o golangci-lint
|
||||
|
||||
7
.github/workflows/release.yaml
vendored
@@ -12,11 +12,12 @@ permissions:
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: gha-rs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
## Not needed on ubuntu-latest
|
||||
# Must come before Checkout, otherwise goreleaser fails
|
||||
- name: Provide GPG and Git
|
||||
run: sudo apt update && sudo apt -qq -y install gnupg git curl zip unzip tar bzip2 make
|
||||
# - name: Provide GPG and Git
|
||||
# run: sudo apt update && sudo apt -qq -y install gnupg git curl zip unzip tar bzip2 make
|
||||
|
||||
# Must come after git executable is provided
|
||||
- name: Checkout
|
||||
|
||||
1
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
/bin/
|
||||
vendor/
|
||||
.idea/
|
||||
coverage.out
|
||||
/dist/
|
||||
|
||||
13
.ko.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
# Refer to https://ko.build/configuration/#overriding-go-build-settings
|
||||
builds:
|
||||
- id: holos
|
||||
dir: .
|
||||
main: ./cmd/holos
|
||||
env:
|
||||
- GOPRIVATE=github.com/holos-run/\*
|
||||
ldflags:
|
||||
- -s
|
||||
- -w
|
||||
- -X
|
||||
# Makefile provides GIT_DETAIL and GIT_SUFFIX.
|
||||
- github.com/holos-run/holos/version.GitDescribe={{.Env.GIT_DETAIL}}{{.Env.GIT_SUFFIX}}
|
||||
33
Makefile
@@ -48,13 +48,16 @@ bumpmajor: ## Bump the major version.
|
||||
show-version: ## Print the full version.
|
||||
@echo $(VERSION)
|
||||
|
||||
.PHONY: tag
|
||||
tag: ## Tag a release
|
||||
git tag v$(VERSION)
|
||||
|
||||
.PHONY: tidy
|
||||
tidy: ## Tidy go module.
|
||||
go mod tidy
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Format code.
|
||||
cd docs/examples && cue fmt ./...
|
||||
cd internal/generate/platforms && cue fmt ./...
|
||||
go fmt ./...
|
||||
|
||||
@@ -89,11 +92,14 @@ clean: ## Clean executables.
|
||||
test: ## Run tests.
|
||||
scripts/test
|
||||
|
||||
.PHONY: golangci-lint
|
||||
golangci-lint:
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## Run linters.
|
||||
lint: golangci-lint ## Run linters.
|
||||
buf lint
|
||||
cd internal/frontend/holos && ng lint
|
||||
golangci-lint run
|
||||
./hack/cspell
|
||||
|
||||
.PHONY: coverage
|
||||
@@ -117,25 +123,28 @@ go-deps: ## tool versions pinned in tools.go
|
||||
go install honnef.co/go/tools/cmd/staticcheck
|
||||
go install golang.org/x/tools/cmd/godoc
|
||||
go install github.com/princjef/gomarkdoc/cmd/gomarkdoc
|
||||
go install github.com/google/ko
|
||||
# curl https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash
|
||||
|
||||
.PHONY: frontend-deps
|
||||
frontend-deps: ## Install Angular deps for go generate
|
||||
cd internal/frontend/holos && npm install
|
||||
cd internal/frontend/holos && npm install --save-dev @bufbuild/buf @connectrpc/protoc-gen-connect-es
|
||||
cd internal/frontend/holos && npm install @connectrpc/connect @connectrpc/connect-web @bufbuild/protobuf
|
||||
# https://github.com/connectrpc/connect-query-es/blob/1350b6f07b6aead81793917954bdb1cc3ce09df9/packages/protoc-gen-connect-query/README.md?plain=1#L23
|
||||
cd internal/frontend/holos && npm install --save-dev @connectrpc/protoc-gen-connect-query @bufbuild/protoc-gen-es
|
||||
cd internal/frontend/holos && npm install @connectrpc/connect-query @bufbuild/protobuf
|
||||
|
||||
.PHONY: website-deps
|
||||
website-deps: ## Install Docusaurus deps for go generate
|
||||
cd doc/website && npm install
|
||||
|
||||
.PHONY: image
|
||||
image: build ## Docker image build
|
||||
docker build . -t ${DOCKER_REPO}:v$(shell ./bin/holos --version)
|
||||
docker push ${DOCKER_REPO}:v$(shell ./bin/holos --version)
|
||||
.PHONY: image # refer to .ko.yaml as well
|
||||
image: ## Container image build for workflows/publish.yaml
|
||||
KO_DOCKER_REPO=$(DOCKER_REPO) GIT_DETAIL=$(GIT_DETAIL) GIT_SUFFIX=$(GIT_SUFFIX) ko build --platform=all --bare ./cmd/holos --tags $(GIT_DETAIL)$(GIT_SUFFIX) --tags latest
|
||||
|
||||
.PHONY: prod-deploy
|
||||
prod-deploy: install image ## deploy to PROD
|
||||
GIT_DETAIL=$(GIT_DETAIL) GIT_SUFFIX=$(GIT_SUFFIX) bash ./hack/deploy
|
||||
|
||||
.PHONY: dev-deploy
|
||||
dev-deploy: install image ## deploy to dev
|
||||
GIT_DETAIL=$(GIT_DETAIL) GIT_SUFFIX=$(GIT_SUFFIX) bash ./hack/deploy-dev
|
||||
|
||||
.PHONY: website
|
||||
website: ## Build website
|
||||
|
||||
19
README.md
@@ -1,4 +1,4 @@
|
||||
## Holos - A Holostic Development Platform
|
||||
## Holos - A Holistic Development Platform
|
||||
|
||||
<img width="50%"
|
||||
align="right"
|
||||
@@ -9,24 +9,27 @@ Building and maintaining a software development platform is a complex and time
|
||||
consuming endeavour. Organizations often dedicate a team of 3-4 who need 6-12
|
||||
months to build the platform.
|
||||
|
||||
Holos is a tool and a reference platform to reduce the compexity and speed up
|
||||
Holos is a tool and a reference platform to reduce the complexity and speed up
|
||||
the process of building a modern, cloud native software development platform.
|
||||
|
||||
- **Accelerate new projects** - Reduce time to market and operational complexity by starting your new project on top of the Holos reference platform.
|
||||
- **Modernize existing projects** - Incrementally incorporate your existing platform services into Holos for simpler integration.
|
||||
- **Unified configuration model** - Increase safety and reduce the risk of config changes with CUE.
|
||||
- **First class Helm and Kustomize support** - Leverage and reuse your existing investment in existing configuration tools such as Helm and Kustomize.
|
||||
- **Modern Authentication and Authorization** - Holos seamlessly integrates platform identity and access mangement with zero-trust beyond corp style authorization policy.
|
||||
- **Accelerate new projects** - Reduce time to market and operational complexity by starting your new project on top of the Holos reference platform.
|
||||
- **Modernize existing projects** - Incrementally incorporate your existing platform services into Holos for simpler integration.
|
||||
- **Unified configuration model** - Increase safety and reduce the risk of config changes with CUE.
|
||||
- **First class Helm and Kustomize support** - Leverage and reuse your existing investment in existing configuration tools such as Helm and Kustomize.
|
||||
- **Modern Authentication and Authorization** - Holos seamlessly integrates platform identity and access management with zero-trust beyond corp style authorization policy.
|
||||
|
||||
## Quick Installation
|
||||
|
||||
```console
|
||||
go install github.com/holos-run/holos/cmd/holos@latest
|
||||
```
|
||||
|
||||
## Docs and Support
|
||||
The documentation for developing and using Holos is avaialble at: https://holos.run
|
||||
|
||||
The documentation for developing and using Holos is available at: https://holos.run
|
||||
|
||||
For discussion and support, [open a discussion](https://github.com/orgs/holos-run/discussions/new/choose).
|
||||
|
||||
## License
|
||||
|
||||
Holos is licensed under Apache 2.0 as found in the [LICENSE file](LICENSE).
|
||||
|
||||
1
Tiltfile
@@ -61,6 +61,7 @@ docker_build_with_restart(
|
||||
entrypoint=[
|
||||
'/app/bin/holos.linux',
|
||||
'server',
|
||||
'--log-format=text',
|
||||
'--oidc-issuer=https://login.holos.run',
|
||||
'--oidc-audience=275804490387516853@holos_quickstart', # auth proxy
|
||||
'--oidc-audience=270319630705329162@holos_platform', # holos cli
|
||||
|
||||
226
api/author/v1alpha3/definitions.go
Normal file
@@ -0,0 +1,226 @@
|
||||
// Package v1alpha3 contains CUE definitions intended as convenience wrappers
|
||||
// around the core data types defined in package core. The purpose of these
|
||||
// wrappers is to make life easier for platform engineers by reducing boiler
|
||||
// plate code and generating component build plans in a consistent manner.
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
core "github.com/holos-run/holos/api/core/v1alpha3"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
//go:generate ../../../hack/gendoc
|
||||
|
||||
// Component represents the fields common the different kinds of component. All
|
||||
// components have a name, support mixing in resources, and produce a BuildPlan.
|
||||
type ComponentFields struct {
|
||||
// Name represents the Component name.
|
||||
Name string
|
||||
// Resources are kubernetes api objects to mix into the output.
|
||||
Resources map[string]any
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
|
||||
ArgoConfig ArgoConfig
|
||||
// BuildPlan represents the derived BuildPlan for the Holos cli to render.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
|
||||
// Helm provides a BuildPlan via the Output field which contains one HelmChart
|
||||
// from package core. Useful as a convenience wrapper to render a HelmChart
|
||||
// with optional mix-in resources and Kustomization post-processing.
|
||||
type Helm struct {
|
||||
ComponentFields `json:",inline"`
|
||||
|
||||
// Version represents the chart version.
|
||||
Version string
|
||||
// Namespace represents the helm namespace option when rendering the chart.
|
||||
Namespace string
|
||||
|
||||
// Repo represents the chart repository
|
||||
Repo struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values interface{} `cue:"{...}"`
|
||||
|
||||
// Chart represents the derived HelmChart for inclusion in the BuildPlan
|
||||
// Output field value. The default HelmChart field values are derived from
|
||||
// other Helm field values and should be sufficient for most use cases.
|
||||
Chart core.HelmChart
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor bool `cue:"true | *false"`
|
||||
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches map[core.InternalLabel]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
|
||||
}
|
||||
|
||||
// Kustomize provides a BuildPlan via the Output field which contains one
|
||||
// KustomizeBuild from package core.
|
||||
type Kustomize struct {
|
||||
ComponentFields `json:",inline"`
|
||||
// Kustomization represents the kustomize build plan for holos to render.
|
||||
Kustomization core.KustomizeBuild
|
||||
}
|
||||
|
||||
// Kubernetes provides a BuildPlan via the Output field which contains inline
|
||||
// API Objects provided directly from CUE.
|
||||
type Kubernetes struct {
|
||||
ComponentFields `json:",inline"`
|
||||
// Objects represents the kubernetes api objects for the Component.
|
||||
Objects core.KubernetesObjects
|
||||
}
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for a Component.
|
||||
// Useful to define once at the root of the Platform configuration and reuse
|
||||
// across all Components.
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an ArgoCD Application resource for GitOps if true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// ClusterName represents the cluster within the platform the Application
|
||||
// resource is intended for.
|
||||
ClusterName string
|
||||
// DeployRoot represents the path from the git repository root to the `deploy`
|
||||
// rendering output directory. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
DeployRoot string `cue:"string | *\".\""`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
// AppProject represents the ArgoCD Project to associate the Application with.
|
||||
AppProject string `cue:"string | *\"default\""`
|
||||
}
|
||||
|
||||
// Cluster represents a cluster managed by the Platform.
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
|
||||
// Fleet represents a named collection of similarly configured Clusters. Useful
|
||||
// to segregate workload clusters from their management cluster.
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
|
||||
// StandardFleets represents the standard set of Clusters in a Platform
|
||||
// segmented into Fleets by their purpose. The management Fleet contains a
|
||||
// single Cluster, for example a GKE autopilot cluster with no workloads
|
||||
// deployed for reliability and cost efficiency. The workload Fleet contains
|
||||
// all other Clusters which contain workloads and sync Secrets from the
|
||||
// management cluster.
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\"}"`
|
||||
}
|
||||
|
||||
// Platform is a convenience structure to produce a core Platform specification
|
||||
// value in the Output field. Useful to collect components at the root of the
|
||||
// Platform configuration tree as a struct, which are automatically converted
|
||||
// into a list for the core Platform spec output.
|
||||
type Platform struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `cue:"string | *\"holos\""`
|
||||
// Components is a structured map of components to manage by their name.
|
||||
Components map[string]core.PlatformSpecComponent
|
||||
// Model represents the Platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `cue:"{...}"`
|
||||
// Output represents the core Platform spec for the holos cli to iterate over
|
||||
// and render each listed Component, injecting the Model.
|
||||
Output core.Platform
|
||||
// Domain represents the primary domain the Platform operates in. This field
|
||||
// is intended as a sensible default for component authors to reference and
|
||||
// platform operators to define.
|
||||
Domain string `cue:"string | *\"holos.localhost\""`
|
||||
}
|
||||
|
||||
// Organization represents organizational metadata useful across the platform.
|
||||
type Organization struct {
|
||||
Name string
|
||||
DisplayName string
|
||||
Domain string
|
||||
}
|
||||
|
||||
// OrganizationStrict represents organizational metadata useful across the
|
||||
// platform. This is an example of using CUE regular expressions to constrain
|
||||
// and validate configuration.
|
||||
type OrganizationStrict struct {
|
||||
Organization `json:",inline"`
|
||||
// Name represents the organization name as a resource name. Must be 63
|
||||
// characters or less. Must start with a letter. May contain non-repeating
|
||||
// hyphens, letters, and numbers. Must end with a letter or number.
|
||||
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
|
||||
// DisplayName represents the human readable organization name.
|
||||
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
|
||||
}
|
||||
|
||||
// Projects represents projects managed by the platform team for use by other
|
||||
// teams using the platform.
|
||||
type Projects map[core.NameLabel]Project
|
||||
|
||||
// Project represents logical grouping of components owned by one or more teams.
|
||||
// Useful for the platform team to manage resources for project teams to use.
|
||||
type Project struct {
|
||||
// Name represents project name.
|
||||
Name string
|
||||
// Owner represents the team who own this project.
|
||||
Owner Owner
|
||||
// Namespaces represents the namespaces assigned to this project.
|
||||
Namespaces map[core.NameLabel]Namespace
|
||||
// Hostnames represents the host names to expose for this project.
|
||||
Hostnames map[core.NameLabel]Hostname
|
||||
}
|
||||
|
||||
// Owner represents the owner of a resource. For example, the name and email
|
||||
// address of an engineering team.
|
||||
type Owner struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
// Namespace represents a Kubernetes namespace.
|
||||
type Namespace struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Hostname represents the left most dns label of a domain name.
|
||||
type Hostname struct {
|
||||
// Name represents the subdomain to expose, e.g. "www"
|
||||
Name string
|
||||
// Namespace represents the namespace metadata.name field of backend object
|
||||
// reference.
|
||||
Namespace string
|
||||
// Service represents the Service metadata.name field of backend object
|
||||
// reference.
|
||||
Service string
|
||||
// Port represents the Service port of the backend object reference.
|
||||
Port int
|
||||
}
|
||||
290
api/author/v1alpha4/definitions.go
Normal file
@@ -0,0 +1,290 @@
|
||||
// # Author API
|
||||
//
|
||||
// Package v1alpha4 contains ergonomic CUE definitions for Holos component
|
||||
// authors. These definitions serve as adapters to produce [Core API] resources
|
||||
// for the holos command line tool.
|
||||
//
|
||||
// [Core API]: https://holos.run/docs/api/core/v1alpha4/
|
||||
package v1alpha4
|
||||
|
||||
import core "github.com/holos-run/holos/api/core/v1alpha4"
|
||||
|
||||
//go:generate ../../../hack/gendoc
|
||||
|
||||
// Platform assembles a Core API [Platform] in the Resource field for the holos
|
||||
// render platform command. Use the Components field to register components
|
||||
// with the platform using a struct. This struct is converted into a list for
|
||||
// final output to holos.
|
||||
//
|
||||
// See related:
|
||||
//
|
||||
// - [Component] collection of components composing the platform.
|
||||
// - [Platform] resource assembled for holos to process.
|
||||
//
|
||||
// [Platform]: https://holos.run/docs/api/core/v1alpha4/#Platform
|
||||
// [Component]: https://holos.run/docs/api/core/v1alpha4/#Component
|
||||
type Platform struct {
|
||||
Name string
|
||||
Components map[NameLabel]core.Component
|
||||
Resource core.Platform
|
||||
}
|
||||
|
||||
// Cluster represents a cluster managed by the Platform.
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
|
||||
// Fleet represents a named collection of similarly configured Clusters. Useful
|
||||
// to segregate workload clusters from their management cluster.
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
|
||||
// StandardFleets represents the standard set of Clusters in a Platform
|
||||
// segmented into Fleets by their purpose. The management Fleet contains a
|
||||
// single Cluster, for example a GKE autopilot cluster with no workloads
|
||||
// deployed for reliability and cost efficiency. The workload Fleet contains
|
||||
// all other Clusters which contain workloads and sync Secrets from the
|
||||
// management cluster.
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\"}"`
|
||||
}
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration associated with a
|
||||
// [BuildPlan]. Useful to define once at the root of the Platform configuration
|
||||
// and reuse across all components.
|
||||
//
|
||||
// [BuildPlan]: https://holos.run/docs/api/core/v1alpha4/#buildplan
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an Application resource when true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// Root represents the path from the git repository root to the WriteTo output
|
||||
// directory, the behavior of the holos render component --write-to flag and
|
||||
// the Core API Component WriteTo field. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
Root string `cue:"string | *\"deploy\""`
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
// AppProject represents the ArgoCD Project to associate the Application with.
|
||||
AppProject string `cue:"string | *\"default\""`
|
||||
}
|
||||
|
||||
// Organization represents organizational metadata useful across the platform.
|
||||
type Organization struct {
|
||||
Name string
|
||||
DisplayName string
|
||||
Domain string
|
||||
}
|
||||
|
||||
// OrganizationStrict represents organizational metadata useful across the
|
||||
// platform. This is an example of using CUE regular expressions to constrain
|
||||
// and validate configuration.
|
||||
type OrganizationStrict struct {
|
||||
Organization `json:",inline"`
|
||||
// Name represents the organization name as a resource name. Must be 63
|
||||
// characters or less. Must start with a letter. May contain non-repeating
|
||||
// hyphens, letters, and numbers. Must end with a letter or number.
|
||||
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
|
||||
// DisplayName represents the human readable organization name.
|
||||
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
|
||||
}
|
||||
|
||||
// Kubernetes provides a [BuildPlan] via the Output field which contains inline
|
||||
// API Objects provided directly from CUE in the Resources field of
|
||||
// [ComponentConfig].
|
||||
//
|
||||
// See related:
|
||||
//
|
||||
// - [ComponentConfig]
|
||||
// - [BuildPlan]
|
||||
//
|
||||
// [BuildPlan]: https://holos.run/docs/api/core/v1alpha4/#BuildPlan
|
||||
type Kubernetes struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
|
||||
// Helm provides a [BuildPlan] via the Output field which generates manifests
|
||||
// from a helm chart with optional mix-in resources provided directly from CUE
|
||||
// in the Resources field.
|
||||
//
|
||||
// This definition is a convenient way to produce a [BuildPlan] composed of
|
||||
// three [Resources] generators with one [Kustomize] transformer.
|
||||
//
|
||||
// See related:
|
||||
//
|
||||
// - [ComponentConfig]
|
||||
// - [Chart]
|
||||
// - [Values]
|
||||
// - [BuildPlan]
|
||||
//
|
||||
// [BuildPlan]: https://holos.run/docs/api/core/v1alpha4/#BuildPlan
|
||||
// [Chart]: https://holos.run/docs/api/core/v1alpha4/#Chart
|
||||
// [Values]: https://holos.run/docs/api/core/v1alpha4/#Values
|
||||
type Helm struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// Chart represents a Helm chart.
|
||||
Chart core.Chart
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values core.Values
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
|
||||
// Kustomize provides a [BuildPlan] via the Output field which generates
|
||||
// manifests from a kustomize kustomization with optional mix-in resources
|
||||
// provided directly from CUE in the Resources field.
|
||||
//
|
||||
// See related:
|
||||
//
|
||||
// - [ComponentConfig]
|
||||
// - [BuildPlan]
|
||||
//
|
||||
// [BuildPlan]: https://holos.run/docs/api/core/v1alpha4/#buildplan
|
||||
type Kustomize struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
|
||||
// ComponentConfig represents the configuration common to all kinds of
|
||||
// component.
|
||||
//
|
||||
// - [Helm] charts.
|
||||
// - [Kubernetes] resources generated from CUE.
|
||||
// - [Kustomize] bases.
|
||||
//
|
||||
// See the following resources for additional details:
|
||||
//
|
||||
// - [Resources]
|
||||
// - [ArgoConfig]
|
||||
// - [KustomizeConfig]
|
||||
// - [BuildPlan]
|
||||
//
|
||||
// [BuildPlan]: https://holos.run/docs/api/core/v1alpha4/#BuildPlan
|
||||
// [Resources]: https://holos.run/docs/api/core/v1alpha4/#Resources
|
||||
type ComponentConfig struct {
|
||||
// Name represents the BuildPlan metadata.name field. Used to construct the
|
||||
// fully rendered manifest file path.
|
||||
Name string
|
||||
// Component represents the path to the component producing the BuildPlan.
|
||||
Component string
|
||||
// Cluster represents the name of the cluster this BuildPlan is for.
|
||||
Cluster string
|
||||
// Resources represents kubernetes resources mixed into the rendered manifest.
|
||||
Resources core.Resources
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this BuildPlan.
|
||||
ArgoConfig ArgoConfig
|
||||
// CommonLabels represents common labels to manage on all rendered manifests.
|
||||
CommonLabels map[string]string
|
||||
// Namespace manages the metadata.namespace field on all resources except the
|
||||
// ArgoCD Application.
|
||||
Namespace string `json:",omitempty"`
|
||||
|
||||
// KustomizeConfig represents the configuration for kustomize.
|
||||
KustomizeConfig KustomizeConfig
|
||||
}
|
||||
|
||||
// KustomizeConfig represents the configuration for kustomize post processing.
|
||||
// The Files field is used to mixing in static manifest files from the component
|
||||
// directory. The Resources field is used for mixing in manifests from network
|
||||
// locations urls.
|
||||
//
|
||||
// See related:
|
||||
//
|
||||
// - [ComponentConfig]
|
||||
// - [Kustomization]
|
||||
//
|
||||
// [Kustomization]: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
|
||||
type KustomizeConfig struct {
|
||||
// Kustomization represents the kustomization used to transform resources.
|
||||
// Note the resources field is internally managed from the Files and Resources fields.
|
||||
Kustomization map[string]any `json:",omitempty"`
|
||||
// Files represents files to copy from the component directory for kustomization.
|
||||
Files map[string]struct{ Source string } `cue:"{[NAME=_]: Source: NAME}"`
|
||||
// Resources represents additional entries to included in the resources list.
|
||||
Resources map[string]struct{ Source string } `cue:"{[NAME=_]: Source: NAME}"`
|
||||
}
|
||||
|
||||
// Projects represents projects managed by the platform team for use by other
|
||||
// teams using the platform.
|
||||
type Projects map[NameLabel]Project
|
||||
|
||||
// Project represents logical grouping of components owned by one or more teams.
|
||||
// Useful for the platform team to manage resources for project teams to use.
|
||||
type Project struct {
|
||||
// Name represents project name.
|
||||
Name string
|
||||
// Owner represents the team who own this project.
|
||||
Owner Owner
|
||||
// Namespaces represents the namespaces assigned to this project.
|
||||
Namespaces map[NameLabel]Namespace
|
||||
// Hostnames represents the host names to expose for this project.
|
||||
Hostnames map[NameLabel]Hostname
|
||||
// CommonLabels represents common labels to manage on all rendered manifests.
|
||||
CommonLabels map[string]string
|
||||
}
|
||||
|
||||
// Owner represents the owner of a resource. For example, the name and email
|
||||
// address of an engineering team.
|
||||
type Owner struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
// Namespace represents a Kubernetes namespace.
|
||||
type Namespace struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Hostname represents the left most dns label of a domain name.
|
||||
type Hostname struct {
|
||||
// Name represents the subdomain to expose, e.g. "www"
|
||||
Name string
|
||||
// Namespace represents the namespace metadata.name field of backend object
|
||||
// reference.
|
||||
Namespace string
|
||||
// Service represents the Service metadata.name field of backend object
|
||||
// reference.
|
||||
Service string
|
||||
// Port represents the Service port of the backend object reference.
|
||||
Port int
|
||||
}
|
||||
|
||||
// NameLabel signals the common use case of converting a struct to a list where
|
||||
// the name field of each value unifies with the field name of the outer struct.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// S: [NameLabel=string]: name: NameLabel
|
||||
// S: jeff: _
|
||||
// S: gary: _
|
||||
// S: nate: _
|
||||
// L: [for x in S {x}]
|
||||
// // L is [{name: "jeff"}, {name: "gary"}, {name: "nate"}]
|
||||
type NameLabel string
|
||||
53
api/core/v1alpha3/apiobjects.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package v1alpha3
|
||||
|
||||
import "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
// InternalLabel is an arbitrary unique identifier internal to holos itself.
|
||||
// The holos cli is expected to never write a InternalLabel value to rendered
|
||||
// output files, therefore use a [InternalLabel] when the identifier must be
|
||||
// unique and internal. Defined as a type for clarity and type checking.
|
||||
//
|
||||
// A InternalLabel is useful to convert a CUE struct to a list, for example
|
||||
// producing a list of [APIObject] resources from an [APIObjectMap]. A CUE
|
||||
// struct using InternalLabel keys is guaranteed to not lose data when rendering
|
||||
// output because a InternalLabel is expected to never be written to the final
|
||||
// output.
|
||||
type InternalLabel string
|
||||
|
||||
// NameLabel is a unique identifier useful to convert a CUE struct to a list
|
||||
// when the values have a Name field with a default value. This type is
|
||||
// intended to indicate the common use case of converting a struct to a list
|
||||
// where the Name field of the value aligns with the struct field name.
|
||||
type NameLabel string
|
||||
|
||||
// Kind is a kubernetes api object kind. Defined as a type for clarity and type
|
||||
// checking.
|
||||
type Kind string
|
||||
|
||||
// APIObject represents the most basic generic form of a single kubernetes api
|
||||
// object. Represented as a JSON object internally for compatibility between
|
||||
// tools, for example loading from CUE.
|
||||
type APIObject structpb.Struct
|
||||
|
||||
// APIObjectMap represents the marshalled yaml representation of kubernetes api
|
||||
// objects. Do not produce an APIObjectMap directly, instead use [APIObjects]
|
||||
// to produce the marshalled yaml representation from CUE data, then provide the
|
||||
// result to [Component].
|
||||
type APIObjectMap map[Kind]map[InternalLabel]string
|
||||
|
||||
// APIObjects represents Kubernetes API objects defined directly from CUE code.
|
||||
// Useful to mix in resources to any kind of [Component], for example
|
||||
// adding an ExternalSecret resource to a [HelmChart].
|
||||
//
|
||||
// [Kind] must be the resource kind, e.g. Deployment or Service.
|
||||
//
|
||||
// [InternalLabel] is an arbitrary internal identifier to uniquely identify the resource
|
||||
// within the context of a `holos` command. Holos will never write the
|
||||
// intermediate label to rendered output.
|
||||
//
|
||||
// Refer to [Component] which accepts an [APIObjectMap] field provided by
|
||||
// [APIObjects].
|
||||
type APIObjects struct {
|
||||
APIObjects map[Kind]map[InternalLabel]APIObject `json:"apiObjects"`
|
||||
APIObjectMap APIObjectMap `json:"apiObjectMap"`
|
||||
}
|
||||
52
api/core/v1alpha3/buildplan.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package v1alpha3
|
||||
|
||||
// FilePath represents a file path.
|
||||
type FilePath string
|
||||
|
||||
// FileContent represents file contents.
|
||||
type FileContent string
|
||||
|
||||
// FileContentMap represents a mapping of file paths to file contents.
|
||||
type FileContentMap map[FilePath]FileContent
|
||||
|
||||
// BuildPlan represents a build plan for the holos cli to execute. The purpose
|
||||
// of a BuildPlan is to define one or more [Component] kinds. For example a
|
||||
// [HelmChart], [KustomizeBuild], or [KubernetesObjects].
|
||||
//
|
||||
// A BuildPlan usually has an additional empty [KubernetesObjects] for the
|
||||
// purpose of using the [Component] DeployFiles field to deploy an ArgoCD
|
||||
// or Flux gitops resource for the holos component.
|
||||
type BuildPlan struct {
|
||||
Kind string `json:"kind" cue:"\"BuildPlan\""`
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
|
||||
Spec BuildPlanSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// BuildPlanSpec represents the specification of the build plan.
|
||||
type BuildPlanSpec struct {
|
||||
// Disabled causes the holos cli to take no action over the [BuildPlan].
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
// Components represents multiple [HolosComponent] kinds to manage.
|
||||
Components BuildPlanComponents `json:"components,omitempty"`
|
||||
}
|
||||
|
||||
type BuildPlanComponents struct {
|
||||
Resources map[InternalLabel]KubernetesObjects `json:"resources,omitempty"`
|
||||
KubernetesObjectsList []KubernetesObjects `json:"kubernetesObjectsList,omitempty"`
|
||||
HelmChartList []HelmChart `json:"helmChartList,omitempty"`
|
||||
KustomizeBuildList []KustomizeBuild `json:"kustomizeBuildList,omitempty"`
|
||||
}
|
||||
|
||||
// Kustomize represents resources necessary to execute a kustomize build.
|
||||
// Intended for at least two use cases:
|
||||
//
|
||||
// 1. Process a [KustomizeBuild] [Component] which represents raw yaml
|
||||
// file resources in a holos component directory.
|
||||
// 2. Post process a [HelmChart] [Component] to inject istio, patch jobs,
|
||||
// add custom labels, etc...
|
||||
type Kustomize struct {
|
||||
// KustomizeFiles holds file contents for kustomize, e.g. patch files.
|
||||
KustomizeFiles FileContentMap `json:"kustomizeFiles,omitempty"`
|
||||
// ResourcesFile is the file name used for api objects in kustomization.yaml
|
||||
ResourcesFile string `json:"resourcesFile,omitempty"`
|
||||
}
|
||||
43
api/core/v1alpha3/component.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package v1alpha3
|
||||
|
||||
// Component defines the fields common to all holos component kinds. Every
|
||||
// holos component kind should embed Component.
|
||||
type Component struct {
|
||||
// Kind is a string value representing the resource this object represents.
|
||||
Kind string `json:"kind"`
|
||||
// APIVersion represents the versioned schema of this representation of an object.
|
||||
APIVersion string `json:"apiVersion" cue:"\"v1alpha3\""`
|
||||
// Metadata represents data about the holos component such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
|
||||
// APIObjectMap holds the marshalled representation of api objects. Useful to
|
||||
// mix in resources to each Component type, for example adding an
|
||||
// ExternalSecret to a [HelmChart] Component. Refer to [APIObjects].
|
||||
APIObjectMap APIObjectMap `json:"apiObjectMap,omitempty"`
|
||||
|
||||
// DeployFiles represents file paths relative to the cluster deploy directory
|
||||
// with the value representing the file content. Intended for defining the
|
||||
// ArgoCD Application resource or Flux Kustomization resource from within CUE,
|
||||
// but may be used to render any file related to the build plan from CUE.
|
||||
DeployFiles FileContentMap `json:"deployFiles,omitempty"`
|
||||
|
||||
// Kustomize represents a kubectl kustomize build post-processing step.
|
||||
Kustomize `json:"kustomize,omitempty"`
|
||||
|
||||
// Skip causes holos to take no action regarding this component.
|
||||
Skip bool `json:"skip" cue:"bool | *false"`
|
||||
}
|
||||
|
||||
// Metadata represents data about the object such as the Name.
|
||||
type Metadata struct {
|
||||
// Name represents the name of the holos component.
|
||||
Name string `json:"name"`
|
||||
// Namespace is the primary namespace of the holos component. A holos
|
||||
// component may manage resources in multiple namespaces, in this case
|
||||
// consider setting the component namespace to default.
|
||||
//
|
||||
// This field is optional because not all resources require a namespace,
|
||||
// particularly CRDs and DeployFiles functionality.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
11
api/core/v1alpha3/constants.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package v1alpha3
|
||||
|
||||
const (
|
||||
APIVersion = "v1alpha3"
|
||||
BuildPlanKind = "BuildPlan"
|
||||
HelmChartKind = "HelmChart"
|
||||
// ChartDir is the directory name created in the holos component directory to cache a chart.
|
||||
ChartDir = "vendor"
|
||||
// ResourcesFile is the file name used to store component output when post-processing with kustomize.
|
||||
ResourcesFile = "resources.yaml"
|
||||
)
|
||||
26
api/core/v1alpha3/doc.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Package v1alpha3 contains the core API contract between the holos cli and CUE
|
||||
// configuration code. Platform designers, operators, and software developers
|
||||
// use this API to write configuration in CUE which `holos` loads. The overall
|
||||
// shape of the API defines imperative actions `holos` should carry out to
|
||||
// render the complete yaml that represents a Platform.
|
||||
//
|
||||
// [Platform] defines the complete configuration of a platform. With the holos
|
||||
// reference platform this takes the shape of one management cluster and at
|
||||
// least two workload cluster. Each cluster has multiple [Component]
|
||||
// resources applied to it.
|
||||
//
|
||||
// Each holos component path, e.g. `components/namespaces` produces exactly one
|
||||
// [BuildPlan] which in turn contains a set of [Component] kinds.
|
||||
//
|
||||
// The primary kinds of [Component] are:
|
||||
//
|
||||
// 1. [HelmChart] to render config from a helm chart.
|
||||
// 2. [KustomizeBuild] to render config from [Kustomize]
|
||||
// 3. [KubernetesObjects] to render [APIObjects] defined directly in CUE
|
||||
// configuration.
|
||||
//
|
||||
// Note that Holos operates as a data pipeline, so the output of a [HelmChart]
|
||||
// may be provided to [Kustomize] for post-processing.
|
||||
package v1alpha3
|
||||
|
||||
//go:generate ../../../hack/gendoc
|
||||
38
api/core/v1alpha3/helm.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package v1alpha3
|
||||
|
||||
// HelmChart represents a holos component which wraps around an upstream helm
|
||||
// chart. Holos orchestrates helm by providing values obtained from CUE,
|
||||
// renders the output using `helm template`, then post-processes the helm output
|
||||
// yaml using the general functionality provided by [Component], for
|
||||
// example [Kustomize] post-rendering and mixing in additional kubernetes api
|
||||
// objects.
|
||||
type HelmChart struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"HelmChart\""`
|
||||
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart"`
|
||||
// ValuesContent represents the values.yaml file holos passes to the `helm
|
||||
// template` command.
|
||||
ValuesContent string `json:"valuesContent"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks" cue:"bool | *false"`
|
||||
}
|
||||
|
||||
// Chart represents a helm chart.
|
||||
type Chart struct {
|
||||
// Name represents the chart name.
|
||||
Name string `json:"name"`
|
||||
// Version represents the chart version.
|
||||
Version string `json:"version"`
|
||||
// Release represents the chart release when executing helm template.
|
||||
Release string `json:"release"`
|
||||
// Repository represents the repository to fetch the chart from.
|
||||
Repository Repository `json:"repository,omitempty"`
|
||||
}
|
||||
|
||||
// Repository represents a helm chart repository.
|
||||
type Repository struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
10
api/core/v1alpha3/kubernetesobjects.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package v1alpha3
|
||||
|
||||
const KubernetesObjectsKind = "KubernetesObjects"
|
||||
|
||||
// KubernetesObjects represents a [Component] composed of Kubernetes API
|
||||
// objects provided directly from CUE using [APIObjects].
|
||||
type KubernetesObjects struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"KubernetesObjects\""`
|
||||
}
|
||||
8
api/core/v1alpha3/kustomizebuild.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package v1alpha3
|
||||
|
||||
// KustomizeBuild represents a [Component] that renders plain yaml files in
|
||||
// the holos component directory using `kubectl kustomize build`.
|
||||
type KustomizeBuild struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"KustomizeBuild\""`
|
||||
}
|
||||
44
api/core/v1alpha3/platform.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package v1alpha3
|
||||
|
||||
import "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
// Platform represents a platform to manage. A Platform resource informs holos
|
||||
// which components to build. The platform resource also acts as a container
|
||||
// for the platform model form values provided by the PlatformService. The
|
||||
// primary use case is to collect the cluster names, cluster types, platform
|
||||
// model, and holos components to build into one resource.
|
||||
type Platform struct {
|
||||
// Kind is a string value representing the resource this object represents.
|
||||
Kind string `json:"kind" cue:"\"Platform\""`
|
||||
// APIVersion represents the versioned schema of this representation of an object.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
|
||||
// Metadata represents data about the object such as the Name.
|
||||
Metadata PlatformMetadata `json:"metadata"`
|
||||
|
||||
// Spec represents the specification.
|
||||
Spec PlatformSpec `json:"spec"`
|
||||
}
|
||||
|
||||
type PlatformMetadata struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// PlatformSpec represents the specification of a Platform. Think of a platform
|
||||
// specification as a list of platform components to apply to a list of
|
||||
// kubernetes clusters combined with the user-specified Platform Model.
|
||||
type PlatformSpec struct {
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `json:"model" cue:"{...}"`
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []PlatformSpecComponent `json:"components"`
|
||||
}
|
||||
|
||||
// PlatformSpecComponent represents a holos component to build or render.
|
||||
type PlatformSpecComponent struct {
|
||||
// Path is the path of the component relative to the platform root.
|
||||
Path string `json:"path"`
|
||||
// Cluster is the cluster name to provide when rendering the component.
|
||||
Cluster string `json:"cluster"`
|
||||
}
|
||||
402
api/core/v1alpha4/types.go
Normal file
@@ -0,0 +1,402 @@
|
||||
// # Core API
|
||||
//
|
||||
// Package v1alpha4 contains the core API contract between the holos cli and CUE
|
||||
// configuration code. Platform designers, operators, and software developers
|
||||
// use this API to write configuration in CUE which holos loads. The Core API
|
||||
// is declarative. Each resource represents a desired state necessary for holos
|
||||
// to fully render Kubernetes manifests into plain files.
|
||||
//
|
||||
// The following resources provide important context for the Core API. The
|
||||
// [Author API] is intended for component authors as a convenient adapter for
|
||||
// the Core API resources Holos expects.
|
||||
//
|
||||
// 1. [Technical Overview]
|
||||
// 2. [Quickstart]
|
||||
// 3. [Author API]
|
||||
//
|
||||
// # Platform
|
||||
//
|
||||
// [Platform] defines the complete configuration of a platform. A platform
|
||||
// represents a [Component] collection.
|
||||
//
|
||||
// Inspect a Platform resource holos would process by executing:
|
||||
//
|
||||
// cue export --out yaml ./platform
|
||||
//
|
||||
// # Component
|
||||
//
|
||||
// A [Component] is the combination of CUE code along one path relative to the
|
||||
// platform root directory plus data injected from the [PlatformSpec] via CUE tags.
|
||||
// The platform configuration root is the directory containing cue.mod.
|
||||
//
|
||||
// A [Component] always produces exactly one [BuildPlan].
|
||||
//
|
||||
// # BuildPlan
|
||||
//
|
||||
// A [BuildPlan] contains an [Artifact] collection. A BuildPlan often produces
|
||||
// two artifacts, one containing the fully rendered Kubernetes API resources,
|
||||
// the other containing an additional resource to manage the former with GitOps.
|
||||
// For example, a BuildPlan for a podinfo component produces a manifest
|
||||
// containing a Deployment and a Service, along with a second manifest
|
||||
// containing an ArgoCD Application.
|
||||
//
|
||||
// Inspect a BuildPlan resource holos render component would process by executing:
|
||||
//
|
||||
// cue export --out yaml ./projects/platform/components/namespaces
|
||||
//
|
||||
// # Artifact
|
||||
//
|
||||
// An [Artifact] is one fully rendered manifest file produced from the final
|
||||
// [Transformer] in a sequence of transformers. An Artifact may also be
|
||||
// produced directly from a [Generator], but this use case is uncommon.
|
||||
//
|
||||
// # Transformer
|
||||
//
|
||||
// A [Transformer] takes multiple inputs from prior [Generator] or [Transformer]
|
||||
// outputs, then transforms the data into one output. [Kustomize] is the most
|
||||
// commonly used transformer, though a simple [Join] is also supported.
|
||||
//
|
||||
// 1. [Kustomize] - Patch and transform the output from prior generators or
|
||||
// transformers. See [Introduction to Kustomize].
|
||||
// 2. [Join] - Concatenate multiple prior outputs into one output.
|
||||
//
|
||||
// # Generators
|
||||
//
|
||||
// A [Generator] generates Kubernetes resources. [Helm] and [Resources] are the
|
||||
// most commonly used, often paired together to mix-in resources to an
|
||||
// unmodified Helm chart. A simple [File] generator is also available for use
|
||||
// with the [Kustomize] transformer.
|
||||
//
|
||||
// 1. [Resources] - Generates resources from CUE code.
|
||||
// 2. [Helm] - Generates rendered yaml from a [Chart].
|
||||
// 3. [File] - Generates data by reading a file from the component directory.
|
||||
//
|
||||
// [Introduction to Kustomize]: https://kubectl.docs.kubernetes.io/guides/config_management/introduction/
|
||||
// [Author API]: https://holos.run/docs/api/author/
|
||||
// [Quickstart]: https://holos.run/docs/quickstart/
|
||||
// [Technical Overview]: https://holos.run/docs/technical-overview/
|
||||
package v1alpha4
|
||||
|
||||
//go:generate ../../../hack/gendoc
|
||||
|
||||
// BuildPlan represents a build plan for holos to execute. Each [Platform]
|
||||
// component produces exactly one BuildPlan.
|
||||
//
|
||||
// One or more [Artifact] files are produced by a BuildPlan, representing the
|
||||
// fully rendered manifests for the Kubernetes API Server.
|
||||
//
|
||||
// # Example BuildPlan
|
||||
//
|
||||
// Command:
|
||||
//
|
||||
// cue export --out yaml ./projects/platform/components/namespaces
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// kind: BuildPlan
|
||||
// apiVersion: v1alpha4
|
||||
// metadata:
|
||||
// name: dev-namespaces
|
||||
// spec:
|
||||
// component: projects/platform/components/namespaces
|
||||
// artifacts:
|
||||
// - artifact: clusters/no-cluster/components/dev-namespaces/dev-namespaces.gen.yaml
|
||||
// generators:
|
||||
// - kind: Resources
|
||||
// output: resources.gen.yaml
|
||||
// resources:
|
||||
// Namespace:
|
||||
// dev-jeff:
|
||||
// metadata:
|
||||
// name: dev-jeff
|
||||
// labels:
|
||||
// kubernetes.io/metadata.name: dev-jeff
|
||||
// kind: Namespace
|
||||
// apiVersion: v1
|
||||
// transformers:
|
||||
// - kind: Kustomize
|
||||
// inputs:
|
||||
// - resources.gen.yaml
|
||||
// output: clusters/no-cluster/components/dev-namespaces/dev-namespaces.gen.yaml
|
||||
// kustomize:
|
||||
// kustomization:
|
||||
// commonLabels:
|
||||
// holos.run/component.name: dev-namespaces
|
||||
// resources:
|
||||
// - resources.gen.yaml
|
||||
type BuildPlan struct {
|
||||
// Kind represents the type of the resource.
|
||||
Kind string `json:"kind" cue:"\"BuildPlan\""`
|
||||
// APIVersion represents the versioned schema of the resource.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha4\""`
|
||||
// Metadata represents data about the resource such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
// Spec specifies the desired state of the resource.
|
||||
Spec BuildPlanSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// BuildPlanSpec represents the specification of the [BuildPlan].
|
||||
type BuildPlanSpec struct {
|
||||
// Component represents the component that produced the build plan.
|
||||
// Represented as a path relative to the platform root.
|
||||
Component string `json:"component"`
|
||||
// Disabled causes the holos cli to disregard the build plan.
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
// Artifacts represents the artifacts for holos to build.
|
||||
Artifacts []Artifact `json:"artifacts"`
|
||||
}
|
||||
|
||||
// Artifact represents one fully rendered manifest produced by a [Transformer]
|
||||
// sequence, which transforms a [Generator] collection. A [BuildPlan] produces
|
||||
// an [Artifact] collection.
|
||||
//
|
||||
// Each Artifact produces one manifest file artifact. Generator Output values
|
||||
// are used as Transformer Inputs. The Output field of the final [Transformer]
|
||||
// should have the same value as the Artifact field.
|
||||
//
|
||||
// When there is more than one [Generator] there must be at least one
|
||||
// [Transformer] to combine outputs into one Artifact. If there is a single
|
||||
// Generator, it may directly produce the Artifact output.
|
||||
//
|
||||
// An Artifact is processed concurrently with other artifacts in the same
|
||||
// [BuildPlan]. An Artifact should not use an output from another Artifact as
|
||||
// an input. Each [Generator] may also run concurrently. Each [Transformer] is
|
||||
// executed sequentially starting after all generators have completed.
|
||||
//
|
||||
// Output fields are write-once. It is an error for multiple Generators or
|
||||
// Transformers to produce the same Output value within the context of a
|
||||
// [BuildPlan].
|
||||
type Artifact struct {
|
||||
Artifact FilePath `json:"artifact,omitempty"`
|
||||
Generators []Generator `json:"generators,omitempty"`
|
||||
Transformers []Transformer `json:"transformers,omitempty"`
|
||||
Skip bool `json:"skip,omitempty"`
|
||||
}
|
||||
|
||||
// Generator generates an intermediate manifest for a [Artifact].
|
||||
//
|
||||
// Each Generator in a [Artifact] must have a distinct Output value for a
|
||||
// [Transformer] to reference.
|
||||
//
|
||||
// Refer to [Resources], [Helm], and [File].
|
||||
type Generator struct {
|
||||
// Kind represents the kind of generator. Must be Resources, Helm, or File.
|
||||
Kind string `json:"kind" cue:"\"Resources\" | \"Helm\" | \"File\""`
|
||||
// Output represents a file for a Transformer or Artifact to consume.
|
||||
Output FilePath `json:"output"`
|
||||
// Resources generator. Ignored unless kind is Resources. Resources are
|
||||
// stored as a two level struct. The top level key is the Kind of resource,
|
||||
// e.g. Namespace or Deployment. The second level key is an arbitrary
|
||||
// InternalLabel. The third level is a map[string]any representing the
|
||||
// Resource.
|
||||
Resources Resources `json:"resources,omitempty"`
|
||||
// Helm generator. Ignored unless kind is Helm.
|
||||
Helm Helm `json:"helm,omitempty"`
|
||||
// File generator. Ignored unless kind is File.
|
||||
File File `json:"file,omitempty"`
|
||||
}
|
||||
|
||||
// Resource represents one kubernetes api object.
|
||||
type Resource map[string]any
|
||||
|
||||
// Resources represents a kubernetes resources [Generator] from CUE.
|
||||
type Resources map[Kind]map[InternalLabel]Resource
|
||||
|
||||
// File represents a simple single file copy [Generator]. Useful with a
|
||||
// [Kustomize] [Transformer] to process plain manifest files stored in the
|
||||
// component directory. Multiple File generators may be used to transform
|
||||
// multiple resources.
|
||||
type File struct {
|
||||
// Source represents a file sub-path relative to the component path.
|
||||
Source FilePath `json:"source"`
|
||||
}
|
||||
|
||||
// Helm represents a [Chart] manifest [Generator].
|
||||
type Helm struct {
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart"`
|
||||
// Values represents values for holos to marshal into values.yaml when
|
||||
// rendering the chart.
|
||||
Values Values `json:"values"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks,omitempty"`
|
||||
// Namespace represents the helm namespace flag
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// Values represents [Helm] Chart values generated from CUE.
|
||||
type Values map[string]any
|
||||
|
||||
// Chart represents a [Helm] Chart.
|
||||
type Chart struct {
|
||||
// Name represents the chart name.
|
||||
Name string `json:"name"`
|
||||
// Version represents the chart version.
|
||||
Version string `json:"version"`
|
||||
// Release represents the chart release when executing helm template.
|
||||
Release string `json:"release"`
|
||||
// Repository represents the repository to fetch the chart from.
|
||||
Repository Repository `json:"repository,omitempty"`
|
||||
}
|
||||
|
||||
// Repository represents a [Helm] [Chart] repository.
|
||||
type Repository struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Transformer transforms [Generator] manifests within a [Artifact].
|
||||
type Transformer struct {
|
||||
// Kind represents the kind of transformer. Must be Kustomize, or Join.
|
||||
Kind string `json:"kind" cue:"\"Kustomize\" | \"Join\""`
|
||||
// Inputs represents the files to transform. The Output of prior Generators
|
||||
// and Transformers.
|
||||
Inputs []FilePath `json:"inputs"`
|
||||
// Output represents a file for a subsequent Transformer or Artifact to
|
||||
// consume.
|
||||
Output FilePath `json:"output"`
|
||||
// Kustomize transformer. Ignored unless kind is Kustomize.
|
||||
Kustomize Kustomize `json:"kustomize,omitempty"`
|
||||
// Join transformer. Ignored unless kind is Join.
|
||||
Join Join `json:"join,omitempty"`
|
||||
}
|
||||
|
||||
// Join represents a [Transformer] using [bytes.Join] to concatenate multiple
|
||||
// inputs into one output with a separator. Useful for combining output from
|
||||
// [Helm] and [Resources] together into one [Artifact] when [Kustomize] is
|
||||
// otherwise unnecessary.
|
||||
//
|
||||
// [bytes.Join]: https://pkg.go.dev/bytes#Join
|
||||
type Join struct {
|
||||
Separator string `json:"separator" cue:"string | *\"---\\n\""`
|
||||
}
|
||||
|
||||
// Kustomize represents a kustomization [Transformer].
|
||||
type Kustomize struct {
|
||||
// Kustomization represents the decoded kustomization.yaml file
|
||||
Kustomization Kustomization `json:"kustomization"`
|
||||
// Files holds file contents for kustomize, e.g. patch files.
|
||||
Files FileContentMap `json:"files,omitempty"`
|
||||
}
|
||||
|
||||
// Kustomization represents a kustomization.yaml file for use with the
|
||||
// [Kustomize] [Transformer]. Untyped to avoid tightly coupling holos to
|
||||
// kubectl versions which was a problem for the Flux maintainers. Type checking
|
||||
// is expected to happen in CUE against the kubectl version the user prefers.
|
||||
type Kustomization map[string]any
|
||||
|
||||
// FileContent represents file contents.
|
||||
type FileContent string
|
||||
|
||||
// FileContentMap represents a mapping of file paths to file contents.
|
||||
type FileContentMap map[FilePath]FileContent
|
||||
|
||||
// FilePath represents a file path.
|
||||
type FilePath string
|
||||
|
||||
// InternalLabel is an arbitrary unique identifier internal to holos itself.
|
||||
// The holos cli is expected to never write a InternalLabel value to rendered
|
||||
// output files, therefore use a InternalLabel when the identifier must be
|
||||
// unique and internal. Defined as a type for clarity and type checking.
|
||||
type InternalLabel string
|
||||
|
||||
// Kind is a discriminator. Defined as a type for clarity and type checking.
|
||||
type Kind string
|
||||
|
||||
// NameLabel is a unique identifier useful to convert a CUE struct to a list
|
||||
// when the values have a Name field with a default value. NameLabel indicates
|
||||
// the common use case of converting a struct to a list where the Name field of
|
||||
// the value aligns with the outer struct field name.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// Outer: [NAME=_]: Name: NAME
|
||||
type NameLabel string
|
||||
|
||||
// Platform represents a platform to manage. A Platform resource informs holos
|
||||
// which components to build. The platform resource also acts as a container
|
||||
// for the platform model form values provided by the PlatformService. The
|
||||
// primary use case is to collect the cluster names, cluster types, platform
|
||||
// model, and holos components to build into one resource.
|
||||
type Platform struct {
|
||||
// Kind is a string value representing the resource.
|
||||
Kind string `json:"kind" cue:"\"Platform\""`
|
||||
// APIVersion represents the versioned schema of this resource.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha4\""`
|
||||
// Metadata represents data about the resource such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
|
||||
// Spec represents the specification.
|
||||
Spec PlatformSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// Metadata represents data about the resource such as the Name.
|
||||
type Metadata struct {
|
||||
// Name represents the resource name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// PlatformSpec represents the specification of a [Platform]. Think of a
|
||||
// platform spec as a [Component] collection for multiple kubernetes clusters
|
||||
// combined with the user-specified Platform Model.
|
||||
type PlatformSpec struct {
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []Component `json:"components"`
|
||||
}
|
||||
|
||||
// Component represents the complete context necessary to produce a [BuildPlan].
|
||||
// Component carries information injected from holos render platform to holos
|
||||
// render component to produce each [BuildPlan].
|
||||
//
|
||||
// All of these fields are passed to the holos render component command using
|
||||
// flags, which in turn are injected to CUE using tags. For clarity, CUE field
|
||||
// and tag names should match the struct json tag names below.
|
||||
type Component struct {
|
||||
// Name represents the name of the component. Injected as the tag variable
|
||||
// "holos_name" to set the BuildPlan metadata.name field. Necessary for clear
|
||||
// user feedback during platform rendering.
|
||||
Name string `json:"name"`
|
||||
// Component represents the path of the component relative to the platform
|
||||
// root. Injected as the tag variable "holos_component".
|
||||
Component string `json:"component"`
|
||||
// Cluster is the cluster name to provide when rendering the component.
|
||||
// Injected as the tag variable "holos_cluster".
|
||||
Cluster string `json:"cluster"`
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
// Injected as the tag "holos_model".
|
||||
Model map[string]any `json:"model"`
|
||||
// Tags represents cue @tag variables injected into the holos render component
|
||||
// command from the holos render platform command. Tags with a "holos_"
|
||||
// prefix are reserved for use by the Holos Authors.
|
||||
Tags map[string]string `json:"tags,omitempty"`
|
||||
// WriteTo represents the holos render component --write-to flag. If empty,
|
||||
// the default value for the --write-to flag is used.
|
||||
WriteTo string `json:"writeTo,omitempty"`
|
||||
}
|
||||
|
||||
// Tags represents standardized fields injected into the component [BuildPlan]
|
||||
// from the [Platform].
|
||||
//
|
||||
// Note, tags should have a reasonable default value to easily use cue eval and
|
||||
// cue export without needing to make a bunch of decisions about tag values.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// import core "github.com/holos-run/holos/api/core/v1alpha4"
|
||||
// _Tags: core.#Tags & {
|
||||
// cluster: _ @tag(cluster, type=string)
|
||||
// environment: _ @tag(environment, type=string)
|
||||
// component: _ @tag(component, type=string)
|
||||
// name: _ @tag(name, type=string)
|
||||
// }
|
||||
type Tags struct {
|
||||
// Name represents the BuildPlan metadata.name field injected from the Platform.
|
||||
Name string `json:"name" cue:"string | *\"no-name\""`
|
||||
// Cluster represents the cluster name injected from
|
||||
Cluster string `json:"cluster" cue:"string | *\"no-cluster\""`
|
||||
// Environment represents the build plan environment.
|
||||
Environment string `json:"environment" cue:"string | *\"no-environment\""`
|
||||
// Component represents the path of the component relative to the platform root.
|
||||
Component string `json:"component" cue:"string | *\"no-component\""`
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
@@ -38,7 +39,7 @@ func (bp *BuildPlan) Validate() error {
|
||||
errs = append(errs, fmt.Sprintf("apiVersion invalid: want: %s have: %s", APIVersion, bp.APIVersion))
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("invalid BuildPlan: " + strings.Join(errs, ", "))
|
||||
return errors.New("invalid BuildPlan: " + strings.Join(errs, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
module: "github.com/holos-run/holos"
|
||||
5
doc/md/api.md
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# API Reference
|
||||
|
||||
<DocCardList />
|
||||
5
doc/md/api/author.md
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Author API
|
||||
|
||||
<DocCardList />
|
||||
320
doc/md/api/author/v1alpha3.md
Normal file
@@ -0,0 +1,320 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# v1alpha3
|
||||
|
||||
```go
|
||||
import "github.com/holos-run/holos/api/author/v1alpha3"
|
||||
```
|
||||
|
||||
Package v1alpha3 contains CUE definitions intended as convenience wrappers around the core data types defined in package core. The purpose of these wrappers is to make life easier for platform engineers by reducing boiler plate code and generating component build plans in a consistent manner.
|
||||
|
||||
## Index
|
||||
|
||||
- [type ArgoConfig](<#ArgoConfig>)
|
||||
- [type Cluster](<#Cluster>)
|
||||
- [type ComponentFields](<#ComponentFields>)
|
||||
- [type Fleet](<#Fleet>)
|
||||
- [type Helm](<#Helm>)
|
||||
- [type Hostname](<#Hostname>)
|
||||
- [type Kubernetes](<#Kubernetes>)
|
||||
- [type Kustomize](<#Kustomize>)
|
||||
- [type Namespace](<#Namespace>)
|
||||
- [type Organization](<#Organization>)
|
||||
- [type OrganizationStrict](<#OrganizationStrict>)
|
||||
- [type Owner](<#Owner>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type Project](<#Project>)
|
||||
- [type Projects](<#Projects>)
|
||||
- [type StandardFleets](<#StandardFleets>)
|
||||
|
||||
|
||||
<a name="ArgoConfig"></a>
|
||||
## type ArgoConfig {#ArgoConfig}
|
||||
|
||||
ArgoConfig represents the ArgoCD GitOps configuration for a Component. Useful to define once at the root of the Platform configuration and reuse across all Components.
|
||||
|
||||
```go
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an ArgoCD Application resource for GitOps if true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// ClusterName represents the cluster within the platform the Application
|
||||
// resource is intended for.
|
||||
ClusterName string
|
||||
// DeployRoot represents the path from the git repository root to the `deploy`
|
||||
// rendering output directory. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
DeployRoot string `cue:"string | *\".\""`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
// AppProject represents the ArgoCD Project to associate the Application with.
|
||||
AppProject string `cue:"string | *\"default\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Cluster"></a>
|
||||
## type Cluster {#Cluster}
|
||||
|
||||
Cluster represents a cluster managed by the Platform.
|
||||
|
||||
```go
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="ComponentFields"></a>
|
||||
## type ComponentFields {#ComponentFields}
|
||||
|
||||
Component represents the fields common the different kinds of component. All components have a name, support mixing in resources, and produce a BuildPlan.
|
||||
|
||||
```go
|
||||
type ComponentFields struct {
|
||||
// Name represents the Component name.
|
||||
Name string
|
||||
// Resources are kubernetes api objects to mix into the output.
|
||||
Resources map[string]any
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
|
||||
ArgoConfig ArgoConfig
|
||||
// BuildPlan represents the derived BuildPlan for the Holos cli to render.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Fleet"></a>
|
||||
## type Fleet {#Fleet}
|
||||
|
||||
Fleet represents a named collection of similarly configured Clusters. Useful to segregate workload clusters from their management cluster.
|
||||
|
||||
```go
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Helm"></a>
|
||||
## type Helm {#Helm}
|
||||
|
||||
Helm provides a BuildPlan via the Output field which contains one HelmChart from package core. Useful as a convenience wrapper to render a HelmChart with optional mix\-in resources and Kustomization post\-processing.
|
||||
|
||||
```go
|
||||
type Helm struct {
|
||||
ComponentFields `json:",inline"`
|
||||
|
||||
// Version represents the chart version.
|
||||
Version string
|
||||
// Namespace represents the helm namespace option when rendering the chart.
|
||||
Namespace string
|
||||
|
||||
// Repo represents the chart repository
|
||||
Repo struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values interface{} `cue:"{...}"`
|
||||
|
||||
// Chart represents the derived HelmChart for inclusion in the BuildPlan
|
||||
// Output field value. The default HelmChart field values are derived from
|
||||
// other Helm field values and should be sufficient for most use cases.
|
||||
Chart core.HelmChart
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor bool `cue:"true | *false"`
|
||||
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches map[core.InternalLabel]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Hostname"></a>
|
||||
## type Hostname {#Hostname}
|
||||
|
||||
Hostname represents the left most dns label of a domain name.
|
||||
|
||||
```go
|
||||
type Hostname struct {
|
||||
// Name represents the subdomain to expose, e.g. "www"
|
||||
Name string
|
||||
// Namespace represents the namespace metadata.name field of backend object
|
||||
// reference.
|
||||
Namespace string
|
||||
// Service represents the Service metadata.name field of backend object
|
||||
// reference.
|
||||
Service string
|
||||
// Port represents the Service port of the backend object reference.
|
||||
Port int
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kubernetes"></a>
|
||||
## type Kubernetes {#Kubernetes}
|
||||
|
||||
Kubernetes provides a BuildPlan via the Output field which contains inline API Objects provided directly from CUE.
|
||||
|
||||
```go
|
||||
type Kubernetes struct {
|
||||
ComponentFields `json:",inline"`
|
||||
// Objects represents the kubernetes api objects for the Component.
|
||||
Objects core.KubernetesObjects
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kustomize"></a>
|
||||
## type Kustomize {#Kustomize}
|
||||
|
||||
Kustomize provides a BuildPlan via the Output field which contains one KustomizeBuild from package core.
|
||||
|
||||
```go
|
||||
type Kustomize struct {
|
||||
ComponentFields `json:",inline"`
|
||||
// Kustomization represents the kustomize build plan for holos to render.
|
||||
Kustomization core.KustomizeBuild
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Namespace"></a>
|
||||
## type Namespace {#Namespace}
|
||||
|
||||
Namespace represents a Kubernetes namespace.
|
||||
|
||||
```go
|
||||
type Namespace struct {
|
||||
Name string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Organization"></a>
|
||||
## type Organization {#Organization}
|
||||
|
||||
Organization represents organizational metadata useful across the platform.
|
||||
|
||||
```go
|
||||
type Organization struct {
|
||||
Name string
|
||||
DisplayName string
|
||||
Domain string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="OrganizationStrict"></a>
|
||||
## type OrganizationStrict {#OrganizationStrict}
|
||||
|
||||
OrganizationStrict represents organizational metadata useful across the platform. This is an example of using CUE regular expressions to constrain and validate configuration.
|
||||
|
||||
```go
|
||||
type OrganizationStrict struct {
|
||||
Organization `json:",inline"`
|
||||
// Name represents the organization name as a resource name. Must be 63
|
||||
// characters or less. Must start with a letter. May contain non-repeating
|
||||
// hyphens, letters, and numbers. Must end with a letter or number.
|
||||
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
|
||||
// DisplayName represents the human readable organization name.
|
||||
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Owner"></a>
|
||||
## type Owner {#Owner}
|
||||
|
||||
Owner represents the owner of a resource. For example, the name and email address of an engineering team.
|
||||
|
||||
```go
|
||||
type Owner struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
Platform is a convenience structure to produce a core Platform specification value in the Output field. Useful to collect components at the root of the Platform configuration tree as a struct, which are automatically converted into a list for the core Platform spec output.
|
||||
|
||||
```go
|
||||
type Platform struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `cue:"string | *\"holos\""`
|
||||
// Components is a structured map of components to manage by their name.
|
||||
Components map[string]core.PlatformSpecComponent
|
||||
// Model represents the Platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `cue:"{...}"`
|
||||
// Output represents the core Platform spec for the holos cli to iterate over
|
||||
// and render each listed Component, injecting the Model.
|
||||
Output core.Platform
|
||||
// Domain represents the primary domain the Platform operates in. This field
|
||||
// is intended as a sensible default for component authors to reference and
|
||||
// platform operators to define.
|
||||
Domain string `cue:"string | *\"holos.localhost\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Project"></a>
|
||||
## type Project {#Project}
|
||||
|
||||
Project represents logical grouping of components owned by one or more teams. Useful for the platform team to manage resources for project teams to use.
|
||||
|
||||
```go
|
||||
type Project struct {
|
||||
// Name represents project name.
|
||||
Name string
|
||||
// Owner represents the team who own this project.
|
||||
Owner Owner
|
||||
// Namespaces represents the namespaces assigned to this project.
|
||||
Namespaces map[core.NameLabel]Namespace
|
||||
// Hostnames represents the host names to expose for this project.
|
||||
Hostnames map[core.NameLabel]Hostname
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Projects"></a>
|
||||
## type Projects {#Projects}
|
||||
|
||||
Projects represents projects managed by the platform team for use by other teams using the platform.
|
||||
|
||||
```go
|
||||
type Projects map[core.NameLabel]Project
|
||||
```
|
||||
|
||||
<a name="StandardFleets"></a>
|
||||
## type StandardFleets {#StandardFleets}
|
||||
|
||||
StandardFleets represents the standard set of Clusters in a Platform segmented into Fleets by their purpose. The management Fleet contains a single Cluster, for example a GKE autopilot cluster with no workloads deployed for reliability and cost efficiency. The workload Fleet contains all other Clusters which contain workloads and sync Secrets from the management cluster.
|
||||
|
||||
```go
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\"}"`
|
||||
}
|
||||
```
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
||||
377
doc/md/api/author/v1alpha4.md
Normal file
@@ -0,0 +1,377 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# v1alpha4
|
||||
|
||||
```go
|
||||
import "github.com/holos-run/holos/api/author/v1alpha4"
|
||||
```
|
||||
|
||||
### Author API
|
||||
|
||||
Package v1alpha4 contains ergonomic CUE definitions for Holos component authors. These definitions serve as adapters to produce [Core API](<https://holos.run/docs/api/core/v1alpha4/>) resources for the holos command line tool.
|
||||
|
||||
## Index
|
||||
|
||||
- [type ArgoConfig](<#ArgoConfig>)
|
||||
- [type Cluster](<#Cluster>)
|
||||
- [type ComponentConfig](<#ComponentConfig>)
|
||||
- [type Fleet](<#Fleet>)
|
||||
- [type Helm](<#Helm>)
|
||||
- [type Hostname](<#Hostname>)
|
||||
- [type Kubernetes](<#Kubernetes>)
|
||||
- [type Kustomize](<#Kustomize>)
|
||||
- [type KustomizeConfig](<#KustomizeConfig>)
|
||||
- [type NameLabel](<#NameLabel>)
|
||||
- [type Namespace](<#Namespace>)
|
||||
- [type Organization](<#Organization>)
|
||||
- [type OrganizationStrict](<#OrganizationStrict>)
|
||||
- [type Owner](<#Owner>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type Project](<#Project>)
|
||||
- [type Projects](<#Projects>)
|
||||
- [type StandardFleets](<#StandardFleets>)
|
||||
|
||||
|
||||
<a name="ArgoConfig"></a>
|
||||
## type ArgoConfig {#ArgoConfig}
|
||||
|
||||
ArgoConfig represents the ArgoCD GitOps configuration associated with a [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#buildplan>). Useful to define once at the root of the Platform configuration and reuse across all components.
|
||||
|
||||
```go
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an Application resource when true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// Root represents the path from the git repository root to the WriteTo output
|
||||
// directory, the behavior of the holos render component --write-to flag and
|
||||
// the Core API Component WriteTo field. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
Root string `cue:"string | *\"deploy\""`
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
// AppProject represents the ArgoCD Project to associate the Application with.
|
||||
AppProject string `cue:"string | *\"default\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Cluster"></a>
|
||||
## type Cluster {#Cluster}
|
||||
|
||||
Cluster represents a cluster managed by the Platform.
|
||||
|
||||
```go
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="ComponentConfig"></a>
|
||||
## type ComponentConfig {#ComponentConfig}
|
||||
|
||||
ComponentConfig represents the configuration common to all kinds of component.
|
||||
|
||||
- [Helm](<#Helm>) charts.
|
||||
- [Kubernetes](<#Kubernetes>) resources generated from CUE.
|
||||
- [Kustomize](<#Kustomize>) bases.
|
||||
|
||||
See the following resources for additional details:
|
||||
|
||||
- [Resources](<https://holos.run/docs/api/core/v1alpha4/#Resources>)
|
||||
- [ArgoConfig](<#ArgoConfig>)
|
||||
- [KustomizeConfig](<#KustomizeConfig>)
|
||||
- [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>)
|
||||
|
||||
```go
|
||||
type ComponentConfig struct {
|
||||
// Name represents the BuildPlan metadata.name field. Used to construct the
|
||||
// fully rendered manifest file path.
|
||||
Name string
|
||||
// Component represents the path to the component producing the BuildPlan.
|
||||
Component string
|
||||
// Cluster represents the name of the cluster this BuildPlan is for.
|
||||
Cluster string
|
||||
// Resources represents kubernetes resources mixed into the rendered manifest.
|
||||
Resources core.Resources
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this BuildPlan.
|
||||
ArgoConfig ArgoConfig
|
||||
// CommonLabels represents common labels to manage on all rendered manifests.
|
||||
CommonLabels map[string]string
|
||||
// Namespace manages the metadata.namespace field on all resources except the
|
||||
// ArgoCD Application.
|
||||
Namespace string `json:",omitempty"`
|
||||
|
||||
// KustomizeConfig represents the configuration for kustomize.
|
||||
KustomizeConfig KustomizeConfig
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Fleet"></a>
|
||||
## type Fleet {#Fleet}
|
||||
|
||||
Fleet represents a named collection of similarly configured Clusters. Useful to segregate workload clusters from their management cluster.
|
||||
|
||||
```go
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Helm"></a>
|
||||
## type Helm {#Helm}
|
||||
|
||||
Helm provides a [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>) via the Output field which generates manifests from a helm chart with optional mix\-in resources provided directly from CUE in the Resources field.
|
||||
|
||||
This definition is a convenient way to produce a [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>) composed of three \[Resources\] generators with one [Kustomize](<#Kustomize>) transformer.
|
||||
|
||||
See related:
|
||||
|
||||
- [ComponentConfig](<#ComponentConfig>)
|
||||
- [Chart](<https://holos.run/docs/api/core/v1alpha4/#Chart>)
|
||||
- [Values](<https://holos.run/docs/api/core/v1alpha4/#Values>)
|
||||
- [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>)
|
||||
|
||||
```go
|
||||
type Helm struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// Chart represents a Helm chart.
|
||||
Chart core.Chart
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values core.Values
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Hostname"></a>
|
||||
## type Hostname {#Hostname}
|
||||
|
||||
Hostname represents the left most dns label of a domain name.
|
||||
|
||||
```go
|
||||
type Hostname struct {
|
||||
// Name represents the subdomain to expose, e.g. "www"
|
||||
Name string
|
||||
// Namespace represents the namespace metadata.name field of backend object
|
||||
// reference.
|
||||
Namespace string
|
||||
// Service represents the Service metadata.name field of backend object
|
||||
// reference.
|
||||
Service string
|
||||
// Port represents the Service port of the backend object reference.
|
||||
Port int
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kubernetes"></a>
|
||||
## type Kubernetes {#Kubernetes}
|
||||
|
||||
Kubernetes provides a [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>) via the Output field which contains inline API Objects provided directly from CUE in the Resources field of [ComponentConfig](<#ComponentConfig>).
|
||||
|
||||
See related:
|
||||
|
||||
- [ComponentConfig](<#ComponentConfig>)
|
||||
- [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#BuildPlan>)
|
||||
|
||||
```go
|
||||
type Kubernetes struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kustomize"></a>
|
||||
## type Kustomize {#Kustomize}
|
||||
|
||||
Kustomize provides a [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#buildplan>) via the Output field which generates manifests from a kustomize kustomization with optional mix\-in resources provided directly from CUE in the Resources field.
|
||||
|
||||
See related:
|
||||
|
||||
- [ComponentConfig](<#ComponentConfig>)
|
||||
- [BuildPlan](<https://holos.run/docs/api/core/v1alpha4/#buildplan>)
|
||||
|
||||
```go
|
||||
type Kustomize struct {
|
||||
ComponentConfig `json:",inline"`
|
||||
|
||||
// BuildPlan represents the derived BuildPlan produced for the holos render
|
||||
// component command.
|
||||
BuildPlan core.BuildPlan
|
||||
}
|
||||
```
|
||||
|
||||
<a name="KustomizeConfig"></a>
|
||||
## type KustomizeConfig {#KustomizeConfig}
|
||||
|
||||
KustomizeConfig represents the configuration for kustomize post processing. The Files field is used to mixing in static manifest files from the component directory. The Resources field is used for mixing in manifests from network locations urls.
|
||||
|
||||
See related:
|
||||
|
||||
- [ComponentConfig](<#ComponentConfig>)
|
||||
- [Kustomization](<https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/>)
|
||||
|
||||
```go
|
||||
type KustomizeConfig struct {
|
||||
// Kustomization represents the kustomization used to transform resources.
|
||||
// Note the resources field is internally managed from the Files and Resources fields.
|
||||
Kustomization map[string]any `json:",omitempty"`
|
||||
// Files represents files to copy from the component directory for kustomization.
|
||||
Files map[string]struct{ Source string } `cue:"{[NAME=_]: Source: NAME}"`
|
||||
// Resources represents additional entries to included in the resources list.
|
||||
Resources map[string]struct{ Source string } `cue:"{[NAME=_]: Source: NAME}"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="NameLabel"></a>
|
||||
## type NameLabel {#NameLabel}
|
||||
|
||||
NameLabel signals the common use case of converting a struct to a list where the name field of each value unifies with the field name of the outer struct.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
S: [NameLabel=string]: name: NameLabel
|
||||
S: jeff: _
|
||||
S: gary: _
|
||||
S: nate: _
|
||||
L: [for x in S {x}]
|
||||
// L is [{name: "jeff"}, {name: "gary"}, {name: "nate"}]
|
||||
```
|
||||
|
||||
```go
|
||||
type NameLabel string
|
||||
```
|
||||
|
||||
<a name="Namespace"></a>
|
||||
## type Namespace {#Namespace}
|
||||
|
||||
Namespace represents a Kubernetes namespace.
|
||||
|
||||
```go
|
||||
type Namespace struct {
|
||||
Name string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Organization"></a>
|
||||
## type Organization {#Organization}
|
||||
|
||||
Organization represents organizational metadata useful across the platform.
|
||||
|
||||
```go
|
||||
type Organization struct {
|
||||
Name string
|
||||
DisplayName string
|
||||
Domain string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="OrganizationStrict"></a>
|
||||
## type OrganizationStrict {#OrganizationStrict}
|
||||
|
||||
OrganizationStrict represents organizational metadata useful across the platform. This is an example of using CUE regular expressions to constrain and validate configuration.
|
||||
|
||||
```go
|
||||
type OrganizationStrict struct {
|
||||
Organization `json:",inline"`
|
||||
// Name represents the organization name as a resource name. Must be 63
|
||||
// characters or less. Must start with a letter. May contain non-repeating
|
||||
// hyphens, letters, and numbers. Must end with a letter or number.
|
||||
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
|
||||
// DisplayName represents the human readable organization name.
|
||||
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Owner"></a>
|
||||
## type Owner {#Owner}
|
||||
|
||||
Owner represents the owner of a resource. For example, the name and email address of an engineering team.
|
||||
|
||||
```go
|
||||
type Owner struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
Platform assembles a Core API [Platform](<https://holos.run/docs/api/core/v1alpha4/#Platform>) in the Resource field for the holos render platform command. Use the Components field to register components with the platform using a struct. This struct is converted into a list for final output to holos.
|
||||
|
||||
See related:
|
||||
|
||||
- [Component](<https://holos.run/docs/api/core/v1alpha4/#Component>) collection of components composing the platform.
|
||||
- [Platform](<https://holos.run/docs/api/core/v1alpha4/#Platform>) resource assembled for holos to process.
|
||||
|
||||
```go
|
||||
type Platform struct {
|
||||
Name string
|
||||
Components map[NameLabel]core.Component
|
||||
Resource core.Platform
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Project"></a>
|
||||
## type Project {#Project}
|
||||
|
||||
Project represents logical grouping of components owned by one or more teams. Useful for the platform team to manage resources for project teams to use.
|
||||
|
||||
```go
|
||||
type Project struct {
|
||||
// Name represents project name.
|
||||
Name string
|
||||
// Owner represents the team who own this project.
|
||||
Owner Owner
|
||||
// Namespaces represents the namespaces assigned to this project.
|
||||
Namespaces map[NameLabel]Namespace
|
||||
// Hostnames represents the host names to expose for this project.
|
||||
Hostnames map[NameLabel]Hostname
|
||||
// CommonLabels represents common labels to manage on all rendered manifests.
|
||||
CommonLabels map[string]string
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Projects"></a>
|
||||
## type Projects {#Projects}
|
||||
|
||||
Projects represents projects managed by the platform team for use by other teams using the platform.
|
||||
|
||||
```go
|
||||
type Projects map[NameLabel]Project
|
||||
```
|
||||
|
||||
<a name="StandardFleets"></a>
|
||||
## type StandardFleets {#StandardFleets}
|
||||
|
||||
StandardFleets represents the standard set of Clusters in a Platform segmented into Fleets by their purpose. The management Fleet contains a single Cluster, for example a GKE autopilot cluster with no workloads deployed for reliability and cost efficiency. The workload Fleet contains all other Clusters which contain workloads and sync Secrets from the management cluster.
|
||||
|
||||
```go
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\"}"`
|
||||
}
|
||||
```
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
||||
5
doc/md/api/core.md
Normal file
@@ -0,0 +1,5 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Core API
|
||||
|
||||
<DocCardList />
|
||||
413
doc/md/api/core/v1alpha3.md
Normal file
@@ -0,0 +1,413 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# v1alpha3
|
||||
|
||||
```go
|
||||
import "github.com/holos-run/holos/api/core/v1alpha3"
|
||||
```
|
||||
|
||||
Package v1alpha3 contains the core API contract between the holos cli and CUE configuration code. Platform designers, operators, and software developers use this API to write configuration in CUE which \`holos\` loads. The overall shape of the API defines imperative actions \`holos\` should carry out to render the complete yaml that represents a Platform.
|
||||
|
||||
[Platform](<#Platform>) defines the complete configuration of a platform. With the holos reference platform this takes the shape of one management cluster and at least two workload cluster. Each cluster has multiple [Component](<#Component>) resources applied to it.
|
||||
|
||||
Each holos component path, e.g. \`components/namespaces\` produces exactly one [BuildPlan](<#BuildPlan>) which in turn contains a set of [Component](<#Component>) kinds.
|
||||
|
||||
The primary kinds of [Component](<#Component>) are:
|
||||
|
||||
1. [HelmChart](<#HelmChart>) to render config from a helm chart.
|
||||
2. [KustomizeBuild](<#KustomizeBuild>) to render config from [Kustomize](<#Kustomize>)
|
||||
3. [KubernetesObjects](<#KubernetesObjects>) to render [APIObjects](<#APIObjects>) defined directly in CUE configuration.
|
||||
|
||||
Note that Holos operates as a data pipeline, so the output of a [HelmChart](<#HelmChart>) may be provided to [Kustomize](<#Kustomize>) for post\-processing.
|
||||
|
||||
## Index
|
||||
|
||||
- [Constants](<#constants>)
|
||||
- [type APIObject](<#APIObject>)
|
||||
- [type APIObjectMap](<#APIObjectMap>)
|
||||
- [type APIObjects](<#APIObjects>)
|
||||
- [type BuildPlan](<#BuildPlan>)
|
||||
- [type BuildPlanComponents](<#BuildPlanComponents>)
|
||||
- [type BuildPlanSpec](<#BuildPlanSpec>)
|
||||
- [type Chart](<#Chart>)
|
||||
- [type Component](<#Component>)
|
||||
- [type FileContent](<#FileContent>)
|
||||
- [type FileContentMap](<#FileContentMap>)
|
||||
- [type FilePath](<#FilePath>)
|
||||
- [type HelmChart](<#HelmChart>)
|
||||
- [type InternalLabel](<#InternalLabel>)
|
||||
- [type Kind](<#Kind>)
|
||||
- [type KubernetesObjects](<#KubernetesObjects>)
|
||||
- [type Kustomize](<#Kustomize>)
|
||||
- [type KustomizeBuild](<#KustomizeBuild>)
|
||||
- [type Metadata](<#Metadata>)
|
||||
- [type NameLabel](<#NameLabel>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type PlatformMetadata](<#PlatformMetadata>)
|
||||
- [type PlatformSpec](<#PlatformSpec>)
|
||||
- [type PlatformSpecComponent](<#PlatformSpecComponent>)
|
||||
- [type Repository](<#Repository>)
|
||||
|
||||
|
||||
## Constants
|
||||
|
||||
<a name="APIVersion"></a>
|
||||
|
||||
```go
|
||||
const (
|
||||
APIVersion = "v1alpha3"
|
||||
BuildPlanKind = "BuildPlan"
|
||||
HelmChartKind = "HelmChart"
|
||||
// ChartDir is the directory name created in the holos component directory to cache a chart.
|
||||
ChartDir = "vendor"
|
||||
// ResourcesFile is the file name used to store component output when post-processing with kustomize.
|
||||
ResourcesFile = "resources.yaml"
|
||||
)
|
||||
```
|
||||
|
||||
<a name="KubernetesObjectsKind"></a>
|
||||
|
||||
```go
|
||||
const KubernetesObjectsKind = "KubernetesObjects"
|
||||
```
|
||||
|
||||
<a name="APIObject"></a>
|
||||
## type APIObject {#APIObject}
|
||||
|
||||
APIObject represents the most basic generic form of a single kubernetes api object. Represented as a JSON object internally for compatibility between tools, for example loading from CUE.
|
||||
|
||||
```go
|
||||
type APIObject structpb.Struct
|
||||
```
|
||||
|
||||
<a name="APIObjectMap"></a>
|
||||
## type APIObjectMap {#APIObjectMap}
|
||||
|
||||
APIObjectMap represents the marshalled yaml representation of kubernetes api objects. Do not produce an APIObjectMap directly, instead use [APIObjects](<#APIObjects>) to produce the marshalled yaml representation from CUE data, then provide the result to [Component](<#Component>).
|
||||
|
||||
```go
|
||||
type APIObjectMap map[Kind]map[InternalLabel]string
|
||||
```
|
||||
|
||||
<a name="APIObjects"></a>
|
||||
## type APIObjects {#APIObjects}
|
||||
|
||||
APIObjects represents Kubernetes API objects defined directly from CUE code. Useful to mix in resources to any kind of [Component](<#Component>), for example adding an ExternalSecret resource to a [HelmChart](<#HelmChart>).
|
||||
|
||||
[Kind](<#Kind>) must be the resource kind, e.g. Deployment or Service.
|
||||
|
||||
[InternalLabel](<#InternalLabel>) is an arbitrary internal identifier to uniquely identify the resource within the context of a \`holos\` command. Holos will never write the intermediate label to rendered output.
|
||||
|
||||
Refer to [Component](<#Component>) which accepts an [APIObjectMap](<#APIObjectMap>) field provided by [APIObjects](<#APIObjects>).
|
||||
|
||||
```go
|
||||
type APIObjects struct {
|
||||
APIObjects map[Kind]map[InternalLabel]APIObject `json:"apiObjects"`
|
||||
APIObjectMap APIObjectMap `json:"apiObjectMap"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="BuildPlan"></a>
|
||||
## type BuildPlan {#BuildPlan}
|
||||
|
||||
BuildPlan represents a build plan for the holos cli to execute. The purpose of a BuildPlan is to define one or more [Component](<#Component>) kinds. For example a [HelmChart](<#HelmChart>), [KustomizeBuild](<#KustomizeBuild>), or [KubernetesObjects](<#KubernetesObjects>).
|
||||
|
||||
A BuildPlan usually has an additional empty [KubernetesObjects](<#KubernetesObjects>) for the purpose of using the [Component](<#Component>) DeployFiles field to deploy an ArgoCD or Flux gitops resource for the holos component.
|
||||
|
||||
```go
|
||||
type BuildPlan struct {
|
||||
Kind string `json:"kind" cue:"\"BuildPlan\""`
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
|
||||
Spec BuildPlanSpec `json:"spec"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="BuildPlanComponents"></a>
|
||||
## type BuildPlanComponents {#BuildPlanComponents}
|
||||
|
||||
|
||||
|
||||
```go
|
||||
type BuildPlanComponents struct {
|
||||
Resources map[InternalLabel]KubernetesObjects `json:"resources,omitempty"`
|
||||
KubernetesObjectsList []KubernetesObjects `json:"kubernetesObjectsList,omitempty"`
|
||||
HelmChartList []HelmChart `json:"helmChartList,omitempty"`
|
||||
KustomizeBuildList []KustomizeBuild `json:"kustomizeBuildList,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="BuildPlanSpec"></a>
|
||||
## type BuildPlanSpec {#BuildPlanSpec}
|
||||
|
||||
BuildPlanSpec represents the specification of the build plan.
|
||||
|
||||
```go
|
||||
type BuildPlanSpec struct {
|
||||
// Disabled causes the holos cli to take no action over the [BuildPlan].
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
// Components represents multiple [HolosComponent] kinds to manage.
|
||||
Components BuildPlanComponents `json:"components,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Chart"></a>
|
||||
## type Chart {#Chart}
|
||||
|
||||
Chart represents a helm chart.
|
||||
|
||||
```go
|
||||
type Chart struct {
|
||||
// Name represents the chart name.
|
||||
Name string `json:"name"`
|
||||
// Version represents the chart version.
|
||||
Version string `json:"version"`
|
||||
// Release represents the chart release when executing helm template.
|
||||
Release string `json:"release"`
|
||||
// Repository represents the repository to fetch the chart from.
|
||||
Repository Repository `json:"repository,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Component"></a>
|
||||
## type Component {#Component}
|
||||
|
||||
Component defines the fields common to all holos component kinds. Every holos component kind should embed Component.
|
||||
|
||||
```go
|
||||
type Component struct {
|
||||
// Kind is a string value representing the resource this object represents.
|
||||
Kind string `json:"kind"`
|
||||
// APIVersion represents the versioned schema of this representation of an object.
|
||||
APIVersion string `json:"apiVersion" cue:"\"v1alpha3\""`
|
||||
// Metadata represents data about the holos component such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
|
||||
// APIObjectMap holds the marshalled representation of api objects. Useful to
|
||||
// mix in resources to each Component type, for example adding an
|
||||
// ExternalSecret to a [HelmChart] Component. Refer to [APIObjects].
|
||||
APIObjectMap APIObjectMap `json:"apiObjectMap,omitempty"`
|
||||
|
||||
// DeployFiles represents file paths relative to the cluster deploy directory
|
||||
// with the value representing the file content. Intended for defining the
|
||||
// ArgoCD Application resource or Flux Kustomization resource from within CUE,
|
||||
// but may be used to render any file related to the build plan from CUE.
|
||||
DeployFiles FileContentMap `json:"deployFiles,omitempty"`
|
||||
|
||||
// Kustomize represents a kubectl kustomize build post-processing step.
|
||||
Kustomize `json:"kustomize,omitempty"`
|
||||
|
||||
// Skip causes holos to take no action regarding this component.
|
||||
Skip bool `json:"skip" cue:"bool | *false"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="FileContent"></a>
|
||||
## type FileContent {#FileContent}
|
||||
|
||||
FileContent represents file contents.
|
||||
|
||||
```go
|
||||
type FileContent string
|
||||
```
|
||||
|
||||
<a name="FileContentMap"></a>
|
||||
## type FileContentMap {#FileContentMap}
|
||||
|
||||
FileContentMap represents a mapping of file paths to file contents.
|
||||
|
||||
```go
|
||||
type FileContentMap map[FilePath]FileContent
|
||||
```
|
||||
|
||||
<a name="FilePath"></a>
|
||||
## type FilePath {#FilePath}
|
||||
|
||||
FilePath represents a file path.
|
||||
|
||||
```go
|
||||
type FilePath string
|
||||
```
|
||||
|
||||
<a name="HelmChart"></a>
|
||||
## type HelmChart {#HelmChart}
|
||||
|
||||
HelmChart represents a holos component which wraps around an upstream helm chart. Holos orchestrates helm by providing values obtained from CUE, renders the output using \`helm template\`, then post\-processes the helm output yaml using the general functionality provided by [Component](<#Component>), for example [Kustomize](<#Kustomize>) post\-rendering and mixing in additional kubernetes api objects.
|
||||
|
||||
```go
|
||||
type HelmChart struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"HelmChart\""`
|
||||
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart"`
|
||||
// ValuesContent represents the values.yaml file holos passes to the `helm
|
||||
// template` command.
|
||||
ValuesContent string `json:"valuesContent"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks" cue:"bool | *false"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="InternalLabel"></a>
|
||||
## type InternalLabel {#InternalLabel}
|
||||
|
||||
InternalLabel is an arbitrary unique identifier internal to holos itself. The holos cli is expected to never write a InternalLabel value to rendered output files, therefore use a [InternalLabel](<#InternalLabel>) when the identifier must be unique and internal. Defined as a type for clarity and type checking.
|
||||
|
||||
A InternalLabel is useful to convert a CUE struct to a list, for example producing a list of [APIObject](<#APIObject>) resources from an [APIObjectMap](<#APIObjectMap>). A CUE struct using InternalLabel keys is guaranteed to not lose data when rendering output because a InternalLabel is expected to never be written to the final output.
|
||||
|
||||
```go
|
||||
type InternalLabel string
|
||||
```
|
||||
|
||||
<a name="Kind"></a>
|
||||
## type Kind {#Kind}
|
||||
|
||||
Kind is a kubernetes api object kind. Defined as a type for clarity and type checking.
|
||||
|
||||
```go
|
||||
type Kind string
|
||||
```
|
||||
|
||||
<a name="KubernetesObjects"></a>
|
||||
## type KubernetesObjects {#KubernetesObjects}
|
||||
|
||||
KubernetesObjects represents a [Component](<#Component>) composed of Kubernetes API objects provided directly from CUE using [APIObjects](<#APIObjects>).
|
||||
|
||||
```go
|
||||
type KubernetesObjects struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"KubernetesObjects\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kustomize"></a>
|
||||
## type Kustomize {#Kustomize}
|
||||
|
||||
Kustomize represents resources necessary to execute a kustomize build. Intended for at least two use cases:
|
||||
|
||||
1. Process a [KustomizeBuild](<#KustomizeBuild>) [Component](<#Component>) which represents raw yaml file resources in a holos component directory.
|
||||
2. Post process a [HelmChart](<#HelmChart>) [Component](<#Component>) to inject istio, patch jobs, add custom labels, etc...
|
||||
|
||||
```go
|
||||
type Kustomize struct {
|
||||
// KustomizeFiles holds file contents for kustomize, e.g. patch files.
|
||||
KustomizeFiles FileContentMap `json:"kustomizeFiles,omitempty"`
|
||||
// ResourcesFile is the file name used for api objects in kustomization.yaml
|
||||
ResourcesFile string `json:"resourcesFile,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="KustomizeBuild"></a>
|
||||
## type KustomizeBuild {#KustomizeBuild}
|
||||
|
||||
KustomizeBuild represents a [Component](<#Component>) that renders plain yaml files in the holos component directory using \`kubectl kustomize build\`.
|
||||
|
||||
```go
|
||||
type KustomizeBuild struct {
|
||||
Component `json:",inline"`
|
||||
Kind string `json:"kind" cue:"\"KustomizeBuild\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Metadata"></a>
|
||||
## type Metadata {#Metadata}
|
||||
|
||||
Metadata represents data about the object such as the Name.
|
||||
|
||||
```go
|
||||
type Metadata struct {
|
||||
// Name represents the name of the holos component.
|
||||
Name string `json:"name"`
|
||||
// Namespace is the primary namespace of the holos component. A holos
|
||||
// component may manage resources in multiple namespaces, in this case
|
||||
// consider setting the component namespace to default.
|
||||
//
|
||||
// This field is optional because not all resources require a namespace,
|
||||
// particularly CRDs and DeployFiles functionality.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="NameLabel"></a>
|
||||
## type NameLabel {#NameLabel}
|
||||
|
||||
NameLabel is a unique identifier useful to convert a CUE struct to a list when the values have a Name field with a default value. This type is intended to indicate the common use case of converting a struct to a list where the Name field of the value aligns with the struct field name.
|
||||
|
||||
```go
|
||||
type NameLabel string
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
Platform represents a platform to manage. A Platform resource informs holos which components to build. The platform resource also acts as a container for the platform model form values provided by the PlatformService. The primary use case is to collect the cluster names, cluster types, platform model, and holos components to build into one resource.
|
||||
|
||||
```go
|
||||
type Platform struct {
|
||||
// Kind is a string value representing the resource this object represents.
|
||||
Kind string `json:"kind" cue:"\"Platform\""`
|
||||
// APIVersion represents the versioned schema of this representation of an object.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
|
||||
// Metadata represents data about the object such as the Name.
|
||||
Metadata PlatformMetadata `json:"metadata"`
|
||||
|
||||
// Spec represents the specification.
|
||||
Spec PlatformSpec `json:"spec"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="PlatformMetadata"></a>
|
||||
## type PlatformMetadata {#PlatformMetadata}
|
||||
|
||||
|
||||
|
||||
```go
|
||||
type PlatformMetadata struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="PlatformSpec"></a>
|
||||
## type PlatformSpec {#PlatformSpec}
|
||||
|
||||
PlatformSpec represents the specification of a Platform. Think of a platform specification as a list of platform components to apply to a list of kubernetes clusters combined with the user\-specified Platform Model.
|
||||
|
||||
```go
|
||||
type PlatformSpec struct {
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `json:"model" cue:"{...}"`
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []PlatformSpecComponent `json:"components"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="PlatformSpecComponent"></a>
|
||||
## type PlatformSpecComponent {#PlatformSpecComponent}
|
||||
|
||||
PlatformSpecComponent represents a holos component to build or render.
|
||||
|
||||
```go
|
||||
type PlatformSpecComponent struct {
|
||||
// Path is the path of the component relative to the platform root.
|
||||
Path string `json:"path"`
|
||||
// Cluster is the cluster name to provide when rendering the component.
|
||||
Cluster string `json:"cluster"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Repository"></a>
|
||||
## type Repository {#Repository}
|
||||
|
||||
Repository represents a helm chart repository.
|
||||
|
||||
```go
|
||||
type Repository struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
```
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
||||
537
doc/md/api/core/v1alpha4.md
Normal file
@@ -0,0 +1,537 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# v1alpha4
|
||||
|
||||
```go
|
||||
import "github.com/holos-run/holos/api/core/v1alpha4"
|
||||
```
|
||||
|
||||
### Core API
|
||||
|
||||
Package v1alpha4 contains the core API contract between the holos cli and CUE configuration code. Platform designers, operators, and software developers use this API to write configuration in CUE which holos loads. The Core API is declarative. Each resource represents a desired state necessary for holos to fully render Kubernetes manifests into plain files.
|
||||
|
||||
The following resources provide important context for the Core API. The [Author API](<https://holos.run/docs/api/author/>) is intended for component authors as a convenient adapter for the Core API resources Holos expects.
|
||||
|
||||
1. [Technical Overview](<https://holos.run/docs/technical-overview/>)
|
||||
2. [Quickstart](<https://holos.run/docs/quickstart/>)
|
||||
3. [Author API](<https://holos.run/docs/api/author/>)
|
||||
|
||||
### Platform
|
||||
|
||||
[Platform](<#Platform>) defines the complete configuration of a platform. A platform represents a [Component](<#Component>) collection.
|
||||
|
||||
Inspect a Platform resource holos would process by executing:
|
||||
|
||||
```
|
||||
cue export --out yaml ./platform
|
||||
```
|
||||
|
||||
### Component
|
||||
|
||||
A [Component](<#Component>) is the combination of CUE code along one path relative to the platform root directory plus data injected from the [PlatformSpec](<#PlatformSpec>) via CUE tags. The platform configuration root is the directory containing cue.mod.
|
||||
|
||||
A [Component](<#Component>) always produces exactly one [BuildPlan](<#BuildPlan>).
|
||||
|
||||
### BuildPlan
|
||||
|
||||
A [BuildPlan](<#BuildPlan>) contains an [Artifact](<#Artifact>) collection. A BuildPlan often produces two artifacts, one containing the fully rendered Kubernetes API resources, the other containing an additional resource to manage the former with GitOps. For example, a BuildPlan for a podinfo component produces a manifest containing a Deployment and a Service, along with a second manifest containing an ArgoCD Application.
|
||||
|
||||
Inspect a BuildPlan resource holos render component would process by executing:
|
||||
|
||||
```
|
||||
cue export --out yaml ./projects/platform/components/namespaces
|
||||
```
|
||||
|
||||
### Artifact
|
||||
|
||||
An [Artifact](<#Artifact>) is one fully rendered manifest file produced from the final [Transformer](<#Transformer>) in a sequence of transformers. An Artifact may also be produced directly from a [Generator](<#Generator>), but this use case is uncommon.
|
||||
|
||||
### Transformer
|
||||
|
||||
A [Transformer](<#Transformer>) takes multiple inputs from prior [Generator](<#Generator>) or [Transformer](<#Transformer>) outputs, then transforms the data into one output. [Kustomize](<#Kustomize>) is the most commonly used transformer, though a simple [Join](<#Join>) is also supported.
|
||||
|
||||
1. [Kustomize](<#Kustomize>) \- Patch and transform the output from prior generators or transformers. See [Introduction to Kustomize](<https://kubectl.docs.kubernetes.io/guides/config_management/introduction/>).
|
||||
2. [Join](<#Join>) \- Concatenate multiple prior outputs into one output.
|
||||
|
||||
### Generators
|
||||
|
||||
A [Generator](<#Generator>) generates Kubernetes resources. [Helm](<#Helm>) and [Resources](<#Resources>) are the most commonly used, often paired together to mix\-in resources to an unmodified Helm chart. A simple [File](<#File>) generator is also available for use with the [Kustomize](<#Kustomize>) transformer.
|
||||
|
||||
1. [Resources](<#Resources>) \- Generates resources from CUE code.
|
||||
2. [Helm](<#Helm>) \- Generates rendered yaml from a [Chart](<#Chart>).
|
||||
3. [File](<#File>) \- Generates data by reading a file from the component directory.
|
||||
|
||||
## Index
|
||||
|
||||
- [type Artifact](<#Artifact>)
|
||||
- [type BuildPlan](<#BuildPlan>)
|
||||
- [type BuildPlanSpec](<#BuildPlanSpec>)
|
||||
- [type Chart](<#Chart>)
|
||||
- [type Component](<#Component>)
|
||||
- [type File](<#File>)
|
||||
- [type FileContent](<#FileContent>)
|
||||
- [type FileContentMap](<#FileContentMap>)
|
||||
- [type FilePath](<#FilePath>)
|
||||
- [type Generator](<#Generator>)
|
||||
- [type Helm](<#Helm>)
|
||||
- [type InternalLabel](<#InternalLabel>)
|
||||
- [type Join](<#Join>)
|
||||
- [type Kind](<#Kind>)
|
||||
- [type Kustomization](<#Kustomization>)
|
||||
- [type Kustomize](<#Kustomize>)
|
||||
- [type Metadata](<#Metadata>)
|
||||
- [type NameLabel](<#NameLabel>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type PlatformSpec](<#PlatformSpec>)
|
||||
- [type Repository](<#Repository>)
|
||||
- [type Resource](<#Resource>)
|
||||
- [type Resources](<#Resources>)
|
||||
- [type Tags](<#Tags>)
|
||||
- [type Transformer](<#Transformer>)
|
||||
- [type Values](<#Values>)
|
||||
|
||||
|
||||
<a name="Artifact"></a>
|
||||
## type Artifact {#Artifact}
|
||||
|
||||
Artifact represents one fully rendered manifest produced by a [Transformer](<#Transformer>) sequence, which transforms a [Generator](<#Generator>) collection. A [BuildPlan](<#BuildPlan>) produces an [Artifact](<#Artifact>) collection.
|
||||
|
||||
Each Artifact produces one manifest file artifact. Generator Output values are used as Transformer Inputs. The Output field of the final [Transformer](<#Transformer>) should have the same value as the Artifact field.
|
||||
|
||||
When there is more than one [Generator](<#Generator>) there must be at least one [Transformer](<#Transformer>) to combine outputs into one Artifact. If there is a single Generator, it may directly produce the Artifact output.
|
||||
|
||||
An Artifact is processed concurrently with other artifacts in the same [BuildPlan](<#BuildPlan>). An Artifact should not use an output from another Artifact as an input. Each [Generator](<#Generator>) may also run concurrently. Each [Transformer](<#Transformer>) is executed sequentially starting after all generators have completed.
|
||||
|
||||
Output fields are write\-once. It is an error for multiple Generators or Transformers to produce the same Output value within the context of a [BuildPlan](<#BuildPlan>).
|
||||
|
||||
```go
|
||||
type Artifact struct {
|
||||
Artifact FilePath `json:"artifact,omitempty"`
|
||||
Generators []Generator `json:"generators,omitempty"`
|
||||
Transformers []Transformer `json:"transformers,omitempty"`
|
||||
Skip bool `json:"skip,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="BuildPlan"></a>
|
||||
## type BuildPlan {#BuildPlan}
|
||||
|
||||
BuildPlan represents a build plan for holos to execute. Each [Platform](<#Platform>) component produces exactly one BuildPlan.
|
||||
|
||||
One or more [Artifact](<#Artifact>) files are produced by a BuildPlan, representing the fully rendered manifests for the Kubernetes API Server.
|
||||
|
||||
### Example BuildPlan
|
||||
|
||||
Command:
|
||||
|
||||
```
|
||||
cue export --out yaml ./projects/platform/components/namespaces
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
kind: BuildPlan
|
||||
apiVersion: v1alpha4
|
||||
metadata:
|
||||
name: dev-namespaces
|
||||
spec:
|
||||
component: projects/platform/components/namespaces
|
||||
artifacts:
|
||||
- artifact: clusters/no-cluster/components/dev-namespaces/dev-namespaces.gen.yaml
|
||||
generators:
|
||||
- kind: Resources
|
||||
output: resources.gen.yaml
|
||||
resources:
|
||||
Namespace:
|
||||
dev-jeff:
|
||||
metadata:
|
||||
name: dev-jeff
|
||||
labels:
|
||||
kubernetes.io/metadata.name: dev-jeff
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- resources.gen.yaml
|
||||
output: clusters/no-cluster/components/dev-namespaces/dev-namespaces.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
commonLabels:
|
||||
holos.run/component.name: dev-namespaces
|
||||
resources:
|
||||
- resources.gen.yaml
|
||||
```
|
||||
|
||||
```go
|
||||
type BuildPlan struct {
|
||||
// Kind represents the type of the resource.
|
||||
Kind string `json:"kind" cue:"\"BuildPlan\""`
|
||||
// APIVersion represents the versioned schema of the resource.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha4\""`
|
||||
// Metadata represents data about the resource such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
// Spec specifies the desired state of the resource.
|
||||
Spec BuildPlanSpec `json:"spec"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="BuildPlanSpec"></a>
|
||||
## type BuildPlanSpec {#BuildPlanSpec}
|
||||
|
||||
BuildPlanSpec represents the specification of the [BuildPlan](<#BuildPlan>).
|
||||
|
||||
```go
|
||||
type BuildPlanSpec struct {
|
||||
// Component represents the component that produced the build plan.
|
||||
// Represented as a path relative to the platform root.
|
||||
Component string `json:"component"`
|
||||
// Disabled causes the holos cli to disregard the build plan.
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
// Artifacts represents the artifacts for holos to build.
|
||||
Artifacts []Artifact `json:"artifacts"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Chart"></a>
|
||||
## type Chart {#Chart}
|
||||
|
||||
Chart represents a [Helm](<#Helm>) Chart.
|
||||
|
||||
```go
|
||||
type Chart struct {
|
||||
// Name represents the chart name.
|
||||
Name string `json:"name"`
|
||||
// Version represents the chart version.
|
||||
Version string `json:"version"`
|
||||
// Release represents the chart release when executing helm template.
|
||||
Release string `json:"release"`
|
||||
// Repository represents the repository to fetch the chart from.
|
||||
Repository Repository `json:"repository,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Component"></a>
|
||||
## type Component {#Component}
|
||||
|
||||
Component represents the complete context necessary to produce a [BuildPlan](<#BuildPlan>). Component carries information injected from holos render platform to holos render component to produce each [BuildPlan](<#BuildPlan>).
|
||||
|
||||
All of these fields are passed to the holos render component command using flags, which in turn are injected to CUE using tags. For clarity, CUE field and tag names should match the struct json tag names below.
|
||||
|
||||
```go
|
||||
type Component struct {
|
||||
// Name represents the name of the component. Injected as the tag variable
|
||||
// "holos_name" to set the BuildPlan metadata.name field. Necessary for clear
|
||||
// user feedback during platform rendering.
|
||||
Name string `json:"name"`
|
||||
// Component represents the path of the component relative to the platform
|
||||
// root. Injected as the tag variable "holos_component".
|
||||
Component string `json:"component"`
|
||||
// Cluster is the cluster name to provide when rendering the component.
|
||||
// Injected as the tag variable "holos_cluster".
|
||||
Cluster string `json:"cluster"`
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
// Injected as the tag "holos_model".
|
||||
Model map[string]any `json:"model"`
|
||||
// Tags represents cue @tag variables injected into the holos render component
|
||||
// command from the holos render platform command. Tags with a "holos_"
|
||||
// prefix are reserved for use by the Holos Authors.
|
||||
Tags map[string]string `json:"tags,omitempty"`
|
||||
// WriteTo represents the holos render component --write-to flag. If empty,
|
||||
// the default value for the --write-to flag is used.
|
||||
WriteTo string `json:"writeTo,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="File"></a>
|
||||
## type File {#File}
|
||||
|
||||
File represents a simple single file copy [Generator](<#Generator>). Useful with a [Kustomize](<#Kustomize>) [Transformer](<#Transformer>) to process plain manifest files stored in the component directory. Multiple File generators may be used to transform multiple resources.
|
||||
|
||||
```go
|
||||
type File struct {
|
||||
// Source represents a file sub-path relative to the component path.
|
||||
Source FilePath `json:"source"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="FileContent"></a>
|
||||
## type FileContent {#FileContent}
|
||||
|
||||
FileContent represents file contents.
|
||||
|
||||
```go
|
||||
type FileContent string
|
||||
```
|
||||
|
||||
<a name="FileContentMap"></a>
|
||||
## type FileContentMap {#FileContentMap}
|
||||
|
||||
FileContentMap represents a mapping of file paths to file contents.
|
||||
|
||||
```go
|
||||
type FileContentMap map[FilePath]FileContent
|
||||
```
|
||||
|
||||
<a name="FilePath"></a>
|
||||
## type FilePath {#FilePath}
|
||||
|
||||
FilePath represents a file path.
|
||||
|
||||
```go
|
||||
type FilePath string
|
||||
```
|
||||
|
||||
<a name="Generator"></a>
|
||||
## type Generator {#Generator}
|
||||
|
||||
Generator generates an intermediate manifest for a [Artifact](<#Artifact>).
|
||||
|
||||
Each Generator in a [Artifact](<#Artifact>) must have a distinct Output value for a [Transformer](<#Transformer>) to reference.
|
||||
|
||||
Refer to [Resources](<#Resources>), [Helm](<#Helm>), and [File](<#File>).
|
||||
|
||||
```go
|
||||
type Generator struct {
|
||||
// Kind represents the kind of generator. Must be Resources, Helm, or File.
|
||||
Kind string `json:"kind" cue:"\"Resources\" | \"Helm\" | \"File\""`
|
||||
// Output represents a file for a Transformer or Artifact to consume.
|
||||
Output FilePath `json:"output"`
|
||||
// Resources generator. Ignored unless kind is Resources. Resources are
|
||||
// stored as a two level struct. The top level key is the Kind of resource,
|
||||
// e.g. Namespace or Deployment. The second level key is an arbitrary
|
||||
// InternalLabel. The third level is a map[string]any representing the
|
||||
// Resource.
|
||||
Resources Resources `json:"resources,omitempty"`
|
||||
// Helm generator. Ignored unless kind is Helm.
|
||||
Helm Helm `json:"helm,omitempty"`
|
||||
// File generator. Ignored unless kind is File.
|
||||
File File `json:"file,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Helm"></a>
|
||||
## type Helm {#Helm}
|
||||
|
||||
Helm represents a [Chart](<#Chart>) manifest [Generator](<#Generator>).
|
||||
|
||||
```go
|
||||
type Helm struct {
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart"`
|
||||
// Values represents values for holos to marshal into values.yaml when
|
||||
// rendering the chart.
|
||||
Values Values `json:"values"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks,omitempty"`
|
||||
// Namespace represents the helm namespace flag
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="InternalLabel"></a>
|
||||
## type InternalLabel {#InternalLabel}
|
||||
|
||||
InternalLabel is an arbitrary unique identifier internal to holos itself. The holos cli is expected to never write a InternalLabel value to rendered output files, therefore use a InternalLabel when the identifier must be unique and internal. Defined as a type for clarity and type checking.
|
||||
|
||||
```go
|
||||
type InternalLabel string
|
||||
```
|
||||
|
||||
<a name="Join"></a>
|
||||
## type Join {#Join}
|
||||
|
||||
Join represents a [Transformer](<#Transformer>) using [bytes.Join](<https://pkg.go.dev/bytes#Join>) to concatenate multiple inputs into one output with a separator. Useful for combining output from [Helm](<#Helm>) and [Resources](<#Resources>) together into one [Artifact](<#Artifact>) when [Kustomize](<#Kustomize>) is otherwise unnecessary.
|
||||
|
||||
```go
|
||||
type Join struct {
|
||||
Separator string `json:"separator" cue:"string | *\"---\\n\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Kind"></a>
|
||||
## type Kind {#Kind}
|
||||
|
||||
Kind is a discriminator. Defined as a type for clarity and type checking.
|
||||
|
||||
```go
|
||||
type Kind string
|
||||
```
|
||||
|
||||
<a name="Kustomization"></a>
|
||||
## type Kustomization {#Kustomization}
|
||||
|
||||
Kustomization represents a kustomization.yaml file for use with the [Kustomize](<#Kustomize>) [Transformer](<#Transformer>). Untyped to avoid tightly coupling holos to kubectl versions which was a problem for the Flux maintainers. Type checking is expected to happen in CUE against the kubectl version the user prefers.
|
||||
|
||||
```go
|
||||
type Kustomization map[string]any
|
||||
```
|
||||
|
||||
<a name="Kustomize"></a>
|
||||
## type Kustomize {#Kustomize}
|
||||
|
||||
Kustomize represents a kustomization [Transformer](<#Transformer>).
|
||||
|
||||
```go
|
||||
type Kustomize struct {
|
||||
// Kustomization represents the decoded kustomization.yaml file
|
||||
Kustomization Kustomization `json:"kustomization"`
|
||||
// Files holds file contents for kustomize, e.g. patch files.
|
||||
Files FileContentMap `json:"files,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Metadata"></a>
|
||||
## type Metadata {#Metadata}
|
||||
|
||||
Metadata represents data about the resource such as the Name.
|
||||
|
||||
```go
|
||||
type Metadata struct {
|
||||
// Name represents the resource name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="NameLabel"></a>
|
||||
## type NameLabel {#NameLabel}
|
||||
|
||||
NameLabel is a unique identifier useful to convert a CUE struct to a list when the values have a Name field with a default value. NameLabel indicates the common use case of converting a struct to a list where the Name field of the value aligns with the outer struct field name.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
Outer: [NAME=_]: Name: NAME
|
||||
```
|
||||
|
||||
```go
|
||||
type NameLabel string
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
Platform represents a platform to manage. A Platform resource informs holos which components to build. The platform resource also acts as a container for the platform model form values provided by the PlatformService. The primary use case is to collect the cluster names, cluster types, platform model, and holos components to build into one resource.
|
||||
|
||||
```go
|
||||
type Platform struct {
|
||||
// Kind is a string value representing the resource.
|
||||
Kind string `json:"kind" cue:"\"Platform\""`
|
||||
// APIVersion represents the versioned schema of this resource.
|
||||
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha4\""`
|
||||
// Metadata represents data about the resource such as the Name.
|
||||
Metadata Metadata `json:"metadata"`
|
||||
|
||||
// Spec represents the specification.
|
||||
Spec PlatformSpec `json:"spec"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="PlatformSpec"></a>
|
||||
## type PlatformSpec {#PlatformSpec}
|
||||
|
||||
PlatformSpec represents the specification of a [Platform](<#Platform>). Think of a platform spec as a [Component](<#Component>) collection for multiple kubernetes clusters combined with the user\-specified Platform Model.
|
||||
|
||||
```go
|
||||
type PlatformSpec struct {
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []Component `json:"components"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Repository"></a>
|
||||
## type Repository {#Repository}
|
||||
|
||||
Repository represents a [Helm](<#Helm>) [Chart](<#Chart>) repository.
|
||||
|
||||
```go
|
||||
type Repository struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Resource"></a>
|
||||
## type Resource {#Resource}
|
||||
|
||||
Resource represents one kubernetes api object.
|
||||
|
||||
```go
|
||||
type Resource map[string]any
|
||||
```
|
||||
|
||||
<a name="Resources"></a>
|
||||
## type Resources {#Resources}
|
||||
|
||||
Resources represents a kubernetes resources [Generator](<#Generator>) from CUE.
|
||||
|
||||
```go
|
||||
type Resources map[Kind]map[InternalLabel]Resource
|
||||
```
|
||||
|
||||
<a name="Tags"></a>
|
||||
## type Tags {#Tags}
|
||||
|
||||
Tags represents standardized fields injected into the component [BuildPlan](<#BuildPlan>) from the [Platform](<#Platform>).
|
||||
|
||||
Note, tags should have a reasonable default value to easily use cue eval and cue export without needing to make a bunch of decisions about tag values.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
import core "github.com/holos-run/holos/api/core/v1alpha4"
|
||||
_Tags: core.#Tags & {
|
||||
cluster: _ @tag(cluster, type=string)
|
||||
environment: _ @tag(environment, type=string)
|
||||
component: _ @tag(component, type=string)
|
||||
name: _ @tag(name, type=string)
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
type Tags struct {
|
||||
// Name represents the BuildPlan metadata.name field injected from the Platform.
|
||||
Name string `json:"name" cue:"string | *\"no-name\""`
|
||||
// Cluster represents the cluster name injected from
|
||||
Cluster string `json:"cluster" cue:"string | *\"no-cluster\""`
|
||||
// Environment represents the build plan environment.
|
||||
Environment string `json:"environment" cue:"string | *\"no-environment\""`
|
||||
// Component represents the path of the component relative to the platform root.
|
||||
Component string `json:"component" cue:"string | *\"no-component\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Transformer"></a>
|
||||
## type Transformer {#Transformer}
|
||||
|
||||
Transformer transforms [Generator](<#Generator>) manifests within a [Artifact](<#Artifact>).
|
||||
|
||||
```go
|
||||
type Transformer struct {
|
||||
// Kind represents the kind of transformer. Must be Kustomize, or Join.
|
||||
Kind string `json:"kind" cue:"\"Kustomize\" | \"Join\""`
|
||||
// Inputs represents the files to transform. The Output of prior Generators
|
||||
// and Transformers.
|
||||
Inputs []FilePath `json:"inputs"`
|
||||
// Output represents a file for a subsequent Transformer or Artifact to
|
||||
// consume.
|
||||
Output FilePath `json:"output"`
|
||||
// Kustomize transformer. Ignored unless kind is Kustomize.
|
||||
Kustomize Kustomize `json:"kustomize,omitempty"`
|
||||
// Join transformer. Ignored unless kind is Join.
|
||||
Join Join `json:"join,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Values"></a>
|
||||
## type Values {#Values}
|
||||
|
||||
Values represents [Helm](<#Helm>) Chart values generated from CUE.
|
||||
|
||||
```go
|
||||
type Values map[string]any
|
||||
```
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
||||
724
doc/md/archive/guides/2024-09-15-quickstart.mdx
Normal file
@@ -0,0 +1,724 @@
|
||||
---
|
||||
description: Try Holos with this quick start guide.
|
||||
slug: /archive/2024-09-15-quickstart
|
||||
sidebar_position: 100
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Quickstart
|
||||
|
||||
In this guide, you'll experience how Holos makes the process of operating a
|
||||
Platform safer, easier, and more consistent. We'll use Holos to manage a
|
||||
vendor-provided Helm chart as a Component. Next, we'll mix in our own custom
|
||||
resources to manage the Component with GitOps. Finally, you'll see how Holos
|
||||
makes it safer and easier to maintain software over time by surfacing the exact
|
||||
changes that will be applied when upgrading the vendor's chart to a new version,
|
||||
before they are actually made.
|
||||
|
||||
The [Concepts](/docs/concepts) page defines capitalized terms such as Platform
|
||||
and Component.
|
||||
|
||||
## 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.
|
||||
|
||||
Optionally, if you'd like to apply the rendered manifests to a real Cluster,
|
||||
first complete the [Local Cluster Guide](/docs/guides/local-cluster).
|
||||
|
||||
## Install Holos
|
||||
|
||||
Install Holos with the following command or other methods listed on the
|
||||
[Installation](/docs/install/) page.
|
||||
|
||||
```bash
|
||||
go install github.com/holos-run/holos/cmd/holos@latest
|
||||
```
|
||||
|
||||
## Create a Git Repository
|
||||
|
||||
Start by initializing an empty Git repository. Holos operates on local files
|
||||
stored in a Git repository.
|
||||
|
||||
<Tabs groupId="init">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
mkdir holos-quickstart
|
||||
cd holos-quickstart
|
||||
git init
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
Initialized empty Git repository in /holos-quickstart/.git/
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This guide assumes you will run commands from the root directory of the Git
|
||||
repository unless stated otherwise.
|
||||
|
||||
## Generate the Platform {#Generate-Platform}
|
||||
|
||||
Generate the Platform code in the repository root. A Platform refers to the
|
||||
entire set of software holistically integrated to provide a software development
|
||||
platform for your organization. In this guide, the Platform will include a
|
||||
single Component to demonstrate how the concepts fit together.
|
||||
|
||||
```bash
|
||||
holos generate platform quickstart
|
||||
```
|
||||
|
||||
Commit the generated platform config to the repository.
|
||||
|
||||
<Tabs groupId="commit-platform">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate platform quickstart - $(holos --version)"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main (root-commit) 0b17b7f] holos generate platform quickstart
|
||||
213 files changed, 72349 insertions(+)
|
||||
...
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Generate a Component {#generate-component}
|
||||
|
||||
The platform you generated is currently empty. Run the following command to
|
||||
generate the CUE code that defines a Helm Component.
|
||||
|
||||
<Tabs groupId="gen-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos generate component podinfo --component-version 6.6.1
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
generated component
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The --component-version 6.6.1 flag intentionally installs an older release.
|
||||
You'll see how Holos assists with software upgrades later in this guide.
|
||||
|
||||
The generate component command creates two files: a leaf file,
|
||||
`components/podinfo/podinfo.gen.cue`, and a root file, `podinfo.gen.cue`. Holos
|
||||
leverages the fact that [order is
|
||||
irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/) in CUE to
|
||||
register the component with the Platform by adding a file to the root of the Git
|
||||
repository. The second file defines the component in the leaf component
|
||||
directory.
|
||||
|
||||
<Tabs groupId="podinfo-files">
|
||||
<TabItem value="components/podinfo/podinfo.gen.cue" label="Leaf">
|
||||
`components/podinfo/podinfo.gen.cue`
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
|
||||
let Chart = {
|
||||
Name: "podinfo"
|
||||
Version: "6.6.1"
|
||||
Namespace: "default"
|
||||
|
||||
Repo: name: "podinfo"
|
||||
Repo: url: "https://stefanprodan.github.io/podinfo"
|
||||
|
||||
Values: {}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="podinfo.gen.cue" label="Root">
|
||||
`podinfo.gen.cue`
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Manage podinfo on workload clusters only
|
||||
for Cluster in #Fleets.workload.clusters {
|
||||
#Platform: Components: "\(Cluster.name)/podinfo": {
|
||||
path: "components/podinfo"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
In this example, we provide the minimal information needed to manage the Helm
|
||||
chart: the name, version, Kubernetes namespace for deployment, and the chart
|
||||
repository location.
|
||||
|
||||
This chart deploys cleanly without any values provided, but we include an empty
|
||||
Values struct to show how Holos improves consistency and safety in Helm by
|
||||
leveraging the strong type-checking in CUE. You can safely pass shared values,
|
||||
such as the organization’s domain name, to all Components across all clusters in
|
||||
the Platform by defining them at the root of the configuration.
|
||||
|
||||
Commit the generated component config to the repository.
|
||||
|
||||
<Tabs groupId="commit-component">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate component podinfo - $(holos --version)"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main cc0e90c] holos generate component podinfo
|
||||
2 files changed, 24 insertions(+)
|
||||
create mode 100644 components/podinfo/podinfo.gen.cue
|
||||
create mode 100644 podinfo.gen.cue
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Render the Component
|
||||
|
||||
You can render individual components without adding them to a Platform, which is
|
||||
helpful when developing a new component.
|
||||
|
||||
<Tabs groupId="render-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render component ./components/podinfo --cluster-name=default
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
cached
|
||||
rendered podinfo
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
First, the command caches the Helm chart locally to speed up subsequent
|
||||
renderings. Then, the command runs Helm to produce the output and writes it into
|
||||
the deploy directory.
|
||||
|
||||
<Tabs groupId="tree-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
tree deploy
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
deploy
|
||||
└── clusters
|
||||
└── default
|
||||
└── components
|
||||
└── podinfo
|
||||
└── podinfo.gen.yaml
|
||||
|
||||
5 directories, 1 file
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The component deploys to one cluster named `default`. In practice, the same
|
||||
component is often deployed to multiple clusters, such as `east` and `west` to
|
||||
provide redundancy and increase availability.
|
||||
|
||||
:::tip
|
||||
This example is equivalent to running `helm template` on the chart and saving
|
||||
the output to a file. Holos simplifies this task, making it safer and more
|
||||
consistent when managing many charts.
|
||||
:::
|
||||
|
||||
## Mix in an ArgoCD Application
|
||||
|
||||
We've seen how Holos works with Helm, but we haven't yet explored how Holos
|
||||
makes it easier to consistently and safely manage all of the software in a
|
||||
Platform.
|
||||
|
||||
Holos allows you to easily mix in resources that differentiate your Platform.
|
||||
We'll use this feature to mix in an ArgoCD [Application][application] to manage
|
||||
the podinfo Component with GitOps. We'll define this configuration in a way that
|
||||
can be automatically and consistently reused across all future Components added
|
||||
to the Platform.
|
||||
|
||||
Create a new file named `argocd.cue` in the root of your Git repository with the
|
||||
following contents:
|
||||
|
||||
<Tabs groupId="argocd-config">
|
||||
<TabItem value="command" label="argocd.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
#ArgoConfig: {
|
||||
Enabled: true
|
||||
RepoURL: "https://github.com/holos-run/holos-quickstart-guide"
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
If you plan to apply the rendered output to a real cluster, change the
|
||||
`example.com` RepoURL to the URL of the Git repository you created in this
|
||||
guide. You don't need to change the example if you're just exploring Holos by
|
||||
inspecting the rendered output without applying it to a live cluster.
|
||||
:::
|
||||
|
||||
With this file in place, render the component again.
|
||||
|
||||
<Tabs groupId="render-podinfo-argocd">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render component ./components/podinfo --cluster-name=default
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
wrote deploy file
|
||||
rendered gitops/podinfo
|
||||
rendered podinfo
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos uses the locally cached chart to improve performance and reliability. It
|
||||
then renders the Helm template output along with an ArgoCD Application resource
|
||||
for GitOps.
|
||||
|
||||
:::tip
|
||||
By defining the ArgoCD configuration at the root, we again take advantage of the
|
||||
fact that [order is
|
||||
irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/) in CUE.
|
||||
:::
|
||||
|
||||
Defining the configuration at the root ensures all future leaf Components take
|
||||
the ArgoCD configuration and render an Application manifest for GitOps
|
||||
management.
|
||||
|
||||
<Tabs groupId="tree-podinfo-argocd">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
tree deploy
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
deploy
|
||||
└── clusters
|
||||
└── default
|
||||
├── components
|
||||
│ └── podinfo
|
||||
│ └── podinfo.gen.yaml
|
||||
└── gitops
|
||||
└── podinfo.application.gen.yaml
|
||||
|
||||
6 directories, 2 files
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Notice the new `podinfo.application.gen.yaml` file created by enabling ArgoCD in
|
||||
the Helm component. The Application resource in the file looks like this:
|
||||
|
||||
<Tabs groupId="podinfo-application">
|
||||
<TabItem value="file" label="podinfo.application.gen.yaml">
|
||||
```yaml showLineNumbers
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
path: ./deploy/clusters/default/components/podinfo
|
||||
repoURL: https://example.com/holos-quickstart.git
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
Holos generates a similar Application resource for every additional Component
|
||||
added to your Platform.
|
||||
:::
|
||||
|
||||
Finally, add and commit the results to your Platform's Git repository.
|
||||
|
||||
<Tabs groupId="commit-argo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos render component ./components/podinfo --cluster-name=default"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main f95cef1] holos render component ./components/podinfo --cluster-name=default
|
||||
3 files changed, 134 insertions(+)
|
||||
create mode 100644 argocd.cue
|
||||
create mode 100644 deploy/clusters/default/components/podinfo/podinfo.gen.yaml
|
||||
create mode 100644 deploy/clusters/default/gitops/podinfo.application.gen.yaml
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
In this section, we learned how Holos simplifies mixing resources into
|
||||
Components, like an ArgoCD Application. Holos ensures consistency by managing an
|
||||
Application resource for every Component added to the Platform through the
|
||||
configuration you define in `argocd.cue` at the root of the repository.
|
||||
|
||||
## Define Workload Clusters {#workload-clusters}
|
||||
|
||||
We've generated a Component to manage podinfo and integrated it with our
|
||||
Platform, but rendering the Platform doesn't render podinfo. Podinfo isn't
|
||||
rendered because we haven't assigned any Clusters to the workload Fleet.
|
||||
|
||||
Define two new clusters, `east` and `west`, and assign them to the workload
|
||||
Fleet. Create a new file named `clusters.cue` in the root of your Git repository
|
||||
with the following contents:
|
||||
|
||||
<Tabs groupId="clusters">
|
||||
<TabItem value="clusters.cue" label="clusters.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Define two workload clusters for disaster recovery.
|
||||
#Fleets: workload: clusters: {
|
||||
// In CUE _ indicates values are defined elsewhere.
|
||||
east: _
|
||||
west: _
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This example shows how Holos simplifies configuring multiple clusters with
|
||||
similar configuration by grouping them into a Fleet.
|
||||
|
||||
:::tip
|
||||
Fleets help segment a group of Clusters into one leader and multiple followers
|
||||
by designating one cluster as the primary. Holos makes it safer, easier, and
|
||||
more consistent to reconfigure which cluster is the primary. The primary can be
|
||||
set to automatically restore persistent data from backups, while non-primary
|
||||
clusters can be configured to automatically replicate from the primary.
|
||||
|
||||
Automatic database backup, restore, and streaming replication is an advanced
|
||||
topic enabled by Cloud Native PG and CUE. Check back for a guide on this and
|
||||
other Day 2 operations topics.
|
||||
:::
|
||||
|
||||
## Render the Platform {#render-platform}
|
||||
|
||||
Render the Platform to render the podinfo Component for each of the workload
|
||||
clusters.
|
||||
|
||||
<Tabs groupId="render-platform">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered components/podinfo for cluster west in 99.480792ms
|
||||
rendered components/podinfo for cluster east in 99.882667ms
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The render platform command iterates over every Cluster in the Fleet and renders
|
||||
each Component assigned to the Fleet. Notice the two additional subdirectories
|
||||
created under the deploy directory, one for each cluster: `east` and `west`.
|
||||
|
||||
<Tabs groupId="tree-platform">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
tree deploy
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
deploy
|
||||
└── clusters
|
||||
├── default
|
||||
│ ├── components
|
||||
│ │ └── podinfo
|
||||
│ │ └── podinfo.gen.yaml
|
||||
│ └── gitops
|
||||
│ └── podinfo.application.gen.yaml
|
||||
# highlight-next-line
|
||||
├── east
|
||||
│ ├── components
|
||||
│ │ └── podinfo
|
||||
│ │ └── podinfo.gen.yaml
|
||||
│ └── gitops
|
||||
│ └── podinfo.application.gen.yaml
|
||||
# highlight-next-line
|
||||
└── west
|
||||
├── components
|
||||
│ └── podinfo
|
||||
│ └── podinfo.gen.yaml
|
||||
└── gitops
|
||||
└── podinfo.application.gen.yaml
|
||||
|
||||
14 directories, 6 files
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos ensures consistency and safety by defining the ArgoCD Application once,
|
||||
with strong type checking, at the configuration root.
|
||||
|
||||
New Application resources are automatically generated for the `east` and `west`
|
||||
workload Clusters.
|
||||
|
||||
<Tabs groupId="applications">
|
||||
<TabItem value="east" label="east">
|
||||
`deploy/clusters/east/gitops/podinfo.application.gen.yaml`
|
||||
```yaml showLineNumbers
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
# highlight-next-line
|
||||
path: ./deploy/clusters/east/components/podinfo
|
||||
repoURL: https://example.com/holos-quickstart.git
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="west" label="west">
|
||||
`deploy/clusters/west/gitops/podinfo.application.gen.yaml`
|
||||
```yaml showLineNumbers
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
# highlight-next-line
|
||||
path: ./deploy/clusters/west/components/podinfo
|
||||
repoURL: https://example.com/holos-quickstart.git
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="default" label="default">
|
||||
`deploy/clusters/default/gitops/podinfo.application.gen.yaml`
|
||||
```yaml showLineNumbers
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
# highlight-next-line
|
||||
path: ./deploy/clusters/default/components/podinfo
|
||||
repoURL: https://example.com/holos-quickstart.git
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Add and commit the rendered Platform and workload Clusters.
|
||||
|
||||
<Tabs groupId="commit-render-platform">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos render platform ./platform - $(holos --version)"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main 5aebcf5] holos render platform ./platform - 0.93.2
|
||||
5 files changed, 263 insertions(+)
|
||||
create mode 100644 clusters.cue
|
||||
create mode 100644 deploy/clusters/east/components/podinfo/podinfo.gen.yaml
|
||||
create mode 100644 deploy/clusters/east/gitops/podinfo.application.gen.yaml
|
||||
create mode 100644 deploy/clusters/west/components/podinfo/podinfo.gen.yaml
|
||||
create mode 100644 deploy/clusters/west/gitops/podinfo.application.gen.yaml
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Upgrade a Helm Chart
|
||||
|
||||
Holos is designed to ease the burden of Day 2 operations. With Holos, upgrading
|
||||
software, integrating new software, and making safe platform-wide configuration
|
||||
changes become easier.
|
||||
|
||||
Let's upgrade the podinfo Component to see how this works in practice. First,
|
||||
update the Component version field to the latest upstream Helm chart version.
|
||||
|
||||
<Tabs groupId="gen-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos generate component podinfo --component-version 6.6.2
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
generated component
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Remove the cached chart version.
|
||||
|
||||
<Tabs groupId="gen-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
rm -rf components/podinfo/vendor
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Now re-render the Platform.
|
||||
|
||||
<Tabs groupId="render-platform2">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered components/podinfo for cluster east in 327.10475ms
|
||||
rendered components/podinfo for cluster west in 327.796541ms
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Notice we're still using the upstream chart without modifying it. The Holos
|
||||
component wraps around the chart to mix in additional resources and integrate
|
||||
the component with the broader Platform.
|
||||
|
||||
## Visualize the Changes
|
||||
|
||||
Holos makes it easier to see exactly what changes are made and which resources
|
||||
will be applied to the API server. By design, Holos operates on local files,
|
||||
leaving the task of applying them to ecosystem tools like `kubectl` and ArgoCD.
|
||||
This allows platform operators to inspect changes during code review, or before
|
||||
committing the change at all.
|
||||
|
||||
For example, using `git diff`, we see that the only functional change when
|
||||
upgrading this Helm chart is the deployment of a new container image tag to each
|
||||
cluster. Additionally, we can roll out this change gradually by applying it to
|
||||
the east cluster first, then to the west cluster, limiting the potential blast
|
||||
radius of a problematic change.
|
||||
|
||||
<Tabs groupId="git-diff">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff deploy/clusters/east
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff showLineNumbers
|
||||
diff --git a/deploy/clusters/east/components/podinfo/podinfo.gen.yaml b/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
|
||||
index 7cc3332..8c1647d 100644
|
||||
--- a/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
|
||||
+++ b/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
|
||||
@@ -5,9 +5,9 @@ kind: Service
|
||||
metadata:
|
||||
name: podinfo
|
||||
labels:
|
||||
- helm.sh/chart: podinfo-6.6.1
|
||||
+ helm.sh/chart: podinfo-6.6.2
|
||||
app.kubernetes.io/name: podinfo
|
||||
- app.kubernetes.io/version: "6.6.1"
|
||||
+ app.kubernetes.io/version: "6.6.2"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
type: ClusterIP
|
||||
@@ -29,9 +29,9 @@ kind: Deployment
|
||||
metadata:
|
||||
name: podinfo
|
||||
labels:
|
||||
- helm.sh/chart: podinfo-6.6.1
|
||||
+ helm.sh/chart: podinfo-6.6.2
|
||||
app.kubernetes.io/name: podinfo
|
||||
- app.kubernetes.io/version: "6.6.1"
|
||||
+ app.kubernetes.io/version: "6.6.2"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
replicas: 1
|
||||
@@ -53,7 +53,7 @@ spec:
|
||||
terminationGracePeriodSeconds: 30
|
||||
containers:
|
||||
- name: podinfo
|
||||
# highlight-next-line
|
||||
- image: "ghcr.io/stefanprodan/podinfo:6.6.1"
|
||||
# highlight-next-line
|
||||
+ image: "ghcr.io/stefanprodan/podinfo:6.6.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- ./podinfo
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
Holos is designed to surface the _fully rendered_ manifests intended for the
|
||||
Kubernetes API server, making it easier to see and reason about platform-wide
|
||||
configuration changes.
|
||||
:::
|
||||
|
||||
## Recap {#recap}
|
||||
|
||||
In this quickstart guide, we learned how Holos makes it easier, safer, and more
|
||||
consistent to manage a Platform composed of multiple Clusters and upstream Helm
|
||||
charts.
|
||||
|
||||
We covered how to:
|
||||
|
||||
1. Generate a Git repository for the Platform config.
|
||||
2. Wrap the unmodified upstream podinfo Helm chart into a Component.
|
||||
3. Render an individual Component.
|
||||
4. Mix-in your Platform's unique resources to all Components. For example, ArgoCD Application resources.
|
||||
5. Define multiple similar, but not identical, workload clusters.
|
||||
6. Render the manifests for the entire Platform with the `holos render platform` command.
|
||||
7. Upgrade a Helm chart to the latest version as an important Day 2 task.
|
||||
8. Visualize and surface the details of planned changes Platform wide.
|
||||
|
||||
## Dive Deeper
|
||||
|
||||
If you'd like to dive deeper, check out the [Schema API][schema] and [Core
|
||||
API][core] reference docs. The main difference between the schema and core
|
||||
packages is that the schema is used by users to write refined CUE, while the
|
||||
core package is what the schema produces for `holos` to execute. Users rarely
|
||||
need to interact with the Core API when on the happy path, but can use the core
|
||||
package as an escape hatch when the happy path doesn't go where you want.
|
||||
|
||||
|
||||
[application]: https://argo-cd.readthedocs.io/en/stable/user-guide/application-specification/
|
||||
[schema]: /docs/api/author/v1alpha3/
|
||||
[core]: /docs/api/core/v1alpha3/
|
||||
106
doc/md/archive/guides/2024-09-17-manage-a-project.mdx
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
description: Self service platform resource management for project teams.
|
||||
slug: /archive/guides/2024-09-17-manage-a-project
|
||||
sidebar_position: 250
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Manage a Project
|
||||
|
||||
In this guide we'll explore how Holos easily, safely, and consistently manages
|
||||
platform resources for teams to develop the projects they're working on.
|
||||
|
||||
Intended Audience: Platform Engineers and Software Engineers.
|
||||
|
||||
Goal is to demonstrate how the platform team can consistently, easily, and
|
||||
safely provide platform resources to software engineers.
|
||||
|
||||
Assumption is software engineers have a container they want to deploy onto the
|
||||
platform and make accessible. We'll use httpbin as a stand-in for the dev
|
||||
team's container.
|
||||
|
||||
Project is roughly equivalent to Dev Team for the purpose of this guide, but in
|
||||
practice multiple teams work on a given project over the lifetime of the
|
||||
project, so we structure the files into projects instead of teams.
|
||||
|
||||
## 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 Helm Components.
|
||||
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Kustomize Components.
|
||||
|
||||
If you'd like to apply the manifests we render in this guide complete the
|
||||
following optional, but recommended, steps.
|
||||
|
||||
a. Complete the [Local Cluster] guide to set up a local cluster to work with.
|
||||
b. You'll need a GitHub account to fork the repository associated with this
|
||||
guide.
|
||||
|
||||
## Fork the Guide Repository
|
||||
|
||||
<Tabs groupId="fork">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt showLineNumbers
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This guide assumes you will run commands from the root directory of this
|
||||
repository unless stated otherwise.
|
||||
|
||||
[Quickstart]: /docs/quickstart
|
||||
[Local Cluster]: /docs/guides/local-cluster
|
||||
|
||||
## Render the Platform
|
||||
|
||||
So we can build the basic platform. Don't dwell on the platform bits.
|
||||
|
||||
## Apply the Manifests
|
||||
|
||||
Deploy ArgoCD, but not any of the Application resources.
|
||||
|
||||
## Browse to ArgoCD
|
||||
|
||||
Note there is nothing here yet.
|
||||
|
||||
## Switch to your Fork
|
||||
|
||||
Note all of the Applications change consistently.
|
||||
|
||||
## Apply the Applications
|
||||
|
||||
Note how ArgoCD takes over management, no longer need to k apply.
|
||||
|
||||
## Create a Project
|
||||
|
||||
Project is a conceptual, not technical, thing in Holos. Mainly about how components are laid out in the filesystem tree.
|
||||
|
||||
We use a schematic built into holos as an example, the platform team could use the same or provide a similar template and instructions for development teams to self-serve.
|
||||
|
||||
## Render the Platform
|
||||
|
||||
Notice:
|
||||
|
||||
1. Project is registered with the platform at the root.
|
||||
2. HTTPRoute and Namespace resources are added close to the root in `projects`
|
||||
3. Deployment and Service resources are added at the leaf in `projects/httpbin/backend`
|
||||
|
||||
## Update the image tag
|
||||
|
||||
Add a basic schematic to demonstrate this. May need to add two new flags for image url and image tag to the generate subcommand, but should just be two new fields on the struct.
|
||||
|
||||
## Dive Deeper
|
||||
|
||||
Set the stage for constraints. Ideas: Limit what resources can be added,
|
||||
namespaces can be operated in, enforce labels, etc...
|
||||
|
||||
Simple, consistent, easy constraints.
|
||||
|
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 |
BIN
doc/md/archive/guides/argocd/argocd-login-signedout.png
Normal file
|
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 |
6
doc/md/archive/guides/argocd/index.mdx
Normal file
@@ -0,0 +1,6 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# ArgoCD
|
||||
|
||||
Coming soon.
|
||||
3
doc/md/archive/guides/backstage/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Backstage
|
||||
|
||||
Coming soon.
|
||||
1862
doc/md/archive/guides/expose-a-service.mdx
Normal file
3
doc/md/archive/guides/observability/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Observability
|
||||
|
||||
Coming soon.
|
||||
BIN
doc/md/archive/guides/try-holos/form-pushed.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
687
doc/md/archive/guides/try-holos/index.mdx
Normal file
@@ -0,0 +1,687 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Try Holos Locally
|
||||
|
||||
This guide walks through the process of building and managing a software
|
||||
development platform with Holos. The k3d platform built in this guide is a
|
||||
slimmed down version of the larger, more holistic, Holos reference platform.
|
||||
|
||||
Holos is different from existing tools in a few important ways.
|
||||
|
||||
1. Holos provides a **unified configuration model** purpose built to improve on
|
||||
unmodified Helm charts, Kustomize bases, or anything else that produces
|
||||
structured configuration data.
|
||||
2. Holos all but **eliminates the need to template yaml**, a common source of
|
||||
frustration and errors in production.
|
||||
3. Holos platforms are **composable** and have breadth. The toolchain and
|
||||
techniques scale down to one machine and up to multiple clusters across
|
||||
multiple regions.
|
||||
4. The unified configuration model is well suited to a **Zero Trust security
|
||||
model**. Platform wide policy configuration is easier to manage with Holos.
|
||||
|
||||
---
|
||||
|
||||
This guide assumes commands are run locally. Capitalized terms have specific
|
||||
definitions described in the [Glossary](/docs/glossary).
|
||||
|
||||
## 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.
|
||||
|
||||
:::note
|
||||
|
||||
Registering an account **is recommended** to try out proper authentication and
|
||||
authorization in Holos, but you can complete this guide without signing up.
|
||||
|
||||
:::
|
||||
|
||||
## Goal {#Goal}
|
||||
|
||||
By the end of this guide you'll have built the foundation of a software
|
||||
development platform. The foundation provides Zero Trust security by
|
||||
holistically integrating off-the-shelf open source software.
|
||||
|
||||
1. Istio is configured to authenticate and authorize requests using an OIDC
|
||||
ID-Token issued by ZITADEL before requests reach backend services.
|
||||
2. The platform provides single sign-on and role based access control for all
|
||||
services running on the platform.
|
||||
|
||||
This guide strives to keep things neat and tidy. All of the resources are
|
||||
located in one k3d cluster and one local Git repository. If you want to clean
|
||||
up at any point, do so with:
|
||||
|
||||
```bash
|
||||
k3d cluster delete workload
|
||||
rm -rf holos-k3d
|
||||
```
|
||||
|
||||
## Sign In or Out {#Sign-In}
|
||||
|
||||
Holos provides integrated authentication and authorization which we'll use in
|
||||
this guide to protect a service. We recommend registering an account to see
|
||||
this in action. Registration also enables you to explore the customizable web
|
||||
form that simplifies complex configuration.
|
||||
|
||||
If you opt-out, the platform will be configured to use a fake identity in place
|
||||
of real id tokens.
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Sign In">
|
||||
```bash
|
||||
holos register user
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Opt Out">
|
||||
```bash
|
||||
holos logout
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Create the Platform {#Create-Platform}
|
||||
|
||||
A server-side platform resource in Holos stores the web form used to simplify
|
||||
platform wide configuration.
|
||||
|
||||
First, initialize an empty Git repository:
|
||||
|
||||
```bash
|
||||
mkdir holos-k3d
|
||||
cd holos-k3d
|
||||
git init
|
||||
```
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
Use `holos` to make the rpc call to create the server-side platform
|
||||
resource.
|
||||
|
||||
```bash
|
||||
holos create platform --name k3d --display-name "Try Holos Locally"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
Create a blank `platform.metadata.json` file so subsequent holos commands
|
||||
skip rpc calls.
|
||||
|
||||
```bash
|
||||
touch platform.metadata.json
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Generate the Platform {#Generate-Platform}
|
||||
|
||||
Generate the platform code in the repository root.
|
||||
|
||||
```bash
|
||||
holos generate platform k3d
|
||||
```
|
||||
|
||||
Commit the generated platform config to the repository.
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate platform k3d - $(holos --version)"
|
||||
```
|
||||
|
||||
### Push the Platform Form
|
||||
|
||||
Each Holos platform has a Platform Form used to submit top level, platform-wide
|
||||
configuration values. The purpose of the form is to validate configuration
|
||||
values and simplify complicated configurations and integrations.
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
Push the Platform Form to publish it. Browse to the printed URL to view the
|
||||
form.
|
||||
|
||||
```bash
|
||||
holos push platform form .
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
You will update the Platform Model locally in a later step so there's
|
||||
nothing to do in this step. Only signed-in users can push a Platform Form
|
||||
to the Holos web server.
|
||||
|
||||
```bash
|
||||
# holos push platform form .
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The Platform Form is defined locally in `forms/platform/platform-form.cue`.
|
||||
|
||||
On the web it looks like:
|
||||

|
||||
|
||||
### Update the Platform Model {#Platform-Model}
|
||||
|
||||
Holos needs initial, top level configuration values to render the platform. The
|
||||
Platform Model is the term we use for these values. In this section you will
|
||||
configure role based access control by way of updating the Platform Model.
|
||||
|
||||
In the k3d platform you're building now, role based access control is
|
||||
implemented by asserting against the oidc id token subject. Update the form
|
||||
with the `sub` claim value from your id token. This will ensure only you have
|
||||
access to platform services.
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
Copy and paste the `sub` value into your Platform Form's Subject field.
|
||||
|
||||
```bash
|
||||
holos login --print-claims --log-level=error | jq -r .sub
|
||||
```
|
||||
|
||||
After pasting the `sub` value, click Submit on the form.
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
You don't have an id token when you're signed out, so there's nothing for
|
||||
you to do in this step.
|
||||
|
||||
```bash
|
||||
# holos login --print-claims --log-level=error | jq -r .sub
|
||||
```
|
||||
|
||||
The platform will be configured to assert against the User-Agent header
|
||||
instead.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Pull the Platform Model {#Pull-the-Platform-Model}
|
||||
|
||||
The Platform Model needs to be pulled into the local Git repository after the
|
||||
form has been submitted. Next, we'll run `holos render` which operates
|
||||
exclusively on local files.
|
||||
|
||||
Holos stores the Platform Model in the `platform.config.json` file. Holos
|
||||
provides this file as input to CUE when rendering the platform. This file is
|
||||
intended to be added to version control.
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
Pull the updated Platform Model into the local repository.
|
||||
|
||||
```bash
|
||||
holos pull platform model .
|
||||
git add platform.config.json
|
||||
git commit -m "Add platform model"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
The holos generate platform k3d command created an initial Platform Model in
|
||||
`platform.config.json`. As a result there's nothing to do in this step.
|
||||
|
||||
```bash
|
||||
# holos pull platform model .
|
||||
# git add platform.config.json
|
||||
# git commit -m "Add platform model"
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Render the Platform {#Render-the-Platform}
|
||||
|
||||
Holos has everything necessary to render the platform once the
|
||||
`platform.config.json` file and the code from `holos generate` are in the
|
||||
current directory.
|
||||
|
||||
Rendering a platform is the process of iterating over each platform component
|
||||
and rendering it into plain yaml. Holos does not apply the resulting manifests.
|
||||
Other tools like kubectl, ArgoCD, or Flux are responsible for applying the
|
||||
manifests.
|
||||
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
|
||||
The render command writes the manifest files to the `deploy/` directory. Commit
|
||||
the files so they can be applied via GitOps later.
|
||||
|
||||
```bash
|
||||
git add deploy
|
||||
git commit -m "holos render platform ./platform"
|
||||
```
|
||||
|
||||
:::info[Don't blink, this is where Holos builds the platform]
|
||||
|
||||
It usually takes no more than a few seconds.
|
||||
|
||||
Rendering the holos reference platform currently results in about 500K lines of
|
||||
yaml. In contrast, roughly 80K lines are produced by this slimmed down k3d
|
||||
platform.
|
||||
|
||||
We mention this because the scale doesn't matter as much as it does with other
|
||||
tools. Manage millions of lines of configuration with Holos the same way this
|
||||
guide manages thousands. This is made possible by the unique way CUE unifies
|
||||
all configuration into one single model.
|
||||
|
||||
:::
|
||||
|
||||
## Configure DNS {#DNS}
|
||||
|
||||
Configure your machine to resolve `*.holos.localhost` to your loopback
|
||||
interface. This is necessary for requests to reach the workload cluster.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="macos" label="macOS" default>
|
||||
Cache sudo credentials.
|
||||
|
||||
Admin access is necessary to setup a local dnsmasq instance and configure
|
||||
macOS's DNS resolver.
|
||||
|
||||
```bash
|
||||
sudo -v
|
||||
```
|
||||
|
||||
Resolve *.holos.localhost DNS queries to 127.0.0.1.
|
||||
|
||||
```bash
|
||||
bash ./scripts/local-dns
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux" label="Linux">
|
||||
[NSS-myhostname](http://man7.org/linux/man-pages/man8/nss-myhostname.8.html)
|
||||
ships with many Linux distributions and should resolve *.localhost
|
||||
automatically to 127.0.0.1.
|
||||
|
||||
Otherwise it is installable with:
|
||||
|
||||
```bash
|
||||
sudo apt install libnss-myhostname
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="windows" label="Windows">
|
||||
Ensure the loopback interface has at least the following names in `C:\windows\system32\drivers\etc\hosts`
|
||||
|
||||
```
|
||||
127.0.0.1 httpbin.holos.localhost app.holos.localhost
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Create the Cluster {#Create-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.
|
||||
|
||||
:::
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="evaluate" label="Try Holos" default>
|
||||
Use this command when exploring Holos.
|
||||
|
||||
```bash
|
||||
k3d cluster create workload \
|
||||
--port "443:443@loadbalancer" \
|
||||
--k3s-arg "--disable=traefik@server:0"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="develop" label="Develop Holos">
|
||||
Use this command when developing Holos.
|
||||
|
||||
```bash
|
||||
k3d registry create registry.holos.localhost --port 5100
|
||||
```
|
||||
|
||||
```bash
|
||||
k3d cluster create workload \
|
||||
--registry-use k3d-registry.holos.localhost:5100 \
|
||||
--port "443:443@loadbalancer" \
|
||||
--k3s-arg "--disable=traefik@server:0"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Traefik is disabled because Istio provides the same functionality.
|
||||
|
||||
## Apply the Platform Components {#Apply-Platform-Components}
|
||||
|
||||
Use `kubectl` to apply each platform component. In production, it's common to
|
||||
fully automate this process with ArgoCD, but we use `kubectl` to the same
|
||||
effect.
|
||||
|
||||
### Local CA {#Local-CA}
|
||||
|
||||
Holos platforms use cert manager to issue tls certificates. The browser and
|
||||
tools we're using need to trust these certificates to work together.
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
bash ./scripts/local-ca
|
||||
```
|
||||
|
||||
:::warning
|
||||
|
||||
Take care to run the local-ca script each time you create the workload cluster
|
||||
so that Certificates are issued correctly.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
### Service Mesh
|
||||
|
||||
The platform service mesh provides an ingress gateway and connectivity useful
|
||||
for observability, reliability, and security.
|
||||
|
||||
#### Namespaces
|
||||
|
||||
With Holos, components are automatically added to the namespaces component,
|
||||
useful for centrally managed policies.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/namespaces
|
||||
```
|
||||
|
||||
#### Custom Resource Definitions
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/gateway-api
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istio-base
|
||||
```
|
||||
|
||||
#### Cert Manager {#cert-manager}
|
||||
|
||||
Apply the cert-manager controller.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/cert-manager
|
||||
```
|
||||
|
||||
Apply the ClusterIssuer which issues Certificate resources using the local
|
||||
certificate authority.
|
||||
|
||||
```bash
|
||||
kubectl -n cert-manager wait pod -l app.kubernetes.io/component=webhook --for=condition=Ready
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/local-ca
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/certificates
|
||||
kubectl -n istio-gateways wait certificate httpbin.holos.localhost --for=condition=Ready
|
||||
```
|
||||
|
||||
:::warning
|
||||
|
||||
The certificate will time out before becoming ready if the [local-ca](#Local-CA)
|
||||
script was not run after the cluster was created.
|
||||
|
||||
:::
|
||||
|
||||
#### Istio {#Istio}
|
||||
|
||||
Istio implements the Service Mesh.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istio-cni
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/istiod
|
||||
kubectl apply --server-side=true -f ./deploy/clusters/workload/components/gateway
|
||||
```
|
||||
|
||||
Verify the Gateway is programmed and the listeners have been accepted:
|
||||
|
||||
```bash
|
||||
kubectl -n istio-gateways wait gateway default --for=condition=Accepted
|
||||
```
|
||||
|
||||
#### httpbin {#httpbin}
|
||||
|
||||
httpbin is a simple backend service useful for end-to-end testing.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/httpbin-backend
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/httpbin-routes
|
||||
kubectl -n holos-system wait pod -l app.kubernetes.io/instance=httpbin --for=condition=Ready
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
Browse to [https://httpbin.holos.localhost/](https://httpbin.holos.localhost/)
|
||||
to verify end to end connectivity. You should see the httpbin index page.
|
||||
|
||||
:::
|
||||
|
||||
### Authenticating Proxy
|
||||
|
||||
The auth proxy is responsible for authenticating browser requests, handling the
|
||||
oidc authentication flow, and providing a signed id token to the rest of the
|
||||
services in the mesh.
|
||||
|
||||
#### Cookie Secret
|
||||
|
||||
The auth proxy stores session information in an encrypted cookie. Generate a
|
||||
random cookie encryption Secret and apply.
|
||||
|
||||
```bash
|
||||
LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom \
|
||||
| head -c 32 \
|
||||
| kubectl create secret generic "authproxy" \
|
||||
--from-file=cookiesecret=/dev/stdin \
|
||||
--dry-run=client -o yaml \
|
||||
| kubectl apply -n istio-gateways -f-
|
||||
```
|
||||
|
||||
#### Deployment
|
||||
|
||||
The auth proxy Deployment receives requests from web browsers and responds with
|
||||
an authentication decision.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/authproxy
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/authroutes
|
||||
```
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
<Admonition type="info">
|
||||
Verify authentication is working by browsing to
|
||||
[https://httpbin.holos.localhost/holos/authproxy](https://httpbin.holos.localhost/holos/authproxy).
|
||||
|
||||
We want a simple `Authenticated` response.
|
||||
|
||||
<Admonition type="tip">
|
||||
You may need to refresh the page a few times while the platform configures
|
||||
itself.
|
||||
</Admonition>
|
||||
</Admonition>
|
||||
|
||||
Istio will respond with `no healthy upstream` until the pod becomes ready.
|
||||
Wait for the pod to become ready with:
|
||||
|
||||
```bash
|
||||
kubectl -n holos-system wait pod -l app.kubernetes.io/instance=httpbin --for=condition=Ready
|
||||
```
|
||||
|
||||
Once authenticated, visit
|
||||
[https://httpbin.holos.localhost/holos/authproxy/userinfo](https://httpbin.holos.localhost/holos/authproxy/userinfo)
|
||||
which returns a subset of claims from your id token.
|
||||
|
||||
<Admonition type="warning">
|
||||
If you get `Unauthorized` instead of a json response body, make sure you
|
||||
[authenticated](https://httpbin.holos.localhost/holos/authproxy) first.
|
||||
</Admonition>
|
||||
|
||||
```json
|
||||
{
|
||||
"user": "275552236589843464",
|
||||
"email": "demo@holos.run",
|
||||
"preferredUsername": "demo"
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
The auth proxy will always try to sign you in when you are signed out, so
|
||||
there isn't much to do here. Please do take a moment to glance at the
|
||||
Signed In tab to see how this would work if you were signed in.
|
||||
|
||||
The `k3d` platform relies on `https://login.holos.run` to issue id tokens.
|
||||
Authorization has been configured against fake request headers instead of
|
||||
the real `x-oidc-id-token` header.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Authorization Policy
|
||||
|
||||
Configure authorization policies using attributes of the authenticated request.
|
||||
Authorization policies route web requests through the auth proxy and then
|
||||
validate all requests against the `x-oidc-id-token` header.
|
||||
|
||||
```bash
|
||||
kubectl apply --server-side=true -f deploy/clusters/workload/components/authpolicy
|
||||
```
|
||||
|
||||
Istio make take a few seconds to program the Gateway with the
|
||||
AuthorizationPolicy resources.
|
||||
|
||||
## Try out Zero Trust
|
||||
|
||||
A basic Zero Trust security model is now in place. The platform authenticates
|
||||
and authorizes requests before they reach the backend service.
|
||||
|
||||
### Browser
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
The platform has been configured to authorize requests with a `x-oidc-id-token` header.
|
||||
|
||||
1. Verify authentication is working by browsing to [https://httpbin.holos.localhost/dump/request](https://httpbin.holos.localhost/dump/request).
|
||||
- Refresh the page a few times.
|
||||
- The `httpbin` backend pods should echo back the `x-oidc-id-token`
|
||||
header injected by the auth proxy.
|
||||
2. Note the `x-oidc-id-token` header is not sent by your browser but is
|
||||
received by the backend service.
|
||||
- This design reduces the risk of exposing id tokens in the browser.
|
||||
- Browser request size remains constant as more claims are added to id
|
||||
tokens.
|
||||
- Reliability improves because id tokens often overflow request header
|
||||
buffers when they pass through middle boxes across the internet.
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
The platform has been configured to authorize requests with a `User-Agent: anonymous` header.
|
||||
|
||||
1. Open an incognito window (Cmd+Shift+N) to verify the platform is
|
||||
enforcing the authorization policy.
|
||||
2. Browse to
|
||||
[https://httpbin.holos.localhost/dump/request](https://httpbin.holos.localhost/dump/request)
|
||||
you should be redirected to the sign in page by the auth proxy.
|
||||
- You **do not** need to register or sign in.
|
||||
- This step verifies the platform is redirecting unauthenticated
|
||||
requests to the identity provider.
|
||||
- Navigate back or close and re-open an incognito window.
|
||||
3. Set your `User-Agent` header to `anonymous` using your browser developer tools.
|
||||
- For Chrome the process is described
|
||||
[here](https://developer.chrome.com/docs/devtools/device-mode/override-user-agent#override_the_user_agent_string).
|
||||
- The purpose is to simulate an authenticated request.
|
||||
4. Browse to
|
||||
[https://httpbin.holos.localhost/dump/request](https://httpbin.holos.localhost/dump/request).
|
||||
- The platform should allow the request through to the backend pod.
|
||||
- `httpbin` should echo back your request which should contain `User-Agent: anonymous`.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Command Line
|
||||
|
||||
Verify unauthenticated requests are blocked by default outside the browser.
|
||||
|
||||
```bash
|
||||
curl -I https://httpbin.holos.localhost/dump/request
|
||||
```
|
||||
|
||||
You should receive a `HTTP/2 302` response that redirects to `location:
|
||||
https://login.holos.run` to start the oauth login flow.
|
||||
|
||||
Next, verify authenticated requests are allowed.
|
||||
|
||||
<Tabs groupId="registration">
|
||||
<TabItem value="registered" label="Signed In">
|
||||
The platform is configured to authenticate the id token present in the
|
||||
`x-oidc-id-token` header.
|
||||
|
||||
💡 It also works with `grpcurl`.
|
||||
|
||||
```bash
|
||||
curl -H x-oidc-id-token:$(holos token) https://httpbin.holos.localhost/dump/request
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="unregistered" label="Signed Out">
|
||||
The platform is configured to authorize any request with `User-Agent:
|
||||
anonymous` in place of validating the oidc id token.
|
||||
|
||||
💡 Take a moment to click the Signed In tab, I don't want you to miss how
|
||||
cool `$(holos token)` is.
|
||||
|
||||
```bash
|
||||
curl -A anonymous https://httpbin.holos.localhost/dump/request
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You should receive a response showing the request headers the backend received.
|
||||
|
||||
:::tip
|
||||
|
||||
Note how the platform secures both web browser and command line api access to
|
||||
the backend httpbin service. httpbin itself has no authentication or
|
||||
authorization functionality.
|
||||
|
||||
:::
|
||||
|
||||
## Summary
|
||||
|
||||
Thank you for taking the time to try out Holos. In this guide, you built the
|
||||
foundation of a software development platform that:
|
||||
|
||||
1. Provides a unified configuration model with CUE that
|
||||
- Supports unmodified Helm Charts, Kustomize Kustomizations, plain YAML.
|
||||
- Provides a web form to pass top level parameters.
|
||||
2. Reduces errors by eliminating the need to template unstructured text.
|
||||
3. Is composable and scales down to a local machine.
|
||||
4. Provides an way to safely configure broad authentication and authorization
|
||||
policy.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Dive deeper with the following resources that build on the foundation you have now.
|
||||
|
||||
1. Explore the [Rendering Process](/docs/concepts#rendering) in Holos.
|
||||
2. Dive deeper into the [Platform Manifests](./platform-manifests) rendered in this guide.
|
||||
3. Deploy [ArgoCD](../argocd) onto the foundation you built.
|
||||
4. Deploy [Backstage](../backstage) as a portal to the integrated platform components.
|
||||
|
||||
## Clean-Up
|
||||
|
||||
If you'd like to clean up the resources you created in this guide, remove them
|
||||
with:
|
||||
|
||||
```bash
|
||||
k3d cluster delete workload
|
||||
rm -rf holos-k3d
|
||||
```
|
||||
137
doc/md/archive/guides/try-holos/platform-manifests.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Platform Manifests
|
||||
|
||||
This document provides an example of how Holos uses CUE and Helm to unify and
|
||||
render the platform configuration. It refers to the manifests rendered in the
|
||||
Try Holos Locally guide.
|
||||
|
||||
Take a moment to review the manifests `holos` rendered to build the platform.
|
||||
|
||||
### ArgoCD Application
|
||||
|
||||
Note the Git URL in the Platform Model is used to derive the ArgoCD
|
||||
`Application` resource for all of the platform components.
|
||||
|
||||
```yaml
|
||||
# deploy/clusters/workload/gitops/namespaces.application.gen.yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: namespaces
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
# highlight-next-line
|
||||
path: /deploy/clusters/workload/components/namespaces
|
||||
# highlight-next-line
|
||||
repoURL: https://github.com/holos-run/holos-k3d.git
|
||||
# highlight-next-line
|
||||
targetRevision: HEAD
|
||||
```
|
||||
|
||||
One ArgoCD `Application` resource is produced for each Holos component by
|
||||
default. The CUE definition which produces the rendered output is defined in
|
||||
`buildplan.cue` around line 222.
|
||||
|
||||
:::tip
|
||||
|
||||
Note how CUE does not use error-prone text templates, the language is well
|
||||
specified and typed which reduces errors when unifying the configuration with
|
||||
the Platform Model in the following `#Argo` definition.
|
||||
|
||||
:::
|
||||
|
||||
```cue
|
||||
// buildplan.cue
|
||||
|
||||
// #Argo represents an argocd Application resource for each component, written
|
||||
// using the #HolosComponent.deployFiles field.
|
||||
#Argo: {
|
||||
ComponentName: string
|
||||
|
||||
Application: app.#Application & {
|
||||
metadata: name: ComponentName
|
||||
metadata: namespace: "argocd"
|
||||
spec: {
|
||||
destination: server: "https://kubernetes.default.svc"
|
||||
project: "default"
|
||||
source: {
|
||||
// highlight-next-line
|
||||
path: "\(_Platform.Model.argocd.deployRoot)/deploy/clusters/\(_ClusterName)/components/\(ComponentName)"
|
||||
// highlight-next-line
|
||||
repoURL: _Platform.Model.argocd.repoURL
|
||||
// highlight-next-line
|
||||
targetRevision: _Platform.Model.argocd.targetRevision
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deployFiles represents the output files to write along side the component.
|
||||
deployFiles: "clusters/\(_ClusterName)/gitops/\(ComponentName).application.gen.yaml": yaml.Marshal(Application)
|
||||
}
|
||||
```
|
||||
|
||||
### Helm Chart
|
||||
|
||||
The `cert-manger` component renders using the upstream Helm chart. The build
|
||||
plan that defines the helm chart to use along with the values to provide looks
|
||||
like the following.
|
||||
|
||||
:::tip
|
||||
|
||||
Holos fully supports your existing Helm charts. Consider leveraging `holos` as
|
||||
an alternative to umbrella charts.
|
||||
|
||||
:::
|
||||
|
||||
```cue
|
||||
// components/cert-manager/cert-manager.cue
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
|
||||
let Chart = {
|
||||
Name: "cert-manager"
|
||||
Version: "1.14.5"
|
||||
Namespace: "cert-manager"
|
||||
|
||||
Repo: name: "jetstack"
|
||||
Repo: url: "https://charts.jetstack.io"
|
||||
|
||||
// highlight-next-line
|
||||
Values: {
|
||||
installCRDs: true
|
||||
startupapicheck: enabled: false
|
||||
// Must not use kube-system on gke autopilot. GKE Warden blocks access.
|
||||
// highlight-next-line
|
||||
global: leaderElection: namespace: Namespace
|
||||
|
||||
// https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-resource-requests#min-max-requests
|
||||
resources: requests: {
|
||||
cpu: "250m"
|
||||
memory: "512Mi"
|
||||
"ephemeral-storage": "100Mi"
|
||||
}
|
||||
// highlight-next-line
|
||||
webhook: resources: Values.resources
|
||||
// highlight-next-line
|
||||
cainjector: resources: Values.resources
|
||||
// highlight-next-line
|
||||
startupapicheck: resource: Values.resources
|
||||
|
||||
// https://cloud.google.com/kubernetes-engine/docs/how-to/autopilot-spot-pods
|
||||
nodeSelector: {
|
||||
"kubernetes.io/os": "linux"
|
||||
if _ClusterName == "management" {
|
||||
"cloud.google.com/gke-spot": "true"
|
||||
}
|
||||
}
|
||||
webhook: nodeSelector: Values.nodeSelector
|
||||
cainjector: nodeSelector: Values.nodeSelector
|
||||
startupapicheck: nodeSelector: Values.nodeSelector
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This document captures notes on locally developing Holos.
|
||||
|
||||
Follow the steps in [Try Holos Locally](/docs/tutorial/local/k3d), but take
|
||||
care to select `Develop` tabs when creating the k3d cluster so you have a local
|
||||
Follow the steps in [Try Holos Locally](../guides/try-holos), but take care
|
||||
to select `Develop` tabs when creating the k3d cluster so you have a local
|
||||
registry to push to.
|
||||
|
||||
## Apply Resources
|
||||
3
doc/md/backstory.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Backstory
|
||||
|
||||
Holos is a tool intended to lighten the burden of managing Kubernetes resources. In 2020 we set out to develop a holistic platform composed from open source cloud native components. We quickly became frustrated with how each of the major components packaged and distributed their software in a different way. Many projects choose to distribute their software with Helm charts, while others provide plain yaml files and Kustomize bases. The popular Kube Prometheus Stack project provides Jsonnet to render and update Kubernetes yaml manifests.
|
||||
@@ -2,16 +2,87 @@
|
||||
|
||||
This page describes the terms used within the context of Holos.
|
||||
|
||||
## Platform
|
||||
|
||||
In Holos, a Platform is a comprehensive environment configured using the
|
||||
Kubernetes resource model. It extends beyond traditional Kubernetes
|
||||
functionality by integrating cloud resources through Crossplane, allowing for a
|
||||
unified management approach across both Kubernetes and cloud infrastructure. A
|
||||
Platform typically consists of one Management Cluster, which handles control and
|
||||
secret management, and one or more Workload Clusters, where application
|
||||
workloads are deployed and run. This architecture enables a consistent and
|
||||
scalable approach to managing diverse resources and services within the
|
||||
cloud-native ecosystem.
|
||||
|
||||
## Management Cluster
|
||||
|
||||
In the context of Holos, a Management Cluster is a special Kubernetes cluster
|
||||
that hosts Kubernetes controllers. For example, cert-manager, Cluster api, and
|
||||
Crossplane. A management cluster manages a single platform. The primary
|
||||
function of this cluster is to securely store and manage secrets, ensuring the
|
||||
secure handling of sensitive information such as credentials, API keys, and
|
||||
other confidential data. The Management Cluster serves as a centralized and
|
||||
secure control plane for the platform, facilitating the orchestration and
|
||||
management of other components.
|
||||
|
||||
## Workload Cluster
|
||||
|
||||
In Holos, a Workload Cluster is a Kubernetes cluster designed to host and run
|
||||
application workloads. Unlike the Management Cluster, which focuses on control
|
||||
and secret management, Workload Clusters are dedicated to executing the actual
|
||||
applications and services. These clusters can vary in size and configuration
|
||||
based on the specific needs of the applications they support. Workload Clusters
|
||||
leverage Kubernetes' orchestration capabilities to manage the deployment,
|
||||
scaling, and operation of containerized applications, providing a flexible and
|
||||
scalable environment for running production workloads within the platform.
|
||||
|
||||
## Platform Form
|
||||
|
||||
In Holos, a Platform Form is a customizable web form defined by JSON data. Each
|
||||
platform within Holos has a unique Platform Form, which serves as an interface
|
||||
for configuring and managing the platform's settings and resources. Platform
|
||||
engineers can customize the Platform Form by modifying the underlying CUE
|
||||
(Configuration Unified Engine) code, allowing for tailored configurations that
|
||||
meet specific requirements. This flexibility enables platform engineers to
|
||||
create a user-friendly and specific interface for managing the platform's
|
||||
components and operations.
|
||||
|
||||
## Platform Model
|
||||
|
||||
In Holos, the Platform Model represents the collection of values submitted
|
||||
through the Platform Form. It encapsulates the specific configuration details
|
||||
and settings defined by the platform engineers, serving as the blueprint for the
|
||||
platform's setup and operation. The Platform Model is essential for translating
|
||||
the customized options and parameters from the Platform Form into actionable
|
||||
configurations within the Holos ecosystem, ensuring that the platform operates
|
||||
according to the specified requirements and guidelines.
|
||||
|
||||
## Secret Store
|
||||
|
||||
In Holos, a SecretStore is a repository for securely storing and managing
|
||||
sensitive data such as passwords, API keys, and other confidential information.
|
||||
It is compatible with any secret store supported by the External Secrets
|
||||
Operator. By default, the management cluster serves as the SecretStore to
|
||||
minimize dependencies and simplify the architecture. This setup ensures that
|
||||
secrets are managed in a secure and centralized manner, aligning with the
|
||||
overall security framework of the platform.
|
||||
|
||||
## Service Mesh
|
||||
|
||||
In Holos, a Service Mesh is a dedicated infrastructure layer for managing,
|
||||
observing, and securing service-to-service communications within a microservices
|
||||
architecture. It typically includes features such as load balancing, traffic
|
||||
routing, service discovery, and security policies like mutual TLS and access
|
||||
control. The Service Mesh abstracts these functionalities away from the
|
||||
application code, providing a centralized control plane for managing the
|
||||
interactions between microservices. This facilitates better observability,
|
||||
resilience, and security in complex, distributed environments.
|
||||
|
||||
## Zero Trust
|
||||
|
||||
In the context of Holos and broader security practices, Zero Trust is a security
|
||||
model that assumes no implicit trust is granted to any user, system, or
|
||||
component inside or outside the network. Instead, every request for access is
|
||||
treated as potentially malicious, and verification is required at every stage.
|
||||
This model enforces strict identity verification, continuous monitoring, and
|
||||
least-privilege access policies.
|
||||
|
||||
29
doc/md/guides.md
Normal file
@@ -0,0 +1,29 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Guides
|
||||
|
||||
## Technical Overview
|
||||
|
||||
Please see the [Technical Overview] to learn about Holos. If you're ready to
|
||||
drive in and try Holos, please work through the following guides.
|
||||
|
||||
## Bank of Holos
|
||||
The guides are organized as a progression. We'll use Holos to manage a
|
||||
fictional bank's platform, the Bank of Holos in each of the guides. In doing so
|
||||
we'll take the time to explain the foundational concepts of Holos.
|
||||
|
||||
1. [Quickstart] covers the foundational concepts of Holos.
|
||||
2. [Deploy a Service] explains how to deploy a containerized service using an
|
||||
existing Helm chart. This guide then explains how to deploy a similar service
|
||||
safely and consistently with CUE instead of Helm.
|
||||
3. [Change a Service] covers the day two task of making configuration changes to
|
||||
deployed services safely and consistently.
|
||||
|
||||
---
|
||||
|
||||
<DocCardList />
|
||||
|
||||
[Quickstart]: /docs/quickstart/
|
||||
[Deploy a Service]: /docs/guides/deploy-a-service/
|
||||
[Change a Service]: /docs/guides/change-a-service/
|
||||
[Technical Overview]: /docs/technical-overview/
|
||||
714
doc/md/guides/change-a-service.mdx
Normal file
@@ -0,0 +1,714 @@
|
||||
---
|
||||
description: Change a service on your platform.
|
||||
slug: /guides/change-a-service
|
||||
sidebar_position: 300
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Change a Service
|
||||
|
||||
In this guide, we'll explore how Holos supports the frontend development team at [Bank of Holos] in reconfiguring an already deployed service. Along the way, we'll demonstrate how simple configuration changes are made safer with type checking, and how rendering the complete platform provides clear visibility into those changes.
|
||||
|
||||
This guide builds on the concepts covered in the [Quickstart] and [Deploy a Service] guides.
|
||||
|
||||
## What you'll need {#requirements}
|
||||
|
||||
Like our other guides, this guide is intended to be useful without needing to
|
||||
run each command. If you'd like to apply the manifests to a real Cluster,
|
||||
complete the [Local Cluster Guide](/docs/guides/local-cluster) before this
|
||||
guide.
|
||||
|
||||
You'll need the following tools installed to run the commands in this guide.
|
||||
|
||||
1. [holos](/docs/install) - to build the Platform.
|
||||
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos Components that
|
||||
wrap Helm charts.
|
||||
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Holos
|
||||
Components that render with Kustomize.
|
||||
|
||||
## Fork the Git Repository
|
||||
|
||||
If you haven't already done so, [fork the Bank of
|
||||
Holos](https://github.com/holos-run/bank-of-holos/fork) then clone the
|
||||
repository to your local machine.
|
||||
|
||||
<Tabs groupId="git-clone">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
# Change YourName
|
||||
git clone https://github.com/YourName/bank-of-holos
|
||||
cd bank-of-holos
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
Cloning into 'bank-of-holos'...
|
||||
remote: Enumerating objects: 1177, done.
|
||||
remote: Counting objects: 100% (1177/1177), done.
|
||||
remote: Compressing objects: 100% (558/558), done.
|
||||
remote: Total 1177 (delta 394), reused 1084 (delta 303), pack-reused 0 (from 0)
|
||||
Receiving objects: 100% (1177/1177), 2.89 MiB | 6.07 MiB/s, done.
|
||||
Resolving deltas: 100% (394/394), done.
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Run the rest of the commands in this guide from the root of the repository.
|
||||
|
||||
If you plan to apply the changes we make, you can delete and re-create your
|
||||
local platform synced to the start of this guide.
|
||||
|
||||
```bash
|
||||
./scripts/reset-cluster
|
||||
./scripts/apply
|
||||
```
|
||||
|
||||
## Rename the Bank
|
||||
|
||||
Let's imagine the bank recently re-branded from The Bank of Holos to The
|
||||
Holistic Bank. The software development team responsible for the front end
|
||||
website needs to update the branding accordingly.
|
||||
|
||||
Let's explore how Holos catches errors early, before they land in production,
|
||||
then guides the team to the best place to make a change.
|
||||
|
||||
The bank front end web service is managed by the
|
||||
`projects/bank-of-holos/frontend/components/bank-frontend/` component which
|
||||
refers to the organization display name in `schema.gen.cue`.
|
||||
|
||||
<Tabs groupId="F5B546EB-566F-4B83-84C3-C55B40F55555">
|
||||
<TabItem value="schema.gen.cue" label="schema.gen.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
import api "github.com/holos-run/holos/api/author/v1alpha3"
|
||||
|
||||
// Define the default organization name
|
||||
// highlight-next-line
|
||||
#Organization: DisplayName: string | *"Bank of Holos"
|
||||
#Organization: Name: string | *"bank-of-holos"
|
||||
|
||||
#Organization: api.#OrganizationStrict
|
||||
#Platform: api.#Platform
|
||||
#Fleets: api.#StandardFleets
|
||||
|
||||
_ComponentConfig: {
|
||||
Resources: #Resources
|
||||
ArgoConfig: #ArgoConfig
|
||||
}
|
||||
|
||||
#Helm: api.#Helm & _ComponentConfig
|
||||
#Kustomize: api.#Kustomize & _ComponentConfig
|
||||
#Kubernetes: api.#Kubernetes & _ComponentConfig
|
||||
|
||||
#ArgoConfig: api.#ArgoConfig & {
|
||||
ClusterName: _ClusterName
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="projects/bank-of-holos/frontend/components/bank-frontend/bank-frontend.cue" label="projects/bank-of-holos/frontend/components/bank-frontend/bank-frontend.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Produce a kubernetes objects build plan.
|
||||
(#Kubernetes & Objects).BuildPlan
|
||||
|
||||
let Objects = {
|
||||
Name: "bank-frontend"
|
||||
Namespace: #BankOfHolos.Frontend.Namespace
|
||||
|
||||
// Ensure resources go in the correct namespace
|
||||
Resources: [_]: [_]: metadata: namespace: Namespace
|
||||
|
||||
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/frontend.yaml
|
||||
Resources: {
|
||||
Service: frontend: {
|
||||
metadata: name: "frontend"
|
||||
metadata: labels: {
|
||||
application: "bank-of-holos"
|
||||
environment: "development"
|
||||
team: "frontend"
|
||||
tier: "web"
|
||||
}
|
||||
spec: {
|
||||
selector: {
|
||||
app: "frontend"
|
||||
application: "bank-of-holos"
|
||||
environment: "development"
|
||||
team: "frontend"
|
||||
tier: "web"
|
||||
}
|
||||
_ports: http: {
|
||||
name: "http"
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
protocol: "TCP"
|
||||
}
|
||||
ports: [for x in _ports {x}]
|
||||
}
|
||||
}
|
||||
|
||||
Deployment: frontend: {
|
||||
metadata: name: "frontend"
|
||||
metadata: labels: {
|
||||
application: "bank-of-holos"
|
||||
environment: "development"
|
||||
team: "frontend"
|
||||
tier: "web"
|
||||
}
|
||||
spec: {
|
||||
selector: matchLabels: {
|
||||
app: "frontend"
|
||||
application: "bank-of-holos"
|
||||
environment: "development"
|
||||
team: "frontend"
|
||||
tier: "web"
|
||||
}
|
||||
template: {
|
||||
metadata: labels: {
|
||||
app: "frontend"
|
||||
application: "bank-of-holos"
|
||||
environment: "development"
|
||||
team: "frontend"
|
||||
tier: "web"
|
||||
}
|
||||
spec: {
|
||||
securityContext: {
|
||||
seccompProfile: type: "RuntimeDefault"
|
||||
fsGroup: 1000
|
||||
runAsGroup: 1000
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
}
|
||||
serviceAccountName: "bank-of-holos"
|
||||
terminationGracePeriodSeconds: 5
|
||||
containers: [{
|
||||
env: [{
|
||||
name: "BANK_NAME"
|
||||
// highlight-next-line
|
||||
value: #Organization.DisplayName
|
||||
}, {
|
||||
name: "ENV_PLATFORM"
|
||||
value: "local"
|
||||
}, {
|
||||
name: "VERSION"
|
||||
value: "v0.6.5"
|
||||
}, {
|
||||
name: "PORT"
|
||||
value: "8080"
|
||||
}, {
|
||||
name: "ENABLE_TRACING"
|
||||
value: "false"
|
||||
}, {
|
||||
name: "SCHEME"
|
||||
value: "https"
|
||||
}, {
|
||||
name: "LOG_LEVEL"
|
||||
value: "info"
|
||||
}, {
|
||||
name: "DEFAULT_USERNAME"
|
||||
valueFrom: configMapKeyRef: {
|
||||
key: "DEMO_LOGIN_USERNAME"
|
||||
name: "demo-data-config"
|
||||
}
|
||||
}, {
|
||||
name: "DEFAULT_PASSWORD"
|
||||
valueFrom: configMapKeyRef: {
|
||||
key: "DEMO_LOGIN_PASSWORD"
|
||||
name: "demo-data-config"
|
||||
}
|
||||
}, {
|
||||
name: "REGISTERED_OAUTH_CLIENT_ID"
|
||||
valueFrom: configMapKeyRef: {
|
||||
key: "DEMO_OAUTH_CLIENT_ID"
|
||||
name: "oauth-config"
|
||||
optional: true
|
||||
}
|
||||
}, {
|
||||
name: "ALLOWED_OAUTH_REDIRECT_URI"
|
||||
valueFrom: configMapKeyRef: {
|
||||
key: "DEMO_OAUTH_REDIRECT_URI"
|
||||
name: "oauth-config"
|
||||
optional: true
|
||||
}
|
||||
}]
|
||||
envFrom: [{
|
||||
configMapRef: name: "environment-config"
|
||||
}, {
|
||||
configMapRef: name: "service-api-config"
|
||||
}]
|
||||
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/frontend:v0.6.5@sha256:d72050f70d12383e4434ad04d189b681dc625f696087ddf0b5df641645c9dafa"
|
||||
livenessProbe: {
|
||||
httpGet: {
|
||||
path: "/ready"
|
||||
port: 8080
|
||||
}
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 15
|
||||
timeoutSeconds: 30
|
||||
}
|
||||
name: "front"
|
||||
readinessProbe: {
|
||||
httpGet: {
|
||||
path: "/ready"
|
||||
port: 8080
|
||||
}
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 10
|
||||
}
|
||||
resources: {
|
||||
limits: {
|
||||
cpu: "250m"
|
||||
memory: "128Mi"
|
||||
}
|
||||
requests: {
|
||||
cpu: "100m"
|
||||
memory: "64Mi"
|
||||
}
|
||||
}
|
||||
securityContext: {
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities: drop: ["all"]
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
}
|
||||
volumeMounts: [{
|
||||
mountPath: "/tmp"
|
||||
name: "tmp"
|
||||
}, {
|
||||
mountPath: "/tmp/.ssh"
|
||||
name: "publickey"
|
||||
readOnly: true
|
||||
}]
|
||||
}]
|
||||
volumes: [
|
||||
{
|
||||
emptyDir: {}
|
||||
name: "tmp"
|
||||
},
|
||||
{
|
||||
name: "publickey"
|
||||
secret: {
|
||||
items: [{key: "jwtRS256.key.pub", path: "publickey"}]
|
||||
secretName: "jwt-key"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow HTTPRoutes in the ingress gateway namespace to reference Services
|
||||
// in this namespace.
|
||||
ReferenceGrant: grant: #ReferenceGrant & {
|
||||
metadata: namespace: Namespace
|
||||
}
|
||||
|
||||
// Include shared resources
|
||||
#BankOfHolos.Resources
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Line 6 of the `schema.gen.cue` file defines the _default_ value for
|
||||
`#Organization.DisplayName` by using `string | *"..."`. In CUE, the `*`
|
||||
asterisk character denotes a [default value].
|
||||
|
||||
Line 78 of the `bank-frontend.cue` file refers to `#Organization.DisplayName` to
|
||||
configure the front end web container.
|
||||
|
||||
Let's change the name of the bank by defining a new value for
|
||||
`#Organization.DisplayName` at the root of the configuration. Create
|
||||
`projects/organization.cue` with the following content.
|
||||
|
||||
<Tabs groupId="B386181F-EBE7-469D-8CB5-37631067669B">
|
||||
<TabItem value="projects/organization.cue" label="projects/organization.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
#Organization: DisplayName: "The Holistic-Bank"
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Let's render the platform and see if this changes the name.
|
||||
|
||||
<Tabs groupId="A014333C-3271-4C22-87E6-2B7BF898EA3E">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
#Organization.DisplayName: 2 errors in empty disjunction:
|
||||
#Organization.DisplayName: conflicting values "Bank of Holos" and "The Holistic-Bank":
|
||||
/bank-of-holos/projects/organization.cue:3:29
|
||||
/bank-of-holos/schema.gen.cue:6:39
|
||||
// highlight-next-line
|
||||
#Organization.DisplayName: invalid value "The Holistic-Bank" (out of bound =~"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$"):
|
||||
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:203:25
|
||||
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:188:15
|
||||
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:203:15
|
||||
/bank-of-holos/projects/organization.cue:3:29
|
||||
/bank-of-holos/schema.gen.cue:6:29
|
||||
could not run: could not render component: exit status 1 at internal/render/platform.go:50
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::warning Whoops
|
||||
The development team defined a value that isn't allowed by the
|
||||
configuration.
|
||||
:::
|
||||
|
||||
Someone else in the organization placed a [constraint] on the
|
||||
configuration to ensure the display name contains only letters, numbers, and
|
||||
spaces. This constraint is expressed as a [regular expression].
|
||||
|
||||
:::tip
|
||||
CUE provides clear visibility where to start looking to resolve conflicts. Each
|
||||
file and line number listed is a place the `#Organization.DisplayName` field is
|
||||
defined.
|
||||
:::
|
||||
|
||||
Let's try again, this time replacing the hyphen with a space.
|
||||
|
||||
<Tabs groupId="F93B34FA-C0C6-4793-A32F-DAD094403208">
|
||||
<TabItem value="projects/organization.cue" label="projects/organization.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
#Organization: DisplayName: "The Holistic Bank"
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<Tabs groupId="5FD68778-476A-4F82-8817-71CEE205216E">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered bank-ledger-db for cluster workload in 139.863625ms
|
||||
rendered bank-accounts-db for cluster workload in 151.74875ms
|
||||
rendered bank-balance-reader for cluster workload in 154.356083ms
|
||||
rendered bank-ledger-writer for cluster workload in 161.209541ms
|
||||
rendered bank-userservice for cluster workload in 163.373417ms
|
||||
rendered bank-backend-config for cluster workload in 179.271208ms
|
||||
rendered bank-secrets for cluster workload in 204.35625ms
|
||||
rendered gateway for cluster workload in 118.707583ms
|
||||
rendered httproutes for cluster workload in 140.981541ms
|
||||
rendered bank-transaction-history for cluster workload in 156.066875ms
|
||||
rendered bank-frontend for cluster workload in 300.102292ms
|
||||
rendered bank-contacts for cluster workload in 159.89625ms
|
||||
rendered cni for cluster workload in 150.754458ms
|
||||
rendered istiod for cluster workload in 222.922625ms
|
||||
rendered app-projects for cluster workload in 118.422792ms
|
||||
rendered ztunnel for cluster workload in 142.840625ms
|
||||
rendered cert-manager for cluster workload in 190.938834ms
|
||||
rendered base for cluster workload in 340.679416ms
|
||||
rendered local-ca for cluster workload in 107.120334ms
|
||||
rendered external-secrets for cluster workload in 145.020834ms
|
||||
rendered argocd for cluster workload in 299.690917ms
|
||||
rendered namespaces for cluster workload in 115.862334ms
|
||||
rendered gateway-api for cluster workload in 225.783833ms
|
||||
rendered external-secrets-crds for cluster workload in 339.741166ms
|
||||
rendered crds for cluster workload in 421.849041ms
|
||||
rendered platform in 718.015959ms
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip Success
|
||||
Great, the platform rendered. We know the display name is valid according to
|
||||
the constraints.
|
||||
:::
|
||||
|
||||
Let's see if the new display name value updated the configuration for the bank
|
||||
frontend.
|
||||
|
||||
<Tabs groupId="6C068651-2061-4262-BE1E-7BB3E7EB66CB">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
On branch main
|
||||
Your branch and 'jeffmccune/main' have diverged,
|
||||
and have 2 and 4 different commits each, respectively.
|
||||
(use "git pull" to merge the remote branch into yours)
|
||||
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
// highlight-next-line
|
||||
modified: deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
|
||||
modified: deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
projects/organization.cue
|
||||
|
||||
no changes added to commit (use "git add" and/or "git commit -a")
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<Tabs groupId="4A20831E-461B-4EDE-8F6E-E73C3AEC12DB">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff
|
||||
diff --git a/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml b/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
|
||||
index 7914756..250c660 100644
|
||||
--- a/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
|
||||
+++ b/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
|
||||
@@ -9,7 +9,7 @@ spec:
|
||||
clusterResourceWhitelist:
|
||||
- group: '*'
|
||||
kind: '*'
|
||||
- description: Holos managed AppProject for Bank of Holos
|
||||
+ description: Holos managed AppProject for The Holistic Bank
|
||||
destinations:
|
||||
- namespace: '*'
|
||||
server: '*'
|
||||
@@ -26,7 +26,7 @@ spec:
|
||||
clusterResourceWhitelist:
|
||||
- group: '*'
|
||||
kind: '*'
|
||||
- description: Holos managed AppProject for Bank of Holos
|
||||
+ description: Holos managed AppProject for The Holistic Bank
|
||||
destinations:
|
||||
- namespace: '*'
|
||||
server: '*'
|
||||
@@ -43,7 +43,7 @@ spec:
|
||||
clusterResourceWhitelist:
|
||||
- group: '*'
|
||||
kind: '*'
|
||||
- description: Holos managed AppProject for Bank of Holos
|
||||
+ description: Holos managed AppProject for The Holistic Bank
|
||||
destinations:
|
||||
- namespace: '*'
|
||||
server: '*'
|
||||
@@ -60,7 +60,7 @@ spec:
|
||||
clusterResourceWhitelist:
|
||||
- group: '*'
|
||||
kind: '*'
|
||||
- description: Holos managed AppProject for Bank of Holos
|
||||
+ description: Holos managed AppProject for The Holistic Bank
|
||||
destinations:
|
||||
- namespace: '*'
|
||||
server: '*'
|
||||
diff --git a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
index dae6f93..d41516b 100644
|
||||
--- a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
+++ b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
@@ -71,7 +71,7 @@ spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: BANK_NAME
|
||||
- value: Bank of Holos
|
||||
+ value: The Holistic Bank
|
||||
- name: ENV_PLATFORM
|
||||
value: local
|
||||
- name: VERSION
|
||||
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::danger
|
||||
The new display name changed the frontend container, but it _also_ affected the
|
||||
app-projects component owned by the platform team.
|
||||
:::
|
||||
|
||||
Submitting a pull request would trigger a code review from the platform
|
||||
engineering team who manages the app-projects component. Let's see how to
|
||||
narrow the change down to limit the scope to the bank's user facing services.
|
||||
All of these services are managed under `projects/bank-of-holos/` Move the
|
||||
`organization.cue` file into this folder to limit the scope of configuration to
|
||||
the the components contained within.
|
||||
|
||||
```bash
|
||||
mv projects/organization.cue projects/bank-of-holos/
|
||||
```
|
||||
|
||||
Render the platform and let's see what changed.
|
||||
|
||||
<Tabs groupId="0FFEC244-B59B-4136-9C82-837985DC2AB8">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered bank-ledger-db for cluster workload in 163.814917ms
|
||||
rendered bank-accounts-db for cluster workload in 163.960208ms
|
||||
rendered bank-userservice for cluster workload in 164.1625ms
|
||||
rendered bank-ledger-writer for cluster workload in 169.185291ms
|
||||
rendered bank-balance-reader for cluster workload in 174.5455ms
|
||||
rendered bank-backend-config for cluster workload in 178.092125ms
|
||||
rendered bank-secrets for cluster workload in 202.305334ms
|
||||
rendered gateway for cluster workload in 122.81725ms
|
||||
rendered httproutes for cluster workload in 134.121084ms
|
||||
rendered bank-contacts for cluster workload in 146.4185ms
|
||||
rendered bank-frontend for cluster workload in 311.35425ms
|
||||
rendered bank-transaction-history for cluster workload in 160.103ms
|
||||
rendered cni for cluster workload in 145.762083ms
|
||||
rendered istiod for cluster workload in 216.0065ms
|
||||
rendered app-projects for cluster workload in 117.684333ms
|
||||
rendered ztunnel for cluster workload in 144.555292ms
|
||||
rendered cert-manager for cluster workload in 178.247917ms
|
||||
rendered base for cluster workload in 336.679ms
|
||||
rendered external-secrets for cluster workload in 142.21825ms
|
||||
rendered local-ca for cluster workload in 101.249ms
|
||||
rendered argocd for cluster workload in 280.54525ms
|
||||
rendered namespaces for cluster workload in 106.822042ms
|
||||
rendered gateway-api for cluster workload in 200.459791ms
|
||||
rendered external-secrets-crds for cluster workload in 470.125833ms
|
||||
rendered crds for cluster workload in 844.388666ms
|
||||
rendered platform in 1.154937084s
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<Tabs groupId="DE4FEEE5-FC53-48A6-BC6F-D0EA1DBFD00C">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff
|
||||
diff --git a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
index dae6f93..d41516b 100644
|
||||
--- a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
+++ b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
|
||||
@@ -71,7 +71,7 @@ spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: BANK_NAME
|
||||
- value: Bank of Holos
|
||||
+ value: The Holistic Bank
|
||||
- name: ENV_PLATFORM
|
||||
value: local
|
||||
- name: VERSION
|
||||
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip Success
|
||||
Great! This time, the only manifest affected is our `bank-frontend.gen.yaml`.
|
||||
:::
|
||||
|
||||
The `BANK_NAME` environment variable will change as we expect, and only the dev
|
||||
teams managing the bank services components are affected by the change.
|
||||
|
||||
Let's commit and push this change and see if it works.
|
||||
|
||||
<Tabs groupId="435D9C60-F841-4CF1-A947-506422E6BAC9">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m 'frontend: rename bank to The Holistic Bank'
|
||||
git push
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main fda74ec] frontend: rename bank to The Holistic Bank
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
create mode 100644 projects/bank-of-holos/organization.cue
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Now that we've pushed the change, let's apply the change to the platform.
|
||||
|
||||
## Apply the Change
|
||||
|
||||
Once we've pushed the change, navigate to the [bank-frontend GitOps
|
||||
Application](https://argocd.holos.localhost/applications/argocd/bank-frontend?view=tree&resource=).
|
||||
We can see the Deployment needs to sync to the desired state we just pushed.
|
||||
|
||||

|
||||
|
||||
Clicking on the frontend Deployment, we see the diff with the change we expect.
|
||||
|
||||

|
||||
|
||||
Sync the change, ArgoCD applies the desired configuration state to the cluster
|
||||
and Kubernetes handles rolling out the updated Deployment resource.
|
||||
|
||||

|
||||
|
||||
Soon, the deployment finishes and the component is in sync again.
|
||||
|
||||

|
||||
|
||||
Finally, let's see if the name actually changed on the website. Navigate to
|
||||
https://bank.holos.localhost/.
|
||||
|
||||

|
||||
|
||||
:::tip Success
|
||||
We successfully made our change and successfully applied the changed
|
||||
configuration to the platform.
|
||||
:::
|
||||
|
||||
Thanks for taking the time to work through this guide which covered:
|
||||
|
||||
- How multiple teams could be impacted by defining configuration at the
|
||||
`projects/` path.
|
||||
- How to scope our change to only affect components within the
|
||||
`projects/bank-of-holos/` path, eliminating the impact on other teams.
|
||||
- How CUE can [constrain] values in Holos, increasing safety.
|
||||
- How to handle a [default value] in CUE.
|
||||
- How CUE surfaces the file and line number of _every_ place to look for where a
|
||||
value is defined, making it faster and easier to troubleshoot problems.
|
||||
|
||||
|
||||
[Quickstart]: /docs/quickstart/
|
||||
[Deploy a Service]: /docs/guides/deploy-a-service/
|
||||
[Change a Service]: /docs/guides/change-a-service/
|
||||
[Helm]: /docs/api/author/v1alpha3/#Helm
|
||||
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
|
||||
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize
|
||||
[ComponentFields]: /docs/api/author/v1alpha3/#ComponentFields
|
||||
[platform-files]: /docs/quickstart/#how-platform-rendering-works
|
||||
[AppProject]: https://argo-cd.readthedocs.io/en/stable/user-guide/projects/
|
||||
[unification operator]: https://cuelang.org/docs/reference/spec/#unification
|
||||
[code-owners]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
||||
[Kustomization API]: https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v5.2/api/types/kustomization.go#L34
|
||||
[cue import]: https://cuelang.org/docs/reference/command/cue-help-import/
|
||||
[cue get go]: https://cuelang.org/docs/concept/how-cue-works-with-go/
|
||||
[timoni-crds]: https://timoni.sh/cue/module/custom-resources/
|
||||
[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute/?h=filter
|
||||
[Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
[hidden field]: https://cuelang.org/docs/tour/references/hidden/
|
||||
[comprehension]: https://cuelang.org/docs/reference/spec/#comprehensions
|
||||
[code owners]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
||||
[ReferenceGrant]: https://gateway-api.sigs.k8s.io/api-types/referencegrant/
|
||||
[Local Cluster Guide]: /docs/guides/local-cluster
|
||||
[Bank of Holos]: https://github.com/holos-run/bank-of-holos
|
||||
[default value]: https://cuelang.org/docs/tour/types/defaults/
|
||||
[constrain]: https://cuelang.org/docs/tour/basics/constraints/
|
||||
[constraint]: https://cuelang.org/docs/tour/basics/constraints/
|
||||
[regular expression]: https://cuelang.org/docs/tour/expressions/regexp/
|
||||
1450
doc/md/guides/deploy-a-service.mdx
Normal file
15
doc/md/guides/helm-component.mdx
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
description: Helm Component
|
||||
slug: /guides/helm-component
|
||||
sidebar_position: 400
|
||||
---
|
||||
|
||||
# Helm Component
|
||||
|
||||
The [Deploy a Service](/docs/guides/deploy-a-service/) guide is the best guide
|
||||
we have on wrapping a Helm chart in a Holos Component. The [Helm] section of
|
||||
the Author API may also be useful.
|
||||
|
||||
[Helm]: /docs/api/author/v1alpha3/#Helm
|
||||
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
|
||||
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize
|
||||
BIN
doc/md/guides/img/bank-home.png
Normal file
|
After Width: | Height: | Size: 690 KiB |
BIN
doc/md/guides/img/change-a-service-diff.png
Normal file
|
After Width: | Height: | Size: 997 KiB |
BIN
doc/md/guides/img/change-a-service-in-sync.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
doc/md/guides/img/change-a-service-login-page.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
BIN
doc/md/guides/img/change-a-service-out-of-sync.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
doc/md/guides/img/change-a-service-progressing.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
doc/md/guides/img/deploy-a-service-podinfo-deployed.png
Normal file
|
After Width: | Height: | Size: 1009 KiB |
BIN
doc/md/guides/img/deploy-a-service-podinfo-greetings.png
Normal file
|
After Width: | Height: | Size: 617 KiB |
BIN
doc/md/guides/img/deploy-a-service-podinfo-missing.png
Normal file
|
After Width: | Height: | Size: 706 KiB |
BIN
doc/md/guides/img/deploy-a-service-podinfo-sync.png
Normal file
|
After Width: | Height: | Size: 794 KiB |
20
doc/md/guides/kubernetes-component.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
description: Kubernetes Component
|
||||
slug: /guides/kubernetes-component
|
||||
sidebar_position: 500
|
||||
---
|
||||
|
||||
# Kubernetes Component
|
||||
|
||||
:::warning
|
||||
TODO
|
||||
:::
|
||||
|
||||
This is a placeholder for a guide for managing Kubernetes resources directly
|
||||
from a Holos Component with strong type checking.
|
||||
|
||||
In the meantime, please refer to the [Kubernetes] section of the Author API.
|
||||
|
||||
[Helm]: /docs/api/author/v1alpha3/#Helm
|
||||
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
|
||||
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize
|
||||
20
doc/md/guides/kustomize-component.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
description: Wrap a Kustomize Kustomization in a Holos Component.
|
||||
slug: /guides/kustomize-component
|
||||
sidebar_position: 600
|
||||
---
|
||||
|
||||
# Kustomize Component
|
||||
|
||||
:::warning
|
||||
TODO
|
||||
:::
|
||||
|
||||
This is a placeholder for a guide on wrapping a Kustomize Kustomization base
|
||||
with a Holos component.
|
||||
|
||||
In the meantime, please refer to the [Kustomize] section of the Author API.
|
||||
|
||||
[Helm]: /docs/api/author/v1alpha3/#Helm
|
||||
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
|
||||
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize
|
||||
277
doc/md/guides/local-cluster.mdx
Normal file
@@ -0,0 +1,277 @@
|
||||
---
|
||||
description: Build a local Cluster to use with these guides.
|
||||
slug: /guides/local-cluster
|
||||
sidebar_position: 999
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
The [Concepts](/docs/concepts) page defines capitalized terms such as Platform
|
||||
and Component.
|
||||
|
||||
## 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, apply and explore the manifests Holos renders
|
||||
in the [Quickstart](/docs/quickstart) guide.
|
||||
808
doc/md/guides/quickstart.mdx
Normal file
@@ -0,0 +1,808 @@
|
||||
---
|
||||
description: Try Holos with this quick start guide.
|
||||
slug: /quickstart
|
||||
sidebar_position: 100
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
|
||||
# Quickstart
|
||||
|
||||
Welcome to the Holos Quickstart guide. Holos is an open source tool to manage
|
||||
software development platforms safely, easily, and consistently. We'll use
|
||||
Holos to manage a fictional bank's platform, the Bank of Holos. In doing so
|
||||
we'll take the time to explain the foundational concepts of Holos.
|
||||
|
||||
1. **Platform** - Holos breaks a Platform down into Components owned by teams.
|
||||
2. **Component** - Components are CUE wrappers around unmodified upstream
|
||||
vendor Helm Charts, Kustomize Bases, or plain Kubernetes manifests.
|
||||
3. **CUE** - We write CUE to configure the platform. We'll cover the basics of
|
||||
CUE syntax and why Holos uses CUE.
|
||||
4. **Tree Unification** - CUE files are organized into a unified filesystem
|
||||
tree. We'll cover how unification makes it easier and safer for multiple teams
|
||||
to change the platform.
|
||||
|
||||
The Bank of Holos provides a good example of how Holos is designed to make it
|
||||
easier for multiple teams to deliver services on a platform. These teams are:
|
||||
|
||||
- **Platform**
|
||||
- **Software development**
|
||||
- **Security**
|
||||
- **Quality Assurance**
|
||||
|
||||
In this guide we'll show how Holos enables teams to work autonomously
|
||||
while still allowing the platform team to enforce the standards and policies
|
||||
they care about to provide a secure and consistent software development platform.
|
||||
|
||||
Here's a screenshot of the retail banking application we'll build and deploy on
|
||||
our platform. We'll keep each of these teams in mind as we work through the
|
||||
guides. Each of our guides focuses on different aspects of delivering the Bank
|
||||
of Holos.
|
||||
|
||||

|
||||
|
||||
## What you'll need {#requirements}
|
||||
|
||||
This guide is intended to be informative without needing to run the commands.
|
||||
If you'd like to render the platform and apply the manifests to a real Cluster,
|
||||
complete the [Local Cluster Guide](/docs/guides/local-cluster) before this
|
||||
guide.
|
||||
|
||||
You'll need the following tools installed to run the commands in this guide.
|
||||
|
||||
1. [holos](/docs/install) - to build the Platform.
|
||||
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos Components that
|
||||
wrap Helm charts.
|
||||
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Holos
|
||||
Components that render with Kustomize.
|
||||
|
||||
## Install Holos
|
||||
|
||||
Start by installing the `holos` command line tool with the following command.
|
||||
If you don't have Go, refer to [Installation](/docs/install/) to download the
|
||||
executable.
|
||||
|
||||
<Tabs groupId="go-install">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
go install github.com/holos-run/holos/cmd/holos@latest
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
go: downloading github.com/holos-run/holos v0.95.1
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
Nearly all day-to-day platform management tasks use the `holos` command line
|
||||
tool to render plain Kubernetes manifests.
|
||||
:::
|
||||
|
||||
## Fork the Git Repository
|
||||
|
||||
Building a software development platform from scratch takes time so we've
|
||||
published an example for our guides. [Fork the Bank of
|
||||
Holos](https://github.com/holos-run/bank-of-holos/fork) to get started.
|
||||
|
||||
Clone the repository to your local machine.
|
||||
|
||||
<Tabs groupId="git-clone">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
# Change YourName
|
||||
git clone https://github.com/YourName/bank-of-holos
|
||||
cd bank-of-holos
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
Cloning into 'bank-of-holos'...
|
||||
remote: Enumerating objects: 1177, done.
|
||||
remote: Counting objects: 100% (1177/1177), done.
|
||||
remote: Compressing objects: 100% (558/558), done.
|
||||
remote: Total 1177 (delta 394), reused 1084 (delta 303), pack-reused 0 (from 0)
|
||||
Receiving objects: 100% (1177/1177), 2.89 MiB | 6.07 MiB/s, done.
|
||||
Resolving deltas: 100% (394/394), done.
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Run the rest of the commands in this guide from the root of the repository.
|
||||
|
||||
## Configuring GitOps {#configuring-gitops}
|
||||
|
||||
The Bank of Holos platform is organized as a collection of software components.
|
||||
Each component represents a piece of software provided by an upstream vendor,
|
||||
for example ArgoCD, or software developed in-house. Components are also used to
|
||||
glue together, or integrate, other components into the platform.
|
||||
|
||||
The platform team provides ArgoCD as a means for teams to implement GitOps
|
||||
within their software development workflow. Each team using the Bank of Holos
|
||||
platform uses a Holos resource provided by the platform team to create their
|
||||
ArgoCD Application definition. In doing so, the platform team has provided
|
||||
a "golden path" for each team to independently make the changes they need
|
||||
while still centrally enforcing the policies that provide a consistent and
|
||||
safe experience.
|
||||
|
||||
Currently each team is using the upstream `bank-of-repo` repository as their
|
||||
source of truth. We'll start by changing ArgoCD to point to our fork. This will
|
||||
allow us to be able to see the results of our changes in ArgoCD using a GitOps
|
||||
workflow.
|
||||
|
||||
<Tabs groupId="argocd-config">
|
||||
<TabItem value="command" label="projects/argocd-config.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
#ArgoConfig: {
|
||||
Enabled: true
|
||||
// highlight-next-line
|
||||
RepoURL: "https://github.com/holos-run/bank-of-holos"
|
||||
}
|
||||
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Change the RepoURL to the URL of your fork. For example:
|
||||
|
||||
<Tabs groupId="F3BF73E3-3A70-40AF-9D4D-7134AF0A1763">
|
||||
<TabItem value="command" label="projects/argocd-config.cue">
|
||||
```diff showLineNumbers
|
||||
diff --git a/projects/argocd-config.cue b/projects/argocd-config.cue
|
||||
index 5264f48..0214e99 100644
|
||||
--- a/projects/argocd-config.cue
|
||||
+++ b/projects/argocd-config.cue
|
||||
@@ -2,5 +2,5 @@ package holos
|
||||
|
||||
#ArgoConfig: {
|
||||
Enabled: true
|
||||
- RepoURL: "https://github.com/holos-run/bank-of-holos"
|
||||
+ RepoURL: "https://github.com/jeffmccune/bank-of-holos"
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We need to render the platform manifests after we make changes.
|
||||
|
||||
## Render the Platform
|
||||
|
||||
Platform rendering is is the process of looping over all the components in the
|
||||
platform and rendering each one into plain kubernetes manifest files. Holos is
|
||||
designed to write plain manifest files which can be applied to Kubernetes, but
|
||||
stops short of applying them so it's easier for team members to review and
|
||||
understand changes before they're made.
|
||||
|
||||
<Tabs groupId="219C5B3D-1369-45F9-B010-64A87EF71190">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered app-projects for cluster workload in 206.109166ms
|
||||
rendered httproutes for cluster workload in 222.3885ms
|
||||
rendered istio-cni for cluster workload in 236.061167ms
|
||||
rendered istio-gateway for cluster workload in 238.973167ms
|
||||
rendered istio-ztunnel for cluster workload in 240.000042ms
|
||||
rendered istiod for cluster workload in 275.385709ms
|
||||
rendered bank-accounts-db for cluster workload in 215.252708ms
|
||||
rendered bank-backend-config for cluster workload in 245.383333ms
|
||||
rendered bank-secrets for cluster workload in 273.477458ms
|
||||
rendered bank-userservice for cluster workload in 234.866375ms
|
||||
rendered istio-base for cluster workload in 541.965042ms
|
||||
rendered argocd for cluster workload in 352.4625ms
|
||||
rendered bank-frontend for cluster workload in 374.208084ms
|
||||
rendered bank-ledger-db for cluster workload in 224.120125ms
|
||||
rendered bank-ledger-writer for cluster workload in 237.136042ms
|
||||
rendered bank-balance-reader for cluster workload in 233.804083ms
|
||||
rendered bank-transaction-history for cluster workload in 236.114542ms
|
||||
rendered bank-contacts for cluster workload in 222.469875ms
|
||||
rendered argocd-crds for cluster workload in 812.078042ms
|
||||
rendered gateway-api for cluster workload in 173.66425ms
|
||||
rendered external-secrets for cluster workload in 231.326958ms
|
||||
rendered local-ca for cluster workload in 183.12425ms
|
||||
rendered namespaces for cluster workload in 173.256125ms
|
||||
rendered cert-manager for cluster workload in 432.088959ms
|
||||
rendered external-secrets-crds for cluster workload in 496.282459ms
|
||||
rendered platform in 1.106735958s
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Rendering the platform to plain manifest files allows us to see the changes
|
||||
clearly. We can see this one line change affected dozens ArgoCD Application
|
||||
resources across the platform.
|
||||
|
||||
<Tabs groupId="266D26D4-31FC-45D1-88EF-EAD23BBBDCDD">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
On branch main
|
||||
Your branch is up to date with 'origin/main'.
|
||||
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git restore <file>..." to discard changes in working directory)
|
||||
modified: deploy/clusters/workload/gitops/app-projects.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/argocd-crds.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/argocd.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-accounts-db.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-backend-config.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-balance-reader.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-contacts.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-frontend.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-ledger-db.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-ledger-writer.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-secrets.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-transaction-history.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/bank-userservice.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/cert-manager.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/external-secrets-crds.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/external-secrets.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/gateway-api.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/httproutes.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/istio-base.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/istio-cni.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/istio-gateway.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/istio-ztunnel.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/istiod.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/local-ca.gen.yaml
|
||||
modified: deploy/clusters/workload/gitops/namespaces.gen.yaml
|
||||
modified: projects/argocd-config.cue
|
||||
|
||||
no changes added to commit (use "git add" and/or "git commit -a")
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Take a look at the Application resource for the bank-frontend component to see
|
||||
the changed `spec.source.repoURL` field.
|
||||
|
||||
<Tabs groupId="665E5402-FB42-4975-B654-3922EE73EE07">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff deploy/clusters/workload/gitops/bank-frontend.gen.yaml
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff showLineNumbers
|
||||
diff --git a/deploy/clusters/workload/gitops/bank-frontend.gen.yaml b/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
|
||||
index 3a3dec0..22e21bb 100644
|
||||
--- a/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
|
||||
+++ b/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
|
||||
@@ -11,5 +11,5 @@ spec:
|
||||
project: default
|
||||
source:
|
||||
path: deploy/clusters/workload/components/bank-frontend
|
||||
- repoURL: https://github.com/holos-run/bank-of-holos
|
||||
+ repoURL: https://github.com/jeffmccune/bank-of-holos
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We'll add, commit, and push this change to our fork then take a little time to
|
||||
explain what happened when we made the change and rendered the platform.
|
||||
|
||||
<Tabs groupId="BD6A968F-FFDF-486B-8EC0-BA8B39C19303">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m 'quickstart: change argocd repo url to our fork'
|
||||
git push origin
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main f2f8bc2] quickstart: change argocd repo url to our fork
|
||||
26 files changed, 26 insertions(+), 26 deletions(-)
|
||||
Enumerating objects: 41, done.
|
||||
Counting objects: 100% (41/41), done.
|
||||
Delta compression using up to 14 threads
|
||||
Compressing objects: 100% (31/31), done.
|
||||
Writing objects: 100% (33/33), 2.95 KiB | 2.95 MiB/s, done.
|
||||
Total 33 (delta 28), reused 0 (delta 0), pack-reused 0
|
||||
remote: Resolving deltas: 100% (28/28), completed with 4 local objects.
|
||||
To github.com:jeffmccune/bank-of-holos.git
|
||||
c2951ec..f2f8bc2 main -> main
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Platform Rendering Explained
|
||||
|
||||
So what happens when we run `holos render platform`? We saw `holos` write plain
|
||||
manifest files, let's dive into how and why we implemented platform rendering
|
||||
like this.
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: Figure 1 - Render 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>]
|
||||
|
||||
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>]
|
||||
|
||||
P[<a href="/docs/api/core/v1alpha3#Kustomize">Kustomize</a>]
|
||||
Y[Kubernetes <br/>Resources]
|
||||
G[GitOps <br/>Resource]
|
||||
FS[Local Files]
|
||||
|
||||
C[Kube API Server]
|
||||
|
||||
PS --> HC --> BP
|
||||
BP --> H --> P
|
||||
BP --> K --> P
|
||||
BP --> O --> P
|
||||
|
||||
P --> Y --> FS
|
||||
P --> G --> FS
|
||||
|
||||
FS --> ArgoCD --> C
|
||||
FS --> Flux --> C
|
||||
FS --> kubectl --> C
|
||||
```
|
||||
|
||||
### Why do we render the platform? {#why-render-the-platform}
|
||||
|
||||
We built Holos to make the process of managing a platform safer, easier, and
|
||||
more consistent. Before Holos we used Helm, Kustomize, and scripts to glue
|
||||
together all of the software that goes into a platform. Then we coaxed the
|
||||
output of each tool into something that works with GitOps. This approach has a
|
||||
number of shortcomings. We wanted to see the manifests before ArgoCD or Flux
|
||||
applied them, so we wrote a lot of difficult to maintain scripts to get the
|
||||
template output into something useful. We tried avoiding the scripts by having
|
||||
ArgoCD handle the Helm charts directly, but we could no longer see the changes
|
||||
clearly during code review.
|
||||
|
||||
The platform rendering process allows us to have it both ways. We avoid the
|
||||
unsafe text templates and glue scripts by using CUE. We're able to review the
|
||||
exact changes that _will be_ applied during code review because holos renders
|
||||
the whole platform to plain manifest files.
|
||||
|
||||
Finally, because we usually make each change by rendering the whole platform,
|
||||
we're able to see and consider how a single-line change, like the one we just
|
||||
made, affects the whole platform. Before we made Holos we were frustrated with
|
||||
how difficult it was to get this zoomed-out, broad perspective of each change we
|
||||
made.
|
||||
|
||||
:::tip
|
||||
Holos implements the [rendered manifests pattern] so you don't have to build it
|
||||
yourself.
|
||||
:::
|
||||
|
||||
### How does platform rendering work? {#how-platform-rendering-works}
|
||||
|
||||
Holos is declarative. CUE provides resources that declare what `holos` needs to
|
||||
do. The output of `holos` is always the same for the same inputs, so `holos` is
|
||||
also idempotent.
|
||||
|
||||
When we run `holos render platform`, CUE builds the Platform specification
|
||||
(spec). This is a fancy way of saying a list of software to manage on each
|
||||
cluster in the platform. The CUE files in the `platform` directory provide the
|
||||
platform spec to `holos`.
|
||||
|
||||
Let's open up two of these CUE files to see how this works. Ignore the other
|
||||
files for now, they behave the same as these two.
|
||||
|
||||
<Tabs groupId="6F01F2F7-C101-4212-A844-0E370B836B54">
|
||||
<TabItem value="argocd" label="platform/argocd.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Manage the Component on every Cluster in the Platform
|
||||
for Fleet in #Fleets {
|
||||
for Cluster in Fleet.clusters {
|
||||
#Platform: Components: "\(Cluster.name):argocd-crds": {
|
||||
name: "argocd-crds"
|
||||
component: "projects/platform/components/argocd/crds"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
#Platform: Components: "\(Cluster.name):argocd": {
|
||||
name: "argocd"
|
||||
component: "projects/platform/components/argocd/argocd"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="external-secrets" label="platform/external-secrets.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Manage the component on every cluster in the platform
|
||||
for Fleet in #Fleets {
|
||||
for Cluster in Fleet.clusters {
|
||||
#Platform: Components: "\(Cluster.name):external-secrets-crds": {
|
||||
name: "external-secrets-crds"
|
||||
component: "projects/platform/components/external-secrets-crds"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
#Platform: Components: "\(Cluster.name):external-secrets": {
|
||||
name: "external-secrets"
|
||||
component: "projects/platform/components/external-secrets"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
There's quite a few new concepts to unpack in these two CUE files.
|
||||
|
||||
1. A Fleet is just a collection of clusters that share a similar, but not
|
||||
identical configuration. Most platforms have a management fleet with one
|
||||
cluster to manage the platform, and a workload fleet for clusters that host the
|
||||
services we deploy onto the platform.
|
||||
2. A Cluster is a Kubernetes cluster. Each component is rendered to plain
|
||||
manifests for a cluster.
|
||||
|
||||
:::important
|
||||
On lines 6 and 11 we see a Component being assigned to the Platform. We also
|
||||
start to dive into the syntax of CUE, which we need to understand a little
|
||||
before going further.
|
||||
:::
|
||||
|
||||
> In its simplest form, CUE looks a lot like JSON. This is because CUE is a
|
||||
superset of JSON. Or, put differently: all valid JSON is CUE.[^1]
|
||||
>
|
||||
> 1. C-style comments are allowed
|
||||
> 2. field names without special characters don't need to be quoted
|
||||
> 3. commas after a field are optional (and are usually omitted)
|
||||
> 4. commas after the final element of a list are allowed
|
||||
> 5. **the outermost curly braces in a CUE file are optional**
|
||||
>
|
||||
> JSON objects are called structs in CUE. JSON arrays are called lists, Object
|
||||
members are called fields, which link their name, or label, to a value.
|
||||
|
||||
There are two important things to know about CUE to understand these two files.
|
||||
First, the curly braces have been omitted which is item 5 on the list above.
|
||||
Second, CUE is about _unification_.
|
||||
|
||||
:::important
|
||||
Unlike most other languages, it is common to declare the same field in multiple
|
||||
places. CUE **unifies** the value of the field. We can think of CUE as a
|
||||
Configuration Unification Engine.
|
||||
:::
|
||||
|
||||
Now that we know curly braces can be omitted and values are unified, we can
|
||||
understand how the rest of the CUE files in the platform directory behave.
|
||||
|
||||
:::tip
|
||||
Each CUE file in the platform directory adds components to the
|
||||
`#Platform.Components` struct.
|
||||
:::
|
||||
|
||||
The final file in the directory is responsible for producing the Platform spec.
|
||||
It looks like this.
|
||||
|
||||
<Tabs groupId="166F0925-9405-4571-A0AB-C7E2107876FD">
|
||||
<TabItem value="command" label="platform/platform.gen.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
import api "github.com/holos-run/holos/api/author/v1alpha4"
|
||||
|
||||
#Platform: api.#Platform & {
|
||||
Name: "guide"
|
||||
}
|
||||
|
||||
// Render a Platform resource for holos to process
|
||||
#Platform.Resource
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This file provides the value of the `#Platform.Resource` field, the platform
|
||||
spec, to `holos`.
|
||||
|
||||
Let's take a look at that Output value:
|
||||
|
||||
<Tabs groupId="475C92AC-C6DA-4FB9-859C-722921277CFC">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
cue export --out yaml ./platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```yaml showLineNumbers
|
||||
kind: Platform
|
||||
apiVersion: v1alpha4
|
||||
metadata:
|
||||
name: guide
|
||||
spec:
|
||||
components: # This is a trimmed list for readability.
|
||||
- name: bank-secrets
|
||||
component: projects/bank-of-holos/security/components/bank-secrets
|
||||
cluster: workload
|
||||
model: {}
|
||||
- name: bank-frontend
|
||||
component: projects/bank-of-holos/frontend/components/bank-frontend
|
||||
cluster: workload
|
||||
model: {}
|
||||
- name: bank-backend-config
|
||||
component: projects/bank-of-holos/backend/components/bank-backend-config
|
||||
cluster: workload
|
||||
model: {}
|
||||
- name: bank-accounts-db
|
||||
component: projects/bank-of-holos/backend/components/bank-accounts-db
|
||||
cluster: workload
|
||||
model: {}
|
||||
- name: bank-userservice
|
||||
component: projects/bank-of-holos/backend/components/bank-userservice
|
||||
cluster: workload
|
||||
model: {}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
You don't normally need to execute `cue`, CUE is built into `holos`. We use it
|
||||
here to gain insight.
|
||||
:::
|
||||
|
||||
We see the platform spec is essentially a list of components, each assigned to a
|
||||
cluster.
|
||||
|
||||
:::important
|
||||
Notice CUE unifies `Components` from multiple files into one list.
|
||||
|
||||
We'll see this unification behavior again and again. Unification is the
|
||||
defining characteristic of CUE that makes it a unique, powerful, and _safe_
|
||||
configuration language.
|
||||
:::
|
||||
|
||||
Holos takes this list of components and builds each one by executing the following command.
|
||||
|
||||
```bash
|
||||
holos render component --cluster-name="example" "path/to/the/component"
|
||||
```
|
||||
|
||||
We can think of platform rendering as rendering a list of components, passing
|
||||
the cluster name each time. Rendering each component writes the fully rendered
|
||||
manifest for that component to the `deploy/` directory, organized by cluster for
|
||||
GitOps.
|
||||
|
||||
## Render a Component
|
||||
|
||||
Rendering a component works much the same way as rendering a platform. `holos`
|
||||
uses CUE to produce a specification, then processes it. The specification of a
|
||||
component is called a BuildPlan. A BuildPlan is a list of zero or more
|
||||
kubernetes resources, Helm charts, Kustomize bases, and additional files to
|
||||
write into the `deploy/` directory.
|
||||
|
||||
Now let's look at the cert-manager component. Notice the
|
||||
`platform/cert-manager.cue` file has the field `path:
|
||||
"projects/platform/components/cert-manager"`. This path indicates where to
|
||||
start working with the cert-manager component.
|
||||
|
||||
<Tabs groupId="129DD743-0FE3-44C0-ACA4-6569C98BA40E">
|
||||
<TabItem value="cert-manager" label="projects/platform/components/cert-manager/cert-manager.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).BuildPlan
|
||||
|
||||
let Chart = {
|
||||
Name: "cert-manager"
|
||||
Namespace: #CertManager.Namespace
|
||||
|
||||
Chart: {
|
||||
version: #CertManager.Version
|
||||
repository: {
|
||||
name: "jetstack"
|
||||
url: "https://charts.jetstack.io"
|
||||
}
|
||||
}
|
||||
|
||||
Values: {
|
||||
installCRDs: true
|
||||
startupapicheck: enabled: false
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="root" label="projects/cert-manager.cue">
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Platform wide configuration
|
||||
#CertManager: {
|
||||
Version: "1.15.3"
|
||||
Namespace: "cert-manager"
|
||||
}
|
||||
|
||||
// Register the namespace
|
||||
#Namespaces: (#CertManager.Namespace): _
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This file introduces a few new concepts.
|
||||
|
||||
1. Line 4 indicates this component produces a BuildPlan that wraps a Helm Chart.
|
||||
2. On line 6 `let` binds a name to an expression for the current scope. The
|
||||
current file in this case.
|
||||
3. Notice Chart is referenced on line 4 before it's bound on line 6. **Order is
|
||||
irrelevant in CUE**. Complex changes are simpler and easier when we don't have
|
||||
to think about order.
|
||||
4. The chart version and namespace are defined in a different file closer to the
|
||||
root, `projects/cert-manager.cue`
|
||||
5. We define Helm values in CUE to take advantage of strong type checking and
|
||||
manage multiple Helm charts consistently with platform wide values.
|
||||
|
||||
Let's take a look at the BuildPlan that results from the CUE configuration
|
||||
described above.
|
||||
|
||||
<Tabs groupId="B54D5791-4E5B-4148-A368-62D9BE80760C">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
cue export --out yaml ./projects/platform/components/cert-manager
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```yaml showLineNumbers
|
||||
kind: BuildPlan
|
||||
apiVersion: v1alpha4
|
||||
metadata:
|
||||
name: cert-manager
|
||||
spec:
|
||||
component: no-component
|
||||
artifacts:
|
||||
- artifact: clusters/no-cluster/components/cert-manager/cert-manager.gen.yaml
|
||||
generators:
|
||||
- kind: Helm
|
||||
output: helm.gen.yaml
|
||||
helm:
|
||||
chart:
|
||||
name: cert-manager
|
||||
version: 1.15.3
|
||||
release: cert-manager
|
||||
repository:
|
||||
name: jetstack
|
||||
url: https://charts.jetstack.io
|
||||
values:
|
||||
installCRDs: true
|
||||
startupapicheck:
|
||||
enabled: false
|
||||
enableHooks: false
|
||||
namespace: cert-manager
|
||||
- kind: Resources
|
||||
output: resources.gen.yaml
|
||||
resources: {}
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- helm.gen.yaml
|
||||
- resources.gen.yaml
|
||||
output: combined.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
resources:
|
||||
- helm.gen.yaml
|
||||
- resources.gen.yaml
|
||||
kind: Kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- combined.gen.yaml
|
||||
output: clusters/no-cluster/components/cert-manager/cert-manager.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
namespace: cert-manager
|
||||
commonLabels:
|
||||
holos.run/component.name: cert-manager
|
||||
resources:
|
||||
- combined.gen.yaml
|
||||
- artifact: clusters/no-cluster/gitops/cert-manager.gen.yaml
|
||||
generators:
|
||||
- kind: Resources
|
||||
output: application.gen.yaml
|
||||
resources:
|
||||
Application:
|
||||
cert-manager:
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: cert-manager
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
path: deploy/clusters/no-cluster/components/cert-manager
|
||||
repoURL: https://github.com/jeffmccune/bank-of-holos
|
||||
targetRevision: main
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- application.gen.yaml
|
||||
output: clusters/no-cluster/gitops/cert-manager.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
commonLabels:
|
||||
holos.run/component.name: cert-manager
|
||||
resources:
|
||||
- application.gen.yaml
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::important
|
||||
Again, you don't normally need to execute `cue`, it's built into `holos`. We
|
||||
use it here to show how Holos works with Helm.
|
||||
:::
|
||||
|
||||
Looking at the BuildPlan, we see `holos` will render the Helm chart into the
|
||||
deploy directory along with an ArgoCD Application resource in the `gitops/`
|
||||
directory.
|
||||
|
||||
:::tip
|
||||
The BuildPlan API is flexible enough to write any file into the `deploy/`
|
||||
directory. Holos uses this flexibility to support both Flux and ArgoCD.
|
||||
:::
|
||||
|
||||
When we run `cue export`, we get back a [Core API] BuildPlan. The BuildPlan is
|
||||
produced by the `#Helm` definition on line 4 which is part of the [Author API].
|
||||
The Core API is the contract between CUE and `holos`. As such, it's not as
|
||||
friendly as the Author API. The Author API is the contract component authors
|
||||
and platform engineers use to configure and manage the platform. The Author API
|
||||
is meant for people, the Core API is meant for machines. This explains why we
|
||||
see quite a few fields in the exported BuildPlan we didn't cover in this guide.
|
||||
Day to day we don't need to be concerned with those fields because the Author
|
||||
API handles them for us.
|
||||
|
||||
:::tip
|
||||
Our intent is to provide an ergonomic way to manage the platform with the Author
|
||||
API.
|
||||
:::
|
||||
|
||||
When the Author API doesn't offer a path forward, authors may use the Core API
|
||||
directly from CUE. We can think of the Core API as an escape hatch for the
|
||||
Author API. We'll see some examples of this in action in the more advanced
|
||||
guides.
|
||||
|
||||
## Review
|
||||
|
||||
Let's review the concepts we've covered in this guide:
|
||||
|
||||
- A Holos platform is comprised of the CUE files that define the platform specification within the `platform` directory.
|
||||
- The files in the `platform` directory each model an individual Holos component, and provide the path to the directory where the component's CUE configuration resides.
|
||||
- A Holos platform must be rendered to generate Kubernetes manifest files.
|
||||
- Holos resources enable teams to work autonomously while still allowing for centralized enforcement of company policies.
|
||||
- Changes to one component can impact other components, and we can use `holos render platform` with `git diff` to assess the impact.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Thank you for finishing the Quickstart guide. Dive deeper with the next guide
|
||||
on how to [Deploy a Service] which explains how to take one of your existing
|
||||
Helm charts or Deployments and manage it with Holos.
|
||||
|
||||
[application]: https://argo-cd.readthedocs.io/en/stable/user-guide/application-specification/
|
||||
[core]: /docs/api/core/v1alpha4/
|
||||
[Core API]: /docs/api/core/
|
||||
[Author API]: /docs/api/author/
|
||||
[Deploy a Service]: /docs/guides/deploy-a-service/
|
||||
[Manage a Project]: /docs/guides/manage-a-project/
|
||||
[rendered manifests pattern]: https://akuity.io/blog/the-rendered-manifests-pattern/
|
||||
[^1]: [The Basics of CUE](https://cuelang.org/docs/tour/basics/json-superset/)
|
||||
@@ -1,64 +0,0 @@
|
||||
# Introduction
|
||||
|
||||
⚡️ Holos will help you build your **software development platform in no time.**
|
||||
|
||||
💸 Building a software development platform is **time consuming and expensive**. Spend more time building features for your customers and less time managing your development platform.
|
||||
|
||||
💥 Already have a platform? Add new features and services to your platform easily with Holos.
|
||||
|
||||
🧐 Holos is a platform builder. It builds a hollistic software development platform composed of best-of-breed cloud native open source projects. Holos is also a tool to make it easier to manage cloud infrastructure by providing a typed alternative to yaml templates.
|
||||
|
||||
## Features
|
||||
|
||||
Holos was built to solve two main problems:
|
||||
|
||||
1. Building a platform usually takes 3 engineers 6-9 months of effort. Holos provides a reference platform that enables you to deploy and customize your platform in a fraction of the time.
|
||||
2. Configuration changes often cause outages. Existing tools like Helm make it difficult to understand the impact a configuration change will have. Holos provides a unique, unified configuration model powered by CUE that makes it safer and easier to roll out configuration changes.
|
||||
|
||||
A core principle of Holos is that organizations gain value from owning the the platform they build on. Avoid vendor lock-in, future price hikes, and expensive licensing changes by building on a solid foundation of open source, cloud native computing foundation backed projects.
|
||||
|
||||
The following features are built into the Holos reference platform.
|
||||
|
||||
:::tip
|
||||
|
||||
Don't see your preferred technology in the stack? Holos is designed to enable you to swap out components of the platform tech stack.
|
||||
|
||||
:::
|
||||
|
||||
- **Continuous Delivery**
|
||||
- Holos builds a GitOps workflow for each application running in the platform.
|
||||
- Developers push changes which are automatically deployed.
|
||||
- Powered by [ArgoCD](https://argo-cd.readthedocs.io/en/stable/)
|
||||
- **Identity and Access Management** (IAM)
|
||||
- Holos builds a standard OIDC identity provider for you.
|
||||
- Integrates with your exisitng IAM and SSO system, or works independently.
|
||||
- Powerful customer identity and access management features.
|
||||
- Role based access control.
|
||||
- Powered by [ZITADEL](https://zitadel.com/)
|
||||
- **Zero Trust**
|
||||
- Authenticate and Authorize users at the platform layer instead of or in addition to the application layer.
|
||||
- Integrated with observability to measure and alert about problems before customers complain.
|
||||
- Powered by [Istio](https://istio.io/)
|
||||
- **Observability**
|
||||
- Holos collects performance and availability metrics automatically, without requiring application changes.
|
||||
- Optional, deeper integration into the application layer.
|
||||
- Distributed Tracing
|
||||
- Logging
|
||||
- Powered by Prometheus, Grafana, Loki, and OpenTelemetry.
|
||||
- **Data Platform**
|
||||
- Integrated management of PostgreSQL
|
||||
- Automatic backups
|
||||
- Automatic restore from backup
|
||||
- Quickly fail over across multiple regions
|
||||
- **Multi-Region**
|
||||
- Holos is designed to operate in multiple regions and multiple clouds.
|
||||
- Keep customer data in the region that makes the most sense for your business.
|
||||
- Easily cut over from one region to another for redundancy and business continuity.
|
||||
|
||||
## Development Status
|
||||
|
||||
Holos is being actively developed by [Open Infrastructure Services](https://openinfrastructure.co). Release can be found [here](https://github.com/holos-run/holos/releases).
|
||||
|
||||
## Adoption
|
||||
|
||||
Organizations who have officially adopted Holos can be found [here](https://github.com/holos-run/holos/blob/main/ADOPTERS.md).
|
||||
53
doc/md/introduction.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
description: Holos Documentation
|
||||
slug: /
|
||||
---
|
||||
|
||||
# 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,81 +1,3 @@
|
||||
# Architecture
|
||||
|
||||
This page describes the architecture of the Holos reference platform.
|
||||
|
||||
## Overview
|
||||
|
||||
The reference platform manages three kubernetes clusters by default. One management cluster and two workload clusters.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Management"
|
||||
secrets(Secrets)
|
||||
c1(Controllers)
|
||||
end
|
||||
|
||||
subgraph "Primary"
|
||||
s1p(Service 1)
|
||||
s2p(Service 2)
|
||||
end
|
||||
|
||||
subgraph "Standby"
|
||||
s1s(Service 1)
|
||||
s2s(Service 2)
|
||||
end
|
||||
|
||||
classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
|
||||
classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
|
||||
classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
|
||||
class c1,s1p,s2p,s1s,s2s,secrets k8s;
|
||||
class Management,Primary,Standby cluster;
|
||||
|
||||
```
|
||||
|
||||
|
||||
The services in each cluster type are:
|
||||
|
||||
:::tip
|
||||
The management cluster is designed to operate reliably on spot instances. A highly available management cluster typically costs less than a cup of coffee per month to operate.
|
||||
:::
|
||||
|
||||
1. Management Cluster
|
||||
- **SecretStore** to provide namespace scoped secrets to workload clusters.
|
||||
- **CertManager** to provision TLS certificates and make them available to workload clusters.
|
||||
- **ClusterAPI** to provision and manage workload clusters via GitOps. For example, EKS or GKE clusters.
|
||||
- **Crossplane** to provision and manage cloud resources via GitOps. For example, buckets, managed databases, any other cloud resource.
|
||||
- **CronJobs** to refresh short lived credentials. For example image pull credentials.
|
||||
- **ArgoCD** to manage resources within the management cluster via GitOps.
|
||||
2. Primary Workload Cluster
|
||||
- **ArgoCD** to continuously deploy your applications and services via GitOps.
|
||||
- **External Secrets Operator** to synchronize namespace scoped secrets.
|
||||
- **Istio** to provide a Gateway to expose services.
|
||||
- **ZITADEL** to provide SSO login for all other services (e.g. ArgoCD, Grafana, Backstage, etc...)
|
||||
- **PostgreSQL** for in-cluster databases.
|
||||
- **Backstage** to provide your developer portal into the whole platform.
|
||||
- **Observability** implemented by Prometheus, Grafana, and Loki to provide monitoring and logging.
|
||||
- **AuthorizationPolicy** to provide role based access control to all services in the cluster.
|
||||
3. Standby Workload Cluster
|
||||
- Identical configuration to the primary cluster.
|
||||
- May be scaled down to zero to reduce expenses.
|
||||
- Intended to take the primary cluster role quickly, within minutes, for disaster recovery or regular maintenance purposes.
|
||||
|
||||
## Security
|
||||
|
||||
### Namespaces
|
||||
|
||||
Namespaces are security boundaries in the reference platform. A given namespace is treated as the same security context across multiple clusters following the [SIG Multi-cluster Position](https://github.com/kubernetes/community/blob/dd4c8b704ef1c9c3bfd928c6fa9234276d61ad18/sig-multicluster/namespace-sameness-position-statement.md).
|
||||
|
||||
The namespace sameness principle makes role based access control straightforward to manage and comprehend. For example, granting a developer the ability to create secrets in namespace `example` means the developer has the ability to do so in the secret store in the management cluster and also synchronize the secret to the services they own in the workload clusters.
|
||||
|
||||
## Data Platform
|
||||
|
||||
Holos is designed to work with two distinct types of databases by default:
|
||||
|
||||
1. In-cluster PostgresSQL databases for lower cost and rapid development and testing.
|
||||
2. Out-of-cluster SQL databases for production services, e.g. RDS, CloudSQL, Aurora, Redshift, etc...
|
||||
|
||||
:::tip
|
||||
To simplify maintenance the holos reference platform provisions databases from the most recent backup by default.
|
||||
:::
|
||||
|
||||
In-cluster databases in the holos reference platform automatically save backups to an S3 or GCS bucket. For regular maintenance and disaster recovery, the standby cluster automatically restores databases from the most recent backup in the bucket. This capability makes maintenance much simpler, most maintenance tasks are carried out on the standby cluster which is then promoted to the primary. Software upgrades in particular are intended to be carried out against the standby, verified, then promoted to primary. Once live traffic shifts to the upgraded services in the new primary the previous cluster can be spun down to save cost or upgraded safely in place.
|
||||
Coming soon.
|
||||
|
||||
31
doc/md/runbooks/deploy.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Deployment
|
||||
|
||||
This document describes how deployment from `main` is configured.
|
||||
|
||||
1. Refer to the publish workflow.
|
||||
2. Uses a SSH deploy key to:
|
||||
3. Clone the holos-infra repo.
|
||||
4. Write the image tag to saas/userdata/components/dev-holos-app/images.json
|
||||
5. Run holos render platform ./platform
|
||||
6. Commit and push the results.
|
||||
7. ArgoCD takes over the rollout.
|
||||
|
||||
## Credentials
|
||||
|
||||
TODO: Lock this down more, the deploy key has too much access to the infra
|
||||
repository.
|
||||
|
||||
```bash
|
||||
mkdir -p tmp
|
||||
cd tmp
|
||||
ssh-keygen -t ed25519 -f holos-infra.key -m pem -C holos-run/holos -N ''
|
||||
gh secret set DEPLOY_SSH_PRIVATE_KEY < holos-infra.key
|
||||
gh api --method POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
/repos/holos-run/holos-infra/keys \
|
||||
-f title='holos-run/holos deploy key' \
|
||||
-f key="$(cat holos-infra.key.pub)" \
|
||||
-F read_only=false
|
||||
cd ..
|
||||
rm -rf tmp
|
||||
```
|
||||
3
doc/md/runbooks/login/failover.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Overview
|
||||
|
||||
TODO: This runbook needs to be updated to reflect the switch from PGO to CNPG.
|
||||
13
doc/md/start.md
Normal file
@@ -0,0 +1,13 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Get Started
|
||||
|
||||
## Start with the [Quickstart] guide
|
||||
|
||||
---
|
||||
|
||||
These documents provide additional context to supplement the [Quickstart] guide.
|
||||
|
||||
<DocCardList />
|
||||
|
||||
[Quickstart]: /docs/quickstart/
|
||||
15
doc/md/start/comparison.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
description: Compare Holos with other tools in the ecosystem.
|
||||
slug: /comparison
|
||||
sidebar_position: 300
|
||||
---
|
||||
|
||||
# Comparison
|
||||
|
||||
## Helm
|
||||
|
||||
## Kustomize
|
||||
|
||||
## ArgoCD
|
||||
|
||||
## Flux
|
||||
370
doc/md/start/concepts.md
Normal file
@@ -0,0 +1,370 @@
|
||||
---
|
||||
description: Learn the concepts and domain language Holos uses.
|
||||
slug: /concepts
|
||||
sidebar_position: 200
|
||||
---
|
||||
|
||||
# Concepts
|
||||
|
||||
## Introduction
|
||||
|
||||
This page is intended as a high level conceptual overview of the key concepts in
|
||||
Holos. Refer to the [Core API](/docs/api/core/) for low level reference
|
||||
documentation.
|
||||
|
||||
Holos is a tool built for platform engineers. The Holos authors share three
|
||||
core values which guide our design decisions for the tool.
|
||||
|
||||
1. Safety
|
||||
2. Ease of use
|
||||
3. Consistency
|
||||
|
||||
Each of the following concepts are intended to support and strengthen one or
|
||||
more of these core values. In this way we hope to lighten the burden carried by
|
||||
platform engineers.
|
||||
|
||||
## Concepts
|
||||
|
||||
- [Component](<#component>) - The primary building block in Holos, wraps a Helm chart, Kustomize base, or plain resources defined in CUE.
|
||||
- [Platform](<#platform>) - A collection of Components integrated into a software development platform.
|
||||
- [Model](<#model>) - Structured data included in the Platform specification, available to all Components. For example, your organization's domain name.
|
||||
- [Rendering](<#rendering>) - Holos is a tool that makes the process of rendering Kubernetes manifests safer, easier, and consistent.
|
||||
- [Cluster](<#cluster>) - A Kubernetes cluster. Components are rendered for and applied to a Cluster.
|
||||
- [Fleet](<#fleet>) - A collection of Clusters with a similar purpose. A Platform is typically composed of two Fleets, one for management the second for workloads.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Platform[<a href="#platform">Platform</a>]
|
||||
Cluster[<a href="#cluster">Cluster</a>]
|
||||
Fleet[<a href="#fleet">Fleet</a>]
|
||||
Component[<a href="#component">Component</a>]
|
||||
Helm[<a href="#component">Helm</a>]
|
||||
Kustomize[<a href="#component">Kustomize</a>]
|
||||
CUE[<a href="#component">CUE</a>]
|
||||
|
||||
Cluster --> Platform
|
||||
Fleet --> Cluster
|
||||
Component --> Fleet
|
||||
Helm --> Component
|
||||
Kustomize --> Component
|
||||
CUE --> Component
|
||||
```
|
||||
|
||||
:::tip
|
||||
This graph is organized as a tree. We often say configuration at the root
|
||||
defines the broad Platform. Configuration at a leaf defines a Component of the
|
||||
Platform. The concept of a tree also reflects the filesystem organization of
|
||||
the configuration.
|
||||
:::
|
||||
|
||||
<!--
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: Figure 1 - Holos Concepts
|
||||
---
|
||||
mindmap
|
||||
root((Holos))
|
||||
Platform
|
||||
Components
|
||||
HelmChart
|
||||
KustomizeBuild
|
||||
KubernetesObjects
|
||||
Model
|
||||
name: Example Org
|
||||
domain: example.com
|
||||
Renders
|
||||
YAML Files
|
||||
Kubernetes Manifests
|
||||
ArgoCD Application
|
||||
FluxCD Kustomization
|
||||
```
|
||||
|
||||
-->
|
||||
|
||||
|
||||
## Component
|
||||
|
||||
A Component is the primary building block when managing software with Holos. A
|
||||
software project you wish to integrate into your platform, for example ArgoCD,
|
||||
is managed using one or more components.
|
||||
|
||||
The primary Component kinds are:
|
||||
|
||||
1. **HelmChart** to render config provided by Helm.
|
||||
2. **KustomizeBuild** to render config provided by Kustomize.
|
||||
3. **KubernetesObjects** to render config provided by CUE.
|
||||
|
||||
Components are intended to integrate unmodified upstream software releases into
|
||||
your Platform. In this way, the focus of a Component is more about the unique
|
||||
differentiating aspects of your platform than the upstream software contained in
|
||||
the Component.
|
||||
|
||||
#### Example HelmChart Component
|
||||
|
||||
The ArgoCD Component is a good example of a HelmChart component because it takes
|
||||
advantage of most of the key features that empower you to focus on the key
|
||||
differentiators of your unique platform.
|
||||
|
||||
Take note of the following key points in this example ArgoCD Component:
|
||||
|
||||
1. The Component wraps the ArgoCD Helm Chart in a way that's easy to upgrade and maintain over time.
|
||||
2. Newer Gateway API resources are mixed-in replacing the older Ingress resource included in the chart.
|
||||
3. Helm output is passed through Kustomize to configure secure mutual TLS encryption.
|
||||
4. Helm values are easier and safer to manipulate with CUE instead of text markup.
|
||||
5. Kustomize is easier and safer to manipulate with CUE instead of text markup.
|
||||
6. Platform data Model values are easily accessible, for example the OIDC issuer and the organizations's domain name.
|
||||
|
||||
The Component wraps around the unmodified upstream ArgoCD helm chart
|
||||
providing easier upgrades as new versions are released.
|
||||
|
||||
Note how the Component facilitates composition by allowing us to mix-in new
|
||||
functionality from the ecosystem without modifying the upstream chart. The
|
||||
Platform this Component integrates with uses the new Gateway API, but the
|
||||
upstream helm chart does not yet support Gateway API. See how the Resources
|
||||
field is used to mix-in a ReferenceGrant from the Gateway API without modifying
|
||||
the upstream helm chart.
|
||||
|
||||
The Platform uses Istio to implement service to service encryption with mutual
|
||||
TLS. The Component passes the Helm output to Kustomize to integrate with Istio.
|
||||
Kustomize is used to patch the argocd-server Deployment resource to inject the
|
||||
Istio sidecar for mutual TLS.
|
||||
|
||||
Helm values are safer and easier to work with in CUE. Note how you can modify
|
||||
helm values using well defined data instead of manipulating text yaml files.
|
||||
Similarly, the yaml files used for Kustomize are produced by CUE, which is again
|
||||
safer and easier because the Kustomize spec has been imported into CUE and is
|
||||
validated.
|
||||
|
||||
Finally, the domain name used by this Platform is easily accessible from the
|
||||
PlatformSpec which is defined at the root level and made available to all
|
||||
components integrated into the platform. Similarly, data values shared by all
|
||||
of the Components that make up ArgoCD is defined in a structure accessible by
|
||||
each of these components.
|
||||
|
||||
```cue
|
||||
package holos
|
||||
|
||||
import (
|
||||
"encoding/yaml"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
|
||||
let Chart = {
|
||||
Name: "argo-cd"
|
||||
Namespace: "argocd"
|
||||
Version: "7.1.1"
|
||||
|
||||
Chart: chart: release: "argocd"
|
||||
|
||||
// The upstream chart uses a Job to create the argocd-redis Secret. Enable
|
||||
// hooks to enable the Job.
|
||||
Chart: enableHooks: true
|
||||
|
||||
Repo: name: "argocd"
|
||||
Repo: url: "https://argoproj.github.io/argo-helm"
|
||||
|
||||
// Ensure all of our mix-in resources go into the same namespace as the Chart.
|
||||
Resources: [_]: [_]: metadata: namespace: Namespace
|
||||
|
||||
// Grant the Gateway namespace the ability to refer to the backend service
|
||||
// from HTTPRoute resources.
|
||||
Resources: ReferenceGrant: (#IstioGatewaysNamespace): #ReferenceGrant
|
||||
|
||||
// Pass the helm output through kustomize.
|
||||
EnableKustomizePostProcessor: true
|
||||
|
||||
// Force all resources into the component namespace, some resources in the
|
||||
// helm chart do not specify the namespace so they will get mis-applied
|
||||
// when the kubectl (client-go) context is another namespace.
|
||||
KustomizeFiles: "kustomization.yaml": namespace: Namespace
|
||||
|
||||
// Patch the backend with the service mesh sidecar.
|
||||
KustomizePatches: {
|
||||
mesh: {
|
||||
target: {
|
||||
group: "apps"
|
||||
version: "v1"
|
||||
kind: "Deployment"
|
||||
name: "argocd-server"
|
||||
}
|
||||
patch: yaml.Marshal(IstioInject)
|
||||
}
|
||||
}
|
||||
|
||||
Values: #Values & {
|
||||
kubeVersionOverride: "1.29.0"
|
||||
// handled in the argo-crds component
|
||||
crds: install: false
|
||||
global: domain: "argocd.\(_Platform.Model.org.domain)"
|
||||
dex: enabled: false
|
||||
// the service mesh handles secure mTLS
|
||||
configs: params: "server.insecure": true
|
||||
configs: cm: {
|
||||
"admin.enabled": false
|
||||
"oidc.config": yaml.Marshal(OIDCConfig)
|
||||
"users.anonymous.enabled": "false"
|
||||
}
|
||||
|
||||
// Refer to https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/
|
||||
let Policy = [
|
||||
"g, argocd-view, role:readonly",
|
||||
"g, prod-cluster-view, role:readonly",
|
||||
"g, prod-cluster-edit, role:readonly",
|
||||
"g, prod-cluster-admin, role:admin",
|
||||
]
|
||||
|
||||
configs: rbac: "policy.csv": strings.Join(Policy, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
let IstioInject = [{
|
||||
op: "add",
|
||||
path: "/spec/template/metadata/labels/sidecar.istio.io~1inject",
|
||||
value: "true",
|
||||
}]
|
||||
|
||||
let OIDCConfig = {
|
||||
name: "Holos Platform"
|
||||
issuer: _ArgoCD.issuerURL
|
||||
clientID: _ArgoCD.clientID
|
||||
requestedScopes: _ArgoCD.scopesList
|
||||
// Set redirect uri to https://argocd.example.com/pkce/verify
|
||||
enablePKCEAuthentication: true
|
||||
// groups is essential for rbac
|
||||
requestedIDTokenClaims: groups: essential: true
|
||||
}
|
||||
```
|
||||
|
||||
## Platform
|
||||
|
||||
A Platform refers to all of the software and services integrated together to
|
||||
provide your organization's software development platform. Holos is designed to
|
||||
manage all of the resources that compose your Platform using the [Kubernetes
|
||||
Resource Model][krm] (KRM). Nearly all platforms are larger than Kubernetes
|
||||
itself. For example, your developers likely need a GCS or S3 bucket to store
|
||||
data. Holos takes advantage of Crossplane to manage resources in a consistent
|
||||
way.
|
||||
|
||||
Holos defines a [Platform][Platform] object which collects multiple Components
|
||||
together along with organizational data defined by your Model. Consider the
|
||||
following example, which is a Platform that manages a single Component which
|
||||
manages namespaces for each cluster in the Platform.
|
||||
|
||||
```cue
|
||||
package holos
|
||||
|
||||
import v1 "github.com/holos-run/holos/api/v1alpha2"
|
||||
|
||||
v1.#Platform & {
|
||||
metadata: name: "example"
|
||||
|
||||
spec: components: [{
|
||||
path: "components/namespaces"
|
||||
cluster: "cluster1"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
This platform is rendered by the command:
|
||||
|
||||
```bash
|
||||
holos render platform ./platform
|
||||
```
|
||||
|
||||
When Holos renders the platform, it iterates over each component, generates and
|
||||
executes a [BuildPlan][BuildPlan], then writes the fully rendered output of the
|
||||
component to the filesystem. In this simple example, two files are produced:
|
||||
|
||||
1. `deploy/clusters/cluster1/components/namespaces/namespaces.gen.yaml`
|
||||
2. `deploy/clusters/cluster1/gitops/namespaces.application.gen.yaml`
|
||||
|
||||
The first file is a plain kubernetes manifest containing Namespace resources.
|
||||
The second file is an ArgoCD Application resource to deploy and manage the
|
||||
resources defined in the first file.
|
||||
|
||||
## Model
|
||||
|
||||
The Platform Model is where you store top-level data values used throughout
|
||||
multiple components in your Platform. Your organization's domain name is a
|
||||
prime example of the kind of data stored in the Model. Many components derive
|
||||
host names from your organization's domain name. CUE makes this process safe,
|
||||
easy, and consistent. For example:
|
||||
|
||||
```cue
|
||||
hostname: "argocd.\(_Platform.Model.org.domain)"
|
||||
```
|
||||
|
||||
When Holos renders a Platform, the model is loaded from a JSON file in the local
|
||||
filesystem. The platform model file is intended to be committed to version
|
||||
control along with the rest of the Holos Platform and Component code.
|
||||
|
||||
Holos additionally provides a web ui and form to make it easy to enter and
|
||||
validate top level configuration data. You have complete control over the web
|
||||
form, it's rendered from JSON data defined by CUE. Customizing the web form is
|
||||
an advanced topic, the key concept to take away is the Model is for top level,
|
||||
platform-wide data. You control the shape and structure of the Model, and you
|
||||
have the ability to collect Model values using a simple web form.
|
||||
|
||||
## Rendering
|
||||
|
||||
Holos uses the Kubernetes resource model to manage configuration. The Holos
|
||||
command line interface is the primary method you'll use to manage your platform.
|
||||
Holos uses CUE to provide a unified configuration model of the platform. This
|
||||
unified configuration is built up from components packaged with Helm, Kustomize,
|
||||
CUE, or any other tool that can produce Kubernetes resource manifests as output.
|
||||
|
||||
This process can be thought of as a data **rendering pipeline**. The key
|
||||
concept is that Holos will always produce fully rendered output, but delegates
|
||||
the _application_ of the configuration to other tools like kubectl apply,
|
||||
ArgoCD, or Flux.
|
||||
|
||||
```mermaid
|
||||
---
|
||||
title: Figure 1 - Render 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>]
|
||||
|
||||
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>]
|
||||
|
||||
P[<a href="/docs/api/core/v1alpha3#Kustomize">Kustomize</a>]
|
||||
Y[Kubernetes <br/>Resources]
|
||||
G[GitOps <br/>Resource]
|
||||
FS[Local Files]
|
||||
|
||||
C[Kube API Server]
|
||||
|
||||
PS --> HC --> BP
|
||||
BP --> H --> P
|
||||
BP --> K --> P
|
||||
BP --> O --> P
|
||||
|
||||
P --> Y --> FS
|
||||
P --> G --> FS
|
||||
|
||||
FS --> ArgoCD --> C
|
||||
FS --> Flux --> C
|
||||
FS --> kubectl --> C
|
||||
```
|
||||
|
||||
## Cluster
|
||||
|
||||
A Cluster represents a Kubernetes cluster. One component may be reused across
|
||||
multiple different Clusters.
|
||||
|
||||
## Fleet
|
||||
|
||||
A Fleet represents a group of Clusters that share a similar purpose. A Platform
|
||||
typically has two Fleets, one for management and one for workloads.
|
||||
|
||||
[krm]: https://docs.google.com/document/d/1RmHXdLhNbyOWPW_AtnnowaRfGejw-qlKQIuLKQWlwzs/view#heading=h.sa6p0aye4ide
|
||||
[Platform]: /docs/api/core/v1alpha2/#Platform
|
||||
[BuildPlan]: /docs/api/core/v1alpha2/#BuildPlan
|
||||