Compare commits

..

17 Commits

Author SHA1 Message Date
Jeff McCune
8a7a010b94 version 0.94.0 2024-09-15 15:41:17 -07:00
Jeff McCune
2454f6e9ee generate: app-projects to organize ArgoCD Applications into Projects
Previously all generated ArgoCD Application resources go into the
default project following the Quickstart guide.  The configuration code
is being organized into the concept of projects in the filesystem, so we
want to the GitOps configuration to also reflect this concept of
projects.

This patch extends the ArgoConfig user facing schema to accept a project
string.  The app-projects component automatically manages AppProject
resources in the argocd namespace for each of the defined projects.

This allows CUE configuration in the a project directory to specify the
project name so that all Applications are automatically assigned to the
correct project.
2024-09-15 14:57:13 -07:00
Jeff McCune
63d00bfddf schema: handle ArgoConfig for all component kinds
Providing ArgoConfig only works with the Helm kind without this patch.
This is a problem because we want to produce an Application for every
supported component kind when rendering the platform.

This patch threads the ArgoConfig struct described in the Quickstart
guide through every supported component kind.
2024-09-15 13:09:07 -07:00
Jeff McCune
f34da6c24e generate: add schematic for manage a project guide gitops
This patch configures the platform to generate Application resources for
all of the components in the manage a project guide.
2024-09-15 12:57:51 -07:00
Jeff McCune
1d98069b73 generate: add httproutes schematic
Define a place for components to register HTTPRoute resources the
platform team needs to manage in the Gateway namespace.

The files are organized to delegate to the platform team.

This patch also fixes the naming of the argocd component so that the
Service is argocd-server instead of argo-cd-argocd-server.
2024-09-15 12:32:45 -07:00
Jeff McCune
e956b64d04 schematic: comment how kustomization of argocd crds works
This is the only example we have right now of producing a kustomization
entirely from CUE.
2024-09-15 09:37:42 -07:00
Jeff McCune
054d33b498 builder: add kustomization post-processing to kubernetes build plans (#246)
Holos does not post-process a KubernetesObjects core package build plan
with kustomize.  This is necessary to pass the ArgoCD version through to
Kustomize to fetch the correct crds.

This patch enables the kustomization and provides an example in the
argocd schematic.

Result: The KubernetesObjects component doesn't actually have any
resources defined, so holos creates an empty `build-plan-resources.yaml`
file.  This is fine, the kustomize post-processing adds the actual
resources via https URL passing in the correct ArgoCD version.

```
❯ holos render component --cluster-name=workload ./projects/platform/components/argocd/crds --log-level=debug --log-format=text
9:20AM DBG config.go:166 finalized config from flags version=0.93.4 state=finalized
9:20AM DBG builder.go:234 cue: building instances version=0.93.4
9:20AM DBG builder.go:251 cue: validating instance version=0.93.4 dir=/Users/jeff/Holos/holos-manage-a-project-guide/projects/platform/components/argocd/crds
9:20AM DBG builder.go:256 cue: decoding holos build plan version=0.93.4 dir=/Users/jeff/Holos/holos-manage-a-project-guide/projects/platform/components/argocd/crds
9:20AM DBG builder.go:270 cue: discriminated build kind: BuildPlan version=0.93.4 dir=/Users/jeff/Holos/holos-manage-a-project-guide/projects/platform/components/argocd/crds kind=BuildPlan apiVersion=v1alpha3
9:20AM DBG builder.go:314 allocated results slice version=0.93.4 cap=1
9:20AM DBG result.go:156 wrote: /var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146/build-plan-resources.yaml version=0.93.4 op=write path=/var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146/build-plan-resources.yaml bytes=0
9:20AM DBG result.go:169 wrote: /var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146/kustomization.yaml version=0.93.4 op=write path=/var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146/kustomization.yaml bytes=174
9:20AM DBG run.go:40 running: kubectl version=0.93.4 name=kubectl args="[kustomize /var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146]"
9:20AM DBG remove.go:16 tmp: removed version=0.93.4 path=/var/folders/22/zt67pphj6h1fgknqfy23ppl80000gn/T/holos.kustomize3526125146
9:20AM DBG builder.go:350 returning results version=0.93.4 len=1
9:20AM DBG result.go:214 out: wrote deploy/clusters/workload/components/argocd-crds/argocd-crds.gen.yaml version=0.93.4 action=write path=deploy/clusters/workload/components/argocd-crds/argocd-crds.gen.yaml status=ok
9:20AM INF render.go:79 rendered argocd-crds version=0.93.4 cluster=workload name=argocd-crds status=ok action=rendered
```

Closes: #246
2024-09-15 09:25:25 -07:00
Jeff McCune
f2f75a4e00 generate: fix argo-cd component 2024-09-15 09:06:53 -07:00
Jeff McCune
a0cf73faf9 generate: remove argocd kustomization.yaml 2024-09-15 09:00:41 -07:00
Jeff McCune
d74655c632 generate: add argocd schematic
Using the projects layout.

This patch also includes a method to pass a version to a Kustomization.
2024-09-15 08:57:57 -07:00
Jeff McCune
b8019429b8 docs: add manage a project guide draft (#242)
Initial draft of the Manage a Project guide focused on how a development
team can self serve resources provided by a platform team.
2024-09-14 15:35:12 -07:00
Jeff McCune
9c08214118 docs: add the outline of the projects guide (#242) 2024-09-14 13:43:31 -07:00
Jeff McCune
f58d791e03 api: move #Resources to package holos
Previously, the #Resources struct listing valid resources to use with
APIObjects in each of the components types was closed.  This made it
very difficult for users to mix in new resources and use the Kubernetes
component kind.

This patch moves the definition of the valid resources to package holos
from the schema API.  The schema still enforces some light constraints,
but doesn't keep the struct closed.

A new convention is introduced in the form of configuring all components
using _ComponentConfig defined at the root, then unifying this struct
with all of the component kinds.  See schema.gen.cue for how this works.

This approach enables mixing in ArgoCD applications to all component
kinds, not just Helm as was done previously.  Similarly, the
user-constrained #Resources definition unifies with all component kinds.

It's OK to leave the yaml.Marshall in the schema API.  The user
shouldn't ever have to deal with #APIObjects, instead they should pass
Resources through the schema API which will use APIObjects to create
apiObjectMap for each component type and the BuildPlan.

This is still more awkward than I want, but it's a good step in the
right direction.
2024-09-13 16:43:12 -07:00
Jeff McCune
836033e16a docs: move istio-gateway to a separate schematic
Without this patch the istio-gateway component isn't functional, the
HTTPRoute created for httpbin isn't programmed correctly.  There is no
Gateway resource, just a deployment created by the istio helm chart.

This patch replaces the helm chart with a Gateway resource as was done
previously in the k3d platform schematic.

This patch also simplifies the certificate management to issue a single
cert valid for the platform domain and a wildcard.  We intentionally
avoid building a dynamic Gateway.spec.listeners structure to keep the
expose a service guide relatively simple and focused on getting started
with Holos.
2024-09-13 11:13:18 -07:00
Jeff McCune
77279d9baf docs: add httpbin routes section to expose a service guide
This patch adds the httpbin routes component.  It's missing the
Certificate component, the next step is to wire up automatic certificate
management in the gateway configuration, which is a prime use case for
holos.  Similar to how we register components and namespaces, we'll
register certificates.

This patch also adds the #Platform.Domain field to the user facing
schema API.  We previously stored the domain in the Model but it makes
sense to lift it up to the Platform and have a sensible default value
for it.

Another example of #237 needing to be addressed soon.
2024-09-12 17:35:06 -07:00
Jeff McCune
bf19aee1a7 docs: add httpbin workload section to expose a service
This patch manages the httpbin Deployment, Service, and ReferenceGrant.
The remaining final step is to expose the service with an HTTPRoute and
Certificate.

We again needed to add a field to the schema APIObjects to get this to
work.  We need to fix #237 soon.  We'll need to do it again for the
HTTPRoute and Certificate resources.
2024-09-12 16:55:09 -07:00
Jeff McCune
4de88b3155 docs: insert cert-manager after namespaces in expose a service
The progression of namespaces, cert-manager, then gateway api and istio
makes much more sense than the previous progression of gateway api,
namespaces, istio.

cert-manager builds nicely on top of namespaces.  gateway api are only
crds necessary for istio.

This patch also adds the local-ca component which surfaces issue #237
The Kubernetes APIObjects are unnecessarily constrained to resources we
define in the schema.  We need to move the marshal code into package
holos so the user can add their own resource kinds.
2024-09-12 15:20:08 -07:00
133 changed files with 6528 additions and 1321 deletions

View File

@@ -17,8 +17,11 @@
"buildplan",
"cainjector",
"CAROOT",
"certificaterequests",
"certificatesigningrequests",
"clsx",
"clusterissuer",
"clusterissuers",
"clusterrole",
"clusterrolebinding",
"configmap",
@@ -45,6 +48,7 @@
"flushcache",
"gatewayclasses",
"gendoc",
"ggnpl",
"ghaction",
"gitops",
"godoc",
@@ -57,10 +61,12 @@
"holoslogger",
"horizontalpodautoscaler",
"httpbin",
"httproute",
"httproutes",
"Infima",
"isatty",
"istiod",
"jbrx",
"jetstack",
"Jsonnet",
"killall",
@@ -71,12 +77,15 @@
"Kustomizations",
"kustomize",
"ldflags",
"leaderelection",
"libnss",
"loadbalancer",
"mattn",
"mccutchen",
"mindmap",
"mktemp",
"msqbn",
"mtls",
"Multicluster",
"mutatingwebhookconfiguration",
"mxcl",
@@ -86,6 +95,7 @@
"orgid",
"otelconnect",
"Parentspanid",
"pcjc",
"peerauthentications",
"pflag",
"pipefail",
@@ -100,12 +110,15 @@
"proxyconfigs",
"Pulumi",
"putenv",
"qjbp",
"quickstart",
"referencegrant",
"referencegrants",
"requestauthentications",
"retryable",
"rolebinding",
"ropc",
"seccomp",
"SECRETKEY",
"secretstores",
"serverlb",
@@ -117,6 +130,7 @@
"startupapicheck",
"stefanprodan",
"structpb",
"subjectaccessreviews",
"svclb",
"systemconnect",
"tablewriter",

View File

@@ -11,18 +11,29 @@ import (
//go:generate ../../../hack/gendoc
// Component represents the fields common the different kinds of component. All
// components have a name, support mixing in resources, and produce a BuildPlan.
type ComponentFields struct {
// Name represents the Component name.
Name string
// Resources are kubernetes api objects to mix into the output.
Resources map[string]any
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig ArgoConfig
// BuildPlan represents the derived BuildPlan for the Holos cli to render.
BuildPlan core.BuildPlan
}
// Helm provides a BuildPlan via the Output field which contains one HelmChart
// from package core. Useful as a convenience wrapper to render a HelmChart
// with optional mix-in resources and Kustomization post-processing.
type Helm struct {
// Name represents the Component name.
Name string
ComponentFields `json:",inline"`
// Version represents the chart version.
Version string
// Namespace represents the helm namespace option when rendering the chart.
Namespace string
// Resources are kubernetes api objects to mix into the output.
Resources map[string]any
// Repo represents the chart repository
Repo struct {
@@ -57,27 +68,23 @@ type Helm struct {
// KustomizeResources represents additional resources files to include in the
// kustomize resources list.
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig ArgoConfig
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
}
// Resources represents the default schema for a Kubernetes API object resource.
// For example, a Service, Namespace or Deployment. The top level key is the
// kind of resource so default behavior and strict schema enforcement may be
// enforced for the kind. The second level keys are an arbitrary internal
// label, which serves as the default value for the resource metadata name
// field, but may differ for situations where the same resource kind and name
// are managed in different namespaces.
//
// Refer to [definitions.cue] for the CUE schema definition as an example to
// build on when defining your own Components.
//
// [definitions.cue]: https://github.com/holos-run/holos/blob/main/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue#L9
// type Resources map[string]map[string]any
// Kustomize provides a BuildPlan via the Output field which contains one
// KustomizeBuild from package core.
type Kustomize struct {
ComponentFields `json:",inline"`
// Kustomization represents the kustomize build plan for holos to render.
Kustomization core.KustomizeBuild
}
// Kubernetes provides a BuildPlan via the Output field which contains inline
// API Objects provided directly from CUE.
type Kubernetes struct {
ComponentFields `json:",inline"`
// Objects represents the kubernetes api objects for the Component.
Objects core.KubernetesObjects
}
// ArgoConfig represents the ArgoCD GitOps configuration for a Component.
// Useful to define once at the root of the Platform configuration and reuse
@@ -99,6 +106,8 @@ type ArgoConfig struct {
// Application.spec.source.targetRevision field. Defaults to the branch named
// main.
TargetRevision string `cue:"string | *\"main\""`
// AppProject represents the ArgoCD Project to associate the Application with.
AppProject string `cue:"string | *\"default\""`
}
// Cluster represents a cluster managed by the Platform.
@@ -147,29 +156,8 @@ type Platform struct {
// Output represents the core Platform spec for the holos cli to iterate over
// and render each listed Component, injecting the Model.
Output core.Platform
}
// Kustomize provides a BuildPlan via the Output field which contains one
// KustomizeBuild from package core.
type Kustomize struct {
// Name represents the Component name.
Name string
// Kustomization represents the kustomize build plan for holos to render.
Kustomization core.KustomizeBuild
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
}
// Kubernetes provides a BuildPlan via the Output field which contains inline
// API Objects provided directly from CUE.
type Kubernetes struct {
// Name represents the Component name.
Name string
// Resources represents the kubernetes api objects for the Component.
Resources map[string]any
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
// Domain represents the primary domain the Platform operates in. This field
// is intended as a sensible default for component authors to reference and
// platform operators to define.
Domain string `cue:"string | *\"holos.localhost\""`
}

View File

@@ -12,6 +12,7 @@ Package v1alpha3 contains CUE definitions intended as convenience wrappers aroun
- [type ArgoConfig](<#ArgoConfig>)
- [type Cluster](<#Cluster>)
- [type ComponentFields](<#ComponentFields>)
- [type Fleet](<#Fleet>)
- [type Helm](<#Helm>)
- [type Kubernetes](<#Kubernetes>)
@@ -43,6 +44,8 @@ type ArgoConfig struct {
// Application.spec.source.targetRevision field. Defaults to the branch named
// main.
TargetRevision string `cue:"string | *\"main\""`
// AppProject represents the ArgoCD Project to associate the Application with.
AppProject string `cue:"string | *\"default\""`
}
```
@@ -62,6 +65,24 @@ type Cluster struct {
}
```
<a name="ComponentFields"></a>
## type ComponentFields {#ComponentFields}
Component represents the fields common the different kinds of component. All components have a name, support mixing in resources, and produce a BuildPlan.
```go
type ComponentFields struct {
// Name represents the Component name.
Name string
// Resources are kubernetes api objects to mix into the output.
Resources map[string]any
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig ArgoConfig
// BuildPlan represents the derived BuildPlan for the Holos cli to render.
BuildPlan core.BuildPlan
}
```
<a name="Fleet"></a>
## type Fleet {#Fleet}
@@ -82,14 +103,12 @@ Helm provides a BuildPlan via the Output field which contains one HelmChart from
```go
type Helm struct {
// Name represents the Component name.
Name string
ComponentFields `json:",inline"`
// Version represents the chart version.
Version string
// Namespace represents the helm namespace option when rendering the chart.
Namespace string
// Resources are kubernetes api objects to mix into the output.
Resources map[string]any
// Repo represents the chart repository
Repo struct {
@@ -124,12 +143,6 @@ type Helm struct {
// KustomizeResources represents additional resources files to include in the
// kustomize resources list.
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig ArgoConfig
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
}
```
@@ -140,13 +153,9 @@ Kubernetes provides a BuildPlan via the Output field which contains inline API O
```go
type Kubernetes struct {
// Name represents the Component name.
Name string
// Resources represents the kubernetes api objects for the Component.
Resources map[string]any
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
ComponentFields `json:",inline"`
// Objects represents the kubernetes api objects for the Component.
Objects core.KubernetesObjects
}
```
@@ -157,14 +166,9 @@ Kustomize provides a BuildPlan via the Output field which contains one Kustomize
```go
type Kustomize struct {
// Name represents the Component name.
Name string
ComponentFields `json:",inline"`
// Kustomization represents the kustomize build plan for holos to render.
Kustomization core.KustomizeBuild
// Output represents the derived BuildPlan for the Holos cli to render.
Output core.BuildPlan
}
```
@@ -185,6 +189,10 @@ type Platform struct {
// Output represents the core Platform spec for the holos cli to iterate over
// and render each listed Component, injecting the Model.
Output core.Platform
// Domain represents the primary domain the Platform operates in. This field
// is intended as a sensible default for component authors to reference and
// platform operators to define.
Domain string `cue:"string | *\"holos.localhost\""`
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,799 +0,0 @@
---
description: Use Holos to expose a Service with the Gateway API.
slug: /guides/expose-a-service
sidebar_position: 200
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
# Expose a Service
In this guide, you'll learn how to expose a service with Holos using the Gateway
API.
The [Concepts](/docs/concepts) page defines capitalized terms such as Platform
and Component.
## What you'll need {#requirements}
You'll need the following tools installed to complete this guide.
1. [holos](/docs/install) - to build the Platform.
2. [helm](https://helm.sh/docs/intro/install/) - to render Helm Components.
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Kustomize Components.
Optionally, if you'd like to apply the rendered manifests to a real Cluster,
first complete the [localhost Guide](../local-cluster).
## Create a Git Repository
Start by initializing an empty Git repository. Holos operates on local files
stored in a Git repository.
<Tabs groupId="init">
<TabItem value="command" label="Command">
```bash
mkdir expose-a-service
cd expose-a-service
git init
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
Initialized empty Git repository in /expose-a-service/.git/
```
</TabItem>
</Tabs>
This guide assumes you will run commands from the root directory of the Git
repository unless stated otherwise.
## Generate the Platform {#Generate-Platform}
Start by generating a platform with one workload Cluster. The `guide` Platform
is intended as a starting point for all of our guides.
<Tabs groupId="generate-platform">
<TabItem value="command" label="Command">
```bash
holos generate platform guide
holos generate component workload-cluster
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
generated component
```
</TabItem>
</Tabs>
Commit the generated platform config to the repository.
<Tabs groupId="commit-platform">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "holos generate platform guide - $(holos --version)"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
[main (root-commit) 0b17b7f] holos generate platform guide - 0.93.3
213 files changed, 72349 insertions(+)
...
```
</TabItem>
</Tabs>
## Gateway API
The Gateway API is an official Kubernetes project focused on L4 and L7 routing .
You'll use the custom resources defined by the Gateway API to expose the httpbin
service outside of the cluster. The Kubernetes Gateway API does not come
installed by default on most Kubernetes clusters, so we need to manage the
custom resource definitions (CRDs).
Run the following command to generate a Component to manage the Gateway API.
<Tabs groupId="gen-gateway-api">
<TabItem value="command" label="Command">
```bash
holos generate component gateway-api
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
generated component
```
</TabItem>
</Tabs>
The command generates two main configuration files, one at the leaf, and another
at the root of the tree. At the leaf, the config produces a Kustomize build
plan for Holos to render. At the root, the config adds the Component to all
Clusters in the Platform.
Notice the `kustomization.yaml` file at the leaf. This is an unmodified
upstream copy of the standard way to install the Gateway API.
<Tabs groupId="gateway-api-files">
<TabItem value="components/gateway-api/gateway-api.cue" label="Leaf">
`components/gateway-api/gateway-api.cue`
```cue showLineNumbers
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "gateway-api"}).Output
```
</TabItem>
<TabItem value="kustomization.yaml" label="kustomization.yaml">
`components/gateway-api/kustomization.yaml`
```yaml showLineNumbers
resources:
- standard/gateway.networking.k8s.io_gatewayclasses.yaml
- standard/gateway.networking.k8s.io_gateways.yaml
- standard/gateway.networking.k8s.io_grpcroutes.yaml
- standard/gateway.networking.k8s.io_httproutes.yaml
- standard/gateway.networking.k8s.io_referencegrants.yaml
```
</TabItem>
<TabItem value="gateway-api.gen.cue" label="Root">
`gateway-api.gen.cue`
```cue showLineNumbers
package holos
// Manage on every Cluster in the Platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/gateway-api": {
path: "components/gateway-api"
cluster: Cluster.name
}
}
}
```
</TabItem>
</Tabs>
Render the Platform to render the Component for the workload clusters.
<Tabs groupId="render-platform-gateway">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
rendered components/gateway-api for cluster workload in 279.312292ms
```
</TabItem>
</Tabs>
:::tip
This example is equivalent to running `kubectl kustomize
./components/gateway-api` and saving the output to a file. Holos simplifies
this task and makes it consistent with Helm and other tools.
:::
Add and commit the Component and rendered Platform.
<Tabs groupId="commit-gateway-api">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "add gateway-api component"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
[main 88575a5] add gateway-api component
9 files changed, 26907 insertions(+)
create mode 100644 components/gateway-api/gateway-api.cue
create mode 100644 components/gateway-api/kustomization.yaml
create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gatewayclasses.yaml
create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_gateways.yaml
create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_grpcroutes.yaml
create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_httproutes.yaml
create mode 100644 components/gateway-api/standard/gateway.networking.k8s.io_referencegrants.yaml
create mode 100644 deploy/clusters/workload/components/gateway-api/gateway-api.gen.yaml
create mode 100644 gateway-api.gen.cue
```
</TabItem>
</Tabs>
Optionally apply the rendered component to your cluster.
<Tabs groupId="apply-gateway-api">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/gateway-api
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io serverside-applied
```
</TabItem>
</Tabs>
## Namespaces
We often need to manage namespaces prior to workloads being deployed. This is
necessary because a namespace is a security boundary. Holos makes it easier,
safer, and more consistent to manage service accounts, role bindings, and
secrets prior to deploying workloads into a namespace.
We'll see how this works with the namespaces component, which offers a mechanism
for other components to register their namespaces. The namespaces component
initializes each registered namespace, optionally mixing in resources
consistently.
Run the following command to generate the namespaces component.
<Tabs groupId="gen-namespaces">
<TabItem value="command" label="Command">
```bash
holos generate component namespaces
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
generated component
```
</TabItem>
</Tabs>
The command generates two main configuration files like we've seen with other
components. One file at the leaf, and another at the root. The leaf uses a
Kubernetes build plan to produce resources directly from CUE.
<Tabs groupId="namespaces-files">
<TabItem value="components/namespaces/namespaces.cue" label="Leaf">
`components/namespaces/namespaces.cue`
```cue showLineNumbers
package holos
let Objects = {
Name: "namespaces"
// highlight-next-line
Resources: Namespace: #Namespaces
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
```
</TabItem>
<TabItem value="namespaces.gen.cue" label="Root">
`namespaces.gen.cue`
```cue showLineNumbers
package holos
import corev1 "k8s.io/api/core/v1"
// #Namespaces defines all managed namespaces in the Platform.
// Holos adopts the sig-multicluster position of namespace sameness.
#Namespaces: {
// Validate against v1 of the kubernetes core api
// highlight-next-line
[Name=string]: corev1.#Namespace & {
metadata: name: Name
}
}
// Manage the Component on every Cluster in the Platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/namespaces": {
path: "components/namespaces"
cluster: Cluster.name
}
}
}
```
</TabItem>
</Tabs>
Notice the highlighted line in the leaf file. Resources are managed directly in
CUE at the leaf using the Kubernetes component. This is the same mechanism used
to mix-in resources to Helm and Kustomize components. The leaf refers to
`#Namespaces` defined at the root. At the root `#Namespaces` enforces a
constraint: each Namespace must conform to the `k8s.io/api/core/v1`
specification.
:::important
We've covered three kinds of components so far. The [Quickstart] guide
introduced Helm. We've used Kustomize and Kubernetes in this guide.
Holos offers a consistent way to manage these different kinds of packaging
safely and easily.
:::
- At the **leaf** Holos tailors the component to your platform, mixing
in resources and customizing the rendered output.
- At the **root** Holos integrates a component with the rest of your platform.
You'll see this pattern again and again as you build your platform.
Render the platform to render the component for the workload clusters.
<Tabs groupId="render-platform-gateway">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
rendered components/namespaces for cluster workload in 72.675292ms
rendered components/gateway-api for cluster workload in 259.174583ms
```
</TabItem>
</Tabs>
Add and commit the configuration and rendered manifests.
<Tabs groupId="commit-gateway-api">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "add namespaces component"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
[main 1bf0d61] add namespaces component
3 files changed, 30 insertions(+)
create mode 100644 components/namespaces/namespaces.cue
create mode 100644 deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
create mode 100644 namespaces.gen.cue
```
</TabItem>
</Tabs>
`#Namespaces` is currently empty, so the rendered output of
`namespaces.gen.yaml` is also empty.
:::tip
Namespaces will be automatically managed as we add more components to the
platform over time.
:::
## Istio
We'll manage Istio to implement the Gateway API so we can expose the httpbin
service outside of the cluster.
Run the following command to generate the istio components.
<Tabs groupId="gen-istio">
<TabItem value="command" label="Command">
```bash
holos generate component istio
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
generated component
```
</TabItem>
</Tabs>
:::important
Mix in the `istio-k3d` component if you're applying the rendered manifests to
k3d as described in our [Local Cluster] guide.
:::
Skip this step if you aren't using k3d. Istio needs to be configured to refer
to the nonstandard cni configuration paths k3d uses.
<Tabs groupId="gen-istio-k3d">
<TabItem value="command" label="Command">
```bash
holos generate component istio-k3d
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
generated component
```
</TabItem>
<TabItem value="file" label="istio-k3d.gen.cue">
Holos makes it easier and safer to mix-in this additional configuration at the root.
```cue showLineNumbers
package holos
// If you are using k3d with the default Flannel CNI, you must append some
// values to your installation command, as k3d uses nonstandard locations for
// CNI configuration and binaries.
//
// See https://istio.io/latest/docs/ambient/install/platform-prerequisites/#k3d
#Istio: Values: cni: {
cniConfDir: "/var/lib/rancher/k3s/agent/etc/cni/net.d"
cniBinDir: "/bin"
}
```
</TabItem>
</Tabs>
Consistent with the other components we've seen, the istio components define
configuration at the root and leafs of the tree. Unlike previous components
we've generated, this command generated multiple components to manage Istio.
<Tabs groupId="tree-istio">
<TabItem value="command" label="Command">
```bash
tree components/istio
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
components/istio
├── base
│   ├── istio-base.cue
│   └── values.gen.cue
├── cni
│   ├── cni.cue
│   └── values.gen.cue
├── gateway
│   ├── gateway.cue
│   └── values.gen.cue
├── istiod
│   ├── istiod.cue
│   └── values.gen.cue
└── ztunnel
├── values.gen.cue
└── ztunnel.cue
6 directories, 10 files
```
</TabItem>
</Tabs>
These components share the configuration defined at the root in `istio.gen.cue`.
Let's review how Holos makes it safer and easier to share Helm values defined at
the root with the istiod and cni components defined at the leaf.
1. istiod and cni use version `"1.23.1"` and namespace `"istio-system"` defined at
the root.
2. The Helm value to configure ambient (sidecar-less) mode is defined once at
the root.
3. The root adds a constraint to fail validation if the istio system namespace
is not `"istio-system"`. Future upgrades are safer with this constraint, if the
upstream vendor changes the default in the future the component will fail
validation.
4. The root registers two Namespaces, `"istio-system"` and `"istio-ingress"`.
5. The root manages the components on all workload clusters in the platform.
<Tabs groupId="istio-files">
<TabItem value="istiod.cue" label="istiod">
Leaf `components/istio/istiod/istiod.cue`
```cue showLineNumbers
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
let Chart = {
Name: "istiod"
// highlight-next-line
Version: #Istio.Version
// highlight-next-line
Namespace: #Istio.System.Namespace
Chart: chart: name: "istiod"
Repo: name: "istio"
Repo: url: "https://istio-release.storage.googleapis.com/charts"
// highlight-next-line
Values: #Istio.Values
}
```
</TabItem>
<TabItem value="cni.cue" label="cni">
Leaf `components/istio/cni/cni.cue`
```cue showLineNumbers
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
let Chart = {
Name: "istio-cni"
// highlight-next-line
Version: #Istio.Version
// highlight-next-line
Namespace: #Istio.System.Namespace
Chart: chart: name: "cni"
Repo: name: "istio"
Repo: url: "https://istio-release.storage.googleapis.com/charts"
// highlight-next-line
Values: #Istio.Values
}
```
</TabItem>
<TabItem value="istio.gen.cue" label="Root">
Root `istio.gen.cue`
```cue showLineNumbers
package holos
// #Istio represents platform wide configuration
#Istio: {
// highlight-next-line
Version: "1.23.1"
// highlight-next-line
System: Namespace: "istio-system"
Gateway: Namespace: "istio-ingress"
// Constrain Helm values for safer, easier upgrades and consistency across
// platform components.
// highlight-next-line
Values: global: istioNamespace: System.Namespace
// Configure ambient mode
// highlight-next-line
Values: profile: "ambient"
}
// Register the Namespaces
#Namespaces: (#Istio.System.Namespace): _
#Namespaces: (#Istio.Gateway.Namespace): _
// Manage istio on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: {
"\(Cluster.name)/istio-base": {
path: "components/istio/base"
cluster: Cluster.name
}
"\(Cluster.name)/istiod": {
path: "components/istio/istiod"
cluster: Cluster.name
}
"\(Cluster.name)/istio-cni": {
path: "components/istio/cni"
cluster: Cluster.name
}
"\(Cluster.name)/istio-ztunnel": {
path: "components/istio/ztunnel"
cluster: Cluster.name
}
"\(Cluster.name)/istio-gateway": {
path: "components/istio/gateway"
cluster: Cluster.name
}
}
}
```
</TabItem>
</Tabs>
:::tip
Many software projects managed by Holos are organized into a collection of
components working together, for example to safely manage custom resource
definitions, secrets, and policy separately from the workloads that rely on
them.
:::
Render the platform to render the istio components for the workload clusters.
<Tabs groupId="render-platform-istio">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
rendered components/namespaces for cluster workload in 85.490833ms
rendered components/istio/ztunnel for cluster workload in 111.784667ms
rendered components/istio/cni for cluster workload in 112.362417ms
rendered components/istio/base for cluster workload in 113.058ms
rendered components/istio/gateway for cluster workload in 119.018208ms
rendered components/istio/istiod for cluster workload in 127.736334ms
rendered components/gateway-api for cluster workload in 181.922333ms
```
</TabItem>
</Tabs>
Add and commit the configuration and rendered manifests.
<Tabs groupId="commit-istio">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "add istio"
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
[main aca8ff6] add istio
18 files changed, 18955 insertions(+)
create mode 100644 components/istio/base/istio-base.cue
create mode 100644 components/istio/base/values.gen.cue
create mode 100644 components/istio/cni/cni.cue
create mode 100644 components/istio/cni/values.gen.cue
create mode 100644 components/istio/gateway/gateway.cue
create mode 100644 components/istio/gateway/values.gen.cue
create mode 100644 components/istio/istiod/istiod.cue
create mode 100644 components/istio/istiod/values.gen.cue
create mode 100644 components/istio/ztunnel/values.gen.cue
create mode 100644 components/istio/ztunnel/ztunnel.cue
create mode 100644 deploy/clusters/workload/components/istio-base/istio-base.gen.yaml
create mode 100644 deploy/clusters/workload/components/istio-cni/istio-cni.gen.yaml
create mode 100644 deploy/clusters/workload/components/istio-gateway/istio-gateway.gen.yaml
create mode 100644 deploy/clusters/workload/components/istio-ztunnel/istio-ztunnel.gen.yaml
create mode 100644 deploy/clusters/workload/components/istiod/istiod.gen.yaml
create mode 100644 istio-k3d.gen.cue
create mode 100644 istio.gen.cue
```
</TabItem>
</Tabs>
Optionally apply the rendered component to your cluster.
<Tabs groupId="apply-istio-namespaces">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/namespaces
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
namespace/istio-ingress serverside-applied
namespace/istio-system serverside-applied
```
</TabItem>
</Tabs>
<Tabs groupId="apply-istio-base">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-base
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
customresourcedefinition.apiextensions.k8s.io/wasmplugins.extensions.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/destinationrules.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/envoyfilters.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/gateways.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/proxyconfigs.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/serviceentries.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/sidecars.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/virtualservices.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/workloadentries.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/workloadgroups.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/authorizationpolicies.security.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/peerauthentications.security.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/requestauthentications.security.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/telemetries.telemetry.istio.io serverside-applied
serviceaccount/istio-reader-service-account serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/istiod-default-validator serverside-applied
```
</TabItem>
</Tabs>
<Tabs groupId="apply-istiod">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/istiod
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
poddisruptionbudget.policy/istiod serverside-applied
serviceaccount/istiod serverside-applied
configmap/istio serverside-applied
configmap/istio-sidecar-injector serverside-applied
clusterrole.rbac.authorization.k8s.io/istiod-clusterrole-istio-system serverside-applied
clusterrole.rbac.authorization.k8s.io/istiod-gateway-controller-istio-system serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-reader-clusterrole-istio-system serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istiod-clusterrole-istio-system serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istiod-gateway-controller-istio-system serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istio-reader-clusterrole-istio-system serverside-applied
role.rbac.authorization.k8s.io/istiod serverside-applied
rolebinding.rbac.authorization.k8s.io/istiod serverside-applied
service/istiod serverside-applied
deployment.apps/istiod serverside-applied
horizontalpodautoscaler.autoscaling/istiod serverside-applied
mutatingwebhookconfiguration.admissionregistration.k8s.io/istio-sidecar-injector serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/istio-validator-istio-system serverside-applied
```
</TabItem>
</Tabs>
<Tabs groupId="apply-istio-cni">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-cni
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
serviceaccount/istio-cni serverside-applied
configmap/istio-cni-config serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-cni serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-cni-repair-role serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-cni-ambient serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istio-cni serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istio-cni-repair-rolebinding serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/istio-cni-ambient serverside-applied
daemonset.apps/istio-cni-node serverside-applied
```
</TabItem>
</Tabs>
<Tabs groupId="apply-istio-ztunnel">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-ztunnel
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
serviceaccount/ztunnel serverside-applied
daemonset.apps/ztunnel serverside-applied
```
</TabItem>
</Tabs>
<Tabs groupId="apply-istio-gateway">
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-gateway
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
serviceaccount/gateway serverside-applied
role.rbac.authorization.k8s.io/gateway serverside-applied
rolebinding.rbac.authorization.k8s.io/gateway serverside-applied
service/gateway serverside-applied
deployment.apps/gateway serverside-applied
horizontalpodautoscaler.autoscaling/gateway serverside-applied
```
</TabItem>
</Tabs>
Make sure all pod containers become ready.
<Tabs groupId="apply-istio-ready">
<TabItem value="command" label="Command">
```bash
kubectl get pods -A
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
NAMESPACE NAME READY STATUS RESTARTS AGE
istio-ingress gateway-6748c5f547-s46pj 1/1 Running 0 26s
istio-system istio-cni-node-852nr 1/1 Running 0 2m9s
istio-system istiod-5b4d8d4c77-t694z 1/1 Running 0 3m15s
istio-system ztunnel-msqbn 1/1 Running 0 63s
kube-system coredns-576bfc4dc7-2g4k9 1/1 Running 0 113m
kube-system local-path-provisioner-6795b5f9d8-wsz8p 1/1 Running 0 113m
kube-system metrics-server-557ff575fb-fctr7 1/1 Running 0 113m
kube-system svclb-gateway-5d311af0-fp5mk 3/3 Running 0 26s
```
</TabItem>
</Tabs>
Once all pods are ready, we're ready to manage httpbin so we can route http
traffic to it.
## httpbin
[Quickstart]: /docs/quickstart
[Local Cluster]: /docs/guides/local-cluster

View File

@@ -88,7 +88,7 @@ Finally, add your trusted certificate authority.
<TabItem value="command" label="Command">
```bash
kubectl apply --server-side=true -f "$(mkcert -CAROOT)/namespace.yaml"
kubectl apply --server-side=true -f "$(mkcert -CAROOT)/local-ca.yaml"
kubectl apply --server-side=true -n cert-manager -f "$(mkcert -CAROOT)/local-ca.yaml"
```
</TabItem>
<TabItem value="output" label="Output">

View File

@@ -0,0 +1,106 @@
---
description: Self service platform resource management for project teams.
slug: /guides/manage-a-project
sidebar_position: 200
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
# Manage a Project
In this guide we'll explore how Holos easily, safely, and consistently manages
platform resources for teams to develop the projects they're working on.
Intended Audience: Platform Engineers and Software Engineers.
Goal is to demonstrate how the platform team can consistently, easily, and
safely provide platform resources to software engineers.
Assumption is software engineers have a container they want to deploy onto the
platform and make accessible. We'll use httpbin as a stand-in for the dev
team's container.
Project is roughly equivalent to Dev Team for the purpose of this guide, but in
practice multiple teams work on a given project over the lifetime of the
project, so we structure the files into projects instead of teams.
## What you'll need {#requirements}
You'll need the following tools installed to complete this guide.
1. [holos](/docs/install) - to build the Platform.
2. [helm](https://helm.sh/docs/intro/install/) - to render Helm Components.
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Kustomize Components.
If you'd like to apply the manifests we render in this guide complete the
following optional, but recommended, steps.
a. Complete the [Local Cluster] guide to set up a local cluster to work with.
b. You'll need a GitHub account to fork the repository associated with this
guide.
## Fork the Guide Repository
<Tabs groupId="fork">
<TabItem value="command" label="Command">
```bash
```
</TabItem>
<TabItem value="output" label="Output">
```txt showLineNumbers
```
</TabItem>
</Tabs>
This guide assumes you will run commands from the root directory of this
repository unless stated otherwise.
[Quickstart]: /docs/quickstart
[Local Cluster]: /docs/guides/local-cluster
## Render the Platform
So we can build the basic platform. Don't dwell on the platform bits.
## Apply the Manifests
Deploy ArgoCD, but not any of the Application resources.
## Browse to ArgoCD
Note there is nothing here yet.
## Switch to your Fork
Note all of the Applications change consistently.
## Apply the Applications
Note how ArgoCD takes over management, no longer need to k apply.
## Create a Project
Project is a conceptual, not technical, thing in Holos. Mainly about how components are laid out in the filesystem tree.
We use a schematic built into holos as an example, the platform team could use the same or provide a similar template and instructions for development teams to self-serve.
## Render the Platform
Notice:
1. Project is registered with the platform at the root.
2. HTTPRoute and Namespace resources are added close to the root in `projects`
3. Deployment and Service resources are added at the leaf in `projects/httpbin/backend`
## Update the image tag
Add a basic schematic to demonstrate this. May need to add two new flags for image url and image tag to the generate subcommand, but should just be two new fields on the struct.
## Dive Deeper
Set the stage for constraints. Ideas: Limit what resources can be added,
namespaces can be operated in, enforce labels, etc...
Simple, consistent, easy constraints.

View File

@@ -263,7 +263,7 @@ following contents:
#ArgoConfig: {
Enabled: true
RepoURL: "https://example.com/holos-quickstart.git"
RepoURL: "https://github.com/holos-run/holos-quickstart-guide"
}
```
</TabItem>

View File

@@ -5,10 +5,10 @@
*/
/* Enable wrapping by default for mobile */
pre code {
/* pre code {
white-space: pre-wrap;
overflow-wrap: anywhere;
}
} */
/* You can override the default Infima variables here. */
:root {

View File

@@ -1,4 +1,4 @@
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "{{ .Name }}"}).Output
(#Kustomize & {Name: "{{ .Name }}"}).BuildPlan

View File

@@ -18,4 +18,4 @@ let Objects = {
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan

View File

@@ -8,4 +8,4 @@ let Objects = {
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan

View File

@@ -17,4 +17,4 @@ let Chart = {
}
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan

View File

@@ -12,4 +12,4 @@ let Chart = {
}
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan

View File

@@ -0,0 +1,11 @@
package holos
// Manage the Component on every Cluster in the Platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/app-projects": {
path: "projects/platform/components/app-projects"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,17 @@
package holos
import ap "argoproj.io/appproject/v1alpha1"
// Registration point for AppProjects
#AppProjects: [Name=string]: ap.#AppProject & {
metadata: name: Name
metadata: namespace: #ArgoCD.Namespace
spec: description: string | *"Holos managed AppProject"
spec: clusterResourceWhitelist: [{group: "*", kind: "*"}]
spec: destinations: [{namespace: "*", server: "*"}]
spec: sourceRepos: ["*"]
}
// Define at least the platform project. Other components can register projects
// the same way from the root of the configuration.
#AppProjects: platform: _

View File

@@ -0,0 +1,9 @@
package holos
let Objects = {
Name: "app-projects"
Resources: AppProject: #AppProjects
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan

View File

@@ -0,0 +1,5 @@
{
"name": "app-projects",
"short": "#AppProjects registration point",
"long": "Manage ArgoCD AppProject resources centrally."
}

View File

@@ -0,0 +1,6 @@
package holos
#ArgoConfig: {
Enabled: true
RepoURL: "https://github.com/holos-run/holos-manage-a-project-guide"
}

View File

@@ -0,0 +1,3 @@
package holos
#ArgoConfig: AppProject: #AppProjects.platform.metadata.name

View File

@@ -0,0 +1,5 @@
{
"name": "argocd-config-manage-a-project-guide",
"short": "generate applications for the manage-a-project guide",
"long": "https://github.com/holos-run/holos-manage-a-project-guide"
}

View File

@@ -0,0 +1,15 @@
package holos
// Manage the Component on every Cluster in the Platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/argocd-crds": {
path: "projects/platform/components/argocd/crds"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/argocd": {
path: "projects/platform/components/argocd/argocd"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,13 @@
package holos
// #ArgoCD represents platform wide configuration
#ArgoCD: {
Version: "2.12.3"
Namespace: "argocd"
}
// Register namespaces
#Namespaces: (#ArgoCD.Namespace): _
// Register the HTTPRoute to the backend Service
#HTTPRoutes: argocd: _backendRefs: "argocd-server": namespace: #ArgoCD.Namespace

View File

@@ -0,0 +1,60 @@
package holos
import "strings"
// Produce a helm chart build plan.
(#Helm & Chart).BuildPlan
let Chart = {
Name: "argocd"
Namespace: #ArgoCD.Namespace
Version: "7.5.2"
Repo: name: "argocd"
Repo: url: "https://argoproj.github.io/argo-helm"
Chart: chart: name: "argo-cd"
Chart: chart: release: Name
// Upstream uses a Kubernetes Job to create the argocd-redis Secret. Enable
// hooks to enable the Job.
Chart: enableHooks: true
Resources: [_]: [_]: metadata: namespace: Namespace
// Grant the Gateway namespace the ability to refer to the backend service
// from HTTPRoute resources.
Resources: ReferenceGrant: (#Istio.Gateway.Namespace): #ReferenceGrant
EnableKustomizePostProcessor: true
// Force all resources into the component namespace, some resources in the
// helm chart may not specify the namespace so they may get mis-applied
// depending on the kubectl (client-go) context.
KustomizeFiles: "kustomization.yaml": namespace: Namespace
Values: #Values & {
kubeVersionOverride: "1.29.0"
// handled in the argo-crds component
crds: install: false
// Configure the same fqdn the HTTPRoute is configured with.
global: domain: #HTTPRoutes.argocd.spec.hostnames[0]
dex: enabled: false
// the platform handles mutual tls to the backend
configs: params: "server.insecure": true
configs: cm: {
"admin.enabled": false
"oidc.config": "{}"
"users.anonymous.enabled": "true"
}
// Refer to https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/
let Policy = [
"g, argocd-view, role:readonly",
"g, prod-cluster-view, role:readonly",
"g, prod-cluster-edit, role:readonly",
"g, prod-cluster-admin, role:admin",
]
configs: rbac: "policy.csv": strings.Join(Policy, "\n")
configs: rbac: "policy.default": "role:admin"
}
}

View File

@@ -0,0 +1,33 @@
package holos
import (
"encoding/yaml"
ks "sigs.k8s.io/kustomize/api/types"
)
(#Kubernetes & {Name: "argocd-crds"}).BuildPlan
// Holos stages BuildPlan resources as an intermediate step of the rendering
// pipeline. The purpose is to provide the resources to kustomize for
// post-processing.
let BuildPlanResources = "build-plan-resources.yaml"
let Kustomization = ks.#Kustomization & {
apiVersion: "kustomize.config.k8s.io/v1beta1"
kind: "Kustomization"
resources: [
// Kustomize the intermediate build plan resources.
BuildPlanResources,
// Mix-in external resources.
"https://github.com/argoproj/argo-cd//manifests/crds/?ref=v\(#ArgoCD.Version)",
]
}
// Generate a kustomization.yaml directly from CUE so we can provide the correct
// version.
spec: components: kubernetesObjectsList: [{
// intermediate build plan resources to kustomize. Necessary to activate the
// kustomization post-rendering step in holos.
kustomize: resourcesFile: BuildPlanResources
kustomize: kustomizeFiles: "kustomization.yaml": yaml.Marshal(Kustomization)
}]

View File

@@ -0,0 +1,5 @@
{
"name": "argocd",
"short": "declaritive gitops for kubernetes",
"long": "Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes."
}

View File

@@ -0,0 +1,20 @@
package holos
// Platform wide configuration
#CertManager: {
Version: "{{ .Version }}"
Namespace: "{{ .Namespace }}"
}
// Register the namespace
#Namespaces: (#CertManager.Namespace): _
// Manage the component on every cluster in the platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/{{ .Name }}": {
path: "components/cert-manager"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,16 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).BuildPlan
let Chart = {
Name: "{{ .Name }}"
Version: #CertManager.Version
Namespace: #CertManager.Namespace
Repo: name: "{{ .RepoName }}"
Repo: url: "{{ .RepoURL }}"
Values: installCRDs: true
Values: startupapicheck: enabled: false
}

View File

@@ -0,0 +1,10 @@
{
"name": "cert-manager",
"short": "cloud native X.509 certificate management for kubernetes",
"long": "cert-manager creates tls certificates for workloads in your kubernetes cluster and renews the certificates before they expire.",
"chart": "",
"reponame": "jetstack",
"repourl": "https://charts.jetstack.io",
"version": "1.15.3",
"namespace": "cert-manager"
}

View File

@@ -1,4 +1,4 @@
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "gateway-api"}).Output
(#Kustomize & {Name: "gateway-api"}).BuildPlan

View File

@@ -0,0 +1,37 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "{{ .Name }}"
Namespace: #Istio.Gateway.Namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: HTTPRoute: (#HTTPRouteClone & {Name: "httpbin"}).BuildPlan
}
#HTTPRouteClone: {
Name: string
let Host = "\(Name).\(#Platform.Domain)"
Output: "\(Name)": {
metadata: namespace: _
metadata: name: Name
metadata: labels: app: Name
spec: hostnames: [Host]
spec: parentRefs: [{
name: "default"
namespace: metadata.namespace
}]
spec: rules: [
{
matches: [{path: {type: "PathPrefix", value: "/"}}]
backendRefs: [{
name: Name
namespace: #HTTPBin.Namespace
port: #HTTPBin.Port
}]
},
]
}
}

View File

@@ -0,0 +1,9 @@
package holos
// Manage the component on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name)/{{ .Name }}": {
path: "components/httpbin/routes"
cluster: Cluster.name
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "httpbin-routes",
"short": "expose httpbin with httproute resources",
"long": "expose httpbin with httproute resources",
"namespace": "istio-ingress"
}

View File

@@ -0,0 +1,61 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "{{ .Name }}"
Namespace: #HTTPBin.Namespace
// Constrain resources to the httpbin namespace
Resources: [_]: [_]: metadata: namespace: #HTTPBin.Namespace
Resources: {
Deployment: httpbin: {
metadata: name: "httpbin"
metadata: labels: app: metadata.name
spec: {
selector: matchLabels: {
app: metadata.labels.app
"app.kubernetes.io/instance": app
}
template: {
metadata: labels: selector.matchLabels
spec: securityContext: seccompProfile: type: "RuntimeDefault"
spec: containers: [{
name: "httpbin"
image: "quay.io/holos/mccutchen/go-httpbin"
ports: [{containerPort: 8080}]
securityContext: {
seccompProfile: type: "RuntimeDefault"
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 8192
runAsGroup: 8192
capabilities: drop: ["ALL"]
}}]
}
}
}
Service: httpbin: {
metadata: labels: Deployment.httpbin.metadata.labels
spec: {
selector: Deployment.httpbin.spec.selector.matchLabels
_ports: http: {
port: #HTTPBin.Port
targetPort: Deployment.httpbin.spec.template.spec.containers[0].ports[0].containerPort
protocol: "TCP"
name: "http"
}
ports: [for x in _ports {x}]
}
}
// Allow istio-ingress to refer to Services from HTTPRoutes
ReferenceGrant: httpbin: #ReferenceGrant & {
metadata: labels: Deployment.httpbin.metadata.labels
}
}
}

View File

@@ -0,0 +1,18 @@
package holos
// Platform wide configuration
#HTTPBin: {
Namespace: "{{ .Namespace }}"
Port: 80
}
// Register the namespace
#Namespaces: (#HTTPBin.Namespace): _
// Manage the component on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name)/{{ .Name }}": {
path: "components/httpbin/workload"
cluster: Cluster.name
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "httpbin-workload",
"short": "manages the httpbin deployment and service",
"long": "httpbin is useful to inspect requests and responses",
"namespace": "httpbin"
}

View File

@@ -0,0 +1,9 @@
package holos
// Manage on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name)/httproutes": {
path: "projects/platform/components/httproutes"
cluster: Cluster.name
}
}

View File

@@ -0,0 +1,34 @@
package holos
import v1 "gateway.networking.k8s.io/httproute/v1"
// #HTTPRoutes defines managed HTTPRoute resources for the platform. These
// resources are managed in the istio-ingress namespace. Other components
// define the routes they need close to the root of configuration.
#HTTPRoutes: {
// For the guides, we simplify this down to a flat namespace.
[Name=string]: v1.#HTTPRoute & {
let HOST = Name + "." + #Platform.Domain
_backendRefs: [NAME=string]: {
name: NAME
namespace: string
port: number | *80
}
metadata: name: Name
metadata: namespace: #Istio.Gateway.Namespace
metadata: labels: app: Name
spec: hostnames: [HOST]
spec: parentRefs: [{
name: "default"
namespace: metadata.namespace
}]
spec: rules: [
{
matches: [{path: {type: "PathPrefix", value: "/"}}]
backendRefs: [for x in _backendRefs {x}]
},
]
}
}

View File

@@ -0,0 +1,9 @@
package holos
let Objects = {
Name: "httproutes"
Resources: HTTPRoute: #HTTPRoutes
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan

View File

@@ -0,0 +1,5 @@
{
"name": "httproutes",
"short": "#HTTPRoutes registration point",
"long": "Provides the #HTTPRoutes registration point to manage httproutes in the istio-ingress namespace."
}

View File

@@ -0,0 +1,61 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "{{ .Name }}"
Namespace: #Istio.Gateway.Namespace
Resources: {
// The default gateway with all listeners attached to tls certs.
Gateway: default: {
metadata: namespace: Namespace
let Listeners = {
http: {
name: "http"
protocol: "HTTP"
port: 80
allowedRoutes: namespaces: from: "Same"
}
https: {
name: "https"
protocol: "HTTPS"
port: 443
allowedRoutes: namespaces: from: "Same"
tls: mode: "Terminate"
tls: certificateRefs: [{
kind: "Secret"
name: "gateway-cert"
}]
}
}
spec: listeners: [for x in Listeners {x}]
}
// Manage a simple cert for example.com and *.example.com
Certificate: "gateway-cert": {
metadata: name: "gateway-cert"
metadata: namespace: Namespace
spec: commonName: #Platform.Domain
spec: dnsNames: [spec.commonName, "*.\(spec.commonName)"]
spec: secretName: metadata.name
spec: issuerRef: {
kind: "ClusterIssuer"
name: "local-ca"
}
}
// Manage a service account to prevent ArgoCD from pruning it.
ServiceAccount: "default-istio": {
metadata: namespace: Namespace
metadata: labels: {
"gateway.istio.io/managed": "istio.io-gateway-controller"
"gateway.networking.k8s.io/gateway-name": "default"
"istio.io/gateway-name": "default"
}
}
}
}

View File

@@ -0,0 +1,7 @@
# Gateway API
This component uses the [Gateway API][1] to manage an istio Gateway. This will
become the default method in upstream istio so it is the preferred method in
Holos.
[1]: https://gateway-api.sigs.k8s.io/

View File

@@ -0,0 +1,17 @@
package holos
// #Istio represents platform wide configuration
#Istio: Gateway: Namespace: "istio-ingress"
// Register the Namespaces
#Namespaces: (#Istio.Gateway.Namespace): _
// Manage istio on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: {
"\(Cluster.name)/{{ .Name }}": {
path: "components/istio/gateway"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,5 @@
{
"name": "istio-gateway",
"short": "kubernetes ingress gateway api",
"long": "Gateway API ingress gateway with certificate management"
}

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istio-base"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istio-cni"

View File

@@ -1,17 +0,0 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
let Chart = {
Name: "istio-gateway"
Version: #Istio.Version
Namespace: #Istio.Gateway.Namespace
Chart: chart: name: "gateway"
Repo: name: "istio"
Repo: url: "https://istio-release.storage.googleapis.com/charts"
Values: #Istio.Values
}

View File

@@ -1,160 +0,0 @@
package holos
// imported from the 1.23.1 gateway chart
// cue import components/istio/gateway/vendor/gateway/values.yaml
#Istio: Values: {
// "defaults" is a workaround for Helm limitations. Users should NOT set ".defaults" explicitly, but rather directly set the fields internally.
// For instance, instead of `--set defaults.foo=bar`, just set `--set foo=bar`.
defaults: {
// Name allows overriding the release name. Generally this should not be set
name: ""
// revision declares which revision this gateway is a part of
revision: ""
// Controls the spec.replicas setting for the Gateway deployment if set.
// Otherwise defaults to Kubernetes Deployment default (1).
replicaCount: null
kind: "Deployment"
rbac: {
// If enabled, roles will be created to enable accessing certificates from Gateways. This is not needed
// when using http://gateway-api.org/.
enabled: true
}
serviceAccount: {
// If set, a service account will be created. Otherwise, the default is used
create: true
// Annotations to add to the service account
annotations: {}
// The name of the service account to use.
// If not set, the release name is used
name: ""
}
podAnnotations: {
"prometheus.io/port": "15020"
"prometheus.io/scrape": "true"
"prometheus.io/path": "/stats/prometheus"
"inject.istio.io/templates": "gateway"
"sidecar.istio.io/inject": "true"
}
// Define the security context for the pod.
// If unset, this will be automatically set to the minimum privileges required to bind to port 80 and 443.
// On Kubernetes 1.22+, this only requires the `net.ipv4.ip_unprivileged_port_start` sysctl.
securityContext: {}
containerSecurityContext: {}
service: {
// Type of service. Set to "None" to disable the service entirely
type: "LoadBalancer"
ports: [{
name: "status-port"
port: 15021
protocol: "TCP"
targetPort: 15021
}, {
name: "http2"
port: 80
protocol: "TCP"
targetPort: 80
}, {
name: "https"
port: 443
protocol: "TCP"
targetPort: 443
}]
annotations: {}
loadBalancerIP: ""
loadBalancerSourceRanges: []
externalTrafficPolicy: ""
externalIPs: []
ipFamilyPolicy: ""
//# Whether to automatically allocate NodePorts (only for LoadBalancers).
// allocateLoadBalancerNodePorts: false
ipFamilies: []
}
resources: {
requests: {
cpu: "100m"
memory: "128Mi"
}
limits: {
cpu: "2000m"
memory: "1024Mi"
}
}
autoscaling: {
enabled: true
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: {}
autoscaleBehavior: {}
}
// Pod environment variables
env: {}
// Labels to apply to all resources
labels: {}
// Annotations to apply to all resources
annotations: {}
nodeSelector: {}
tolerations: []
topologySpreadConstraints: []
affinity: {}
// If specified, the gateway will act as a network gateway for the given network.
networkGateway: ""
// Specify image pull policy if default behavior isn't desired.
// Default behavior: latest images will be Always else IfNotPresent
imagePullPolicy: ""
imagePullSecrets: []
// This value is used to configure a Kubernetes PodDisruptionBudget for the gateway.
//
// By default, the `podDisruptionBudget` is disabled (set to `{}`),
// which means that no PodDisruptionBudget resource will be created.
//
// To enable the PodDisruptionBudget, configure it by specifying the
// `minAvailable` or `maxUnavailable`. For example, to set the
// minimum number of available replicas to 1, you can update this value as follows:
//
// podDisruptionBudget:
// minAvailable: 1
//
// Or, to allow a maximum of 1 unavailable replica, you can set:
//
// podDisruptionBudget:
// maxUnavailable: 1
//
// You can also specify the `unhealthyPodEvictionPolicy` field, and the valid values are `IfHealthyBudget` and `AlwaysAllow`.
// For example, to set the `unhealthyPodEvictionPolicy` to `AlwaysAllow`, you can update this value as follows:
//
// podDisruptionBudget:
// minAvailable: 1
// unhealthyPodEvictionPolicy: AlwaysAllow
//
// To disable the PodDisruptionBudget, you can leave it as an empty object `{}`:
//
// podDisruptionBudget: {}
//
podDisruptionBudget: {}
terminationGracePeriodSeconds: 30
// A list of `Volumes` added into the Gateway Pods. See
// https://kubernetes.io/docs/concepts/storage/volumes/.
volumes: []
// A list of `VolumeMounts` added into the Gateway Pods. See
// https://kubernetes.io/docs/concepts/storage/volumes/.
volumeMounts: []
// Configure this to a higher priority class in order to make sure your Istio gateway pods
// will not be killed because of low priority class.
// Refer to https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
// for more detail.
priorityClassName: ""
}
}

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istiod"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istio-ztunnel"

View File

@@ -3,8 +3,7 @@ package holos
// #Istio represents platform wide configuration
#Istio: {
Version: "1.23.1"
System: Namespace: "istio-system"
Gateway: Namespace: "istio-ingress"
System: Namespace: "istio-system"
// Constrain Helm values for safer, easier upgrades and consistency across
// platform components.
@@ -15,8 +14,7 @@ package holos
}
// Register the Namespaces
#Namespaces: (#Istio.System.Namespace): _
#Namespaces: (#Istio.Gateway.Namespace): _
#Namespaces: (#Istio.System.Namespace): _
// Manage istio on workload clusters
for Cluster in #Fleets.workload.clusters {
@@ -37,9 +35,5 @@ for Cluster in #Fleets.workload.clusters {
path: "components/istio/ztunnel"
cluster: Cluster.name
}
"\(Cluster.name)/istio-gateway": {
path: "components/istio/gateway"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,20 @@
package holos
import ci "cert-manager.io/clusterissuer/v1"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "local-ca"
Namespace: #CertManager.Namespace
Resources: ClusterIssuer: LocalCA: ci.#ClusterIssuer & {
metadata: name: "local-ca"
metadata: namespace: #CertManager.Namespace
// The secret name must align with the local cluster guide at
// https://holos.run/docs/guides/local-cluster/
spec: ca: secretName: "local-ca"
}
}

View File

@@ -0,0 +1,11 @@
package holos
// Manage the component on every cluster in the platform
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/{{ .Name }}": {
path: "components/local-ca"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "local-ca",
"short": "manages a cluster issuer for use with our guides",
"long": "manages a cluster issuer that uses the mkcert ca private key to issue certs",
"namespace": "cert-manager"
}

View File

@@ -6,4 +6,4 @@ let Objects = {
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "{{ .Name }}"

View File

@@ -0,0 +1,17 @@
package holos
import rg "gateway.networking.k8s.io/referencegrant/v1beta1"
#ReferenceGrant: rg.#ReferenceGrant & {
metadata: name: #Istio.Gateway.Namespace
metadata: namespace: string
spec: from: [{
group: "gateway.networking.k8s.io"
kind: "HTTPRoute"
namespace: #Istio.Gateway.Namespace
}]
spec: to: [{
group: ""
kind: "Service"
}]
}

View File

@@ -0,0 +1,4 @@
{
"name": "referencegrant",
"short": "provides #ReferenceGrant at the root"
}

View File

@@ -668,5 +668,5 @@ import (
}
}
}
}] & [_, ...]
}]
}

View File

@@ -13,12 +13,27 @@ import (
"google.golang.org/protobuf/types/known/structpb"
)
// Component represents the fields common the different kinds of component. All
// components have a name, support mixing in resources, and produce a BuildPlan.
#ComponentFields: {
// Name represents the Component name.
Name: string
// Resources are kubernetes api objects to mix into the output.
Resources: {...} @go(,map[string]any)
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig: #ArgoConfig
// BuildPlan represents the derived BuildPlan for the Holos cli to render.
BuildPlan: core.#BuildPlan
}
// Helm provides a BuildPlan via the Output field which contains one HelmChart
// from package core. Useful as a convenience wrapper to render a HelmChart
// with optional mix-in resources and Kustomization post-processing.
#Helm: {
// Name represents the Component name.
Name: string
#ComponentFields
// Version represents the chart version.
Version: string
@@ -26,9 +41,6 @@ import (
// Namespace represents the helm namespace option when rendering the chart.
Namespace: string
// Resources are kubernetes api objects to mix into the output.
Resources: {...} @go(,map[string]any)
// Repo represents the chart repository
Repo: {
name: string @go(Name)
@@ -62,12 +74,24 @@ import (
// KustomizeResources represents additional resources files to include in the
// kustomize resources list.
KustomizeResources: {...} & {[string]: {...}} @go(,map[string]any)
}
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
ArgoConfig: #ArgoConfig
// Kustomize provides a BuildPlan via the Output field which contains one
// KustomizeBuild from package core.
#Kustomize: {
#ComponentFields
// Output represents the derived BuildPlan for the Holos cli to render.
Output: core.#BuildPlan
// Kustomization represents the kustomize build plan for holos to render.
Kustomization: core.#KustomizeBuild
}
// Kubernetes provides a BuildPlan via the Output field which contains inline
// API Objects provided directly from CUE.
#Kubernetes: {
#ComponentFields
// Objects represents the kubernetes api objects for the Component.
Objects: core.#KubernetesObjects
}
// ArgoConfig represents the ArgoCD GitOps configuration for a Component.
@@ -94,6 +118,9 @@ import (
// Application.spec.source.targetRevision field. Defaults to the branch named
// main.
TargetRevision: string & (string | *"main")
// AppProject represents the ArgoCD Project to associate the Application with.
AppProject: string & (string | *"default")
}
// Cluster represents a cluster managed by the Platform.
@@ -148,30 +175,9 @@ import (
// Output represents the core Platform spec for the holos cli to iterate over
// and render each listed Component, injecting the Model.
Output: core.#Platform
}
// Kustomize provides a BuildPlan via the Output field which contains one
// KustomizeBuild from package core.
#Kustomize: {
// Name represents the Component name.
Name: string
// Kustomization represents the kustomize build plan for holos to render.
Kustomization: core.#KustomizeBuild
// Output represents the derived BuildPlan for the Holos cli to render.
Output: core.#BuildPlan
}
// Kubernetes provides a BuildPlan via the Output field which contains inline
// API Objects provided directly from CUE.
#Kubernetes: {
// Name represents the Component name.
Name: string
// Resources represents the kubernetes api objects for the Component.
Resources: {...} @go(,map[string]any)
// Output represents the derived BuildPlan for the Holos cli to render.
Output: core.#BuildPlan
// Domain represents the primary domain the Platform operates in. This field
// is intended as a sensible default for component authors to reference and
// platform operators to define.
Domain: string & (string | *"holos.localhost")
}

View File

@@ -0,0 +1,16 @@
package v1alpha3
import "encoding/yaml"
// #APIObjects defines the output format for kubernetes api objects. The holos
// cli expects the yaml representation of each api object in the apiObjectMap
// field.
#APIObjects: {
apiObjects: {...}
for kind, v in apiObjects {
for name, obj in v {
apiObjectMap: (kind): (name): yaml.Marshal(obj)
}
}
}

View File

@@ -4,41 +4,47 @@ import (
"encoding/yaml"
core "github.com/holos-run/holos/api/core/v1alpha3"
kc "sigs.k8s.io/kustomize/api/types"
corev1 "k8s.io/api/core/v1"
appsv1 "k8s.io/api/apps/v1"
rbacv1 "k8s.io/api/rbac/v1"
batchv1 "k8s.io/api/batch/v1"
app "argoproj.io/application/v1alpha1"
)
#Resources: {
[Kind=string]: [InternalLabel=string]: {
kind: Kind
metadata: name: string | *InternalLabel
}
#Platform: {
Name: _
Model: _
Components: [string]: _
ClusterRole: [_]: rbacv1.#ClusterRole
ClusterRoleBinding: [_]: rbacv1.#ClusterRoleBinding
ConfigMap: [_]: corev1.#ConfigMap
CronJob: [_]: batchv1.#CronJob
Deployment: [_]: appsv1.#Deployment
Job: [_]: batchv1.#Job
Namespace: [_]: corev1.#Namespace
Role: [_]: rbacv1.#Role
RoleBinding: [_]: rbacv1.#RoleBinding
Service: [_]: corev1.#Service
ServiceAccount: [_]: corev1.#ServiceAccount
StatefulSet: [_]: appsv1.#StatefulSet
...
// TODO: Rename this field to the kind of thing it produces like we renamed
// component Output to BuildPlan.
Output: metadata: name: Name
Output: spec: model: Model
Output: spec: components: [for c in Components {c}]
}
#BuildPlan: core.#BuildPlan & {
_Name: string
_Namespace?: string
_ArgoConfig: #ArgoConfig
if _ArgoConfig.Enabled {
let NAME = "gitops/\(_Name)"
// Render the ArgoCD Application for GitOps as an additional Component of
// the BuildPlan.
spec: components: resources: (NAME): {
metadata: name: NAME
if _Namespace != _|_ {
metadata: namespace: _Namespace
}
deployFiles: (#Argo & {ComponentName: _Name, ArgoConfig: _ArgoConfig}).deployFiles
}
}
}
#Helm: {
Name: string
Version: string
Namespace: string
Resources: #Resources
Resources: _
Repo: {
name: string | *""
@@ -51,7 +57,7 @@ import (
metadata: name: string | *Name
metadata: namespace: string | *Namespace
chart: name: string | *Name
chart: release: chart.name
chart: release: string | *chart.name
chart: version: string | *Version
chart: repository: Repo
@@ -71,7 +77,7 @@ import (
}
}
apiObjectMap: (#APIObjects & {apiObjects: Resources}).apiObjectMap
apiObjectMap: (core.#APIObjects & {apiObjects: Resources}).apiObjectMap
}
// EnableKustomizePostProcessor processes helm output with kustomize if true.
@@ -105,8 +111,7 @@ import (
// ArgoConfig represents the ArgoCD GitOps integration for this Component.
ArgoConfig: _
// output represents the build plan provided to the holos cli.
Output: #BuildPlan & {
BuildPlan: #BuildPlan & {
_Name: Name
_Namespace: Namespace
_ArgoConfig: ArgoConfig
@@ -114,24 +119,35 @@ import (
}
}
#BuildPlan: core.#BuildPlan & {
_Name: string
_Namespace?: string
_ArgoConfig: #ArgoConfig
#Kustomize: {
Name: _
Resources: {...}
Kustomization: metadata: name: string | *Name
Kustomization: apiObjectMap: (core.#APIObjects & {apiObjects: Resources}).apiObjectMap
if _ArgoConfig.Enabled {
let NAME = "gitops/\(_Name)"
// ArgoConfig represents the ArgoCD GitOps integration for this Component.
ArgoConfig: _
// Render the ArgoCD Application for GitOps as an additional Component of
// the BuildPlan.
spec: components: resources: (NAME): {
metadata: name: NAME
if _Namespace != _|_ {
metadata: namespace: _Namespace
}
BuildPlan: #BuildPlan & {
_Name: Name
_ArgoConfig: ArgoConfig
spec: components: kustomizeBuildList: [Kustomization]
}
}
deployFiles: (#Argo & {ComponentName: _Name, ArgoConfig: _ArgoConfig}).deployFiles
}
#Kubernetes: {
Name: _
Resources: {...}
Objects: metadata: name: string | *Name
Objects: apiObjectMap: (core.#APIObjects & {apiObjects: Resources}).apiObjectMap
// ArgoConfig represents the ArgoCD GitOps integration for this Component.
ArgoConfig: _
BuildPlan: #BuildPlan & {
_Name: Name
_ArgoConfig: ArgoConfig
spec: components: kubernetesObjectsList: [Objects]
}
}
@@ -146,7 +162,7 @@ import (
metadata: namespace: "argocd"
spec: {
destination: server: "https://kubernetes.default.svc"
project: "default"
project: ArgoConfig.AppProject
source: {
path: "\(ArgoConfig.DeployRoot)/deploy/clusters/\(ArgoConfig.ClusterName)/components/\(ComponentName)"
repoURL: ArgoConfig.RepoURL
@@ -176,58 +192,3 @@ import (
maxDuration: string | *"3m0s"
}
}
// #APIObjects defines the output format for kubernetes api objects. The holos
// cli expects the yaml representation of each api object in the apiObjectMap
// field.
#APIObjects: core.#APIObjects & {
// apiObjects represents the un-marshalled form of each kubernetes api object
// managed by a holos component.
apiObjects: {
[Kind=string]: {
[string]: {
kind: Kind
...
}
}
}
// apiObjectMap holds the marshalled representation of apiObjects
for kind, v in apiObjects {
for name, obj in v {
apiObjectMap: (kind): (name): yaml.Marshal(obj)
}
}
}
#Platform: {
Name: _
Model: _
Components: [string]: _
Output: metadata: name: Name
Output: spec: model: Model
Output: spec: components: [for c in Components {c}]
}
#Kustomize: {
Name: _
Kustomization: metadata: name: string | *Name
Output: #BuildPlan & {
_Name: Name
spec: components: kustomizeBuildList: [Kustomization]
}
}
#Kubernetes: {
Name: _
Resources: #Resources
Output: #BuildPlan & {
_Name: Name
// resources is a map unlike other build plans which use a list.
spec: components: resources: (Name): {
metadata: name: Name
apiObjectMap: (#APIObjects & {apiObjects: Resources}).apiObjectMap
}
}
}

View File

@@ -1,33 +1,12 @@
package v1alpha1
import "encoding/yaml"
import core "k8s.io/api/core/v1"
// #APIObjects defines the output format for kubernetes api objects. The holos
// cli expects the yaml representation of each api object in the apiObjectMap
// field.
#APIObjects: {
// apiObjects represents the un-marshalled form of each kubernetes api object
// managed by a holos component.
apiObjects: {
[Kind=string]: {
[string]: {
kind: Kind
...
}
}
ConfigMap: [string]: core.#ConfigMap & {apiVersion: "v1"}
}
apiObjects: [Kind=string]: [string]: kind: Kind
// apiObjectMap holds the marshalled representation of apiObjects
apiObjectMap: {
for kind, v in apiObjects {
"\(kind)": {
for name, obj in v {
"\(name)": yaml.Marshal(obj)
}
}
}
}
apiObjectsMap: [string]: [string]: string
}

View File

@@ -0,0 +1,44 @@
package holos
import (
corev1 "k8s.io/api/core/v1"
appsv1 "k8s.io/api/apps/v1"
rbacv1 "k8s.io/api/rbac/v1"
batchv1 "k8s.io/api/batch/v1"
ci "cert-manager.io/clusterissuer/v1"
rgv1 "gateway.networking.k8s.io/referencegrant/v1beta1"
certv1 "cert-manager.io/certificate/v1"
hrv1 "gateway.networking.k8s.io/httproute/v1"
gwv1 "gateway.networking.k8s.io/gateway/v1"
ap "argoproj.io/appproject/v1alpha1"
)
#Resources: {
[Kind=string]: [InternalLabel=string]: {
kind: Kind
metadata: name: string | *InternalLabel
}
AppProject: [_]: ap.#AppProject
Certificate: [_]: certv1.#Certificate
ClusterIssuer: [_]: ci.#ClusterIssuer
ClusterRole: [_]: rbacv1.#ClusterRole
ClusterRoleBinding: [_]: rbacv1.#ClusterRoleBinding
ConfigMap: [_]: corev1.#ConfigMap
CronJob: [_]: batchv1.#CronJob
Deployment: [_]: appsv1.#Deployment
HTTPRoute: [_]: hrv1.#HTTPRoute
Job: [_]: batchv1.#Job
Namespace: [_]: corev1.#Namespace
ReferenceGrant: [_]: rgv1.#ReferenceGrant
Role: [_]: rbacv1.#Role
RoleBinding: [_]: rbacv1.#RoleBinding
Service: [_]: corev1.#Service
ServiceAccount: [_]: corev1.#ServiceAccount
StatefulSet: [_]: appsv1.#StatefulSet
Gateway: [_]: gwv1.#Gateway & {
spec: gatewayClassName: string | *"istio"
}
}

View File

@@ -2,18 +2,18 @@ package holos
import schema "github.com/holos-run/holos/api/schema/v1alpha3"
#Helm: schema.#Helm & {
#Platform: schema.#Platform
#Fleets: schema.#StandardFleets
_ComponentConfig: {
Resources: #Resources
ArgoConfig: #ArgoConfig
}
#Kustomize: schema.#Kustomize
#Kubernetes: schema.#Kubernetes
#Helm: schema.#Helm & _ComponentConfig
#Kustomize: schema.#Kustomize & _ComponentConfig
#Kubernetes: schema.#Kubernetes & _ComponentConfig
#ArgoConfig: schema.#ArgoConfig & {
ClusterName: _ClusterName
}
#Fleets: schema.#StandardFleets
#Platform: schema.#Platform

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Image = "quay.io/holos-run/holos:v0.83.1-7-gd9fe32b"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
_AppInfo: spec: component: "infra"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
_AppInfo: spec: component: "routes"

View File

@@ -6,7 +6,7 @@ import (
)
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "argo-cd"

View File

@@ -1,4 +1,4 @@
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "argo-crds"}).Output
(#Kustomize & {Name: "argo-crds"}).BuildPlan

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "argo-creds"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "argocd-routes"

View File

@@ -14,7 +14,7 @@ import (
// Refer to [Using Cert Manager to Deploy TLS for Postgres on Kubernetes](https://www.crunchydata.com/blog/using-cert-manager-to-deploy-tls-for-postgres-on-kubernetes)
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let SelfSigned = "\(_DBName)-selfsigned"
let RootCA = "\(_DBName)-root-ca"

View File

@@ -3,7 +3,7 @@ package holos
import "encoding/yaml"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let ContainerPort = _Component.spec.port

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
// Restore from backup. Flip this to true after the database is provisioned and
// a backup has been taken.

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "\(_Component.metadata.name)-routes"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "backstage-secrets"

View File

@@ -3,7 +3,7 @@ package holos
import ci "cert-manager.io/clusterissuer/v1"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
// The cloudflare api token is platform scoped, not cluster scoped.
#SecretName: "cloudflare-api-token-secret"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "cert-manager"

View File

@@ -8,4 +8,4 @@ let Objects = {
}
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan

View File

@@ -8,7 +8,7 @@ import (
)
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
// https://github.com/crossplane/crossplane/releases
let CrossplaneVersion = "1.16.0"

View File

@@ -1,4 +1,4 @@
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "crossplane_crds"}).Output
(#Kustomize & {Name: "crossplane_crds"}).BuildPlan

View File

@@ -9,7 +9,7 @@ import (
let NAME = "ecr-creds-manager"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
// The path Pod Identity uses.
let MOUNT = "/var/run/secrets/eks.amazonaws.com/serviceaccount/"

View File

@@ -3,7 +3,7 @@ package holos
let NAME = "ecr-creds-refresher"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let AWS_ACCOUNT = _Platform.Model.aws.accountNumber

View File

@@ -45,4 +45,4 @@ let Chart = {
}
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan

View File

@@ -10,7 +10,7 @@ let REFRESHER = "eso-creds-refresher"
let EMAIL = _Platform.Model.eso.gcpServiceAccount
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: NAME

View File

@@ -10,7 +10,7 @@ import (
let NAME = "eso-creds-refresher"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: NAME

View File

@@ -12,4 +12,4 @@ let Chart = {
}
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan

View File

@@ -1,4 +1,4 @@
package holos
// Produce a kubectl kustomize build plan.
(#Kustomize & {Name: "gateway-api"}).Output
(#Kustomize & {Name: "gateway-api"}).BuildPlan

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istio-base"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "istio-cni"

View File

@@ -3,7 +3,7 @@ package holos
import "encoding/json"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "gateway"
@@ -42,10 +42,10 @@ let Objects = {
}
spec: {
// Work with a struct of listeners instead of a list.
_listeners: (#WildcardListener & {Name: "admin", Selector: _Selector.GrantSubdomainAdmin, Cluster: true}).Output
_listeners: (#WildcardListener & {Name: "login", Selector: _Selector.GrantSubdomainLogin, Cluster: false}).Output
_listeners: (#WildcardListener & {Name: "app", Selector: _Selector.GrantSubdomainApp, Cluster: false}).Output
_listeners: (#WildcardListener & {Name: "app", Selector: _Selector.GrantSubdomainApp, Cluster: true}).Output
_listeners: (#WildcardListener & {Name: "admin", Selector: _Selector.GrantSubdomainAdmin, Cluster: true}).BuildPlan
_listeners: (#WildcardListener & {Name: "login", Selector: _Selector.GrantSubdomainLogin, Cluster: false}).BuildPlan
_listeners: (#WildcardListener & {Name: "app", Selector: _Selector.GrantSubdomainApp, Cluster: false}).BuildPlan
_listeners: (#WildcardListener & {Name: "app", Selector: _Selector.GrantSubdomainApp, Cluster: true}).BuildPlan
listeners: [for x in _listeners {x}]
}
}

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "httpbin-backend"

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "httpbin-routes"
@@ -11,11 +11,11 @@ let Objects = {
Resources: [_]: [_]: metadata: namespace: Namespace
// Multiple HTTPRoutes to test Chrome http2 connection reuse with *.admin
// wildcard cert.
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin"}).Output
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin1"}).Output
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin2"}).Output
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin3"}).Output
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin4"}).Output
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin"}).BuildPlan
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin1"}).BuildPlan
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin2"}).BuildPlan
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin3"}).BuildPlan
HTTPRoute: (#HTTPRouteClone & {Name: "httpbin4"}).BuildPlan
}
}

View File

@@ -1,7 +1,7 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "authpolicy"

View File

@@ -3,7 +3,7 @@ package holos
import "encoding/yaml"
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let AuthProxyPrefix = _AuthProxy.pathPrefix

View File

@@ -3,7 +3,7 @@ package holos
import "encoding/json"
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
let Chart = {
Name: "gateway"

View File

@@ -3,9 +3,9 @@ package holos
import "encoding/yaml"
// Produce a helm chart build plan.
(#Helm & Chart).Output
(#Helm & Chart).BuildPlan
_MeshConfig: (#MeshConfig & {}).Output
_MeshConfig: (#MeshConfig & {}).BuildPlan
let Chart = {
Name: "istiod"

View File

@@ -14,7 +14,7 @@ import (
// Refer to [Using Cert Manager to Deploy TLS for Postgres on Kubernetes](https://www.crunchydata.com/blog/using-cert-manager-to-deploy-tls-for-postgres-on-kubernetes)
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).Output
(#Kubernetes & Objects).BuildPlan
let SelfSigned = "\(_DBName)-selfsigned"
let RootCA = "\(_DBName)-root-ca"

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