mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 08:44:58 +00:00
Compare commits
1 Commits
jeff/comma
...
gl/helm-va
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
924600cb83 |
2
.github/workflows/golangci-lint.yaml
vendored
2
.github/workflows/golangci-lint.yaml
vendored
@@ -27,4 +27,4 @@ jobs:
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v1.64.5
|
||||
version: v1.60
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,4 +12,3 @@ tmp/
|
||||
/holos-k3d/
|
||||
/holos-infra/
|
||||
node_modules/
|
||||
.tmp/
|
||||
|
||||
13
Makefile
13
Makefile
@@ -32,20 +32,17 @@ bump: bumppatch
|
||||
.PHONY: bumppatch
|
||||
bumppatch: ## Bump the patch version.
|
||||
scripts/bump patch
|
||||
HOLOS_UPDATE_SCRIPTS=1 scripts/test
|
||||
|
||||
.PHONY: bumpminor
|
||||
bumpminor: ## Bump the minor version.
|
||||
scripts/bump minor
|
||||
scripts/bump patch 0
|
||||
HOLOS_UPDATE_SCRIPTS=1 scripts/test
|
||||
|
||||
.PHONY: bumpmajor
|
||||
bumpmajor: ## Bump the major version.
|
||||
scripts/bump major
|
||||
scripts/bump minor 0
|
||||
scripts/bump patch 0
|
||||
HOLOS_UPDATE_SCRIPTS=1 scripts/test
|
||||
|
||||
.PHONY: show-version
|
||||
show-version: ## Print the full version.
|
||||
@@ -78,12 +75,6 @@ build: ## Build holos executable.
|
||||
@echo "GOPATH=${GOPATH}"
|
||||
go build -trimpath -o bin/$(BIN_NAME) -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/$(BIN_NAME)
|
||||
|
||||
.PHONY: debug
|
||||
debug: ## Build debug executable.
|
||||
@echo "building ${BIN_NAME}-debug ${VERSION}"
|
||||
@echo "GOPATH=${GOPATH}"
|
||||
go build -o bin/$(BIN_NAME)-debug $(REPO_PATH)/cmd/$(BIN_NAME)
|
||||
|
||||
linux: ## Build holos executable for tilt.
|
||||
@echo "building ${BIN_NAME}.linux ${VERSION}"
|
||||
@echo "GOPATH=${GOPATH}"
|
||||
@@ -163,10 +154,6 @@ website: ## Build website
|
||||
unity: ## https://cuelabs.dev/unity/
|
||||
./scripts/unity
|
||||
|
||||
.PHONY: update-docs
|
||||
update-docs: ## Update doc examples
|
||||
HOLOS_UPDATE_SCRIPTS=1 go test -v ./doc/md/...
|
||||
|
||||
.PHONY: help
|
||||
help: ## Display this help menu.
|
||||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
||||
|
||||
@@ -84,9 +84,6 @@ type Helm struct {
|
||||
Chart core.Chart
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values core.Values
|
||||
// ValueFiles represents value files for migration from helm value
|
||||
// hierarchies. Use Values instead.
|
||||
ValueFiles []core.ValueFile `json:",omitempty"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `cue:"true | *false"`
|
||||
// Namespace sets the helm chart namespace flag if provided.
|
||||
|
||||
@@ -118,12 +118,8 @@ type Helm struct {
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart" yaml:"chart"`
|
||||
// Values represents values for holos to marshal into values.yaml when
|
||||
// rendering the chart. Values follow ValueFiles when both are provided.
|
||||
// rendering the chart.
|
||||
Values Values `json:"values" yaml:"values"`
|
||||
// ValueFiles represents hierarchial value files passed in order to the helm
|
||||
// template -f flag. Useful for migration from an ApplicationSet. Use Values
|
||||
// instead. ValueFiles precede Values when both are provided.
|
||||
ValueFiles []ValueFile `json:"valueFiles,omitempty" yaml:"valueFiles,omitempty"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks,omitempty" yaml:"enableHooks,omitempty"`
|
||||
// Namespace represents the helm namespace flag
|
||||
@@ -134,17 +130,6 @@ type Helm struct {
|
||||
KubeVersion string `json:"kubeVersion,omitempty" yaml:"kubeVersion,omitempty"`
|
||||
}
|
||||
|
||||
// ValueFile represents one Helm value file produced from CUE.
|
||||
type ValueFile struct {
|
||||
// Name represents the file name, e.g. "region-values.yaml"
|
||||
Name string `json:"name" yaml:"name"`
|
||||
// Kind is a discriminator.
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Values\""`
|
||||
// Values represents values for holos to marshal into the file name specified
|
||||
// by Name when rendering the chart.
|
||||
Values Values `json:"values,omitempty" yaml:"values,omitempty"`
|
||||
}
|
||||
|
||||
// Values represents [Helm] Chart values generated from CUE.
|
||||
type Values map[string]any
|
||||
|
||||
@@ -190,13 +175,11 @@ type AuthSource struct {
|
||||
// 1. [Kustomize] - Patch and transform the output from prior generators or
|
||||
// transformers. See [Introduction to Kustomize].
|
||||
// 2. [Join] - Concatenate multiple prior outputs into one output.
|
||||
// 3. [Slice] - Slice an artifact into multiple artifacts using [kubectl-slice].
|
||||
//
|
||||
// [Introduction to Kustomize]: https://kubectl.docs.kubernetes.io/guides/config_management/introduction/
|
||||
// [kubectl-slice]: https://github.com/patrickdappollonio/kubectl-slice
|
||||
type Transformer struct {
|
||||
// Kind represents the kind of transformer. Must be Kustomize, or Join.
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Kustomize\" | \"Join\" | \"Slice\""`
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Kustomize\" | \"Join\""`
|
||||
// Inputs represents the files to transform. The Output of prior Generators
|
||||
// and Transformers.
|
||||
Inputs []FilePath `json:"inputs" yaml:"inputs"`
|
||||
@@ -256,46 +239,12 @@ type Validator struct {
|
||||
Command Command `json:"command,omitempty" yaml:"command,omitempty"`
|
||||
}
|
||||
|
||||
// Command represents a generic command for use as a Generator, Transformer, or
|
||||
// Validator. Holos uses the Go template engine to render the Args field using
|
||||
// data provided by the TaskData field. For example to fill in the fully
|
||||
// qualified temporary directory used to provide inputs to the task.
|
||||
// Command represents a command vetting one or more artifacts. Holos appends
|
||||
// fully qualified input file paths to the end of the args list, then executes
|
||||
// the command. Inputs are written into a temporary directory prior to
|
||||
// executing the command and removed afterwards.
|
||||
type Command struct {
|
||||
// DisplayName represents a friendly display name for the command.
|
||||
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
|
||||
// Args represents the complete command argument vector as a go template.
|
||||
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
|
||||
// OutputRef references the source of the output data.
|
||||
OutputRef OutputRef `json:"outputRef,omitempty" yaml:"outputRef,omitempty"`
|
||||
// TaskData populated by Holos for template rendering.
|
||||
TaskData TaskData `json:"taskData,omitempty" yaml:"taskData,omitempty"`
|
||||
// TODO(jjm): add command environment variable support similar to args.
|
||||
}
|
||||
|
||||
// TaskData represents data values associated with a pipeline task necessary to
|
||||
// execute the task. For example, the randomly generated temporary directory
|
||||
// used to read and write artifact files when executing user defined task
|
||||
// commands. Values of this struct are intended for the Go template engine.
|
||||
//
|
||||
// Holos populates this struct as needed. Holos may treat user provided values
|
||||
// as an error condition.
|
||||
type TaskData struct {
|
||||
// TempDir represents the temp directory holos manages for task artifacts.
|
||||
TempDir string `json:"tempDir,omitempty" yaml:"tempDir,omitempty"`
|
||||
}
|
||||
|
||||
// OutputRef represents a reference to the data source used as the output of a
|
||||
// task. For example, a Generator output may be sourced from standard output or
|
||||
// a file path.
|
||||
type OutputRef struct {
|
||||
// Kind represents the kind of output produced.
|
||||
Kind string `json:"kind,omitempty" yaml:"kind,omitempty" cue:"string | *\"Pipe\" | \"Path\""`
|
||||
// Pipe represents stdout or stderr. Ignored unless kind is Pipe.
|
||||
Pipe string `json:"pipe,omitempty" yaml:"pipe,omitempty" cue:"string | *\"stdout\" | \"stderr\""`
|
||||
// Path represents an artifact path relative to the task temp directory.
|
||||
// Ignored unless kind is Path.
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
// TODO(jjm): support jsonpath or cel references to the output data maybe?
|
||||
}
|
||||
|
||||
// InternalLabel is an arbitrary unique identifier internal to holos itself.
|
||||
|
||||
@@ -11,11 +11,10 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
holosMain := cmd.MakeMain()
|
||||
testscript.Main(m, map[string]func(){
|
||||
"holos": func() { os.Exit(holosMain()) },
|
||||
"cue": func() { os.Exit(cue.Main()) },
|
||||
})
|
||||
os.Exit(testscript.RunMain(m, map[string]func() int{
|
||||
"holos": cmd.MakeMain(),
|
||||
"cue": cue.Main,
|
||||
}))
|
||||
}
|
||||
|
||||
func TestGuides_v1alpha5(t *testing.T) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# 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
|
||||
stdout 'name: has-foo-v1beta1'
|
||||
stdout 'kubeVersion: v'
|
||||
cmp stdout want/helm-template.yaml
|
||||
exec holos render platform ./platform
|
||||
# When no capabilities are specified
|
||||
cmp deploy/components/capabilities/capabilities.gen.yaml want/when-no-capabilities-specified.yaml
|
||||
|
||||
@@ -31,6 +31,7 @@ spec:
|
||||
- kind: Resources
|
||||
output: resources.gen.yaml
|
||||
resources: {}
|
||||
validators: []
|
||||
transformers:
|
||||
- kind: Kustomize
|
||||
inputs:
|
||||
@@ -38,8 +39,7 @@ spec:
|
||||
output: components/no-name/no-name.gen.yaml
|
||||
kustomize:
|
||||
kustomization:
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- resources.gen.yaml
|
||||
validators: []
|
||||
kind: Kustomization
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
|
||||
@@ -86,9 +86,6 @@ type Helm struct {
|
||||
Chart core.Chart
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values core.Values
|
||||
// ValueFiles represents value files for migration from helm value
|
||||
// hierarchies. Use Values instead.
|
||||
ValueFiles []core.ValueFile `json:",omitempty"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `cue:"true | *false"`
|
||||
// Namespace sets the helm chart namespace flag if provided.
|
||||
|
||||
@@ -36,16 +36,13 @@ Package core contains schemas for a [Platform](<#Platform>) and [BuildPlan](<#Bu
|
||||
- [type Kustomization](<#Kustomization>)
|
||||
- [type Kustomize](<#Kustomize>)
|
||||
- [type Metadata](<#Metadata>)
|
||||
- [type OutputRef](<#OutputRef>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type PlatformSpec](<#PlatformSpec>)
|
||||
- [type Repository](<#Repository>)
|
||||
- [type Resource](<#Resource>)
|
||||
- [type Resources](<#Resources>)
|
||||
- [type TaskData](<#TaskData>)
|
||||
- [type Transformer](<#Transformer>)
|
||||
- [type Validator](<#Validator>)
|
||||
- [type ValueFile](<#ValueFile>)
|
||||
- [type Values](<#Values>)
|
||||
|
||||
|
||||
@@ -153,18 +150,11 @@ type Chart struct {
|
||||
<a name="Command"></a>
|
||||
## type Command {#Command}
|
||||
|
||||
Command represents a generic command for use as a Generator, Transformer, or Validator. Holos uses the Go template engine to render the Args field using data provided by the TaskData field. For example to fill in the fully qualified temporary directory used to provide inputs to the task.
|
||||
Command represents a command vetting one or more artifacts. Holos appends fully qualified input file paths to the end of the args list, then executes the command. Inputs are written into a temporary directory prior to executing the command and removed afterwards.
|
||||
|
||||
```go
|
||||
type Command struct {
|
||||
// DisplayName represents a friendly display name for the command.
|
||||
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"`
|
||||
// Args represents the complete command argument vector as a go template.
|
||||
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
|
||||
// OutputRef references the source of the output data.
|
||||
OutputRef OutputRef `json:"outputRef,omitempty" yaml:"outputRef,omitempty"`
|
||||
// TaskData populated by Holos for template rendering.
|
||||
TaskData TaskData `json:"taskData,omitempty" yaml:"taskData,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
@@ -293,12 +283,8 @@ type Helm struct {
|
||||
// Chart represents a helm chart to manage.
|
||||
Chart Chart `json:"chart" yaml:"chart"`
|
||||
// Values represents values for holos to marshal into values.yaml when
|
||||
// rendering the chart. Values follow ValueFiles when both are provided.
|
||||
// rendering the chart.
|
||||
Values Values `json:"values" yaml:"values"`
|
||||
// ValueFiles represents hierarchial value files passed in order to the helm
|
||||
// template -f flag. Useful for migration from an ApplicationSet. Use Values
|
||||
// instead. ValueFiles precede Values when both are provided.
|
||||
ValueFiles []ValueFile `json:"valueFiles,omitempty" yaml:"valueFiles,omitempty"`
|
||||
// EnableHooks enables helm hooks when executing the `helm template` command.
|
||||
EnableHooks bool `json:"enableHooks,omitempty" yaml:"enableHooks,omitempty"`
|
||||
// Namespace represents the helm namespace flag
|
||||
@@ -396,23 +382,6 @@ type Metadata struct {
|
||||
}
|
||||
```
|
||||
|
||||
<a name="OutputRef"></a>
|
||||
## type OutputRef {#OutputRef}
|
||||
|
||||
OutputRef represents a reference to the data source used as the output of a task. For example, a Generator output may be sourced from standard output or a file path.
|
||||
|
||||
```go
|
||||
type OutputRef struct {
|
||||
// Kind represents the kind of output produced.
|
||||
Kind string `json:"kind,omitempty" yaml:"kind,omitempty" cue:"string | *\"Pipe\" | \"Path\""`
|
||||
// Pipe represents stdout or stderr. Ignored unless kind is Pipe.
|
||||
Pipe string `json:"pipe,omitempty" yaml:"pipe,omitempty" cue:"string | *\"stdout\" | \"stderr\""`
|
||||
// Path represents an artifact path relative to the task temp directory.
|
||||
// Ignored unless kind is Path.
|
||||
Path string `json:"path,omitempty" yaml:"path,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
@@ -483,20 +452,6 @@ Resources represents Kubernetes resources. Most commonly used to mix resources i
|
||||
type Resources map[Kind]map[InternalLabel]Resource
|
||||
```
|
||||
|
||||
<a name="TaskData"></a>
|
||||
## type TaskData {#TaskData}
|
||||
|
||||
TaskData represents data values associated with a pipeline task necessary to execute the task. For example, the randomly generated temporary directory used to read and write artifact files when executing user defined task commands. Values of this struct are intended for the Go template engine.
|
||||
|
||||
Holos populates this struct as needed. Holos may treat user provided values as an error condition.
|
||||
|
||||
```go
|
||||
type TaskData struct {
|
||||
// TempDir represents the temp directory holos manages for task artifacts.
|
||||
TempDir string `json:"tempDir,omitempty" yaml:"tempDir,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Transformer"></a>
|
||||
## type Transformer {#Transformer}
|
||||
|
||||
@@ -504,12 +459,11 @@ Transformer combines multiple inputs from prior [Generator](<#Generator>) or [Tr
|
||||
|
||||
1. [Kustomize](<#Kustomize>) \- Patch and transform the output from prior generators or transformers. See [Introduction to Kustomize](<https://kubectl.docs.kubernetes.io/guides/config_management/introduction/>).
|
||||
2. [Join](<#Join>) \- Concatenate multiple prior outputs into one output.
|
||||
3. \[Slice\] \- Slice an artifact into multiple artifacts using [kubectl\\\-slice](<https://github.com/patrickdappollonio/kubectl-slice>).
|
||||
|
||||
```go
|
||||
type Transformer struct {
|
||||
// Kind represents the kind of transformer. Must be Kustomize, or Join.
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Kustomize\" | \"Join\" | \"Slice\""`
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Kustomize\" | \"Join\""`
|
||||
// Inputs represents the files to transform. The Output of prior Generators
|
||||
// and Transformers.
|
||||
Inputs []FilePath `json:"inputs" yaml:"inputs"`
|
||||
@@ -539,23 +493,6 @@ type Validator struct {
|
||||
}
|
||||
```
|
||||
|
||||
<a name="ValueFile"></a>
|
||||
## type ValueFile {#ValueFile}
|
||||
|
||||
ValueFile represents one Helm value file produced from CUE.
|
||||
|
||||
```go
|
||||
type ValueFile struct {
|
||||
// Name represents the file name, e.g. "region-values.yaml"
|
||||
Name string `json:"name" yaml:"name"`
|
||||
// Kind is a discriminator.
|
||||
Kind string `json:"kind" yaml:"kind" cue:"\"Values\""`
|
||||
// Values represents values for holos to marshal into the file name specified
|
||||
// by Name when rendering the chart.
|
||||
Values Values `json:"values,omitempty" yaml:"values,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Values"></a>
|
||||
## type Values {#Values}
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
exec bash -c 'bash -euo pipefail $WORK/command.sh 2>&1'
|
||||
cmp stdout $WORK/output.txt
|
||||
|
||||
-- command.sh --
|
||||
holos --version
|
||||
-- output.txt --
|
||||
0.104.1
|
||||
@@ -1,126 +0,0 @@
|
||||
# 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!
|
||||
@@ -1 +0,0 @@
|
||||
holos --version
|
||||
@@ -1 +0,0 @@
|
||||
0.104.1
|
||||
@@ -1 +0,0 @@
|
||||
EOF
|
||||
@@ -1 +0,0 @@
|
||||
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
|
||||
@@ -1,3 +0,0 @@
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
@@ -1,2 +0,0 @@
|
||||
mkdir holos-tutorial && cd holos-tutorial
|
||||
holos init platform v1alpha5
|
||||
@@ -1 +0,0 @@
|
||||
mkdir -p components/podinfo
|
||||
@@ -1,23 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > components/podinfo/podinfo.cue
|
||||
@@ -1 +0,0 @@
|
||||
deploy/components/podinfo/podinfo.gen.yaml
|
||||
@@ -1,2 +0,0 @@
|
||||
rendered podinfo in 312.472625ms
|
||||
rendered platform in 312.557375ms
|
||||
@@ -1,8 +0,0 @@
|
||||
package holos
|
||||
|
||||
Platform: Components: podinfo: {
|
||||
name: "podinfo"
|
||||
path: "components/podinfo"
|
||||
// Inject a value into the component.
|
||||
parameters: greeting: "Hello Holos!"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > platform/podinfo.cue
|
||||
@@ -1 +0,0 @@
|
||||
holos render platform
|
||||
@@ -1,93 +0,0 @@
|
||||
|
||||
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
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
tree -L 3 -I cue.mod .
|
||||
@@ -1,17 +0,0 @@
|
||||
.
|
||||
|-- 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
|
||||
@@ -1,4 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
|
||||
-- command.sh --
|
||||
holos --version
|
||||
-- output.txt --
|
||||
0.104.1
|
||||
0.102.5
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.104.1
|
||||
0.102.5
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[main aa9749e] 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 656d4ee] 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 3788921] 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 129.142708ms
|
||||
rendered prometheus in 165.260375ms
|
||||
rendered platform in 165.33ms
|
||||
rendered blackbox in 365.936792ms
|
||||
rendered prometheus in 371.855875ms
|
||||
rendered platform in 372.109916ms
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[main 654ae06] 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.096663084s
|
||||
rendered prometheus in 1.151784875s
|
||||
rendered platform in 1.151839916s
|
||||
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 9bc0126] render integrated blackbox and prometheus manifests
|
||||
[main 67efe0d] render integrated blackbox and prometheus manifests
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
exec bash -c 'bash -euo pipefail $WORK/command.sh 2>&1'
|
||||
cmp stdout $WORK/output.txt
|
||||
|
||||
-- command.sh --
|
||||
holos --version
|
||||
-- output.txt --
|
||||
0.104.1
|
||||
@@ -1,226 +0,0 @@
|
||||
# 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'
|
||||
@@ -1 +0,0 @@
|
||||
holos --version
|
||||
@@ -1 +0,0 @@
|
||||
0.104.1
|
||||
@@ -1,36 +0,0 @@
|
||||
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:
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
labels:
|
||||
- includeSelectors: false
|
||||
pairs:
|
||||
app.kubernetes.io/name: httpbin
|
||||
patches: []
|
||||
images:
|
||||
- name: mccutchen/go-httpbin
|
||||
resources:
|
||||
- resources.gen.yaml
|
||||
- httpbin.yaml
|
||||
validators: []
|
||||
@@ -1 +0,0 @@
|
||||
holos cue export --expression holos --out=yaml ./components/httpbin
|
||||
@@ -1 +0,0 @@
|
||||
EOF
|
||||
@@ -1,6 +0,0 @@
|
||||
[main 823e136] 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
|
||||
@@ -1 +0,0 @@
|
||||
git add . && git commit -m 'add httpbin'
|
||||
@@ -1,3 +0,0 @@
|
||||
[main 96f5f45] annotate httpbin for prometheus probes
|
||||
2 files changed, 18 insertions(+)
|
||||
create mode 100644 components/httpbin/patches.cue
|
||||
@@ -1 +0,0 @@
|
||||
git add . && git commit -m 'annotate httpbin for prometheus probes'
|
||||
@@ -1 +0,0 @@
|
||||
git diff
|
||||
@@ -1 +0,0 @@
|
||||
git init . && git add . && git commit -m initial
|
||||
@@ -1,13 +0,0 @@
|
||||
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
|
||||
@@ -1,30 +0,0 @@
|
||||
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}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > components/httpbin/httpbin.cue
|
||||
@@ -1,2 +0,0 @@
|
||||
rendered httpbin in 197.030208ms
|
||||
rendered platform in 197.416416ms
|
||||
@@ -1,16 +0,0 @@
|
||||
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"
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > components/httpbin/patches.cue
|
||||
@@ -1,36 +0,0 @@
|
||||
# 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
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > components/httpbin/httpbin.yaml
|
||||
@@ -1,2 +0,0 @@
|
||||
rendered httpbin in 112.916375ms
|
||||
rendered platform in 112.990333ms
|
||||
@@ -1,3 +0,0 @@
|
||||
mkdir holos-kustomize-tutorial
|
||||
cd holos-kustomize-tutorial
|
||||
holos init platform v1alpha5
|
||||
@@ -1 +0,0 @@
|
||||
mkdir -p components/httpbin
|
||||
@@ -1,8 +0,0 @@
|
||||
package holos
|
||||
|
||||
Platform: Components: {
|
||||
httpbin: {
|
||||
name: "httpbin"
|
||||
path: "components/httpbin"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
cat <<EOF > platform/httpbin.cue
|
||||
@@ -1,2 +0,0 @@
|
||||
rendered httpbin in 111.183042ms
|
||||
rendered platform in 111.265792ms
|
||||
@@ -1 +0,0 @@
|
||||
holos render platform
|
||||
@@ -1,4 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
[[ -s "$1" ]] && [[ -z "${HOLOS_UPDATE_SCRIPTS:-}" ]] && exit 0
|
||||
cat > "$1"
|
||||
@@ -10,7 +10,6 @@ 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
|
||||
|
||||
@@ -22,37 +21,49 @@ 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:
|
||||
|
||||
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';
|
||||
```shell
|
||||
mkdir holos-tutorial && cd holos-tutorial
|
||||
holos init platform v1alpha5
|
||||
```
|
||||
|
||||
<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):
|
||||
The resulting directory structure:
|
||||
|
||||
<Tabs groupId="80D04C6A-BC83-44D0-95CC-CE01B439B159">
|
||||
<TabItem value="tree" label="Tree">
|
||||
<CodeBlock language="txt" showLineNumbers>{TreeOutput}</CodeBlock>
|
||||
```text showLineNumbers
|
||||
holos-tutorial/
|
||||
├── components/
|
||||
│ └── podinfo/
|
||||
│ └── podinfo.cue
|
||||
├── cue.mod/
|
||||
├── platform/
|
||||
│ ├── platform.gen.cue
|
||||
│ └── podinfo.cue
|
||||
├── resources.cue
|
||||
├── schema.cue
|
||||
└── tags.cue
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="details" label="Details">
|
||||
<div style={{display: "flex"}}>
|
||||
<div>
|
||||
<CodeBlock language="txt" showLineNumbers>{TreeOutput}</CodeBlock>
|
||||
```text showLineNumbers
|
||||
holos-tutorial/
|
||||
├── components/
|
||||
│ └── podinfo/
|
||||
│ └── podinfo.cue
|
||||
├── cue.mod/
|
||||
├── platform/
|
||||
│ ├── platform.gen.cue
|
||||
│ └── podinfo.cue
|
||||
├── resources.cue
|
||||
├── schema.cue
|
||||
└── tags.cue
|
||||
```
|
||||
</div>
|
||||
<div>
|
||||
- **Line 1** The platform root is the `holos-tutorial` directory we created.
|
||||
@@ -61,24 +72,22 @@ 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 `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
|
||||
- **Line 5** The CUE module directory. Schema definitions for Kubernetes and
|
||||
Holos resources reside within the `cue.mod` directory.
|
||||
- **Line 6** The platform directory is the **main entrypoint** for the `holos
|
||||
render platform` command.
|
||||
- **Line 10** `platform.gen.cue` is initialized by `holos init platform` and
|
||||
- **Line 7** `platform.gen.cue` is initialized by `holos init platform` and
|
||||
contains the Platform spec.
|
||||
- **Line 11** `podinfo.cue` integrates podinfo with the platform by adding the
|
||||
- **Line 8** `podinfo.cue` integrates podinfo with the platform by adding the
|
||||
component to the platform spec. We'll add ths file after the next section.
|
||||
- **Line 13** `resources.cue` Defines the Kubernetes resources available to
|
||||
- **Line 9** `resources.cue` Defines the Kubernetes resources available to
|
||||
manage in CUE.
|
||||
- **Line 14** `schema.cue` Defines the configuration common to all component
|
||||
- **Line 10** `schema.cue` Defines the configuration common to all component
|
||||
kinds.
|
||||
- **Line 15** `tags.cue` Defines where component parameter values are injected
|
||||
- **Line 11** `tags.cue` Defines where component parameter values are injected
|
||||
into the overall platform configuration. We don't need to be concerned with
|
||||
this file until we cover component parameters.
|
||||
- **Lines 9-15** Initialized by `holos init platform`, user editable after
|
||||
- **Lines 9-11** Initialized by `holos init platform`, user editable after
|
||||
initialization.
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,15 +98,40 @@ initialization.
|
||||
|
||||
Configure the `podinfo` component:
|
||||
|
||||
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';
|
||||
```bash
|
||||
mkdir -p components/podinfo
|
||||
```
|
||||
```bash
|
||||
cat <<EOF > components/podinfo/podinfo.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
<CodeBlock language="bash">{MkdirComponents}</CodeBlock>
|
||||
<CodeBlock language="bash">{PodinfoHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{PodinfoBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
// 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
|
||||
```
|
||||
|
||||
:::important
|
||||
Like Go packages, CUE loads all `*.cue` files in the component directory to
|
||||
@@ -114,12 +148,22 @@ root-level `schema.cue`.
|
||||
|
||||
Register the `podinfo` component in `platform/podinfo.cue`:
|
||||
|
||||
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';
|
||||
```bash
|
||||
cat <<EOF > platform/podinfo.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
<CodeBlock language="bash">{RegisterPodinfoHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{RegisterPodinfoBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
Platform: Components: podinfo: {
|
||||
name: "podinfo"
|
||||
path: "components/podinfo"
|
||||
// Inject a value into the component.
|
||||
parameters: greeting: "Hello Holos!"
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
|
||||
:::tip
|
||||
Parameter names are unrestricted, except for the reserved `holos_` prefix.
|
||||
@@ -129,42 +173,161 @@ 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">
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="txt">{RegisterComponentsOutput}</CodeBlock>
|
||||
```
|
||||
cached podinfo 6.6.2
|
||||
rendered podinfo in 1.938665041s
|
||||
rendered platform in 1.938759417s
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos executes `helm template` with locally cached charts to generate:
|
||||
|
||||
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>
|
||||
```txt
|
||||
deploy/components/podinfo/podinfo.gen.yaml
|
||||
```
|
||||
|
||||
<Tabs groupId="0E9C231D-D0E8-410A-A4A0-601842A086A6">
|
||||
<TabItem value="service" label="Service">
|
||||
<CodeBlock language="yaml" showLineNumbers>{RenderedService}</CodeBlock>
|
||||
```yaml showLineNumbers
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 9898
|
||||
protocol: TCP
|
||||
targetPort: http
|
||||
- name: grpc
|
||||
port: 9999
|
||||
protocol: TCP
|
||||
targetPort: grpc
|
||||
selector:
|
||||
app.kubernetes.io/name: podinfo
|
||||
type: ClusterIP
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="deployment" label="Deployment">
|
||||
<CodeBlock language="yaml" showLineNumbers>{RenderedDeployment}</CodeBlock>
|
||||
```yaml showLineNumbers
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: podinfo
|
||||
app.kubernetes.io/version: 6.6.2
|
||||
helm.sh/chart: podinfo-6.6.2
|
||||
name: podinfo
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxUnavailable: 1
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
prometheus.io/port: "9898"
|
||||
prometheus.io/scrape: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- ./podinfo
|
||||
- --port=9898
|
||||
- --cert-path=/data/cert
|
||||
- --port-metrics=9797
|
||||
- --grpc-port=9999
|
||||
- --grpc-service-name=podinfo
|
||||
- --level=info
|
||||
- --random-delay=false
|
||||
- --random-error=false
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
- name: PODINFO_UI_COLOR
|
||||
value: '#34577c'
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/healthz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
name: podinfo
|
||||
ports:
|
||||
- containerPort: 9898
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 9797
|
||||
name: http-metrics
|
||||
protocol: TCP
|
||||
- containerPort: 9999
|
||||
name: grpc
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/readyz
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
limits: null
|
||||
requests:
|
||||
cpu: 1m
|
||||
memory: 16Mi
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: data
|
||||
terminationGracePeriodSeconds: 30
|
||||
volumes:
|
||||
- emptyDir: {}
|
||||
name: data
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos renders the component with the greeting injected from the platform spec.
|
||||
|
||||
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>
|
||||
```shell
|
||||
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
|
||||
```
|
||||
```yaml
|
||||
env:
|
||||
- name: PODINFO_UI_MESSAGE
|
||||
value: Hello Holos!
|
||||
```
|
||||
|
||||
## Breaking it down
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
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)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -15,12 +15,10 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
holosMain := cmd.MakeMain()
|
||||
|
||||
testscript.Main(m, map[string]func(){
|
||||
"holos": func() { os.Exit(holosMain()) },
|
||||
"cue": func() { os.Exit(cue.Main()) },
|
||||
})
|
||||
os.Exit(testscript.RunMain(m, map[string]func() int{
|
||||
"holos": cmd.MakeMain(),
|
||||
"cue": cue.Main,
|
||||
}))
|
||||
}
|
||||
|
||||
// Run these with go test -v to see the verbose names
|
||||
|
||||
@@ -7,7 +7,6 @@ sidebar_position: 45
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
# Kustomize
|
||||
|
||||
@@ -25,17 +24,6 @@ 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>
|
||||
@@ -51,14 +39,18 @@ Use `holos` to generate a minimal platform directory structure. First, create
|
||||
and navigate into a blank directory. Then, run the `holos init platform`
|
||||
command.
|
||||
|
||||
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>
|
||||
```shell
|
||||
mkdir holos-kustomize-tutorial
|
||||
cd holos-kustomize-tutorial
|
||||
holos init platform v1alpha5
|
||||
```
|
||||
|
||||
Make a commit to track changes.
|
||||
|
||||
<CodeBlock language="bash">{GitInit}</CodeBlock>
|
||||
```bash
|
||||
git init . && git add . && git commit -m initial
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -67,26 +59,97 @@ Make a commit to track changes.
|
||||
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">
|
||||
<CodeBlock language="bash">{MkdirComponent}</CodeBlock>
|
||||
```bash
|
||||
mkdir -p components/httpbin
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="components/httpbin/httpbin.cue" label="httpbin.cue">
|
||||
<CodeBlock language="bash">{HttpbinComponentHeader}</CodeBlock>
|
||||
<CodeBlock language="cue" showLineNumbers>{HttpbinComponentBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
```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
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="components/httpbin/httpbin.yaml" label="httpbin.yaml">
|
||||
<CodeBlock language="bash">{HttpbinYamlHeader}</CodeBlock>
|
||||
<CodeBlock language="yaml" showLineNumbers>{HttpbinYamlBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
```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
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -98,38 +161,56 @@ 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.
|
||||
|
||||
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';
|
||||
```bash
|
||||
cat <<EOF > platform/httpbin.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
<CodeBlock language="bash">{RegisterComponentHeader}</CodeBlock>
|
||||
<CodeBlock language="cue">{RegisterComponentBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
Platform: Components: {
|
||||
httpbin: {
|
||||
name: "httpbin"
|
||||
path: "components/httpbin"
|
||||
}
|
||||
}
|
||||
```
|
||||
```bash
|
||||
EOF
|
||||
```
|
||||
|
||||
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">
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="txt">{RegisterComponentOutput}</CodeBlock>
|
||||
```txt
|
||||
rendered httpbin in 707.554666ms
|
||||
rendered platform in 707.9845ms
|
||||
```
|
||||
</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">
|
||||
<CodeBlock language="bash">{GitCommitComponent}</CodeBlock>
|
||||
```bash
|
||||
git add . && git commit -m 'add httpbin'
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="txt">{GitCommitComponentOutput}</CodeBlock>
|
||||
```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
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -139,15 +220,55 @@ 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">
|
||||
<CodeBlock language="bash">{CueExport}</CodeBlock>
|
||||
```bash
|
||||
holos cue export --expression holos --out=yaml ./components/httpbin
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="yaml">{BuildplanOutput}</CodeBlock>
|
||||
```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: {}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -170,12 +291,30 @@ need to edit any YAML files manually.
|
||||
Add a new `patches.cue` file to the `httpbin` component with the following
|
||||
content.
|
||||
|
||||
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';
|
||||
```bash
|
||||
cat <<EOF > components/httpbin/patches.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
|
||||
<CodeBlock language="bash">{HttpbinPatchHeader}</CodeBlock>
|
||||
<CodeBlock language="bash" showLineNumbers>{HttpbinPatchBody}</CodeBlock>
|
||||
<CodeBlock language="bash">{EofTrailer}</CodeBlock>
|
||||
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
|
||||
```
|
||||
|
||||
:::note
|
||||
We use a hidden `_patches` field to easily unify data into a struct, then
|
||||
@@ -186,43 +325,62 @@ 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">
|
||||
<CodeBlock language="bash">{RenderCommand}</CodeBlock>
|
||||
```bash
|
||||
holos render platform
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="txt">{KustomizePatchRenderOutput}</CodeBlock>
|
||||
```txt
|
||||
rendered httpbin in 197.030208ms
|
||||
rendered platform in 197.416416ms
|
||||
```
|
||||
</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">
|
||||
<CodeBlock language="bash">{GitDiff}</CodeBlock>
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="diff">{GitDiffOutput}</CodeBlock>
|
||||
```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
|
||||
|
||||
```
|
||||
</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">
|
||||
<CodeBlock language="bash">{GitCommitFinal}</CodeBlock>
|
||||
```bash
|
||||
git add . && git commit -m 'annotate httpbin for prometheus probes'
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
<CodeBlock language="txt">{GitCommitFinalOutput}</CodeBlock>
|
||||
```txt
|
||||
[main 6eeeadb] annotate httpbin for prometheus probes
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
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,7 +18,3 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Auto-generated doc examples
|
||||
multi-sources-example/
|
||||
kargo-demo/
|
||||
|
||||
@@ -1,627 +0,0 @@
|
||||
---
|
||||
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/
|
||||
@@ -1,37 +0,0 @@
|
||||
# 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.104.1
|
||||
-- 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'
|
||||
@@ -1,25 +0,0 @@
|
||||
# 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
|
||||
@@ -1,83 +0,0 @@
|
||||
# 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
|
||||
@@ -1,205 +0,0 @@
|
||||
# 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
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
# 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
|
||||
}]
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
git clone https://github.com/holos-run/multi-sources-example.git
|
||||
cd multi-sources-example
|
||||
@@ -1 +0,0 @@
|
||||
Cloning into 'multi-sources-example'...
|
||||
@@ -1 +0,0 @@
|
||||
6a882ac5aee7241e0130a59737cc46db5f636a21
|
||||
@@ -1,2 +0,0 @@
|
||||
git branch -f work start
|
||||
git checkout work
|
||||
@@ -1 +0,0 @@
|
||||
Switched to branch 'work'
|
||||
@@ -1 +0,0 @@
|
||||
holos --version
|
||||
@@ -1 +0,0 @@
|
||||
0.104.1
|
||||
@@ -1 +0,0 @@
|
||||
appsets/4-final/all-my-envs-appset-with-version.yaml
|
||||
@@ -1,49 +0,0 @@
|
||||
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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
my-chart/templates/deployment.yaml
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
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 }}
|
||||
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
my-chart/templates/service.yaml
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: simple-service
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: trivial-go-web-app
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
@@ -1 +0,0 @@
|
||||
cat <<'EOF' > config/environments/environments.cue
|
||||
@@ -1 +0,0 @@
|
||||
EOF
|
||||
@@ -1,21 +0,0 @@
|
||||
@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]+$"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
holos init platform v1alpha5 --force
|
||||
@@ -1,2 +0,0 @@
|
||||
CUE_EXPERIMENT=embed holos cue export --out=yaml \
|
||||
./config/environments
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user