mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 16:54:58 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7e0470c48 | ||
|
|
d5c7b82684 | ||
|
|
7d0392e596 | ||
|
|
410b882d1d | ||
|
|
e2648202dc | ||
|
|
44c2fe220a | ||
|
|
fe1ae2fa80 | ||
|
|
8fbee1cbd9 | ||
|
|
982db2cccc |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,3 +12,4 @@ tmp/
|
||||
/holos-k3d/
|
||||
/holos-infra/
|
||||
node_modules/
|
||||
.tmp/
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# https://github.com/holos-run/holos/issues/330
|
||||
exec holos init platform v1alpha5 --force
|
||||
# Make sure the helm chart works with plain helm
|
||||
exec helm template ./components/capabilities/vendor/0.1.0/capabilities
|
||||
cmp stdout want/helm-template.yaml
|
||||
stdout 'name: has-foo-v1beta1'
|
||||
stdout 'kubeVersion: v'
|
||||
exec holos render platform ./platform
|
||||
# When no capabilities are specified
|
||||
cmp deploy/components/capabilities/capabilities.gen.yaml want/when-no-capabilities-specified.yaml
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
exec bash -c 'bash -euo pipefail $WORK/command.sh 2>&1'
|
||||
cmp stdout $WORK/output.txt
|
||||
|
||||
-- command.sh --
|
||||
holos --version
|
||||
-- output.txt --
|
||||
0.103.0
|
||||
126
doc/md/tutorial/_hello-holos/examples/02-hello-holos.txt
Normal file
126
doc/md/tutorial/_hello-holos/examples/02-hello-holos.txt
Normal file
@@ -0,0 +1,126 @@
|
||||
# Set $HOME because:
|
||||
# - Helm uses it for temporary files
|
||||
# - Git requires it for setting author name/email globally
|
||||
env HOME=$WORK/.tmp
|
||||
chmod 0755 $WORK/update.sh
|
||||
|
||||
# Configure git author for testscript execution
|
||||
exec git config --global user.name 'Holos Docs'
|
||||
exec git config --global user.email 'hello@holos.run'
|
||||
exec git config --global init.defaultBranch main
|
||||
|
||||
# Remove the tutorial directory if it already exists
|
||||
exec rm -rf holos-tutorial
|
||||
|
||||
# Create and change to the tutorial directory, and then initialize the Holos platform
|
||||
exec bash -c 'bash -euo pipefail $WORK/mkdir-and-init.sh'
|
||||
cd holos-tutorial
|
||||
|
||||
# Create the components directory
|
||||
exec bash -c 'bash -euo pipefail $WORK/mkdir-components.sh'
|
||||
|
||||
# Combine and execute the multiline podinfo component header/body/trailer files
|
||||
exec cat $WORK/podinfo-component-header.sh ../podinfo-component-body.cue ../eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Combine and execute the multiline platform registration header/body/trailer files
|
||||
exec cat $WORK/register-podinfo-header.sh ../register-podinfo-body.cue ../eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Render the platform, capture stdout, and use update.sh to gate whether the
|
||||
# output file should be updated.
|
||||
#
|
||||
# NOTE: The [net] condition will test whether external network access is available
|
||||
[net] exec bash -c 'bash -euo pipefail $WORK/render.sh 2>&1'
|
||||
[net] stdin stdout
|
||||
exec $WORK/update.sh $WORK/register-components-output.txt
|
||||
|
||||
# Generate and update the tree of the tutorial directory (omitting the cue.mod directory)
|
||||
exec bash -c 'bash -euo pipefail $WORK/tree.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/tree.txt
|
||||
|
||||
# Split the rendered manifest into two separate files to display separately
|
||||
exec bash -c 'bash -euo pipefail $WORK/split-rendered-manifest.sh $WORK/holos-tutorial/deploy/components/podinfo/podinfo.gen.yaml $WORK'
|
||||
|
||||
# Grep for the Hello Holos message and write the output file
|
||||
exec bash -c 'bash -euo pipefail $WORK/grep-for-message.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/grepped-output.txt
|
||||
|
||||
# Clean up the tutorial directory and tmp $HOME directory
|
||||
cd $WORK
|
||||
exec rm -rf holos-tutorial
|
||||
exec rm -rf $HOME
|
||||
|
||||
-- update.sh --
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
-- mkdir-and-init.sh --
|
||||
mkdir holos-tutorial && cd holos-tutorial
|
||||
holos init platform v1alpha5
|
||||
-- tree.sh --
|
||||
tree -L 3 -I cue.mod .
|
||||
-- mkdir-components.sh --
|
||||
mkdir -p components/podinfo
|
||||
-- podinfo-component-header.sh --
|
||||
cat <<EOF > components/podinfo/podinfo.cue
|
||||
-- podinfo-component-body.cue --
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
holos: HelmChart.BuildPlan
|
||||
|
||||
HelmChart: #Helm & {
|
||||
Name: "podinfo"
|
||||
Chart: {
|
||||
version: "6.6.2"
|
||||
repository: {
|
||||
name: "podinfo"
|
||||
url: "https://stefanprodan.github.io/podinfo"
|
||||
}
|
||||
}
|
||||
// Holos marshals Values into values.yaml for Helm.
|
||||
Values: {
|
||||
// message is a string with a default value. @tag indicates a value may
|
||||
// be injected from the platform spec component parameters.
|
||||
ui: {
|
||||
message: string | *"Hello World" @tag(greeting, type=string)
|
||||
}
|
||||
}
|
||||
}
|
||||
-- eof-trailer.sh --
|
||||
EOF
|
||||
-- register-podinfo-header.sh --
|
||||
cat <<EOF > platform/podinfo.cue
|
||||
-- register-podinfo-body.cue --
|
||||
package holos
|
||||
|
||||
Platform: Components: podinfo: {
|
||||
name: "podinfo"
|
||||
path: "components/podinfo"
|
||||
// Inject a value into the component.
|
||||
parameters: greeting: "Hello Holos!"
|
||||
}
|
||||
-- render.sh --
|
||||
holos render platform
|
||||
-- register-components-output.txt --
|
||||
cached podinfo 6.6.2
|
||||
rendered podinfo in 1.938665041s
|
||||
rendered platform in 1.938759417s
|
||||
-- podinfo-rendered-path.sh --
|
||||
deploy/components/podinfo/podinfo.gen.yaml
|
||||
-- split-rendered-manifest.sh --
|
||||
awk 'BEGIN {RS="---"} NR==1 {print > "service.yaml"} NR==2 {print > "deployment.yaml"}' $1
|
||||
mv service.yaml $2/rendered-service.yaml
|
||||
mv deployment.yaml $2/rendered-deployment.yaml
|
||||
-- grep-for-message.sh --
|
||||
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
|
||||
-- grepped-output.txt --
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
@@ -0,0 +1 @@
|
||||
holos --version
|
||||
@@ -0,0 +1 @@
|
||||
0.103.0
|
||||
@@ -0,0 +1 @@
|
||||
EOF
|
||||
@@ -0,0 +1 @@
|
||||
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
|
||||
@@ -0,0 +1,3 @@
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
@@ -0,0 +1,2 @@
|
||||
mkdir holos-tutorial && cd holos-tutorial
|
||||
holos init platform v1alpha5
|
||||
@@ -0,0 +1 @@
|
||||
mkdir -p components/podinfo
|
||||
@@ -0,0 +1,23 @@
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
holos: HelmChart.BuildPlan
|
||||
|
||||
HelmChart: #Helm & {
|
||||
Name: "podinfo"
|
||||
Chart: {
|
||||
version: "6.6.2"
|
||||
repository: {
|
||||
name: "podinfo"
|
||||
url: "https://stefanprodan.github.io/podinfo"
|
||||
}
|
||||
}
|
||||
// Holos marshals Values into values.yaml for Helm.
|
||||
Values: {
|
||||
// message is a string with a default value. @tag indicates a value may
|
||||
// be injected from the platform spec component parameters.
|
||||
ui: {
|
||||
message: string | *"Hello World" @tag(greeting, type=string)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > components/podinfo/podinfo.cue
|
||||
@@ -0,0 +1 @@
|
||||
deploy/components/podinfo/podinfo.gen.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
rendered podinfo in 544.501875ms
|
||||
rendered platform in 544.608125ms
|
||||
@@ -0,0 +1,8 @@
|
||||
package holos
|
||||
|
||||
Platform: Components: podinfo: {
|
||||
name: "podinfo"
|
||||
path: "components/podinfo"
|
||||
// Inject a value into the component.
|
||||
parameters: greeting: "Hello Holos!"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > platform/podinfo.cue
|
||||
@@ -0,0 +1 @@
|
||||
holos render platform
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/port: "9898"
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- ./podinfo
|
||||
- --port=9898
|
||||
- --cert-path=/data/cert
|
||||
- --port-metrics=9797
|
||||
- --grpc-port=9999
|
||||
- --grpc-service-name=podinfo
|
||||
- --level=info
|
||||
- --random-delay=false
|
||||
- --random-error=false
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: '#34577c'
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/healthz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
name: podinfo
|
||||
ports:
|
||||
- containerPort: 9898
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 9797
|
||||
name: http-metrics
|
||||
protocol: TCP
|
||||
- containerPort: 9999
|
||||
name: grpc
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/readyz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits: null
|
||||
requests:
|
||||
cpu: 1m
|
||||
memory: 16Mi
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: data
|
||||
terminationGracePeriodSeconds: 30
|
||||
volumes:
|
||||
- emptyDir: {}
|
||||
name: data
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- name: grpc
|
||||
port: 9999
|
||||
protocol: TCP
|
||||
targetPort: grpc
|
||||
selector:
|
||||
app.kubernetes.io/name: podinfo
|
||||
type: ClusterIP
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
awk 'BEGIN {RS="---"} NR==1 {print > "service.yaml"} NR==2 {print > "deployment.yaml"}' $1
|
||||
mv service.yaml $2/rendered-service.yaml
|
||||
mv deployment.yaml $2/rendered-deployment.yaml
|
||||
@@ -0,0 +1 @@
|
||||
tree -L 3 -I cue.mod .
|
||||
17
doc/md/tutorial/_hello-holos/script-02-hello-holos/tree.txt
Normal file
17
doc/md/tutorial/_hello-holos/script-02-hello-holos/tree.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
.
|
||||
|-- components
|
||||
| `-- podinfo
|
||||
| |-- podinfo.cue
|
||||
| `-- vendor
|
||||
|-- deploy
|
||||
| `-- components
|
||||
| `-- podinfo
|
||||
|-- platform
|
||||
| |-- platform.gen.cue
|
||||
| `-- podinfo.cue
|
||||
|-- platform.metadata.json
|
||||
|-- resources.cue
|
||||
|-- schema.cue
|
||||
`-- tags.cue
|
||||
|
||||
8 directories, 7 files
|
||||
4
doc/md/tutorial/_hello-holos/script-02-hello-holos/update.sh
Executable file
4
doc/md/tutorial/_hello-holos/script-02-hello-holos/update.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
@@ -1 +1 @@
|
||||
0.102.5
|
||||
0.103.0
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[main e1c6859] add blackbox configuration
|
||||
[main 1adcd08] add blackbox configuration
|
||||
1 file changed, 15 insertions(+)
|
||||
create mode 100644 config/prometheus/blackbox.cue
|
||||
create mode 100644 components/blackbox.cue
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
[main 668706a] integrate blackbox and prometheus together
|
||||
3 files changed, 1348 insertions(+), 2 deletions(-)
|
||||
create mode 100644 components/prometheus/values.cue.orig
|
||||
[main 4221803] integrate blackbox and prometheus together
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[main 7bc6772] import values
|
||||
[main 52e90ea] import values
|
||||
2 files changed, 1815 insertions(+)
|
||||
create mode 100644 components/blackbox/values.cue
|
||||
create mode 100644 components/prometheus/values.cue
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
rendered blackbox in 146.654292ms
|
||||
rendered prometheus in 178.845292ms
|
||||
rendered platform in 178.9115ms
|
||||
rendered blackbox in 365.936792ms
|
||||
rendered prometheus in 371.855875ms
|
||||
rendered platform in 372.109916ms
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[main d144f24] add blackbox and prometheus
|
||||
[main b5df111] add blackbox and prometheus
|
||||
5 files changed, 1550 insertions(+)
|
||||
create mode 100644 components/blackbox/blackbox.cue
|
||||
create mode 100644 components/prometheus/prometheus.cue
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
rendered blackbox in 1.794799666s
|
||||
rendered prometheus in 1.835097625s
|
||||
rendered platform in 1.835185792s
|
||||
cached prometheus-blackbox-exporter 9.0.1
|
||||
rendered blackbox in 3.825430417s
|
||||
cached prometheus 25.27.0
|
||||
rendered prometheus in 4.840089667s
|
||||
rendered platform in 4.840137792s
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[main 1399737] render integrated blackbox and prometheus manifests
|
||||
[main 67efe0d] render integrated blackbox and prometheus manifests
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
7
doc/md/tutorial/_kustomize/examples/01-holos-version.txt
Normal file
7
doc/md/tutorial/_kustomize/examples/01-holos-version.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
exec bash -c 'bash -euo pipefail $WORK/command.sh 2>&1'
|
||||
cmp stdout $WORK/output.txt
|
||||
|
||||
-- command.sh --
|
||||
holos --version
|
||||
-- output.txt --
|
||||
0.103.0
|
||||
226
doc/md/tutorial/_kustomize/examples/02-kustomize.txt
Normal file
226
doc/md/tutorial/_kustomize/examples/02-kustomize.txt
Normal file
@@ -0,0 +1,226 @@
|
||||
# Set $HOME because:
|
||||
# - Helm uses it for temporary files
|
||||
# - Git requires it for setting author name/email globally
|
||||
env HOME=$WORK/.tmp
|
||||
chmod 0755 $WORK/update.sh
|
||||
|
||||
# Configure git author for testscript execution
|
||||
exec git config --global user.name 'Holos Docs'
|
||||
exec git config --global user.email 'hello@holos.run'
|
||||
exec git config --global init.defaultBranch main
|
||||
|
||||
# Remove the tutorial directory if it already exists
|
||||
exec rm -rf holos-kustomize-tutorial
|
||||
|
||||
# Create and change to the tutorial directory, and then initialize the Holos platform
|
||||
exec bash -c 'bash -euo pipefail $WORK/mkdir-and-init.sh'
|
||||
cd holos-kustomize-tutorial
|
||||
|
||||
# Initialize git
|
||||
exec bash -c 'bash -euo pipefail $WORK/git-init.sh'
|
||||
|
||||
# Create the component directory
|
||||
exec bash -c 'bash -euo pipefail $WORK/mkdir-component.sh'
|
||||
|
||||
# Combine and execute the multiline httpbin component header/body/trailer files
|
||||
exec cat $WORK/httpbin-component-header.sh $WORK/httpbin-component-body.cue $WORK/eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Combine and execute the multiline httpbin yaml header/body/trailer files
|
||||
exec cat $WORK/httpbin-yaml-header.sh $WORK/httpbin-yaml-body.yaml $WORK/eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Combine and execute the multiline registration header/body/trailer files
|
||||
exec cat $WORK/register-component-header.sh $WORK/register-component-body.cue $WORK/eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Render the platform, capture stdout, and use update.sh to gate whether the
|
||||
# output file should be updated.
|
||||
#
|
||||
# NOTE: The [net] condition will test whether external network access is available
|
||||
[net] exec bash -c 'bash -euo pipefail $WORK/render.sh 2>&1'
|
||||
[net] stdin stdout
|
||||
exec $WORK/update.sh $WORK/register-component-output.txt
|
||||
|
||||
# Git commit and capture output
|
||||
exec bash -c 'bash -euo pipefail $WORK/git-commit-component.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/git-commit-component-output.txt
|
||||
|
||||
# Export Build Plan and capture output
|
||||
exec bash -c 'bash -euo pipefail $WORK/cue-export.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/buildplan-output.cue
|
||||
|
||||
# Combine and execute the multiline kustomize patch header/body/trailer files
|
||||
exec cat $WORK/httpbin-patch-header.sh $WORK/httpbin-patch-body.cue $WORK/eof-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Render the platform and capture output
|
||||
[net] exec bash -c 'bash -euo pipefail $WORK/render.sh 2>&1'
|
||||
[net] stdin stdout
|
||||
exec $WORK/update.sh $WORK/kustomize-patch-render-output.txt
|
||||
|
||||
# Git diff and capture output
|
||||
exec bash -c 'bash -euo pipefail $WORK/git-diff.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/git.diff
|
||||
|
||||
# Git commit and capture output
|
||||
exec bash -c 'bash -euo pipefail $WORK/git-commit-final.sh'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/git-commit-final-output.txt
|
||||
|
||||
# Clean up the tutorial directory and tmp $HOME directory
|
||||
cd $WORK
|
||||
exec rm -rf holos-kustomize-tutorial
|
||||
exec rm -rf $HOME
|
||||
|
||||
-- update.sh --
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
-- mkdir-and-init.sh --
|
||||
mkdir holos-kustomize-tutorial
|
||||
cd holos-kustomize-tutorial
|
||||
holos init platform v1alpha5
|
||||
-- git-init.sh --
|
||||
git init . && git add . && git commit -m initial
|
||||
-- mkdir-component.sh --
|
||||
mkdir -p components/httpbin
|
||||
-- httpbin-component-header.sh --
|
||||
cat <<EOF > components/httpbin/httpbin.cue
|
||||
-- httpbin-component-body.cue --
|
||||
package holos
|
||||
|
||||
// Produce a Kustomize BuildPlan for Holos
|
||||
holos: Kustomize.BuildPlan
|
||||
|
||||
// https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/README.md
|
||||
Kustomize: #Kustomize & {
|
||||
KustomizeConfig: {
|
||||
// Files tells Holos to copy the file from the component path to the
|
||||
// temporary directory Holos uses for BuildPlan execution.
|
||||
Files: {
|
||||
"httpbin.yaml": _
|
||||
}
|
||||
CommonLabels: {
|
||||
"app.kubernetes.io/name": "httpbin"
|
||||
}
|
||||
// Kustomization represents a kustomization.yaml file in CUE. Holos
|
||||
// marshals this field into a `kustomization.yaml` while processing a
|
||||
// BuildPlan. See
|
||||
// https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
|
||||
Kustomization: {
|
||||
images: [{name: "mccutchen/go-httpbin"}]
|
||||
// Use a hidden field to compose patches easily with a struct. Hidden
|
||||
// fields are not included in exported structures.
|
||||
_patches: {}
|
||||
// Convert the hidden struct to a list.
|
||||
patches: [for x in _patches {x}]
|
||||
}
|
||||
}
|
||||
}
|
||||
-- eof-trailer.sh --
|
||||
EOF
|
||||
-- httpbin-yaml-header.sh --
|
||||
cat <<EOF > components/httpbin/httpbin.yaml
|
||||
-- httpbin-yaml-body.yaml --
|
||||
# https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/resources.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: httpbin
|
||||
image: mccutchen/go-httpbin
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
resources: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
appProtocol: http
|
||||
-- register-component-header.sh --
|
||||
cat <<EOF > platform/httpbin.cue
|
||||
-- register-component-body.cue --
|
||||
package holos
|
||||
|
||||
Platform: Components: {
|
||||
httpbin: {
|
||||
name: "httpbin"
|
||||
path: "components/httpbin"
|
||||
}
|
||||
}
|
||||
-- git-commit-component.sh --
|
||||
git add . && git commit -m 'add httpbin'
|
||||
-- cue-export.sh --
|
||||
holos cue export --expression holos --out=yaml ./components/httpbin
|
||||
-- httpbin-patch-header.sh --
|
||||
cat <<EOF > components/httpbin/patches.cue
|
||||
-- httpbin-patch-body.cue --
|
||||
package holos
|
||||
|
||||
import "encoding/yaml"
|
||||
|
||||
// Mix in a Kustomize patch to the configuration.
|
||||
Kustomize: KustomizeConfig: Kustomization: _patches: {
|
||||
probe: {
|
||||
target: kind: "Service"
|
||||
target: name: "httpbin"
|
||||
patch: yaml.Marshal([{
|
||||
op: "add"
|
||||
path: "/metadata/annotations/prometheus.io~1probe"
|
||||
value: "true"
|
||||
}])
|
||||
}
|
||||
}
|
||||
-- httpbin-component-output.txt --
|
||||
rendered httpbin in 197.030208ms
|
||||
rendered platform in 197.416416ms
|
||||
-- render.sh --
|
||||
holos render platform
|
||||
-- git-diff.sh --
|
||||
git diff
|
||||
-- git.diff --
|
||||
diff --git a/deploy/components/httpbin/httpbin.gen.yaml b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
index 298b9a8..a16bd1a 100644
|
||||
--- a/deploy/components/httpbin/httpbin.gen.yaml
|
||||
+++ b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
@@ -1,6 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
+ annotations:
|
||||
+ prometheus.io/probe: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: httpbin
|
||||
name: httpbin
|
||||
-- git-commit-final.sh --
|
||||
git add . && git commit -m 'annotate httpbin for prometheus probes'
|
||||
@@ -0,0 +1 @@
|
||||
holos --version
|
||||
@@ -0,0 +1 @@
|
||||
0.103.0
|
||||
@@ -0,0 +1,36 @@
|
||||
kind: BuildPlan
|
||||
apiVersion: v1alpha5
|
||||
metadata:
|
||||
name: no-name
|
||||
spec:
|
||||
artifacts:
|
||||
- artifact: components/no-name/no-name.gen.yaml
|
||||
generators:
|
||||
- kind: Resources
|
||||
output: resources.gen.yaml
|
||||
resources: {}
|
||||
- kind: File
|
||||
output: httpbin.yaml
|
||||
file:
|
||||
source: httpbin.yaml
|
||||
validators: []
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- resources.gen.yaml
|
||||
- httpbin.yaml
|
||||
output: components/no-name/no-name.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
labels:
|
||||
- includeSelectors: false
|
||||
pairs:
|
||||
app.kubernetes.io/name: httpbin
|
||||
patches: []
|
||||
images:
|
||||
- name: mccutchen/go-httpbin
|
||||
resources:
|
||||
- resources.gen.yaml
|
||||
- httpbin.yaml
|
||||
kind: Kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
@@ -0,0 +1 @@
|
||||
holos cue export --expression holos --out=yaml ./components/httpbin
|
||||
@@ -0,0 +1 @@
|
||||
EOF
|
||||
@@ -0,0 +1,6 @@
|
||||
[main f0dd632] add httpbin
|
||||
4 files changed, 113 insertions(+)
|
||||
create mode 100644 components/httpbin/httpbin.cue
|
||||
create mode 100644 components/httpbin/httpbin.yaml
|
||||
create mode 100644 deploy/components/httpbin/httpbin.gen.yaml
|
||||
create mode 100644 platform/httpbin.cue
|
||||
@@ -0,0 +1 @@
|
||||
git add . && git commit -m 'add httpbin'
|
||||
@@ -0,0 +1,3 @@
|
||||
[main b120712] annotate httpbin for prometheus probes
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100644 components/httpbin/patches.cue
|
||||
@@ -0,0 +1 @@
|
||||
git add . && git commit -m 'annotate httpbin for prometheus probes'
|
||||
@@ -0,0 +1 @@
|
||||
git diff
|
||||
@@ -0,0 +1 @@
|
||||
git init . && git add . && git commit -m initial
|
||||
13
doc/md/tutorial/_kustomize/script-02-kustomize/git.diff
Normal file
13
doc/md/tutorial/_kustomize/script-02-kustomize/git.diff
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/deploy/components/httpbin/httpbin.gen.yaml b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
index 298b9a8..a16bd1a 100644
|
||||
--- a/deploy/components/httpbin/httpbin.gen.yaml
|
||||
+++ b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
@@ -1,6 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
+ annotations:
|
||||
+ prometheus.io/probe: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: httpbin
|
||||
name: httpbin
|
||||
@@ -0,0 +1,30 @@
|
||||
package holos
|
||||
|
||||
// Produce a Kustomize BuildPlan for Holos
|
||||
holos: Kustomize.BuildPlan
|
||||
|
||||
// https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/README.md
|
||||
Kustomize: #Kustomize & {
|
||||
KustomizeConfig: {
|
||||
// Files tells Holos to copy the file from the component path to the
|
||||
// temporary directory Holos uses for BuildPlan execution.
|
||||
Files: {
|
||||
"httpbin.yaml": _
|
||||
}
|
||||
CommonLabels: {
|
||||
"app.kubernetes.io/name": "httpbin"
|
||||
}
|
||||
// Kustomization represents a kustomization.yaml file in CUE. Holos
|
||||
// marshals this field into a `kustomization.yaml` while processing a
|
||||
// BuildPlan. See
|
||||
// https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
|
||||
Kustomization: {
|
||||
images: [{name: "mccutchen/go-httpbin"}]
|
||||
// Use a hidden field to compose patches easily with a struct. Hidden
|
||||
// fields are not included in exported structures.
|
||||
_patches: {}
|
||||
// Convert the hidden struct to a list.
|
||||
patches: [for x in _patches {x}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > components/httpbin/httpbin.cue
|
||||
@@ -0,0 +1,2 @@
|
||||
rendered httpbin in 197.030208ms
|
||||
rendered platform in 197.416416ms
|
||||
@@ -0,0 +1,16 @@
|
||||
package holos
|
||||
|
||||
import "encoding/yaml"
|
||||
|
||||
// Mix in a Kustomize patch to the configuration.
|
||||
Kustomize: KustomizeConfig: Kustomization: _patches: {
|
||||
probe: {
|
||||
target: kind: "Service"
|
||||
target: name: "httpbin"
|
||||
patch: yaml.Marshal([{
|
||||
op: "add"
|
||||
path: "/metadata/annotations/prometheus.io~1probe"
|
||||
value: "true"
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > components/httpbin/patches.cue
|
||||
@@ -0,0 +1,36 @@
|
||||
# https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/resources.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: httpbin
|
||||
image: mccutchen/go-httpbin
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
resources: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
appProtocol: http
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > components/httpbin/httpbin.yaml
|
||||
@@ -0,0 +1,2 @@
|
||||
rendered httpbin in 132.00525ms
|
||||
rendered platform in 132.124042ms
|
||||
@@ -0,0 +1,3 @@
|
||||
mkdir holos-kustomize-tutorial
|
||||
cd holos-kustomize-tutorial
|
||||
holos init platform v1alpha5
|
||||
@@ -0,0 +1 @@
|
||||
mkdir -p components/httpbin
|
||||
@@ -0,0 +1,8 @@
|
||||
package holos
|
||||
|
||||
Platform: Components: {
|
||||
httpbin: {
|
||||
name: "httpbin"
|
||||
path: "components/httpbin"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cat <<EOF > platform/httpbin.cue
|
||||
@@ -0,0 +1,2 @@
|
||||
rendered httpbin in 175.057083ms
|
||||
rendered platform in 175.145292ms
|
||||
1
doc/md/tutorial/_kustomize/script-02-kustomize/render.sh
Normal file
1
doc/md/tutorial/_kustomize/script-02-kustomize/render.sh
Normal file
@@ -0,0 +1 @@
|
||||
holos render platform
|
||||
4
doc/md/tutorial/_kustomize/script-02-kustomize/update.sh
Executable file
4
doc/md/tutorial/_kustomize/script-02-kustomize/update.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
@@ -10,6 +10,7 @@ import TabItem from '@theme/TabItem';
|
||||
import RenderingOverview from '@site/src/diagrams/rendering-overview.mdx';
|
||||
import PlatformSequence from '@site/src/diagrams/render-platform-sequence.mdx';
|
||||
import ComponentSequence from '@site/src/diagrams/render-component-sequence.mdx';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
# Hello Holos
|
||||
|
||||
@@ -21,49 +22,37 @@ This introduces the core concept of wrapping Helm charts as Holos Components.
|
||||
|
||||
## Implementation
|
||||
|
||||
### Holos Version
|
||||
|
||||
Ensure you have a current version of `holos` installed. This document was
|
||||
tested with the following version.
|
||||
|
||||
import HolosVersionCommand from '!!raw-loader!./_hello-holos/script-01-holos-version/command.sh';
|
||||
import HolosVersionOutput from '!!raw-loader!./_hello-holos/script-01-holos-version/output.txt';
|
||||
|
||||
<CodeBlock language="bash">{HolosVersionCommand}</CodeBlock>
|
||||
<CodeBlock language="txt">{HolosVersionOutput}</CodeBlock>
|
||||
|
||||
### Initialize Platform Structure
|
||||
|
||||
Create and initialize a minimal platform:
|
||||
|
||||
```shell
|
||||
mkdir holos-tutorial && cd holos-tutorial
|
||||
holos init platform v1alpha5
|
||||
```
|
||||
import MkdirAndInit from '!!raw-loader!./_hello-holos/script-02-hello-holos/mkdir-and-init.sh';
|
||||
import TreeOutput from '!!raw-loader!./_hello-holos/script-02-hello-holos/tree.txt';
|
||||
|
||||
The resulting directory structure:
|
||||
<CodeBlock language="bash">{MkdirAndInit}</CodeBlock>
|
||||
|
||||
For reference, the directory structure you will attain by the end of this tutorial
|
||||
is listed below (NOTE: we have omitted the `cue.mod` directory for brevity):
|
||||
|
||||
<Tabs groupId="80D04C6A-BC83-44D0-95CC-CE01B439B159">
|
||||
<TabItem value="tree" label="Tree">
|
||||
```text showLineNumbers
|
||||
holos-tutorial/
|
||||
├── components/
|
||||
│ └── podinfo/
|
||||
│ └── podinfo.cue
|
||||
├── cue.mod/
|
||||
├── platform/
|
||||
│ ├── platform.gen.cue
|
||||
│ └── podinfo.cue
|
||||
├── resources.cue
|
||||
├── schema.cue
|
||||
└── tags.cue
|
||||
```
|
||||
<CodeBlock language="txt" showLineNumbers>{TreeOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="details" label="Details">
|
||||
<div style={{display: "flex"}}>
|
||||
<div>
|
||||
```text showLineNumbers
|
||||
holos-tutorial/
|
||||
├── components/
|
||||
│ └── podinfo/
|
||||
│ └── podinfo.cue
|
||||
├── cue.mod/
|
||||
├── platform/
|
||||
│ ├── platform.gen.cue
|
||||
│ └── podinfo.cue
|
||||
├── resources.cue
|
||||
├── schema.cue
|
||||
└── tags.cue
|
||||
```
|
||||
<CodeBlock language="txt" showLineNumbers>{TreeOutput}</CodeBlock>
|
||||
</div>
|
||||
<div>
|
||||
- **Line 1** The platform root is the `holos-tutorial` directory we created.
|
||||
@@ -72,22 +61,24 @@ anywhere.
|
||||
- **Line 3** A component is a collection of `*.cue` files at a path.
|
||||
- **Line 4** We'll create this file and configure the podinfo helm chart in the
|
||||
next section.
|
||||
- **Line 5** The CUE module directory. Schema definitions for Kubernetes and
|
||||
Holos resources reside within the `cue.mod` directory.
|
||||
- **Line 6** The platform directory is the **main entrypoint** for the `holos
|
||||
- **Line 5** The `vendor` directory contains a cached copy of the Helm chart that
|
||||
was fetched for the component.
|
||||
- **Line 6** Rendered manifests are placed within the `deploy` directory following
|
||||
the structure of the `components/` directory.
|
||||
- **Line 9** The platform directory is the **main entrypoint** for the `holos
|
||||
render platform` command.
|
||||
- **Line 7** `platform.gen.cue` is initialized by `holos init platform` and
|
||||
- **Line 10** `platform.gen.cue` is initialized by `holos init platform` and
|
||||
contains the Platform spec.
|
||||
- **Line 8** `podinfo.cue` integrates podinfo with the platform by adding the
|
||||
- **Line 11** `podinfo.cue` integrates podinfo with the platform by adding the
|
||||
component to the platform spec. We'll add ths file after the next section.
|
||||
- **Line 9** `resources.cue` Defines the Kubernetes resources available to
|
||||
- **Line 13** `resources.cue` Defines the Kubernetes resources available to
|
||||
manage in CUE.
|
||||
- **Line 10** `schema.cue` Defines the configuration common to all component
|
||||
- **Line 14** `schema.cue` Defines the configuration common to all component
|
||||
kinds.
|
||||
- **Line 11** `tags.cue` Defines where component parameter values are injected
|
||||
- **Line 15** `tags.cue` Defines where component parameter values are injected
|
||||
into the overall platform configuration. We don't need to be concerned with
|
||||
this file until we cover component parameters.
|
||||
- **Lines 9-11** Initialized by `holos init platform`, user editable after
|
||||
- **Lines 9-15** Initialized by `holos init platform`, user editable after
|
||||
initialization.
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,40 +89,15 @@ initialization.
|
||||
|
||||
Configure the `podinfo` component:
|
||||
|
||||
```bash
|
||||
mkdir -p components/podinfo
|
||||
```
|
||||
```bash
|
||||
cat <<EOF > components/podinfo/podinfo.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
import MkdirComponents from '!!raw-loader!./_hello-holos/script-02-hello-holos/mkdir-components.sh';
|
||||
import PodinfoHeader from '!!raw-loader!./_hello-holos/script-02-hello-holos/podinfo-component-header.sh';
|
||||
import PodinfoBody from '!!raw-loader!./_hello-holos/script-02-hello-holos/podinfo-component-body.cue';
|
||||
import EofTrailer from '!!raw-loader!./_hello-holos/script-02-hello-holos/eof-trailer.sh';
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
holos: HelmChart.BuildPlan
|
||||
|
||||
HelmChart: #Helm & {
|
||||
Name: "podinfo"
|
||||
Chart: {
|
||||
version: "6.6.2"
|
||||
repository: {
|
||||
name: "podinfo"
|
||||
url: "https://stefanprodan.github.io/podinfo"
|
||||
}
|
||||
}
|
||||
// Holos marshals Values into values.yaml for Helm.
|
||||
Values: {
|
||||
// message is a string with a default value. @tag indicates a value may
|
||||
// be injected from the platform spec component parameters.
|
||||
ui: {
|
||||
message: string | *"Hello World" @tag(greeting, type=string)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{MkdirComponents}</CodeBlock>
|
||||
<CodeBlock language="bash">{PodinfoHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{PodinfoBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
|
||||
:::important
|
||||
Like Go packages, CUE loads all `*.cue` files in the component directory to
|
||||
@@ -148,22 +114,12 @@ root-level `schema.cue`.
|
||||
|
||||
Register the `podinfo` component in `platform/podinfo.cue`:
|
||||
|
||||
```bash
|
||||
cat <<EOF > platform/podinfo.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
import RegisterPodinfoHeader from '!!raw-loader!./_hello-holos/script-02-hello-holos/register-podinfo-header.sh';
|
||||
import RegisterPodinfoBody from '!!raw-loader!./_hello-holos/script-02-hello-holos/register-podinfo-body.cue';
|
||||
|
||||
Platform: Components: podinfo: {
|
||||
name: "podinfo"
|
||||
path: "components/podinfo"
|
||||
// Inject a value into the component.
|
||||
parameters: greeting: "Hello Holos!"
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{RegisterPodinfoHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{RegisterPodinfoBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
|
||||
:::tip
|
||||
Parameter names are unrestricted, except for the reserved `holos_` prefix.
|
||||
@@ -173,161 +129,42 @@ Parameter names are unrestricted, except for the reserved `holos_` prefix.
|
||||
|
||||
Render the `podinfo` configuration:
|
||||
|
||||
import RenderCommand from '!!raw-loader!./_hello-holos/script-02-hello-holos/render.sh';
|
||||
import RegisterComponentsOutput from '!!raw-loader!./_hello-holos/script-02-hello-holos/register-components-output.txt';
|
||||
|
||||
<Tabs groupId="E150C802-7162-4FBF-82A7-77D9ADAEE847">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```
|
||||
cached podinfo 6.6.2
|
||||
rendered podinfo in 1.938665041s
|
||||
rendered platform in 1.938759417s
|
||||
```
|
||||
<CodeBlock language="txt">{RegisterComponentsOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos executes `helm template` with locally cached charts to generate:
|
||||
|
||||
```txt
|
||||
deploy/components/podinfo/podinfo.gen.yaml
|
||||
```
|
||||
import PodinfoRenderedPath from '!!raw-loader!./_hello-holos/script-02-hello-holos/podinfo-rendered-path.sh';
|
||||
import RenderedService from '!!raw-loader!./_hello-holos/script-02-hello-holos/rendered-service.yaml';
|
||||
import RenderedDeployment from '!!raw-loader!./_hello-holos/script-02-hello-holos/rendered-deployment.yaml';
|
||||
|
||||
<CodeBlock language="txt">{PodinfoRenderedPath}</CodeBlock>
|
||||
|
||||
<Tabs groupId="0E9C231D-D0E8-410A-A4A0-601842A086A6">
|
||||
<TabItem value="service" label="Service">
|
||||
```yaml showLineNumbers
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- name: grpc
|
||||
port: 9999
|
||||
protocol: TCP
|
||||
targetPort: grpc
|
||||
selector:
|
||||
app.kubernetes.io/name: podinfo
|
||||
type: ClusterIP
|
||||
```
|
||||
<CodeBlock language="yaml" showLineNumbers>{RenderedService}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="deployment" label="Deployment">
|
||||
```yaml showLineNumbers
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/port: "9898"
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- ./podinfo
|
||||
- --port=9898
|
||||
- --cert-path=/data/cert
|
||||
- --port-metrics=9797
|
||||
- --grpc-port=9999
|
||||
- --grpc-service-name=podinfo
|
||||
- --level=info
|
||||
- --random-delay=false
|
||||
- --random-error=false
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: '#34577c'
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/healthz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
name: podinfo
|
||||
ports:
|
||||
- containerPort: 9898
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 9797
|
||||
name: http-metrics
|
||||
protocol: TCP
|
||||
- containerPort: 9999
|
||||
name: grpc
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/readyz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits: null
|
||||
requests:
|
||||
cpu: 1m
|
||||
memory: 16Mi
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: data
|
||||
terminationGracePeriodSeconds: 30
|
||||
volumes:
|
||||
- emptyDir: {}
|
||||
name: data
|
||||
```
|
||||
<CodeBlock language="yaml" showLineNumbers>{RenderedDeployment}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos renders the component with the greeting injected from the platform spec.
|
||||
|
||||
```shell
|
||||
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
|
||||
```
|
||||
```yaml
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
```
|
||||
import GrepForMessage from '!!raw-loader!./_hello-holos/script-02-hello-holos/grep-for-message.sh';
|
||||
import GreppedOutput from '!!raw-loader!./_hello-holos/script-02-hello-holos/grepped-output.txt';
|
||||
|
||||
<CodeBlock language="bash">{GrepForMessage}</CodeBlock>
|
||||
<CodeBlock language="yaml">{GreppedOutput}</CodeBlock>
|
||||
|
||||
## Breaking it down
|
||||
|
||||
|
||||
19
doc/md/tutorial/hello-holos_test.go
Normal file
19
doc/md/tutorial/hello-holos_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Run these with go test -v to see the verbose names
|
||||
func TestHelloHolos(t *testing.T) {
|
||||
t.Run("TestHelloHolos", func(t *testing.T) {
|
||||
// Get an ordered list of test script files.
|
||||
dir := "_hello-holos"
|
||||
for _, file := range sortedTestScripts(t, filepath.Join(dir, "examples")) {
|
||||
t.Run("examples", func(t *testing.T) {
|
||||
runOneScript(t, dir, file)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -7,6 +7,7 @@ sidebar_position: 45
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
# Kustomize
|
||||
|
||||
@@ -24,6 +25,17 @@ covered in the [Helm Values] tutorial.
|
||||
|
||||
## The Code
|
||||
|
||||
### Holos Version
|
||||
|
||||
Ensure you have a current version of `holos` installed. This document was
|
||||
tested with the following version.
|
||||
|
||||
import HolosVersionCommand from '!!raw-loader!./_kustomize/script-01-holos-version/command.sh';
|
||||
import HolosVersionOutput from '!!raw-loader!./_kustomize/script-01-holos-version/output.txt';
|
||||
|
||||
<CodeBlock language="bash">{HolosVersionCommand}</CodeBlock>
|
||||
<CodeBlock language="txt">{HolosVersionOutput}</CodeBlock>
|
||||
|
||||
### Generating the structure
|
||||
|
||||
<Tabs>
|
||||
@@ -39,18 +51,14 @@ Use `holos` to generate a minimal platform directory structure. First, create
|
||||
and navigate into a blank directory. Then, run the `holos init platform`
|
||||
command.
|
||||
|
||||
```shell
|
||||
mkdir holos-kustomize-tutorial
|
||||
cd holos-kustomize-tutorial
|
||||
holos init platform v1alpha5
|
||||
```
|
||||
import MkdirAndInit from '!!raw-loader!./_kustomize/script-02-kustomize/mkdir-and-init.sh';
|
||||
import GitInit from '!!raw-loader!./_kustomize/script-02-kustomize/git-init.sh';
|
||||
|
||||
<CodeBlock language="bash">{MkdirAndInit}</CodeBlock>
|
||||
|
||||
Make a commit to track changes.
|
||||
|
||||
```bash
|
||||
git init . && git add . && git commit -m initial
|
||||
```
|
||||
|
||||
<CodeBlock language="bash">{GitInit}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -59,97 +67,26 @@ git init . && git add . && git commit -m initial
|
||||
Create the `httpbin` component directory, and add the `httpbin.cue` and
|
||||
`httpbin.yaml` files to it for configuration and setup.
|
||||
|
||||
import MkdirComponent from '!!raw-loader!./_kustomize/script-02-kustomize/mkdir-component.sh';
|
||||
import HttpbinComponentHeader from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-component-header.sh';
|
||||
import HttpbinComponentBody from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-component-body.cue';
|
||||
import EofTrailer from '!!raw-loader!./_kustomize/script-02-kustomize/eof-trailer.sh';
|
||||
import HttpbinYamlHeader from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-yaml-header.sh';
|
||||
import HttpbinYamlBody from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-yaml-body.yaml';
|
||||
|
||||
<Tabs groupId="800C3AE7-E7F8-4AFC-ABF1-6AFECD945958">
|
||||
<TabItem value="setup" label="Setup">
|
||||
```bash
|
||||
mkdir -p components/httpbin
|
||||
```
|
||||
<CodeBlock language="bash">{MkdirComponent}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="components/httpbin/httpbin.cue" label="httpbin.cue">
|
||||
```bash
|
||||
cat <<EOF > components/httpbin/httpbin.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
// Produce a Kustomize BuildPlan for Holos
|
||||
holos: Kustomize.BuildPlan
|
||||
|
||||
// https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/README.md
|
||||
Kustomize: #Kustomize & {
|
||||
KustomizeConfig: {
|
||||
// Files tells Holos to copy the file from the component path to the
|
||||
// temporary directory Holos uses for BuildPlan execution.
|
||||
Files: {
|
||||
"httpbin.yaml": _
|
||||
}
|
||||
CommonLabels: {
|
||||
"app.kubernetes.io/name": "httpbin"
|
||||
}
|
||||
// Kustomization represents a kustomization.yaml file in CUE. Holos
|
||||
// marshals this field into a `kustomization.yaml` while processing a
|
||||
// BuildPlan. See
|
||||
// https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
|
||||
Kustomization: {
|
||||
images: [{name: "mccutchen/go-httpbin"}]
|
||||
// Use a hidden field to compose patches easily with a struct. Hidden
|
||||
// fields are not included in exported structures.
|
||||
_patches: {}
|
||||
// Convert the hidden struct to a list.
|
||||
patches: [for x in _patches {x}]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{HttpbinComponentHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{HttpbinComponentBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="components/httpbin/httpbin.yaml" label="httpbin.yaml">
|
||||
```bash
|
||||
cat <<EOF > components/httpbin/httpbin.yaml
|
||||
```
|
||||
```yaml showLineNumbers
|
||||
# https://github.com/mccutchen/go-httpbin/blob/v2.15.0/kustomize/resources.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: httpbin
|
||||
image: mccutchen/go-httpbin
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /status/200
|
||||
port: http
|
||||
resources: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: httpbin
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
appProtocol: http
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{HttpbinYamlHeader}</CodeBlock>
|
||||
<CodeBlock language="yaml" showLineNumbers>{HttpbinYamlBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -161,56 +98,38 @@ Holos knows the `httpbin.yaml` file is part of the BuildPlan because of the
|
||||
Register `httpbin` with the platform by adding the following file to the
|
||||
platform directory.
|
||||
|
||||
```bash
|
||||
cat <<EOF > platform/httpbin.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
import RegisterComponentHeader from '!!raw-loader!./_kustomize/script-02-kustomize/register-component-header.sh';
|
||||
import RegisterComponentBody from '!!raw-loader!./_kustomize/script-02-kustomize/register-component-body.cue';
|
||||
|
||||
Platform: Components: {
|
||||
httpbin: {
|
||||
name: "httpbin"
|
||||
path: "components/httpbin"
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{RegisterComponentHeader}</CodeBlock>
|
||||
<CodeBlock language="cue">{RegisterComponentBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
|
||||
Render the platform.
|
||||
|
||||
import RenderCommand from '!!raw-loader!./_kustomize/script-02-kustomize/render.sh';
|
||||
import RegisterComponentOutput from '!!raw-loader!./_kustomize/script-02-kustomize/register-component-output.txt';
|
||||
|
||||
<Tabs groupId="B120D5D1-0EAB-41E0-AD21-15526EBDD53D">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered httpbin in 707.554666ms
|
||||
rendered platform in 707.9845ms
|
||||
```
|
||||
<CodeBlock language="txt">{RegisterComponentOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Commit the results.
|
||||
|
||||
import GitCommitComponent from '!!raw-loader!./_kustomize/script-02-kustomize/git-commit-component.sh';
|
||||
import GitCommitComponentOutput from '!!raw-loader!./_kustomize/script-02-kustomize/git-commit-component-output.txt';
|
||||
|
||||
<Tabs groupId="446CC550-A634-45C0-BEC7-992E5C56D4FA">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add . && git commit -m 'add httpbin'
|
||||
```
|
||||
<CodeBlock language="bash">{GitCommitComponent}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main c05f9ef] add httpbin
|
||||
4 files changed, 118 insertions(+)
|
||||
create mode 100644 components/httpbin/httpbin.cue
|
||||
create mode 100644 components/httpbin/httpbin.yaml
|
||||
create mode 100644 deploy/components/httpbin/httpbin.gen.yaml
|
||||
create mode 100644 platform/httpbin.cue
|
||||
```
|
||||
<CodeBlock language="txt">{GitCommitComponentOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -220,55 +139,15 @@ We can see the [BuildPlan] exported to `holos` by the `holos:
|
||||
Kustomize.BuildPlan` line in `httpbin.cue`. Holos processes this build plan to
|
||||
produce the fully rendered manifests.
|
||||
|
||||
import CueExport from '!!raw-loader!./_kustomize/script-02-kustomize/cue-export.sh';
|
||||
import BuildplanOutput from '!!raw-loader!./_kustomize/script-02-kustomize/buildplan-output.cue';
|
||||
|
||||
<Tabs groupId="DD697D65-5BEC-4B92-BB33-59BE4FEC112F">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos cue export --expression holos --out=yaml ./components/httpbin
|
||||
```
|
||||
<CodeBlock language="bash">{CueExport}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```yaml showLineNumbers
|
||||
kind: BuildPlan
|
||||
apiVersion: v1alpha5
|
||||
metadata:
|
||||
name: no-name
|
||||
spec:
|
||||
artifacts:
|
||||
- artifact: components/no-name/no-name.gen.yaml
|
||||
generators:
|
||||
- kind: Resources
|
||||
output: resources.gen.yaml
|
||||
resources: {}
|
||||
- kind: File
|
||||
output: httpbin.yaml
|
||||
file:
|
||||
source: httpbin.yaml
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
- resources.gen.yaml
|
||||
- httpbin.yaml
|
||||
output: components/no-name/no-name.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
labels:
|
||||
- includeSelectors: false
|
||||
pairs:
|
||||
app.kubernetes.io/name: httpbin
|
||||
patches: []
|
||||
images:
|
||||
- name: mccutchen/go-httpbin
|
||||
resources:
|
||||
- resources.gen.yaml
|
||||
- httpbin.yaml
|
||||
kind: Kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
source:
|
||||
component:
|
||||
name: no-name
|
||||
path: no-path
|
||||
parameters: {}
|
||||
```
|
||||
<CodeBlock language="yaml">{BuildplanOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -291,30 +170,12 @@ need to edit any YAML files manually.
|
||||
Add a new `patches.cue` file to the `httpbin` component with the following
|
||||
content.
|
||||
|
||||
```bash
|
||||
cat <<EOF > components/httpbin/patches.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
import HttpbinPatchHeader from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-patch-header.sh';
|
||||
import HttpbinPatchBody from '!!raw-loader!./_kustomize/script-02-kustomize/httpbin-patch-body.cue';
|
||||
|
||||
import "encoding/yaml"
|
||||
|
||||
// Mix in a Kustomize patch to the configuration.
|
||||
Kustomize: KustomizeConfig: Kustomization: _patches: {
|
||||
probe: {
|
||||
target: kind: "Service"
|
||||
target: name: "httpbin"
|
||||
patch: yaml.Marshal([{
|
||||
op: "add"
|
||||
path: "/metadata/annotations/prometheus.io~1probe"
|
||||
value: "true"
|
||||
}])
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
<CodeBlock language="bash">{HttpbinPatchHeader}</CodeBlock>
|
||||
<CodeBlock language="bash" showLineNumbers>{HttpbinPatchBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
|
||||
:::note
|
||||
We use a hidden `_patches` field to easily unify data into a struct, then
|
||||
@@ -325,62 +186,43 @@ convert the struct into a list for export.
|
||||
|
||||
Render the platform to see the result of the kustomization patch.
|
||||
|
||||
import KustomizePatchRenderOutput from '!!raw-loader!./_kustomize/script-02-kustomize/kustomize-patch-render-output.txt';
|
||||
|
||||
<Tabs groupId="5D1812DD-8E7B-4F97-B349-275214F38B6E">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
rendered httpbin in 197.030208ms
|
||||
rendered platform in 197.416416ms
|
||||
```
|
||||
<CodeBlock language="txt">{KustomizePatchRenderOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos is configuring Kustomize to patch the plain `httpbin.yaml` file with the
|
||||
annotation.
|
||||
|
||||
import GitDiff from '!!raw-loader!./_kustomize/script-02-kustomize/git-diff.sh';
|
||||
import GitDiffOutput from '!!raw-loader!./_kustomize/script-02-kustomize/git.diff';
|
||||
|
||||
<Tabs groupId="3D80279E-8EDE-4B3E-9269-50F5D1C1CA42">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
<CodeBlock language="bash">{GitDiff}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff
|
||||
diff --git a/deploy/components/httpbin/httpbin.gen.yaml b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
index 298b9a8..a16bd1a 100644
|
||||
--- a/deploy/components/httpbin/httpbin.gen.yaml
|
||||
+++ b/deploy/components/httpbin/httpbin.gen.yaml
|
||||
@@ -1,6 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
+ annotations:
|
||||
+ prometheus.io/probe: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: httpbin
|
||||
name: httpbin
|
||||
|
||||
```
|
||||
<CodeBlock language="diff">{GitDiffOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Add and commit the final changes.
|
||||
|
||||
import GitCommitFinal from '!!raw-loader!./_kustomize/script-02-kustomize/git-commit-final.sh';
|
||||
import GitCommitFinalOutput from '!!raw-loader!./_kustomize/script-02-kustomize/git-commit-final-output.txt';
|
||||
|
||||
<Tabs groupId="54C335C8-B382-4277-AE87-0D6556921955">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add . && git commit -m 'annotate httpbin for prometheus probes'
|
||||
```
|
||||
<CodeBlock language="bash">{GitCommitFinal}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main 6eeeadb] annotate httpbin for prometheus probes
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
```
|
||||
<CodeBlock language="txt">{GitCommitFinalOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
19
doc/md/tutorial/kustomize_test.go
Normal file
19
doc/md/tutorial/kustomize_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Run these with go test -v to see the verbose names
|
||||
func TestKustomize(t *testing.T) {
|
||||
t.Run("TestKustomize", func(t *testing.T) {
|
||||
// Get an ordered list of test script files.
|
||||
dir := "_kustomize"
|
||||
for _, file := range sortedTestScripts(t, filepath.Join(dir, "examples")) {
|
||||
t.Run("examples", func(t *testing.T) {
|
||||
runOneScript(t, dir, file)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
4
doc/website/.gitignore
vendored
4
doc/website/.gitignore
vendored
@@ -18,3 +18,7 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Auto-generated doc examples
|
||||
multi-sources-example/
|
||||
kargo-demo/
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
---
|
||||
unlisted: true
|
||||
slug: trade-in-argocd-appsets-for-rendered-manifests
|
||||
title: Trade in the complexity of ArgoCD AppSets for fully rendered manifests
|
||||
authors: [jeff]
|
||||
tags: [holos, helm, gitops]
|
||||
# image: /img/cards/validators.png
|
||||
description: Migrate an ApplicationSet to the rendered manifest pattern with Holos, removing unnecessary complexity.
|
||||
keywords:
|
||||
- Holos
|
||||
- CUE
|
||||
- Configuration
|
||||
- Structure
|
||||
- Kubernetes
|
||||
- Hydrated
|
||||
- Rendered
|
||||
- Manifest
|
||||
- Pattern
|
||||
- Unification
|
||||
- ArgoCD
|
||||
- ApplicationSet
|
||||
- Application
|
||||
- Multi Source
|
||||
- Values Hierarchy
|
||||
- Rendered Manifest Pattern
|
||||
- GitOps
|
||||
- Complexity
|
||||
---
|
||||
|
||||
Kubernetes has a reputation for being too complex. Complexity in software
|
||||
engineering is often categorized as essential or accidental. Methods to expose
|
||||
services to the internet, deploy replicas, manage secrets, configure network
|
||||
connectivity, and control access are examples of essential complexity. They're
|
||||
unavoidable no matter what tools we use.
|
||||
|
||||
Nevertheless, popular tools in the ecosystem bolster this reputation by
|
||||
accidentally piling up layers of complexity unnecessarily. For example, Helm
|
||||
value override hierarchies and ArgoCD ApplicationSet templates. Both tools
|
||||
solve challenging, pervasive problems resulting in their widespread adoption.
|
||||
Unfortunately the trade offs each one makes independently combine together
|
||||
poorly. Helm and ArgoCD ApplicationSets contribute more than their fair share
|
||||
of accidental complexity to the Kubernetes ecosystem.
|
||||
|
||||
Consider the use case of deploying different versions of the same service to
|
||||
multiple environments. An ArgoCD ApplicationSet passing sets of values to one
|
||||
Helm chart is a commonly recommended solution contributing three forms of
|
||||
accidental complexity.
|
||||
|
||||
1. There are multiple layers of Go template abstractions.
|
||||
2. Config values are silently written over at multiple layers in a hierarchy.
|
||||
3. The intermediate and final configuration is remote and out of reach.
|
||||
|
||||
The rendered manifests pattern is an alternative solution leveraging Helm and
|
||||
ArgoCD with less complexity. The pattern reduces complexity by collapsing
|
||||
multiple layers of Go templates and brings the configuration local, within our
|
||||
reach. It still relies on Helm value hierarchies when charts are reused across
|
||||
environments, so it's no silver bullet, but we'll explain in follow up post how
|
||||
Holos can eliminate the accidental complexity of a Helm value files hierarchy.
|
||||
|
||||
There is no widely agreed upon, freely available implementation of the rendered
|
||||
manifest pattern. Engineering teams have to decide whether to implement the
|
||||
pattern from scratch or stick with the more complex, but built-in features of
|
||||
Helm and ArgoCD. These few options indicate a tooling gap in the ecosystem.
|
||||
This gap pushes many organizations toward the accidental complexity of the
|
||||
ApplicationSet solution.
|
||||
|
||||
Holos fills this gap by offering a thoughtful and complete implementation of the
|
||||
rendered manifest pattern in one command line tool. This article is the first
|
||||
in a series exploring how Holos solves the same use case while avoiding the
|
||||
accidental complexity.
|
||||
|
||||
This article walks step-by-step through the process of migrating an
|
||||
ApplicationSet to Holos. I'll explain why we feel the trades we made in Holos
|
||||
are a net improvement. At the end of the article you'll see how you can
|
||||
continue leveraging GitOps with ArgoCD and Helm while gaining the ability to see
|
||||
and comprehend complex configurations clearly, with fewer layers of abstraction.
|
||||
|
||||
{/* truncate */}
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
## Layers of Complexity
|
||||
|
||||
Before diving into the step by step migration, let's explore exactly what we
|
||||
mean by accidental complexity. Consider the ApplicationSet and Helm value
|
||||
hierarchy described in the final recommendation of _[Using Helm Hierarchies in
|
||||
Multi-Source Argo CD Applications for Promoting to Different GitOps
|
||||
Environments][tfa]_. This particular ApplicationSet is a prime example because
|
||||
the approach it takes is often recommended as a solution for deploying a service
|
||||
to multiple clusters and environments.
|
||||
|
||||
Unfortunately the example provided requires us to hold _at least 7 layers of
|
||||
abstraction_ in mind while considering the impact of a change.
|
||||
|
||||
- The ApplicationSet renders an Application template for each `config.json` file.
|
||||
- Each Application `valueFiles` field introduces 5 more layers of potential overrides.
|
||||
- The Helm Chart is another layer of text templates.
|
||||
|
||||
:::important
|
||||
Consider the multiple layers of abstraction in the example provided compared
|
||||
with their replacements shown in the [Goals](#goals) section.
|
||||
:::
|
||||
|
||||
import AppSetPath from '!!raw-loader!./_migrate_appset/script-02-layers-of-complexity/appset.path';
|
||||
import AppSetYAML from '!!raw-loader!./_migrate_appset/script-02-layers-of-complexity/appset.yaml';
|
||||
import DeploymentPath from '!!raw-loader!./_migrate_appset/script-02-layers-of-complexity/deployment.path';
|
||||
import DeploymentYAML from '!!raw-loader!./_migrate_appset/script-02-layers-of-complexity/deployment.yaml';
|
||||
|
||||
<Tabs groupId="layers-of-complexity">
|
||||
<TabItem value="Application Template" label="Application Template">
|
||||
The ApplicationSet template renders a Helm template.
|
||||
<CodeBlock language="txt">{AppSetPath}</CodeBlock>
|
||||
<CodeBlock language="yaml">{AppSetYAML}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Deployment Template" label="Deployment Template">
|
||||
The Helm template renders the final Deployment configuration.
|
||||
<CodeBlock language="txt">{DeploymentPath}</CodeBlock>
|
||||
<CodeBlock language="yaml">{DeploymentYAML}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
These templates would be easier to comprehend if their intermediate state and
|
||||
final configuration were within reach. Unfortunately, it's stored in multiple
|
||||
remote repositories and processed remotely in ArgoCD. ArgoCD is like a black
|
||||
box. Intermediate state is inaccessible. The final configuration is only
|
||||
accessible after it's been applied, far too late to consider what impact a
|
||||
change might have.
|
||||
|
||||
We know the complexity is accidental because we bypass these layers when we run
|
||||
`kubectl edit`. The configuration is fetched, manipulated locally, then pushed
|
||||
back to the cluster without obfuscation.
|
||||
|
||||
We also know the complexity is real. It's too easy to make mistakes when
|
||||
configuration values are silently written over many times along the way. For
|
||||
example, we'll see how the very ApplicationSet we're migrating contains errors
|
||||
which are difficult to fix without insight a tool like `holos` provides.
|
||||
|
||||
## Goals
|
||||
|
||||
We want to eliminate as many layers of accidental complexity as possible with as
|
||||
few changes as possible. Ideally we'll be able to directly see and manipulate
|
||||
the final manifests as they will be applied to the cluster. We also want the
|
||||
migration to balance the conventions and idioms of Holos, Helm, and ArgoCD as
|
||||
much as possible.
|
||||
|
||||
1. Eliminate as many layers of accidental complexity as possible.
|
||||
2. Make as few changes as possible.
|
||||
3. Bring intermediate state and the final configuration within our reach.
|
||||
4. Use each tool idiomatically.
|
||||
|
||||
We'll relocate the unmodified Helm chart, config.json files, and value files to
|
||||
make as few changes as possible. We'll also generate Applications for ArgoCD
|
||||
identical to those generated by the ApplicationSet, but we'll do so with the
|
||||
same [CUE] layer that configures everything else in Holos.
|
||||
|
||||
The migration achieves these goals by rendering clearly readable Application and
|
||||
Deployment resources to local files for ArgoCD to sync via GitOps. Here's how
|
||||
it will look.
|
||||
|
||||
:::important
|
||||
Compare the Application and Deployment with the templates in the [Layers of
|
||||
Complexity](#layers-of-complexity) section.
|
||||
:::
|
||||
|
||||
import AppTreeCommand from '!!raw-loader!./_migrate_appset/script-05-application/tree-deploy.sh'
|
||||
import AppTreeOutput from '!!raw-loader!./_migrate_appset/script-05-application/tree-deploy.txt'
|
||||
import AppPath from '!!raw-loader!./_migrate_appset/script-05-application/app.path'
|
||||
import AppYAML from '!!raw-loader!./_migrate_appset/script-05-application/app.yaml'
|
||||
import ManifestPath from '!!raw-loader!./_migrate_appset/script-05-application/manifest.path'
|
||||
import ManifestYAML from '!!raw-loader!./_migrate_appset/script-05-application/manifest.yaml'
|
||||
|
||||
<Tabs groupId="goal-summary">
|
||||
<TabItem value="Application" label="Application">
|
||||
<CodeBlock language="yaml">
|
||||
{"# "+AppPath}
|
||||
{AppYAML}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Deployment" label="Deployment">
|
||||
<CodeBlock language="yaml">
|
||||
{"# "+ManifestPath}
|
||||
{ManifestYAML}
|
||||
</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Tree" label="Tree">
|
||||
<CodeBlock language="bash">{AppTreeCommand}</CodeBlock>
|
||||
<CodeBlock language="txt">{AppTreeOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The manifests rendered at the end of the migration achieve the goals.
|
||||
|
||||
1. The Application rendered by Holos is readable and complete, replacing the ApplicationSet template rendered remotely.
|
||||
2. The Application is equivalent to those produced by the ApplicationSet.
|
||||
3. The final configuration is within reach in local files. We'll see how Holos exposes intermediate state as we step through the migration in the next section.
|
||||
4. Both ArgoCD and Helm are used idiomatically, passing the value files to render the chart for GitOps.
|
||||
|
||||
## Migration Steps
|
||||
|
||||
We'll migrate each of the three major behaviors of the ApplicationSet to Holos
|
||||
to achieve the goals and complete the migration.
|
||||
|
||||
1. Generate an Application from a template using values provided by each `config.json` file.
|
||||
2. Render `my-chart` to a manifest by providing a hierarchy of helm values determined by `config.json` values.
|
||||
3. Reconcile the rendered manifest with the cluster state.
|
||||
|
||||
We'll start by loading the `config.json` environment data files into CUE without
|
||||
modifying the original data. Then we'll manage a Holos [Platform] [Component]
|
||||
for each environment. We'll wrap `my-chart` in a component definition
|
||||
and pass the value hierarchy to `helm template` the same as ArgoCD does.
|
||||
Finally, we'll mix an ArgoCD Application into each platform component to achieve
|
||||
the same output as the ApplicationSet.
|
||||
|
||||
Along the way we'll see how Holos eliminates accidental complexity and makes it
|
||||
easier to work with the intermediate and final configuration.
|
||||
|
||||
### Initial Setup
|
||||
|
||||
The main branch of the [multi-sources-example] is a fork of the example code
|
||||
from the original article that has already been migrated. We'll roll back to
|
||||
the fork point then step through each of the commits to complete the migration.
|
||||
|
||||
First, clone the repository.
|
||||
|
||||
import GitCloneCommand from '!!raw-loader!./_migrate_appset/script-01-clone/clone.sh';
|
||||
import GitCloneOutput from '!!raw-loader!./_migrate_appset/script-01-clone/clone.txt';
|
||||
|
||||
<Tabs groupId="clone">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{GitCloneCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="txt">{GitCloneOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Then, reset to where it was forked from upstream.
|
||||
|
||||
import GitResetCommand from '!!raw-loader!./_migrate_appset/script-01-clone/reset.sh';
|
||||
import GitResetOutput from '!!raw-loader!./_migrate_appset/script-01-clone/reset.txt';
|
||||
|
||||
|
||||
<Tabs groupId="reset">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{GitResetCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="txt">{GitResetOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
[Install Holos] if you haven't already. This article has been tested with version:
|
||||
|
||||
import HolosVersionCmd from '!!raw-loader!./_migrate_appset/script-01-clone/version.sh';
|
||||
import HolosVersionTxt from '!!raw-loader!./_migrate_appset/script-01-clone/version.txt';
|
||||
|
||||
|
||||
<Tabs groupId="version">
|
||||
<TabItem value="Version" label="Version">
|
||||
<CodeBlock language="txt">{HolosVersionTxt}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{HolosVersionCmd}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Holos Structure
|
||||
|
||||
Holos is organized for use as a GitOps repository. The main folders are:
|
||||
|
||||
| Folder | Description |
|
||||
| - | - |
|
||||
| platform | Entry point for `holos render platform` which renders all manifests. |
|
||||
| config | Configuration data, we'll move the `config.json` files here. |
|
||||
| components | Component definitions live here. Components produce build plans for `holos` to render manifests. We'll wrap `my-chart` in a reusable component definition. |
|
||||
| deploy | Fully rendered manifests are written here for ArgoCD to sync. |
|
||||
| cue.mod | [CUE] type definitions and schemas reside here. |
|
||||
|
||||
|
||||
Initialize the platform.
|
||||
|
||||
import HolosInit from '!!raw-loader!./_migrate_appset/script-03-holos-structure/holos-init.sh';
|
||||
|
||||
<CodeBlock language="bash">{"# --force is necessary when the current directory is not empty\n"+HolosInit}</CodeBlock>
|
||||
|
||||
Now that we've initialized the current directory as a Holos platform repository
|
||||
we can move the example files from the original article into their conventional
|
||||
locations in Holos.
|
||||
|
||||
import MoveFiles from '!!raw-loader!./_migrate_appset/script-03-holos-structure/move-files-around.sh';
|
||||
|
||||
<CodeBlock language="bash">{MoveFiles}</CodeBlock>
|
||||
|
||||
### Environment Configs
|
||||
|
||||
The ApplicationSet generators field iterates over 8 config.json files to
|
||||
instantiate each Application from the spec.template field. We'll migrate this
|
||||
to a similar mechanism in Holos by using CUE's `@embed` feature to load the same
|
||||
files into one struct. We'll manage one Helm Component for each config.json
|
||||
value in the struct. This struct will reside in the `config` field of the
|
||||
`environments` package. Like Go, CUE supports package imports for reuse.
|
||||
|
||||
These `config.json` files moved to the `config/environments/` folder. The
|
||||
`config` folder is the conventional place in Holos for reusable config values
|
||||
like these.
|
||||
|
||||
:::important
|
||||
Holos offers one unified layer with CUE to configure an entire platform
|
||||
holistically, different from other tools like Helm and Kustomize.
|
||||
:::
|
||||
|
||||
Here's how the environments package is defined in CUE.
|
||||
|
||||
import EnvironmentsPackageHeader from '!!raw-loader!./_migrate_appset/script-03-holos-structure/environments-header.sh';
|
||||
import EnvironmentsPackageBody from '!!raw-loader!./_migrate_appset/script-03-holos-structure/environments.cue';
|
||||
import EnvironmentsPackageTrailer from '!!raw-loader!./_migrate_appset/script-03-holos-structure/environments-trailer.sh';
|
||||
|
||||
<CodeBlock language="bash">{EnvironmentsPackageHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{EnvironmentsPackageBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EnvironmentsPackageTrailer}</CodeBlock>
|
||||
|
||||
We moved the original `config.json` files without modifying them, then used
|
||||
CUE's `@embed` feature to load them into the `config` struct. This structure is
|
||||
accessible in CUE by importing the `environments` package, then referencing
|
||||
`environments.config`.
|
||||
|
||||
:::tip
|
||||
Holos and CUE offer fast, local query and manipulation of your configuration
|
||||
data, even in intermediate states.
|
||||
:::
|
||||
|
||||
Here's how the environments package exports to YAML. `cue export` and `cue
|
||||
eval` are handy ways to query intermediate state.
|
||||
|
||||
import InspectEnvironmentsCommand from '!!raw-loader!./_migrate_appset/script-03-holos-structure/inspect-environments.sh';
|
||||
import InspectEnvironmentsOutput from '!!raw-loader!./_migrate_appset/script-03-holos-structure/inspect-environments.txt';
|
||||
|
||||
<Tabs groupId="inspect-environments">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{InspectEnvironmentsCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="yaml" showLineNumbers>{InspectEnvironmentsOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::important
|
||||
CUE populates the `config` field on the first line of output from the `config: _ @embed(...)`
|
||||
lines in `environments.cue`.
|
||||
:::
|
||||
|
||||
Holos and CUE offer multiple improvements over the ApplicationSet we're
|
||||
migrating from.
|
||||
|
||||
1. **Validation** - Each `config.json` file is validated against the `#Config` schema we defined.
|
||||
2. **Ergonomics** - Holos enables fast, local queries over one unified
|
||||
configuration. The data is at hand. We don't need a controller running in a
|
||||
remote cluster. We can query the intermediate config data structure, improving
|
||||
our ability to troubleshoot problems the same way an interactive debugger gives
|
||||
access to intermediate state.
|
||||
3. **Flexibility** - We're no longer locked into ArgoCD functionality. The
|
||||
`environments` package can be imported and re-used across the unified platform
|
||||
configuration layer. We're able to continue processing the rendered manifests
|
||||
with other tools beyond just ArgoCD.
|
||||
|
||||
We've successfully migrated the ApplicationSet generator field to Holos. Next,
|
||||
we'll iterate over this structure to render `my-chart` for each environment.
|
||||
|
||||
### Rendering my-chart
|
||||
|
||||
The next step is to render `my-chart` into complete configuration manifests.
|
||||
Holos implements the same behavior as the Application's `spec.sources.helm`
|
||||
field. Both tools use Helm to render the chart. Holos is different though, it
|
||||
offers a flexible way to transform and validate the output of Helm, then stops
|
||||
once the manifest is written to a local file. ArgoCD doesn't persist rendered
|
||||
manifests, instead it applies them directly to the cluster.
|
||||
|
||||
Where Holos stops is another major difference from ArgoCD and all other tools
|
||||
operating as a controller in the cluster. Holos is designed for GitOps and
|
||||
integration with the rest of the Kubernetes ecosystem. Holos stops after it
|
||||
writes manifests to local files. This clear cut responsibility leaves ample
|
||||
space for subsequent automated workflow operating on the configuration Holos
|
||||
produces.
|
||||
|
||||
For example, consider a progressive delivery pipeline at the right side of this
|
||||
diagram to incrementally roll out configuration changes. ApplicationSets with a
|
||||
Helm source prevents this kind of integration. Holos with an Application Git
|
||||
source enables this kind of integration.
|
||||
|
||||
import RenderingOverview from '@site/src/diagrams/rendering-overview.mdx';
|
||||
|
||||
<RenderingOverview />
|
||||
|
||||
ArgoCD pairs well with other ecosystem tools when it keeps to what it does best:
|
||||
drift detection and reconciliation following GitOps principles. ArgoCD locks
|
||||
out other tools when it renders manifests. The configuration is transient and
|
||||
locked away in the cluster.
|
||||
|
||||
:::important
|
||||
Holos renders `my-chart` to local files, one for each of the environment configs
|
||||
we migrated to the `environments` package.
|
||||
:::
|
||||
|
||||
### Platform Components
|
||||
|
||||
The primary entrypoint for Holos is the `platform/` directory. The `holos
|
||||
render platform` command processes a [Platform] specification exported by CUE
|
||||
from this directory.
|
||||
|
||||
Each Application produced by the ApplicationSet we're migrating maps to a
|
||||
[Component] listed in the `Platform.spec.components` field. Here's how the
|
||||
components are added to the Platform in CUE.
|
||||
|
||||
{/* 987df87 add platform components to replace ApplicationSets.spec.generators */}
|
||||
|
||||
import PlatformChartHeader from '!!raw-loader!./_migrate_appset/script-04-helm-component/platform-my-chart-header.sh';
|
||||
import PlatformChartBody from '!!raw-loader!./_migrate_appset/script-04-helm-component/platform-my-chart.cue';
|
||||
import PlatformChartTrailer from '!!raw-loader!./_migrate_appset/script-04-helm-component/platform-my-chart-trailer.sh';
|
||||
|
||||
<CodeBlock language="bash">{PlatformChartHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{PlatformChartBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{PlatformChartTrailer}</CodeBlock>
|
||||
|
||||
For each of the data objects defined in the `config.json` files, we define a
|
||||
field in the `Platform.Components` struct. We use a struct for convenience,
|
||||
it's easier to compose components into a struct than it is into an ordered list.
|
||||
The Platform author schema converts this struct into the `spec.components` list.
|
||||
|
||||
`#MyChart` is a schema definition acting as a reusable template. For each of
|
||||
the environment config files we build the component configuration from
|
||||
parameters. This is an example of how we compose configuration. The
|
||||
`outputBaseDir` field is composed in from the `env` field configured in the
|
||||
original `config.json` files migrated to CUE.
|
||||
|
||||
We need to add a configuration snippet so each component accepts this parameter
|
||||
and renders manifests into folders organized by environment. The use of `@tag`
|
||||
with the `OutputBaseDir` field indicates the field value is provided by the
|
||||
Platform spec when we run `holos render platform`.
|
||||
|
||||
import ComponentConfigHeader from '!!raw-loader!./_migrate_appset/script-04-helm-component/componentconfig-header.sh';
|
||||
import ComponentConfigBody from '!!raw-loader!./_migrate_appset/script-04-helm-component/componentconfig.cue';
|
||||
import ComponentConfigTrailer from '!!raw-loader!./_migrate_appset/script-04-helm-component/componentconfig-trailer.sh';
|
||||
|
||||
<CodeBlock language="bash">{ComponentConfigHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{ComponentConfigBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{ComponentConfigTrailer}</CodeBlock>
|
||||
|
||||
We can gain insight into how `holos` renders the helm charts from the
|
||||
`config.json` files with the following command. CUE exports the `Platform`
|
||||
specification to `holos`, which iterates over each of the listed components to
|
||||
produce a `BuildPlan`.
|
||||
|
||||
import ShowPlatformCommand from '!!raw-loader!./_migrate_appset/script-04-helm-component/holos-show-platform.sh';
|
||||
import ShowPlatformOutput from '!!raw-loader!./_migrate_appset/script-04-helm-component/holos-show-platform.txt';
|
||||
|
||||
<Tabs groupId="show-platform">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{ShowPlatformCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="yaml" showLineNumbers>{ShowPlatformOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Component Definition
|
||||
|
||||
The next step is to wrap `my-chart` in a Holos [Helm] component definition.
|
||||
Here's how:
|
||||
|
||||
import ComponentHeader from '!!raw-loader!./_migrate_appset/script-04-helm-component/component-my-chart-header.sh';
|
||||
import ComponentBody from '!!raw-loader!./_migrate_appset/script-04-helm-component/component-my-chart.cue';
|
||||
import ComponentFooter from '!!raw-loader!./_migrate_appset/script-04-helm-component/component-my-chart-trailer.sh';
|
||||
|
||||
<CodeBlock language="bash">{ComponentHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{ComponentBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{ComponentFooter}</CodeBlock>
|
||||
|
||||
Note how each parameter we added in the Platform spec is reflected in the
|
||||
component definition with a `@tag`. These are CUE build tags, and the mechanism
|
||||
by which parameters are passed from `holos render platform` to each component.
|
||||
|
||||
Similar to the `config.json` files we migrated, we moved the Helm value files
|
||||
without modifying them. These files are loaded into one struct in CUE using
|
||||
`valueFiles: _ @embed(...)`.
|
||||
|
||||
Like the Platform spec, we can inspect the BuildPlans `holos` executes to render
|
||||
each component to manifest files.
|
||||
|
||||
import ShowBuildPlansCmd from '!!raw-loader!./_migrate_appset/script-04-helm-component/show-buildplans.sh'
|
||||
import ShowBuildPlansOut from '!!raw-loader!./_migrate_appset/script-04-helm-component/show-buildplans.txt'
|
||||
|
||||
<Tabs groupId="show-buildplans">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{ShowBuildPlansCmd}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="yaml" showLineNumbers>{ShowBuildPlansOut}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We can also inspect intermediate configuration like the `valueFiles` struct.
|
||||
|
||||
import ValueFilesCommand from '!!raw-loader!./_migrate_appset/script-04-helm-component/inspect-value-files.sh'
|
||||
import ValueFilesOutput from '!!raw-loader!./_migrate_appset/script-04-helm-component/inspect-value-files.txt'
|
||||
|
||||
<Tabs groupId="inspect-value-files">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{ValueFilesCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="yaml" showLineNumbers>{ValueFilesOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Render the platform to render `my-chart` for each of the configured
|
||||
environments.
|
||||
|
||||
import RenderCommand from '!!raw-loader!./_migrate_appset/script-04-helm-component/render.sh'
|
||||
import RenderOutput from '!!raw-loader!./_migrate_appset/script-04-helm-component/render.txt'
|
||||
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
<CodeBlock language="txt">{RenderOutput}</CodeBlock>
|
||||
|
||||
Holos processes the Platform spec.components field concurrently, rendering each
|
||||
environment to a manifest file into the `deploy` folder. The output looks like:
|
||||
|
||||
import TreeCommand from '!!raw-loader!./_migrate_appset/script-04-helm-component/tree-deploy.sh'
|
||||
import TreeOutput from '!!raw-loader!./_migrate_appset/script-04-helm-component/tree-deploy.txt'
|
||||
|
||||
<Tabs groupId="tree-deploy">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{TreeCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="txt">{TreeOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### ArgoCD Application
|
||||
|
||||
At this point we're rendering `my-chart` with Holos for each environment. The
|
||||
intermediate and final configuration is within our reach. The final step is to
|
||||
render an Application resource for each environment like the original
|
||||
ApplicationSet did.
|
||||
|
||||
Holos offers [ComponentConfig] for the purpose of mixing in configuration to
|
||||
components. The feature is often used to pass each component through
|
||||
`kustomize` to add common labels and annotations. It's also used to mix in
|
||||
GitOps resources like ArgoCD Applications and Flux Kustomizations.
|
||||
|
||||
Here's how to add an Application for every one of the `Platform` components:
|
||||
|
||||
{/* d9125b8 compose argocd application resources into every component */}
|
||||
|
||||
import ComponentConfigGitOpsHeader from '!!raw-loader!./_migrate_appset/script-05-application/componentconfig-gitops-header.sh';
|
||||
import ComponentConfigGitOpsBody from '!!raw-loader!./_migrate_appset/script-05-application/componentconfig-gitops.cue';
|
||||
import ComponentConfigGitOpsTrailer from '!!raw-loader!./_migrate_appset/script-05-application/componentconfig-gitops-trailer.sh';
|
||||
|
||||
<CodeBlock language="bash">{ComponentConfigGitOpsHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{ComponentConfigGitOpsBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{ComponentConfigGitOpsTrailer}</CodeBlock>
|
||||
|
||||
More information about how this works is available in the following pages. For
|
||||
now, it's sufficient to know the ComponentConfig is something we usually set and
|
||||
forget.
|
||||
|
||||
1. [ComponentConfig]
|
||||
2. [GitOps](/docs/v1alpha5/topics/gitops/)
|
||||
|
||||
Now we can render the platform and see each of the Application manifest files.
|
||||
They go into a `gitops` folder so it easy to apply them individually or all at
|
||||
once for ArgoCD to sync the component manifests.
|
||||
|
||||
import AppRenderCommand from '!!raw-loader!./_migrate_appset/script-05-application/render.sh'
|
||||
import AppRenderOutput from '!!raw-loader!./_migrate_appset/script-05-application/render.txt'
|
||||
|
||||
<CodeBlock language="bash">{AppRenderCommand}</CodeBlock>
|
||||
<CodeBlock language="txt">{AppRenderOutput}</CodeBlock>
|
||||
|
||||
<Tabs groupId="tree-deploy-with-application">
|
||||
<TabItem value="Command" label="Command">
|
||||
<CodeBlock language="bash">{AppTreeCommand}</CodeBlock>
|
||||
</TabItem>
|
||||
<TabItem value="Output" label="Output">
|
||||
<CodeBlock language="txt">{AppTreeOutput}</CodeBlock>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The Applications are also fully rendered.
|
||||
|
||||
<CodeBlock language="txt">{AppPath}</CodeBlock>
|
||||
<CodeBlock language="yaml">{AppYAML}</CodeBlock>
|
||||
|
||||
Note how the Application resources Holos produces are easier to read and
|
||||
understand than the original ApplicationSet.
|
||||
|
||||
1. There is no templating.
|
||||
2. There is no helm source, no value hierarchy to comprehend.
|
||||
|
||||
We also have the fully rendered manifest clearly readable and within reach locally.
|
||||
|
||||
<CodeBlock language="yaml">{"# "+ManifestPath+ManifestYAML}</CodeBlock>
|
||||
|
||||
## Wrapping it all up
|
||||
|
||||
1. The manifests are fully rendered and within our reach.
|
||||
2. The Application is clear and at-hand.
|
||||
3. We now have a unified platform configuration layer.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Part 2 - Why are there 8 config.json files but only 7 components rendered? There's a bug!
|
||||
- Part 3 - Can we eliminate the layers of helm value overrides? Yes!
|
||||
- Part 4 - Progressive Delivery. Maybe?
|
||||
|
||||
[tfa]: https://medium.com/containers-101/using-helm-hierarchies-in-multi-source-argo-cd-applications-for-promoting-to-different-gitops-133c3bc93678
|
||||
[ApplicationSet]: https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml
|
||||
[multi-sources-example]: https://github.com/holos-run/multi-sources-example
|
||||
[Platform]: https://holos.run/docs/api/core/#Platform
|
||||
[Component]: https://holos.run/docs/api/core/#Component
|
||||
[ComponentConfig]: https://holos.run/docs/api/author/#ComponentConfig
|
||||
[Helm]: https://holos.run/docs/api/core/#Helm
|
||||
[CUE]: https://cuelang.org
|
||||
[Install Holos]: https://holos.run/docs/setup/
|
||||
37
doc/website/blog/_migrate_appset/examples/01-clone.txtar
Normal file
37
doc/website/blog/_migrate_appset/examples/01-clone.txtar
Normal file
@@ -0,0 +1,37 @@
|
||||
# This doc tested with holos version...
|
||||
exec bash -c 'bash -euo pipefail $WORK/version.sh 2>&1'
|
||||
cmp stdout version.txt
|
||||
|
||||
# Remove the directory if it already exists
|
||||
exec rm -rf multi-sources-example
|
||||
# Clone the repository
|
||||
exec bash -c 'bash -euo pipefail $WORK/clone.sh 2>&1'
|
||||
cmp stdout clone.txt
|
||||
|
||||
# Get the git commit
|
||||
cd multi-sources-example
|
||||
exec git rev-parse --verify origin/HEAD
|
||||
cp stdout $WORK/git.commit
|
||||
|
||||
# Reset to TFA 4-final recommendation
|
||||
exec bash -c 'bash -euo pipefail $WORK/reset.sh 2>&1'
|
||||
cmp stdout $WORK/reset.txt
|
||||
|
||||
# Set the committer
|
||||
exec git config user.email go-test@example.com
|
||||
exec git config user.name 'go test'
|
||||
|
||||
-- version.sh --
|
||||
holos --version
|
||||
-- version.txt --
|
||||
0.103.0
|
||||
-- clone.sh --
|
||||
git clone https://github.com/holos-run/multi-sources-example.git
|
||||
cd multi-sources-example
|
||||
-- clone.txt --
|
||||
Cloning into 'multi-sources-example'...
|
||||
-- reset.sh --
|
||||
git branch -f work start
|
||||
git checkout work
|
||||
-- reset.txt --
|
||||
Switched to branch 'work'
|
||||
@@ -0,0 +1,25 @@
|
||||
# Work in the root of the example repo
|
||||
cd ../script-01-clone/multi-sources-example
|
||||
|
||||
# Reset to where 01-clone left us.
|
||||
exec git clean -fdx
|
||||
exec git reset --hard start
|
||||
|
||||
# Consider the ApplicationSet from the final recommendation...
|
||||
exec bash -c 'cat $(<$WORK/appset.path)'
|
||||
cp stdout $WORK/appset.yaml
|
||||
|
||||
# The Deployment
|
||||
exec bash -c 'cat $(<$WORK/deployment.path)'
|
||||
cp stdout $WORK/deployment.yaml
|
||||
|
||||
# The Service
|
||||
exec bash -c 'cat $(<$WORK/service.path)'
|
||||
cp stdout $WORK/service.yaml
|
||||
|
||||
-- appset.path --
|
||||
appsets/4-final/all-my-envs-appset-with-version.yaml
|
||||
-- service.path --
|
||||
my-chart/templates/service.yaml
|
||||
-- deployment.path --
|
||||
my-chart/templates/deployment.yaml
|
||||
@@ -0,0 +1,83 @@
|
||||
# Work in the root of the example repo
|
||||
cd ../script-01-clone/multi-sources-example
|
||||
|
||||
# 7ce4feb initialize the platform
|
||||
exec bash -c 'bash -euo pipefail $WORK/holos-init.sh 2>&1'
|
||||
|
||||
# f7102d6 reorganize to conventional holos layout
|
||||
exec bash -c 'bash -euo pipefail $WORK/move-files-around.sh 2>&1'
|
||||
|
||||
# 49183ca git mv appsets/4-final/env-config config/environments
|
||||
# Note, the v0.3.0 tag contains the environments.cue prior to being updated to
|
||||
# fix the duplicated config.json file. Commit 1a73e77b fixes this issue as a
|
||||
# later migration step.
|
||||
exec cat $WORK/environments-header.sh $WORK/environments.cue $WORK/environments-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
|
||||
# Inspect the structure
|
||||
exec bash -c 'bash -euo pipefail $WORK/inspect-environments.sh 2>&1'
|
||||
cp stdout $WORK/inspect-environments.txt
|
||||
|
||||
-- holos-init.sh --
|
||||
holos init platform v1alpha5 --force
|
||||
-- move-files-around.sh --
|
||||
# First, we'll move my-chart the original article vendored in
|
||||
# Git to the conventional location Holos uses to vendor charts.
|
||||
mkdir -p components/my-chart/vendor/0.1.0
|
||||
git mv my-chart components/my-chart/vendor/0.1.0/my-chart
|
||||
|
||||
# Helm value files move into the directory that will contain
|
||||
# my-chart component definition. components/my-chart is
|
||||
# conventionally called the "my-chart component directory"
|
||||
git mv my-values components/my-chart/my-values
|
||||
|
||||
# The config.json files are moved without changing their folder structure.
|
||||
# We'll package the data up into an "environments config package" for reuse.
|
||||
mkdir config
|
||||
git mv appsets/4-final/env-config config/environments
|
||||
|
||||
# All of our components will reside in the components directory so
|
||||
# the CUE files `holos init` produced may be moved to keep the
|
||||
# repository root tidy.
|
||||
mv *.cue components/
|
||||
|
||||
# The following files and directories from the original article and
|
||||
# holos init are no longer relevant after the migration.
|
||||
mkdir not-used
|
||||
git mv appsets not-used/appsets
|
||||
git mv example-apps not-used/example-apps
|
||||
rm -f platform.metadata.json
|
||||
|
||||
# Make the commit
|
||||
git add platform components cue.mod .gitignore
|
||||
git commit -m 'reorganize to conventional holos layout'
|
||||
-- environments-header.sh --
|
||||
cat <<'EOF' > config/environments/environments.cue
|
||||
-- environments.cue --
|
||||
@extern(embed)
|
||||
package environments
|
||||
|
||||
// We use cue embed functionality as an equivalent replacement for
|
||||
// ApplicationSet generators.
|
||||
config: _ @embed(glob=*/config.json)
|
||||
config: _ @embed(glob=staging/*/config.json)
|
||||
config: _ @embed(glob=prod/*/config.json)
|
||||
config: _ @embed(glob=integration/*/config.json)
|
||||
|
||||
// With CUE we can constrain the data with a schema.
|
||||
config: [FILEPATH=string]: #Config
|
||||
|
||||
// #Config defines the schema of each config.json file.
|
||||
#Config: {
|
||||
env: "qa" | "integration-gpu" | "integration-non-gpu" | "staging-us" | "staging-eu" | "prod-us" | "prod-eu"
|
||||
region: "us" | "eu"
|
||||
type: "prod" | "non-prod"
|
||||
version: "qa" | "staging" | "prod"
|
||||
chart: =~"^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
}
|
||||
-- environments-trailer.sh --
|
||||
EOF
|
||||
-- inspect-environments.sh --
|
||||
CUE_EXPERIMENT=embed holos cue export --out=yaml \
|
||||
./config/environments
|
||||
@@ -0,0 +1,205 @@
|
||||
# Work in the root of the example repo
|
||||
cd ../script-01-clone/multi-sources-example
|
||||
env HOME=$WORK/.tmp
|
||||
chmod 0755 $WORK/update.sh
|
||||
|
||||
# 987df87 add platform components to replace ApplicationSets.spec.generators
|
||||
exec cat $WORK/platform-my-chart-header.sh $WORK/platform-my-chart.cue $WORK/platform-my-chart-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
exec diff platform/my-chart.cue $WORK/platform-my-chart.cue
|
||||
|
||||
# Configure where manifests are written.
|
||||
exec cat $WORK/componentconfig-header.sh $WORK/componentconfig.cue $WORK/componentconfig-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
exec diff components/componentconfig.cue $WORK/componentconfig.cue
|
||||
|
||||
# Show the platform
|
||||
exec bash -c 'bash -euo pipefail $WORK/holos-show-platform.sh 2>&1'
|
||||
cp stdout $WORK/holos-show-platform.txt
|
||||
|
||||
# Component Definition
|
||||
exec cat $WORK/component-my-chart-header.sh $WORK/component-my-chart.cue $WORK/component-my-chart-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
exec diff components/my-chart/my-chart.cue $WORK/component-my-chart.cue
|
||||
|
||||
# Show the BuildPlans
|
||||
exec bash -c 'bash -euo pipefail $WORK/show-buildplans.sh 2>&1'
|
||||
cp stdout $WORK/show-buildplans.txt
|
||||
|
||||
# Inspect the values
|
||||
exec bash -c 'bash -euo pipefail $WORK/inspect-value-files.sh 2>&1'
|
||||
cp stdout $WORK/inspect-value-files.txt
|
||||
|
||||
# Render the platform, capture stdout, and use update.sh to gate whether the
|
||||
# output file should be updated.
|
||||
exec bash -c 'bash -euo pipefail $WORK/render.sh 2>&1'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/render.txt
|
||||
|
||||
exec bash -c 'bash -euo pipefail $WORK/tree-deploy.sh 2>&1'
|
||||
cp stdout $WORK/tree-deploy.txt
|
||||
|
||||
# Make a commit
|
||||
exec git add .
|
||||
exec git commit -m '04-helm-component.txtar'
|
||||
|
||||
-- tree-deploy.sh --
|
||||
tree deploy
|
||||
-- render.sh --
|
||||
holos render platform
|
||||
-- update.sh --
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
-- show-buildplans.sh --
|
||||
holos show buildplans
|
||||
-- inspect-value-files.sh --
|
||||
CUE_EXPERIMENT=embed holos cue export --out=yaml \
|
||||
./components/my-chart \
|
||||
-e valueFiles
|
||||
-- component-my-chart-header.sh --
|
||||
cat <<'EOF' > components/my-chart/my-chart.cue
|
||||
-- component-my-chart-trailer.sh --
|
||||
EOF
|
||||
-- component-my-chart.cue --
|
||||
@extern(embed)
|
||||
package holos
|
||||
|
||||
import "holos.example/config/environments"
|
||||
|
||||
parameters: {
|
||||
environments.#Config & {
|
||||
env: _ @tag(env)
|
||||
region: _ @tag(region)
|
||||
type: _ @tag(type)
|
||||
version: _ @tag(version)
|
||||
chart: _ @tag(chart)
|
||||
}
|
||||
}
|
||||
|
||||
// component represents the holos component definition, which produces a
|
||||
// BuildPlan for holos to execute, rendering the manifests.
|
||||
component: #Helm & {
|
||||
Chart: {
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L25
|
||||
version: parameters.chart
|
||||
repository: {
|
||||
name: "multi-sources-example"
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L23
|
||||
url: "https://kostis-codefresh.github.io/multi-sources-example"
|
||||
}
|
||||
}
|
||||
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L40
|
||||
// We use kustomize to manage the namespace, similar to how the original
|
||||
// article uses the ApplicationSet template to specify the namespace.
|
||||
KustomizeConfig: Kustomization: namespace: parameters.env
|
||||
|
||||
// Migrate the Helm Hierarchy preserving the behavior of over writing values.
|
||||
// Migrated from [valueFiles]. Later files win.
|
||||
//
|
||||
// [valueFiles]: https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L27-L32
|
||||
ValueFiles: [{
|
||||
name: "common-values.yaml"
|
||||
values: valueFiles["my-values/common-values.yaml"]
|
||||
}, {
|
||||
name: "version-values.yaml"
|
||||
values: valueFiles["my-values/app-version/\(parameters.version)-values.yaml"]
|
||||
}, {
|
||||
name: "type-values.yaml"
|
||||
values: valueFiles["my-values/env-type/\(parameters.type)-values.yaml"]
|
||||
}, {
|
||||
name: "region-values.yaml"
|
||||
values: valueFiles["my-values/regions/\(parameters.region)-values.yaml"]
|
||||
}, {
|
||||
name: "env-values.yaml"
|
||||
values: valueFiles["my-values/envs/\(parameters.env)-values.yaml"]
|
||||
}]
|
||||
}
|
||||
|
||||
// holos represents the output for the holos command line to process. The holos
|
||||
// command line processes a BuildPlan to render the helm chart component.
|
||||
//
|
||||
// Use the holos show buildplans command to see the BuildPlans that holos render
|
||||
// platform renders.
|
||||
holos: component.BuildPlan
|
||||
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L27-L32
|
||||
valueFiles: _ @embed(glob=my-values/*.yaml)
|
||||
valueFiles: _ @embed(glob=my-values/*/*-values.yaml)
|
||||
-- holos-show-platform.sh --
|
||||
holos show platform
|
||||
-- componentconfig-header.sh --
|
||||
cat <<'EOF' > components/componentconfig.cue
|
||||
-- componentconfig-trailer.sh --
|
||||
EOF
|
||||
-- componentconfig.cue --
|
||||
package holos
|
||||
|
||||
#ComponentConfig: {
|
||||
// Inject the output base directory from platform component parameters.
|
||||
OutputBaseDir: string | *"" @tag(outputBaseDir, type=string)
|
||||
}
|
||||
-- platform-my-chart-header.sh --
|
||||
cat <<'EOF' > platform/my-chart.cue
|
||||
-- platform-my-chart-trailer.sh --
|
||||
EOF
|
||||
-- platform-my-chart.cue --
|
||||
package holos
|
||||
|
||||
// Imports ./config/environments/*.cue as the environments cue package. The
|
||||
// package exposes ./config/environments/**/config.json files via the
|
||||
// environments.config struct
|
||||
import "holos.example/config/environments"
|
||||
|
||||
// Manage my-chart for each of the three environments. Platform components are
|
||||
// rendered by the holos render platform command.
|
||||
//
|
||||
// Use the following command command to inspect the Platform spec holos render
|
||||
// platform processes.
|
||||
//
|
||||
// holos show platform
|
||||
//
|
||||
// CONFIG represents each migrated environments/**/config.json file.
|
||||
for CONFIG in environments.config {
|
||||
// Add one holos component for each config.json file to the
|
||||
// Platform.spec.components list.
|
||||
Platform: Components: "\(CONFIG.env)-my-chart": #MyChart & {
|
||||
parameters: {
|
||||
env: CONFIG.env
|
||||
region: CONFIG.region
|
||||
type: CONFIG.type
|
||||
version: CONFIG.version
|
||||
chart: CONFIG.chart
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #MyChart defines a re-usable way to manage my-chart across qa, staging, and
|
||||
// production.
|
||||
#MyChart: {
|
||||
name: "my-chart"
|
||||
path: "components/my-chart"
|
||||
// CUE supports constraints, here we constrain environment to one of three
|
||||
// possible values.
|
||||
parameters: {
|
||||
// Embed the config.json schema (env, region, type, version, chart fields)
|
||||
environments.#Config
|
||||
|
||||
// Define the env field here as any value (_) so we can refer to it.
|
||||
// Otherwise cue complains #MyChart.parameters.outputBaseDir: reference
|
||||
// "env" not found
|
||||
env: _
|
||||
// Write output manifests organized by environment env in this case refers
|
||||
// to the env field defined by environments.#Config
|
||||
outputBaseDir: "environments/\(env)"
|
||||
}
|
||||
// CUE supports string substitution.
|
||||
annotations: "app.holos.run/description": "my-chart \(parameters.chart) for environment \(parameters.env)"
|
||||
// Selector labels
|
||||
labels: env: parameters.env
|
||||
}
|
||||
141
doc/website/blog/_migrate_appset/examples/05-application.txtar
Normal file
141
doc/website/blog/_migrate_appset/examples/05-application.txtar
Normal file
@@ -0,0 +1,141 @@
|
||||
# Work in the root of the example repo
|
||||
cd ../script-01-clone/multi-sources-example
|
||||
chmod 0755 $WORK/update.sh
|
||||
|
||||
# d9125b8 compose argocd application resources into every component
|
||||
exec cat $WORK/componentconfig-gitops-header.sh $WORK/componentconfig-gitops.cue $WORK/componentconfig-gitops-trailer.sh
|
||||
stdin stdout
|
||||
exec bash -xeuo pipefail
|
||||
exec diff components/componentconfig-gitops.cue $WORK/componentconfig-gitops.cue
|
||||
|
||||
# Render the platform, capture stdout, and use update.sh to gate whether the
|
||||
# output file should be updated.
|
||||
exec bash -c 'bash -euo pipefail $WORK/render.sh 2>&1'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/render.txt
|
||||
|
||||
exec bash -c 'bash -euo pipefail $WORK/tree-deploy.sh 2>&1'
|
||||
cp stdout $WORK/tree-deploy.txt
|
||||
|
||||
# Show an example application
|
||||
exec bash -c 'cat $(<$WORK/app.path)'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/app.yaml
|
||||
|
||||
# Show an example manifest
|
||||
exec bash -c 'cat $(<$WORK/manifest.path)'
|
||||
stdin stdout
|
||||
exec $WORK/update.sh $WORK/manifest.yaml
|
||||
|
||||
# Make a commit
|
||||
exec git add .
|
||||
exec git commit -m '05-application.txtar'
|
||||
|
||||
-- manifest.path --
|
||||
deploy/environments/prod-us/components/my-chart/my-chart.gen.yaml
|
||||
-- app.path --
|
||||
deploy/gitops/prod-us-my-chart-application.gen.yaml
|
||||
-- tree-deploy.sh --
|
||||
tree deploy
|
||||
-- render.sh --
|
||||
holos render platform
|
||||
-- update.sh --
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
-- componentconfig-gitops-header.sh --
|
||||
cat <<'EOF' > components/componentconfig-gitops.cue
|
||||
-- componentconfig-gitops-trailer.sh --
|
||||
EOF
|
||||
-- componentconfig-gitops.cue --
|
||||
package holos
|
||||
|
||||
import (
|
||||
"path"
|
||||
app "argoproj.io/application/v1alpha1"
|
||||
)
|
||||
|
||||
parameters: {
|
||||
env: string @tag(env)
|
||||
}
|
||||
|
||||
// #ComponentConfig composes configuration into every Holos Component. Here we
|
||||
// compose an ArgoCD Application resource along side each component to reconcile
|
||||
// the hydrated manifests with the cluster.
|
||||
#ComponentConfig: {
|
||||
Name: _
|
||||
OutputBaseDir: _
|
||||
// Application resources are Environment scoped. Note the combination of
|
||||
// component name and environment must be unique.
|
||||
_ArgoAppName: "\(parameters.env)-\(Name)"
|
||||
|
||||
// Allow other aspects of the platform configuration to refer to
|
||||
// `Component._ArgoApplication` to get a handle on the Application resource
|
||||
// and mix additional configuration in.
|
||||
_ArgoApplication: app.#Application & {
|
||||
metadata: name: _ArgoAppName
|
||||
metadata: namespace: "argocd"
|
||||
metadata: labels: Labels
|
||||
// Label the Application with the env so we can easily filter in the UI.
|
||||
metadata: labels: env: parameters.env
|
||||
spec: {
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L40
|
||||
destination: server: "https://kubernetes.default.svc"
|
||||
destination: namespace: parameters.env
|
||||
project: "default"
|
||||
// source migrated from sources
|
||||
// https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L22-L35
|
||||
source: {
|
||||
path: string | *ResourcesPath
|
||||
repoURL: "https://github.com/holos-run/multi-sources-example"
|
||||
targetRevision: string | *"main"
|
||||
}
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L43-L48
|
||||
syncPolicy: syncOptions: ["CreateNamespace=true"]
|
||||
syncPolicy: automated: prune: true
|
||||
syncPolicy: automated: selfHeal: true
|
||||
}
|
||||
}
|
||||
|
||||
// We combine all Application resources into the deploy/gitops/ folder
|
||||
// assuming Application.metadata.name is unique. This makes it easy to apply
|
||||
// all of the hydrated Application resources in one shot.
|
||||
let ArtifactPath = path.Join(["gitops", "\(_ArgoApplication.metadata.name)-application.gen.yaml"], path.Unix)
|
||||
// Alternatively we could write the Applications along side the OutputBaseDir
|
||||
// let ArtifactPath = path.Join([OutputBaseDir, "gitops", "\(Name)-application.gen.yaml"], path.Unix)
|
||||
|
||||
// ResourcesPath represents the configuration path the Application is
|
||||
// configured to read as a source. This path contains the fully rendered
|
||||
// manifests produced by Holos and written to the GitOps repo.
|
||||
//
|
||||
// For example, to reconcile my-chart.gen.yaml for prod-us:
|
||||
// let ResourcesPath = "deploy/environments/prod-us/components/my-chart"
|
||||
let ResourcesPath = path.Join(["deploy", OutputBaseDir, "components", Name], path.Unix)
|
||||
|
||||
// Add the argocd Application instance label to GitOps so resources are in sync.
|
||||
// This is an example of how Holos makes it easy to add common labels to all
|
||||
// resources regardless of if they come from Helm, CUE, Kustomize, plain YAML
|
||||
// manifests, etc...
|
||||
KustomizeConfig: CommonLabels: "argocd.argoproj.io/instance": _ArgoAppName
|
||||
|
||||
// Labels for the Application itself. We filter the argocd application
|
||||
// instance label so ArgoCD doesn't think the Application resource manages
|
||||
// itself.
|
||||
let Labels = {
|
||||
for k, v in KustomizeConfig.CommonLabels {
|
||||
if k != "argocd.argoproj.io/instance" {
|
||||
(k): v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Artifacts: "\(Name)-application": {
|
||||
artifact: ArtifactPath
|
||||
generators: [{
|
||||
kind: "Resources"
|
||||
output: artifact
|
||||
resources: Application: (_ArgoAppName): _ArgoApplication
|
||||
}]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
git clone https://github.com/holos-run/multi-sources-example.git
|
||||
cd multi-sources-example
|
||||
@@ -0,0 +1 @@
|
||||
Cloning into 'multi-sources-example'...
|
||||
@@ -0,0 +1 @@
|
||||
f35da50452b346d4eea3f3e59ff5ae6b8c221218
|
||||
@@ -0,0 +1,2 @@
|
||||
git branch -f work start
|
||||
git checkout work
|
||||
@@ -0,0 +1 @@
|
||||
Switched to branch 'work'
|
||||
@@ -0,0 +1 @@
|
||||
holos --version
|
||||
@@ -0,0 +1 @@
|
||||
0.103.0
|
||||
@@ -0,0 +1 @@
|
||||
appsets/4-final/all-my-envs-appset-with-version.yaml
|
||||
@@ -0,0 +1,49 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ApplicationSet
|
||||
metadata:
|
||||
name: all-my-envs-from-repo-with-version
|
||||
namespace: argocd
|
||||
spec:
|
||||
goTemplate: true
|
||||
goTemplateOptions: ["missingkey=error"]
|
||||
generators:
|
||||
- git:
|
||||
repoURL: https://github.com/kostis-codefresh/multi-sources-example.git
|
||||
revision: HEAD
|
||||
files:
|
||||
- path: "appsets/4-final/env-config/**/config.json"
|
||||
template:
|
||||
metadata:
|
||||
name: '{{.env}}'
|
||||
spec:
|
||||
# The project the application belongs to.
|
||||
project: default
|
||||
|
||||
sources:
|
||||
- repoURL: https://kostis-codefresh.github.io/multi-sources-example
|
||||
chart: my-chart
|
||||
targetRevision: '{{.chart}}'
|
||||
helm:
|
||||
valueFiles:
|
||||
- $values/my-values/common-values.yaml
|
||||
- $values/my-values/app-version/{{.version}}-values.yaml
|
||||
- $values/my-values/env-type/{{.type}}-values.yaml
|
||||
- $values/my-values/regions/{{.region}}-values.yaml
|
||||
- $values/my-values/envs/{{.env}}-values.yaml
|
||||
- repoURL: 'https://github.com/kostis-codefresh/multi-sources-example.git'
|
||||
targetRevision: HEAD
|
||||
ref: values
|
||||
|
||||
# Destination cluster and namespace to deploy the application
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: '{{.env}}'
|
||||
|
||||
# Sync policy
|
||||
syncPolicy:
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
my-chart/templates/deployment.yaml
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: simple-deployment
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: trivial-go-web-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: trivial-go-web-app
|
||||
spec:
|
||||
containers:
|
||||
- name: webserver-simple
|
||||
imagePullPolicy: Always
|
||||
image: docker.io/kostiscodefresh/simple-env-app:{{ .Values.imageVersion }}
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: ENV
|
||||
value: {{ quote .Values.environment }}
|
||||
- name: ENV_TYPE
|
||||
value: {{ quote .Values.environmentType }}
|
||||
- name: REGION
|
||||
value: {{ quote .Values.region }}
|
||||
- name: PAYPAL_URL
|
||||
value: {{ quote .Values.paypalUrl }}
|
||||
- name: DB_USER
|
||||
value: {{ quote .Values.dbUser }}
|
||||
- name: DB_PASSWORD
|
||||
value: {{ quote .Values.dbPassword }}
|
||||
- name: GPU_ENABLED
|
||||
value: {{ quote .Values.gpuEnabled }}
|
||||
- name: UI_THEME
|
||||
value: {{ quote .Values.userInterfaceTheme }}
|
||||
- name: CACHE_SIZE
|
||||
value: {{ quote .Values.cacheSize }}
|
||||
- name: PAGE_LIMIT
|
||||
value: {{ quote .Values.pageLimit }}
|
||||
- name: SORTING
|
||||
value: {{ quote .Values.sorting }}
|
||||
- name: N_BUCKETS
|
||||
value: {{ quote .Values.nBuckets }}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
my-chart/templates/service.yaml
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: simple-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: trivial-go-web-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
@@ -0,0 +1 @@
|
||||
cat <<'EOF' > config/environments/environments.cue
|
||||
@@ -0,0 +1 @@
|
||||
EOF
|
||||
@@ -0,0 +1,21 @@
|
||||
@extern(embed)
|
||||
package environments
|
||||
|
||||
// We use cue embed functionality as an equivalent replacement for
|
||||
// ApplicationSet generators.
|
||||
config: _ @embed(glob=*/config.json)
|
||||
config: _ @embed(glob=staging/*/config.json)
|
||||
config: _ @embed(glob=prod/*/config.json)
|
||||
config: _ @embed(glob=integration/*/config.json)
|
||||
|
||||
// With CUE we can constrain the data with a schema.
|
||||
config: [FILEPATH=string]: #Config
|
||||
|
||||
// #Config defines the schema of each config.json file.
|
||||
#Config: {
|
||||
env: "qa" | "integration-gpu" | "integration-non-gpu" | "staging-us" | "staging-eu" | "prod-us" | "prod-eu"
|
||||
region: "us" | "eu"
|
||||
type: "prod" | "non-prod"
|
||||
version: "qa" | "staging" | "prod"
|
||||
chart: =~"^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
holos init platform v1alpha5 --force
|
||||
@@ -0,0 +1,2 @@
|
||||
CUE_EXPERIMENT=embed holos cue export --out=yaml \
|
||||
./config/environments
|
||||
@@ -0,0 +1,49 @@
|
||||
config:
|
||||
qa/config.json:
|
||||
env: qa
|
||||
region: us
|
||||
type: non-prod
|
||||
version: qa
|
||||
chart: 0.2.0
|
||||
staging/asia/config.json:
|
||||
env: qa
|
||||
region: us
|
||||
type: non-prod
|
||||
version: qa
|
||||
chart: 0.2.0
|
||||
staging/eu/config.json:
|
||||
env: staging-eu
|
||||
region: eu
|
||||
type: non-prod
|
||||
version: staging
|
||||
chart: 0.2.0
|
||||
prod/eu/config.json:
|
||||
env: prod-eu
|
||||
region: eu
|
||||
type: prod
|
||||
version: prod
|
||||
chart: 0.1.0
|
||||
integration/gpu/config.json:
|
||||
env: integration-gpu
|
||||
region: us
|
||||
type: non-prod
|
||||
version: prod
|
||||
chart: 0.1.0
|
||||
staging/us/config.json:
|
||||
env: staging-us
|
||||
region: us
|
||||
type: non-prod
|
||||
version: staging
|
||||
chart: 0.2.0
|
||||
prod/us/config.json:
|
||||
env: prod-us
|
||||
region: us
|
||||
type: prod
|
||||
version: prod
|
||||
chart: 0.1.0
|
||||
integration/non-gpu/config.json:
|
||||
env: integration-non-gpu
|
||||
region: us
|
||||
type: non-prod
|
||||
version: qa
|
||||
chart: 0.2.0
|
||||
@@ -0,0 +1,30 @@
|
||||
# First, we'll move my-chart the original article vendored in
|
||||
# Git to the conventional location Holos uses to vendor charts.
|
||||
mkdir -p components/my-chart/vendor/0.1.0
|
||||
git mv my-chart components/my-chart/vendor/0.1.0/my-chart
|
||||
|
||||
# Helm value files move into the directory that will contain
|
||||
# my-chart component definition. components/my-chart is
|
||||
# conventionally called the "my-chart component directory"
|
||||
git mv my-values components/my-chart/my-values
|
||||
|
||||
# The config.json files are moved without changing their folder structure.
|
||||
# We'll package the data up into an "environments config package" for reuse.
|
||||
mkdir config
|
||||
git mv appsets/4-final/env-config config/environments
|
||||
|
||||
# All of our components will reside in the components directory so
|
||||
# the CUE files `holos init` produced may be moved to keep the
|
||||
# repository root tidy.
|
||||
mv *.cue components/
|
||||
|
||||
# The following files and directories from the original article and
|
||||
# holos init are no longer relevant after the migration.
|
||||
mkdir not-used
|
||||
git mv appsets not-used/appsets
|
||||
git mv example-apps not-used/example-apps
|
||||
rm -f platform.metadata.json
|
||||
|
||||
# Make the commit
|
||||
git add platform components cue.mod .gitignore
|
||||
git commit -m 'reorganize to conventional holos layout'
|
||||
@@ -0,0 +1 @@
|
||||
cat <<'EOF' > components/my-chart/my-chart.cue
|
||||
@@ -0,0 +1 @@
|
||||
EOF
|
||||
@@ -0,0 +1,65 @@
|
||||
@extern(embed)
|
||||
package holos
|
||||
|
||||
import "holos.example/config/environments"
|
||||
|
||||
parameters: {
|
||||
environments.#Config & {
|
||||
env: _ @tag(env)
|
||||
region: _ @tag(region)
|
||||
type: _ @tag(type)
|
||||
version: _ @tag(version)
|
||||
chart: _ @tag(chart)
|
||||
}
|
||||
}
|
||||
|
||||
// component represents the holos component definition, which produces a
|
||||
// BuildPlan for holos to execute, rendering the manifests.
|
||||
component: #Helm & {
|
||||
Chart: {
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L25
|
||||
version: parameters.chart
|
||||
repository: {
|
||||
name: "multi-sources-example"
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L23
|
||||
url: "https://kostis-codefresh.github.io/multi-sources-example"
|
||||
}
|
||||
}
|
||||
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L40
|
||||
// We use kustomize to manage the namespace, similar to how the original
|
||||
// article uses the ApplicationSet template to specify the namespace.
|
||||
KustomizeConfig: Kustomization: namespace: parameters.env
|
||||
|
||||
// Migrate the Helm Hierarchy preserving the behavior of over writing values.
|
||||
// Migrated from [valueFiles]. Later files win.
|
||||
//
|
||||
// [valueFiles]: https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L27-L32
|
||||
ValueFiles: [{
|
||||
name: "common-values.yaml"
|
||||
values: valueFiles["my-values/common-values.yaml"]
|
||||
}, {
|
||||
name: "version-values.yaml"
|
||||
values: valueFiles["my-values/app-version/\(parameters.version)-values.yaml"]
|
||||
}, {
|
||||
name: "type-values.yaml"
|
||||
values: valueFiles["my-values/env-type/\(parameters.type)-values.yaml"]
|
||||
}, {
|
||||
name: "region-values.yaml"
|
||||
values: valueFiles["my-values/regions/\(parameters.region)-values.yaml"]
|
||||
}, {
|
||||
name: "env-values.yaml"
|
||||
values: valueFiles["my-values/envs/\(parameters.env)-values.yaml"]
|
||||
}]
|
||||
}
|
||||
|
||||
// holos represents the output for the holos command line to process. The holos
|
||||
// command line processes a BuildPlan to render the helm chart component.
|
||||
//
|
||||
// Use the holos show buildplans command to see the BuildPlans that holos render
|
||||
// platform renders.
|
||||
holos: component.BuildPlan
|
||||
|
||||
// Migrated from https://github.com/holos-run/multi-sources-example/blob/v0.1.0/appsets/4-final/all-my-envs-appset-with-version.yaml#L27-L32
|
||||
valueFiles: _ @embed(glob=my-values/*.yaml)
|
||||
valueFiles: _ @embed(glob=my-values/*/*-values.yaml)
|
||||
@@ -0,0 +1 @@
|
||||
cat <<'EOF' > components/componentconfig.cue
|
||||
@@ -0,0 +1 @@
|
||||
EOF
|
||||
@@ -0,0 +1,6 @@
|
||||
package holos
|
||||
|
||||
#ComponentConfig: {
|
||||
// Inject the output base directory from platform component parameters.
|
||||
OutputBaseDir: string | *"" @tag(outputBaseDir, type=string)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
holos show platform
|
||||
@@ -0,0 +1,97 @@
|
||||
apiVersion: v1alpha5
|
||||
kind: Platform
|
||||
metadata:
|
||||
name: default
|
||||
spec:
|
||||
components:
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.2.0 for environment qa
|
||||
labels:
|
||||
env: qa
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.2.0
|
||||
env: qa
|
||||
outputBaseDir: environments/qa
|
||||
region: us
|
||||
type: non-prod
|
||||
version: qa
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.2.0 for environment staging-eu
|
||||
labels:
|
||||
env: staging-eu
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.2.0
|
||||
env: staging-eu
|
||||
outputBaseDir: environments/staging-eu
|
||||
region: eu
|
||||
type: non-prod
|
||||
version: staging
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.2.0 for environment staging-us
|
||||
labels:
|
||||
env: staging-us
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.2.0
|
||||
env: staging-us
|
||||
outputBaseDir: environments/staging-us
|
||||
region: us
|
||||
type: non-prod
|
||||
version: staging
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.1.0 for environment prod-eu
|
||||
labels:
|
||||
env: prod-eu
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.1.0
|
||||
env: prod-eu
|
||||
outputBaseDir: environments/prod-eu
|
||||
region: eu
|
||||
type: prod
|
||||
version: prod
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.1.0 for environment prod-us
|
||||
labels:
|
||||
env: prod-us
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.1.0
|
||||
env: prod-us
|
||||
outputBaseDir: environments/prod-us
|
||||
region: us
|
||||
type: prod
|
||||
version: prod
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.1.0 for environment integration-gpu
|
||||
labels:
|
||||
env: integration-gpu
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.1.0
|
||||
env: integration-gpu
|
||||
outputBaseDir: environments/integration-gpu
|
||||
region: us
|
||||
type: non-prod
|
||||
version: prod
|
||||
path: components/my-chart
|
||||
- annotations:
|
||||
app.holos.run/description: my-chart 0.2.0 for environment integration-non-gpu
|
||||
labels:
|
||||
env: integration-non-gpu
|
||||
name: my-chart
|
||||
parameters:
|
||||
chart: 0.2.0
|
||||
env: integration-non-gpu
|
||||
outputBaseDir: environments/integration-non-gpu
|
||||
region: us
|
||||
type: non-prod
|
||||
version: qa
|
||||
path: components/my-chart
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user