Compare commits

...

41 Commits

Author SHA1 Message Date
Jeff McCune
b737543c13 version: 0.95.0 2024-09-17 08:06:38 -07:00
Jeff McCune
8e150ee0d7 generate: fix external-secrets always out of sync in argocd
Without this patch ArgoCD treats the Application as constantly out of
sync.  This is also a good example of how to patch an arbitrary
component, though it patches the core BuildPlan itself now.  If this is
widely used, it would be nice to add this behavior to the schema api
(aka author api).
2024-09-16 21:22:23 -07:00
Jeff McCune
117a2a886d generate: fix istio-base always out of sync in argocd
Without this patch ArgoCD treats the Application as constantly out of
sync.  This is also a good example of how to patch an arbitrary
component, though it patches the core BuildPlan itself now.  If this is
widely used, it would be nice to add this behavior to the schema api
(aka author api).
2024-09-16 20:46:29 -07:00
Jeff McCune
79b41dfbf5 generate: fix istiod always out of sync in argocd
Without this patch ArgoCD treats the Application as constantly out of
sync.  This is also a good example of how to patch an arbitrary
component, though it patches the core BuildPlan itself now.  If this is
widely used, it would be nice to add this behavior to the schema api
(aka author api).
2024-09-16 20:38:35 -07:00
Jeff McCune
55562f9d83 generate: move istio-k3d schematic to projects structure
To match the current layout of the guide platform we're using for the
guides.
2024-09-16 20:02:23 -07:00
Jeff McCune
e0a636f183 generate: move gateway-api schematic to projects structure
To match the current layout of the guide platform we're using for the
guides.
2024-09-16 19:53:28 -07:00
Jeff McCune
1fa74214cf generate: move istio schematic to projects structure
To match the current layout of the guide platform we're using for the
guides.
2024-09-16 19:51:02 -07:00
Jeff McCune
e5851cac57 generate: fix bank of holos connection reset
Without this patch browsing https://bank.holos.localhost frequently gets
connection reset errors.  These errors are caused by the frontend
deployment redirecting the browser to http, which is not enabled on the
Gateway we use in the guides.

This patch sets the scheme to https which corrects the problems.

See https://github.com/GoogleCloudPlatform/bank-of-anthos/issues/478
2024-09-16 19:29:21 -07:00
Jeff McCune
4a26662b92 generate: add bank-contacts
Needed to load the home page of the Bank of Holos demo.
2024-09-16 19:29:02 -07:00
Jeff McCune
6bc6888ffc generate: add bank-transaction-history
Needed to load the home page of the Bank of Holos demo.
2024-09-16 17:00:15 -07:00
Jeff McCune
dab1f305e1 generate: add bank-balance-reader
Needed to load the home page of the Bank of Holos demo.
2024-09-16 16:52:52 -07:00
Jeff McCune
fbe79dd0af generate: add bank-ledger-db and bank-ledger-writer
Needed to load the home page of the Bank of Holos demo.
2024-09-16 16:46:35 -07:00
Jeff McCune
6d6829b149 generate: refactor bank backend config to a component
To fix ArgoCD SharedResourceWarning.
2024-09-16 16:18:31 -07:00
Jeff McCune
971a3fa280 generate: fix accounts-db using wrong service account
Needs to match the bank-of-holos service account name.
2024-09-16 15:58:50 -07:00
Jeff McCune
7632344cd1 generate: add bank-accounts-db needed by userservice
With this patch the frontend, accounts-db, and userservice all start and
become ready.

The user can log in, but on redirecting to home the site can't be
reached.
2024-09-16 15:51:29 -07:00
Jeff McCune
42067748ad generate: add bank userservice to backend 2024-09-16 15:49:25 -07:00
Jeff McCune
340c3484e5 generate: refactor how the bank jwt-key is created
This makes the example more re-usable, reader need only change the
SecretName, the bash script, and replace the #BankOfHolos references.
2024-09-16 15:02:12 -07:00
Jeff McCune
250238c286 generate: add secret store and external secret to bank-of-holos
Rather than commit the jwt private key to version control like upstream
does, we use a SecretStore and ExternalSecret to sync the secret
generated by the security team in the bank-security namespace.

With this patch the SecretStore validates and the ExternalSecret
automatically syncs the secret from the bank-security namespace to the
bank-frontend namespace.

```
❯ k get ss
NAME            AGE   STATUS   CAPABILITIES   READY
bank-security   1s    Valid    ReadWrite      True

❯ k get es
NAME      STORE           REFRESH INTERVAL   STATUS         READY
jwt-key   bank-security   5s                 SecretSynced   True
```

The pod start successfully.

```
❯ k get pods
NAME                        READY   STATUS    RESTARTS   AGE
frontend-646d797d6b-7jhrx   1/1     Running   0          2m39s

❯ k logs frontend-646d797d6b-7jhrx
{"timestamp": "2024-09-16 21:44:47", "message": "info | Starting gunicorn 22.0.0", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:47", "message": "info | Listening at: http://0.0.0.0:8080 (7)", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:47", "message": "info | Using worker: gthread", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:47", "message": "info | Booting worker with pid: 8", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:57", "message": "create_app | Unable to retrieve cluster name from metadata server metadata.google.internal.", "severity": "WARNING"}
{"timestamp": "2024-09-16 21:44:57", "message": "create_app | Unable to retrieve zone from metadata server metadata.google.internal.", "severity": "WARNING"}
{"timestamp": "2024-09-16 21:44:57", "message": "create_app | Starting frontend service.", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:57", "message": "create_app | 🚫 Tracing disabled.", "severity": "INFO"}
{"timestamp": "2024-09-16 21:44:57", "message": "create_app | Platform is set to 'local'", "severity": "INFO"}
```
2024-09-16 14:47:33 -07:00
Jeff McCune
a223e2b426 generate: fix duplicate external secrets crds
They're handled outside the helm chart to make upgrades easier.
2024-09-16 13:39:04 -07:00
Jeff McCune
63a7da02e7 generate: add external secrets operator
Need this to sync secrets into the bank-frontend and bank-backend
namespace from the bank-security namespace.
2024-09-16 13:29:03 -07:00
Jeff McCune
569f827e30 speed up argocd crds with raw urls 2024-09-16 13:29:02 -07:00
Jeff McCune
4a656db2ec render: log total render platform time 2024-09-16 13:29:02 -07:00
Jeff McCune
77b0933961 generate: add httproute for bank.holos.localhost
Expose Service frontend in the bank-frontend namespace via httproute
https://bank.holos.localhost

Organize into frontend, backend, security projects to align with three
teams who would each own this work.

remove secret from version control

Google added the secret to version control but we can generate the
secret in-cluster.  Holos makes it easier to manage the ExternalSecret
or RoleBinding necessary to get it in the right place.
2024-09-16 12:46:00 -07:00
Jeff McCune
3b796cfbbd generate: add bank-of-holos frontend
We need a way to demonstrate the value Holos offers in a platform team
managing projects for other teams.  This patch addresses the need by
establishing the bank-of-holos schematic, which is a port of the Bank of
Anthos project to Holos.

This patch adds only the frontend to get the process started.  As of
this patch the frontend pod starts and becomes ready but is not exposed
via HTTPRoute.

Refer to https://github.com/GoogleCloudPlatform/bank-of-anthos/
2024-09-15 22:08:28 -07:00
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
176 changed files with 8538 additions and 1361 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,37 @@
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://raw.githubusercontent.com/argoproj/argo-cd/v\(#ArgoCD.Version)/manifests/crds/application-crd.yaml",
"https://raw.githubusercontent.com/argoproj/argo-cd/v\(#ArgoCD.Version)/manifests/crds/applicationset-crd.yaml",
"https://raw.githubusercontent.com/argoproj/argo-cd/v\(#ArgoCD.Version)/manifests/crds/appproject-crd.yaml",
// This method also works, but takes about 5 seconds longer each build.
// "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,51 @@
package holos
// Manage on workload clusters only
for Cluster in #Fleets.workload.clusters {
// Owned by the security team
#Platform: Components: "\(Cluster.name)/bank-secrets": {
path: "projects/bank-of-holos/security/components/bank-secrets"
cluster: Cluster.name
}
// Owned by the frontend team
#Platform: Components: "\(Cluster.name)/bank-frontend": {
path: "projects/bank-of-holos/frontend/components/bank-frontend"
cluster: Cluster.name
}
// Owned by the backend team
#Platform: Components: "\(Cluster.name)/bank-backend-config": {
path: "projects/bank-of-holos/backend/components/bank-backend-config"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-accounts-db": {
path: "projects/bank-of-holos/backend/components/bank-accounts-db"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-userservice": {
path: "projects/bank-of-holos/backend/components/bank-userservice"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-ledger-db": {
path: "projects/bank-of-holos/backend/components/bank-ledger-db"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-ledger-writer": {
path: "projects/bank-of-holos/backend/components/bank-ledger-writer"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-balance-reader": {
path: "projects/bank-of-holos/backend/components/bank-balance-reader"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-transaction-history": {
path: "projects/bank-of-holos/backend/components/bank-transaction-history"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/bank-contacts": {
path: "projects/bank-of-holos/backend/components/bank-contacts"
cluster: Cluster.name
}
}

View File

@@ -0,0 +1,26 @@
package holos
// Platform wide definitions
#BankOfHolos: {
Name: "bank-of-holos"
Frontend: Namespace: "bank-frontend"
Backend: Namespace: "bank-backend"
Security: Namespace: "bank-security"
// Resources to manage in each of the namespaces.
Resources: #Resources
}
// Register namespaces
#Namespaces: (#BankOfHolos.Frontend.Namespace): _
#Namespaces: (#BankOfHolos.Backend.Namespace): _
#Namespaces: (#BankOfHolos.Security.Namespace): _
// Register projects
#AppProjects: "bank-frontend": _
#AppProjects: "bank-backend": _
#AppProjects: "bank-security": _
// Register HTTPRoutes.
// bank.example.com routes to Service frontend in the bank-frontend namespace.
#HTTPRoutes: bank: _backendRefs: frontend: namespace: #BankOfHolos.Frontend.Namespace

View File

@@ -0,0 +1,3 @@
package holos
#ArgoConfig: AppProject: #AppProjects["bank-backend"].metadata.name

View File

@@ -0,0 +1,122 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "accounts"
tier: "db"
}
let Objects = {
Name: "bank-accounts-db"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/accounts-db.yaml
Resources: {
ConfigMap: "accounts-db-config": {
apiVersion: "v1"
data: {
ACCOUNTS_DB_URI: "postgresql://accounts-admin:accounts-pwd@accounts-db:5432/accounts-db"
POSTGRES_DB: "accounts-db"
POSTGRES_PASSWORD: "accounts-pwd"
POSTGRES_USER: "accounts-admin"
}
kind: "ConfigMap"
metadata: {
labels: {
app: "accounts-db"
CommonLabels
}
name: "accounts-db-config"
}
}
Service: "accounts-db": {
apiVersion: "v1"
kind: "Service"
metadata: {
name: "accounts-db"
labels: CommonLabels
}
spec: {
ports: [{
name: "tcp"
port: 5432
protocol: "TCP"
targetPort: 5432
}]
selector: {
app: "accounts-db"
CommonLabels
}
type: "ClusterIP"
}
}
StatefulSet: "accounts-db": {
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata: {
name: "accounts-db"
labels: CommonLabels
}
spec: {
replicas: 1
selector: matchLabels: {
app: "accounts-db"
CommonLabels
}
serviceName: "accounts-db"
template: {
metadata: labels: {
app: "accounts-db"
CommonLabels
}
spec: {
containers: [{
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "accounts-db-config"
}, {
configMapRef: name: "demo-data-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/accounts-db:v0.6.5@sha256:abb955756a82b115e0fd9c5fa1527ae1a744b398b357fd6d7a26348feccad181"
name: "accounts-db"
ports: [{containerPort: 5432}]
resources: {
limits: {
cpu: "250m"
memory: "512Mi"
}
requests: {
cpu: "100m"
memory: "128Mi"
}
}
volumeMounts: [{
mountPath: "/var/lib/postgresql/data"
name: "postgresdb"
subPath: "postgres"
}]
}]
serviceAccount: BankName
serviceAccountName: BankName
volumes: [{
emptyDir: {}
name: "postgresdb"
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
tier: "backend"
}
let Objects = {
Name: "bank-backend-config"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [_]: metadata: labels: CommonLabels
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/userservice.yaml
Resources: {
// Allow HTTPRoutes in the ingress gateway namespace to reference Services
// in this namespace.
ReferenceGrant: grant: #ReferenceGrant & {
metadata: namespace: Namespace
}
// Include shared resources
#BankOfHolos.Resources
}
}

View File

@@ -0,0 +1,179 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "ledger"
tier: "backend"
}
let Objects = {
Name: "bank-balance-reader"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [_]: metadata: labels: CommonLabels
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests
Resources: {
Service: balancereader: {
apiVersion: "v1"
kind: "Service"
metadata: {
name: "balancereader"
labels: CommonLabels
}
spec: {
ports: [{
name: "http"
port: 8080
targetPort: 8080
}]
selector: {
app: "balancereader"
CommonLabels
}
type: "ClusterIP"
}
}
Deployment: balancereader: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
name: "balancereader"
labels: CommonLabels
}
spec: {
selector: matchLabels: {
app: "balancereader"
CommonLabels
}
template: {
metadata: labels: {
app: "balancereader"
CommonLabels
}
spec: {
containers: [{
env: [{
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "ENABLE_METRICS"
value: "false"
}, {
name: "POLL_MS"
value: "100"
}, {
name: "CACHE_SIZE"
value: "1000000"
}, {
name: "JVM_OPTS"
value: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms256m -Xmx512m"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "NAMESPACE"
valueFrom: fieldRef: fieldPath: "metadata.namespace"
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "ledger-db-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/balancereader:v0.6.5@sha256:de01f16554ae2d0b49ac85116e6307da8c0f8a35f50a0cf25e1e4a4fe18dca83"
livenessProbe: {
httpGet: {
path: "/healthy"
port: 8080
}
initialDelaySeconds: 120
periodSeconds: 5
timeoutSeconds: 10
}
name: "balancereader"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "500m"
"ephemeral-storage": "0.5Gi"
memory: "512Mi"
}
requests: {
cpu: "100m"
"ephemeral-storage": "0.5Gi"
memory: "256Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
startupProbe: {
failureThreshold: 30
httpGet: {
path: "/healthy"
port: 8080
}
periodSeconds: 10
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
securityContext: {
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: BankName
terminationGracePeriodSeconds: 5
volumes: [{
emptyDir: {}
name: "tmp"
}, {
name: "publickey"
secret: {
items: [{
key: "jwtRS256.key.pub"
path: "publickey"
}]
secretName: "jwt-key"
}
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,143 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "accounts"
tier: "backend"
}
let Objects = {
Name: "bank-contacts"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [_]: metadata: labels: CommonLabels
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests
Resources: {
Service: contacts: {
apiVersion: "v1"
kind: "Service"
metadata: name: "contacts"
spec: {
ports: [{
name: "http"
port: 8080
targetPort: 8080
}]
selector: {
app: "contacts"
CommonLabels
}
type: "ClusterIP"
}
}
Deployment: contacts: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: name: "contacts"
spec: {
selector: matchLabels: {
app: "contacts"
CommonLabels
}
template: {
metadata: {
labels: {
app: "contacts"
CommonLabels
}
}
spec: {
containers: [{
env: [{
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "LOG_LEVEL"
value: "info"
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "accounts-db-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/contacts:v0.6.5@sha256:e451dcac7d34a7bde979c7f02d4c7ebd83a77aff373e1131ce3a2bba2f7fdc1a"
name: "contacts"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "250m"
"ephemeral-storage": "0.25Gi"
memory: "128Mi"
}
requests: {
cpu: "100m"
"ephemeral-storage": "0.25Gi"
memory: "64Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
securityContext: {
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: BankName
terminationGracePeriodSeconds: 5
volumes: [{
emptyDir: {}
name: "tmp"
}, {
name: "publickey"
secret: {
items: [{
key: "jwtRS256.key.pub"
path: "publickey"
}]
secretName: "jwt-key"
}
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,121 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "ledger"
tier: "db"
}
let Objects = {
Name: "bank-ledger-db"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests
Resources: {
ConfigMap: "ledger-db-config": {
apiVersion: "v1"
metadata: {
name: "ledger-db-config"
labels: {
app: "ledger-db"
CommonLabels
}
}
data: {
POSTGRES_DB: "postgresdb"
POSTGRES_PASSWORD: "password"
POSTGRES_USER: "admin"
SPRING_DATASOURCE_PASSWORD: "password"
SPRING_DATASOURCE_URL: "jdbc:postgresql://ledger-db:5432/postgresdb"
SPRING_DATASOURCE_USERNAME: "admin"
}
}
Service: "ledger-db": {
apiVersion: "v1"
kind: "Service"
metadata: {
name: "ledger-db"
labels: CommonLabels
}
spec: {
ports: [{
name: "tcp"
port: 5432
targetPort: 5432
}]
selector: {
app: "ledger-db"
CommonLabels
}
type: "ClusterIP"
}
}
StatefulSet: "ledger-db": {
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata: {
name: "ledger-db"
labels: CommonLabels
}
spec: {
replicas: 1
selector: matchLabels: {
app: "ledger-db"
CommonLabels
}
serviceName: "ledger-db"
template: {
metadata: labels: {
app: "ledger-db"
CommonLabels
}
spec: {
containers: [{
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "ledger-db-config"
}, {
configMapRef: name: "demo-data-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/ledger-db:v0.6.5@sha256:cc4fd25f301ab6d46b1312244d6931babc4c6cb66c5cb6d31d4a1adfa318a321"
name: "postgres"
ports: [{containerPort: 5432}]
resources: {
limits: {
cpu: "250m"
memory: "1Gi"
}
requests: {
cpu: "100m"
memory: "512Mi"
}
}
volumeMounts: [{
mountPath: "/var/lib/postgresql/data"
name: "postgresdb"
subPath: "postgres"
}]
}]
serviceAccountName: BankName
volumes: [{
emptyDir: {}
name: "postgresdb"
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,169 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "ledger"
tier: "backend"
}
let Objects = {
Name: "bank-ledger-writer"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [_]: metadata: labels: CommonLabels
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests
Resources: {
Service: ledgerwriter: {
apiVersion: "v1"
kind: "Service"
metadata: {
name: "ledgerwriter"
labels: CommonLabels
}
spec: {
ports: [{
name: "http"
port: 8080
targetPort: 8080
}]
selector: {
app: "ledgerwriter"
CommonLabels
}
type: "ClusterIP"
}
}
Deployment: ledgerwriter: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
name: "ledgerwriter"
labels: CommonLabels
}
spec: {
selector: matchLabels: {
app: "ledgerwriter"
CommonLabels
}
template: {
metadata: {
labels: {
app: "ledgerwriter"
CommonLabels
}
}
spec: {
containers: [{
env: [{
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "ENABLE_METRICS"
value: "false"
}, {
name: "JVM_OPTS"
value: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms256m -Xmx512m"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "NAMESPACE"
valueFrom: fieldRef: fieldPath: "metadata.namespace"
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "service-api-config"
}, {
configMapRef: name: "ledger-db-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/ledgerwriter:v0.6.5@sha256:5b66d6888b87993c8ebe260fe33005c4e4bc2bdae4b5682874e1a078d37ff3b2"
name: "ledgerwriter"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "500m"
"ephemeral-storage": "0.5Gi"
memory: "512Mi"
}
requests: {
cpu: "100m"
"ephemeral-storage": "0.5Gi"
memory: "256Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
startupProbe: {
failureThreshold: 30
httpGet: {
path: "/ready"
port: 8080
}
periodSeconds: 10
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
securityContext: {
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: BankName
terminationGracePeriodSeconds: 5
volumes: [{
emptyDir: {}
name: "tmp"
}, {
name: "publickey"
secret: {
items: [{
key: "jwtRS256.key.pub"
path: "publickey"
}]
secretName: "jwt-key"
}
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,187 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "ledger"
tier: "backend"
}
let Objects = {
Name: "bank-transaction-history"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [_]: metadata: labels: CommonLabels
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests
Resources: {
Service: transactionhistory: {
apiVersion: "v1"
kind: "Service"
metadata: {
labels: CommonLabels
name: "transactionhistory"
}
spec: {
ports: [{
name: "http"
port: 8080
targetPort: 8080
}]
selector: {
app: "transactionhistory"
CommonLabels
}
type: "ClusterIP"
}
}
Deployment: transactionhistory: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: {
name: "transactionhistory"
labels: CommonLabels
}
spec: {
selector: matchLabels: {
app: "transactionhistory"
CommonLabels
}
template: {
metadata: {
labels: {
app: "transactionhistory"
CommonLabels
}
}
spec: {
containers: [{
env: [{
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "ENABLE_METRICS"
value: "false"
}, {
name: "POLL_MS"
value: "100"
}, {
name: "CACHE_SIZE"
value: "1000"
}, {
name: "CACHE_MINUTES"
value: "60"
}, {
name: "HISTORY_LIMIT"
value: "100"
}, {
name: "JVM_OPTS"
value: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms256m -Xmx512m"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "NAMESPACE"
valueFrom: fieldRef: fieldPath: "metadata.namespace"
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "ledger-db-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/transactionhistory:v0.6.5@sha256:54a2b0866df44a50832e71b130f3e069fe8bbce71309fb6cf390b19f64d92c09"
livenessProbe: {
httpGet: {
path: "/healthy"
port: 8080
}
initialDelaySeconds: 120
periodSeconds: 5
timeoutSeconds: 10
}
name: "transactionhistory"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 60
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "500m"
"ephemeral-storage": "0.5Gi"
memory: "512Mi"
}
requests: {
cpu: "100m"
"ephemeral-storage": "0.5Gi"
memory: "256Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
startupProbe: {
failureThreshold: 30
httpGet: {
path: "/healthy"
port: 8080
}
periodSeconds: 10
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
securityContext: {
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: BankName
terminationGracePeriodSeconds: 5
volumes: [{
emptyDir: {}
name: "tmp"
}, {
name: "publickey"
secret: {
items: [{
key: "jwtRS256.key.pub"
path: "publickey"
}]
secretName: "jwt-key"
}
}]
}
}
}
}
}
}

View File

@@ -0,0 +1,156 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let BankName = #BankOfHolos.Name
let CommonLabels = {
application: BankName
environment: "development"
team: "accounts"
tier: "backend"
}
let Objects = {
Name: "bank-userservice"
Namespace: #BankOfHolos.Backend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/userservice.yaml
Resources: {
Service: userservice: {
metadata: name: "userservice"
metadata: labels: CommonLabels
spec: {
selector: {
app: "userservice"
CommonLabels
}
_ports: http: {
name: "http"
port: 8080
targetPort: 8080
protocol: "TCP"
}
ports: [for x in _ports {x}]
}
}
Deployment: userservice: {
metadata: name: "userservice"
metadata: labels: CommonLabels
spec: {
selector: matchLabels: {
app: "userservice"
CommonLabels
}
template: {
metadata: labels: {
app: "userservice"
CommonLabels
}
spec: {
serviceAccountName: BankName
terminationGracePeriodSeconds: 5
containers: [{
env: [{
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "TOKEN_EXPIRY_SECONDS"
value: "3600"
}, {
name: "PRIV_KEY_PATH"
value: "/tmp/.ssh/privatekey"
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "accounts-db-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/userservice:v0.6.5@sha256:f91e0e5bd6cdb16f6b867b2e3e874b23dd01f11592de006776f1dfb136702941"
name: "userservice"
ports: [{
containerPort: 8080
name: "http-server"
}]
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "500m"
"ephemeral-storage": "0.25Gi"
memory: "256Mi"
}
requests: {
cpu: "260m"
"ephemeral-storage": "0.25Gi"
memory: "128Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "keys"
readOnly: true
}]
}]
volumes: [{
emptyDir: {}
name: "tmp"
}, {
name: "keys"
secret: {
secretName: "jwt-key"
items: [
{
key: "jwtRS256.key"
path: "privatekey"
},
{
key: "jwtRS256.key.pub"
path: "publickey"
},
]
}
}]
securityContext: {
seccompProfile: type: "RuntimeDefault"
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
}
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
package holos
import (
core "k8s.io/api/core/v1"
es "external-secrets.io/externalsecret/v1beta1"
ss "external-secrets.io/secretstore/v1beta1"
)
let BankName = #BankOfHolos.Name
#BankOfHolos: {
// Resources to make available in each of the project namespaces.
Resources: {
ServiceAccount: (BankName): core.#ServiceAccount & {
apiVersion: "v1"
kind: "ServiceAccount"
metadata: name: BankName
}
// SecretStore to fetch secrets owned by the security team
SecretStore: (BankName): ss.#SecretStore & {
metadata: name: #BankOfHolos.Security.Namespace
spec: provider: {
kubernetes: {
remoteNamespace: #BankOfHolos.Security.Namespace
auth: serviceAccount: name: ServiceAccount[BankName].metadata.name
server: {
url: "https://kubernetes.default.svc"
caProvider: {
type: "ConfigMap"
name: "kube-root-ca.crt"
key: "ca.crt"
}
}
}
}
}
// We do not check the private key into version control.
// https://github.com/GoogleCloudPlatform/bank-of-anthos/tree/v0.6.5/extras/jwt
ExternalSecret: "jwt-key": es.#ExternalSecret & {
metadata: name: "jwt-key"
spec: {
target: name: metadata.name
dataFrom: [{extract: {key: metadata.name}}]
refreshInterval: "5s"
secretStoreRef: kind: "SecretStore"
secretStoreRef: name: SecretStore[BankName].metadata.name
}
}
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/config.yaml
ConfigMap: "environment-config": core.#ConfigMap & {
apiVersion: "v1"
kind: "ConfigMap"
metadata: name: "environment-config"
data: {
LOCAL_ROUTING_NUM: "883745000"
PUB_KEY_PATH: "/tmp/.ssh/publickey"
}
}
ConfigMap: "service-api-config": core.#ConfigMap & {
apiVersion: "v1"
kind: "ConfigMap"
metadata: name: "service-api-config"
data: {
TRANSACTIONS_API_ADDR: "ledgerwriter.\(#BankOfHolos.Backend.Namespace).svc:8080"
BALANCES_API_ADDR: "balancereader.\(#BankOfHolos.Backend.Namespace).svc:8080"
HISTORY_API_ADDR: "transactionhistory.\(#BankOfHolos.Backend.Namespace).svc:8080"
CONTACTS_API_ADDR: "contacts.\(#BankOfHolos.Backend.Namespace).svc:8080"
USERSERVICE_API_ADDR: "userservice.\(#BankOfHolos.Backend.Namespace).svc:8080"
}
}
ConfigMap: "demo-data-config": core.#ConfigMap & {
apiVersion: "v1"
kind: "ConfigMap"
metadata: name: "demo-data-config"
data: {
USE_DEMO_DATA: "True"
DEMO_LOGIN_USERNAME: "testuser"
// All demo user accounts are hardcoded to use the login password 'bankofanthos'
DEMO_LOGIN_PASSWORD: "bankofanthos"
}
}
}
}

View File

@@ -0,0 +1,201 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "bank-frontend"
Namespace: #BankOfHolos.Frontend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/frontend.yaml
Resources: {
Service: frontend: {
metadata: name: "frontend"
metadata: labels: {
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
selector: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
_ports: http: {
name: "http"
port: 80
targetPort: 8080
protocol: "TCP"
}
ports: [for x in _ports {x}]
}
}
Deployment: frontend: {
metadata: name: "frontend"
metadata: labels: {
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
selector: matchLabels: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
template: {
metadata: labels: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
securityContext: {
seccompProfile: type: "RuntimeDefault"
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: "bank-of-holos"
terminationGracePeriodSeconds: 5
containers: [{
env: [{
name: "BANK_NAME"
value: "Bank of Holos"
}, {
name: "ENV_PLATFORM"
value: "local"
}, {
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "SCHEME"
value: "https"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "DEFAULT_USERNAME"
valueFrom: configMapKeyRef: {
key: "DEMO_LOGIN_USERNAME"
name: "demo-data-config"
}
}, {
name: "DEFAULT_PASSWORD"
valueFrom: configMapKeyRef: {
key: "DEMO_LOGIN_PASSWORD"
name: "demo-data-config"
}
}, {
name: "REGISTERED_OAUTH_CLIENT_ID"
valueFrom: configMapKeyRef: {
key: "DEMO_OAUTH_CLIENT_ID"
name: "oauth-config"
optional: true
}
}, {
name: "ALLOWED_OAUTH_REDIRECT_URI"
valueFrom: configMapKeyRef: {
key: "DEMO_OAUTH_REDIRECT_URI"
name: "oauth-config"
optional: true
}
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "service-api-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/frontend:v0.6.5@sha256:d72050f70d12383e4434ad04d189b681dc625f696087ddf0b5df641645c9dafa"
livenessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 60
periodSeconds: 15
timeoutSeconds: 30
}
name: "front"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "250m"
memory: "128Mi"
}
requests: {
cpu: "100m"
memory: "64Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
volumes: [
{
emptyDir: {}
name: "tmp"
},
{
name: "publickey"
secret: {
items: [{key: "jwtRS256.key.pub", path: "publickey"}]
secretName: "jwt-key"
}
},
]
}
}
}
}
// Allow HTTPRoutes in the ingress gateway namespace to reference Services
// in this namespace.
ReferenceGrant: grant: #ReferenceGrant & {
metadata: namespace: Namespace
}
// Include shared resources
#BankOfHolos.Resources
}
}

View File

@@ -0,0 +1,3 @@
package holos
#ArgoConfig: AppProject: #AppProjects["bank-frontend"].metadata.name

View File

@@ -0,0 +1,165 @@
package holos
import (
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
batchv1 "k8s.io/api/batch/v1"
)
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
// This may be useful to copy and generate other secrets.
let SecretName = "jwt-key"
// Roles for reading and writing secrets
let Reader = "\(SecretName)-reader"
let Writer = "\(SecretName)-writer"
// AllowedName represents the service account allowed to read the generated
// secret.
let AllowedName = #BankOfHolos.Name
let Objects = {
Name: "bank-secrets"
Namespace: #BankOfHolos.Security.Namespace
Resources: [_]: [_]: metadata: namespace: Namespace
Resources: [_]: [ID=string]: metadata: name: string | *ID
Resources: {
// Kubernetes ServiceAccount used by the secret generator job.
ServiceAccount: (Writer): corev1.#ServiceAccount
// Role to allow the ServiceAccount to update secrets.
Role: (Writer): rbacv1.#Role & {
rules: [{
apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "update", "patch"]
}]
}
// Bind the role to the service account.
RoleBinding: (Writer): rbacv1.#RoleBinding & {
roleRef: {
apiGroup: "rbac.authorization.k8s.io"
kind: "Role"
name: Role[Writer].metadata.name
}
subjects: [{
kind: "ServiceAccount"
name: ServiceAccount[Writer].metadata.name
namespace: Namespace
}]
}
let JobSpec = {
serviceAccountName: Writer
restartPolicy: "OnFailure"
securityContext: {
seccompProfile: type: "RuntimeDefault"
runAsNonRoot: true
runAsUser: 8192 // app
}
containers: [
{
name: "toolkit"
image: "quay.io/holos-run/toolkit:2024-09-16"
securityContext: {
capabilities: drop: ["ALL"]
allowPrivilegeEscalation: false
}
command: ["/bin/bash"]
args: ["/config/entrypoint"]
env: [{
name: "HOME"
value: "/tmp"
}]
volumeMounts: [{
name: "config"
mountPath: "/config"
readOnly: true
}]
},
]
volumes: [{
name: "config"
configMap: name: Writer
}]
}
Job: (Writer): batchv1.#Job & {
spec: template: spec: JobSpec
}
ConfigMap: (Writer): corev1.#ConfigMap & {
data: entrypoint: ENTRYPOINT
}
// Allow the SecretStore in the frontend and backend namespaces to read the
// secret.
Role: (Reader): rbacv1.#Role & {
rules: [{
apiGroups: [""]
resources: ["secrets"]
resourceNames: [SecretName]
verbs: ["get"]
}]
}
// Grant access to the bank-of-holos service account in the frontend and
// backend namespaces.
RoleBinding: (Reader): rbacv1.#RoleBinding & {
roleRef: {
apiGroup: "rbac.authorization.k8s.io"
kind: "Role"
name: Role[Reader].metadata.name
}
subjects: [{
kind: "ServiceAccount"
name: AllowedName
namespace: #BankOfHolos.Frontend.Namespace
}, {
kind: "ServiceAccount"
name: AllowedName
namespace: #BankOfHolos.Backend.Namespace
},
]
}
}
}
let ENTRYPOINT = """
#! /bin/bash
#
tmpdir="$(mktemp -d)"
finish() {
status=$?
rm -rf "${tmpdir}"
return $status
}
trap finish EXIT
set -euo pipefail
cd "$tmpdir"
mkdir secret
cd secret
echo "generating private key" >&2
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key -q -N "" -C \(AllowedName)
echo "generating public key" >&2
ssh-keygen -e -m PKCS8 -f jwtRS256.key > jwtRS256.key.pub
cd ..
echo "copying secret into kubernetes manifest secret.yaml" >&2
kubectl create secret generic \(SecretName) --from-file=secret --dry-run=client -o yaml > secret.yaml
echo "applying secret.yaml" >&2
kubectl apply --server-side=true -f secret.yaml
echo "cleaning up" >&2
rm -rf secret secret.yaml
echo "ok done" >&2
"""

View File

@@ -0,0 +1,3 @@
package holos
#ArgoConfig: AppProject: #AppProjects["bank-security"].metadata.name

View File

@@ -0,0 +1,5 @@
{
"name": "bank-of-holos",
"short": "demo bank composed of two projects",
"long": "Bank of Holos is a sample HTTP-based web app that simulates a bank's payment processing network, allowing users to create artificial bank accounts and complete transactions."
}

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

@@ -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)/external-secrets-crds": {
path: "projects/platform/components/external-secrets-crds"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name)/external-secrets": {
path: "projects/platform/components/external-secrets"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,10 @@
package holos
// Platform wide configuration
#ExternalSecrets: {
Version: "{{ .Version }}"
Namespace: "external-secrets"
}
// Register the namespace
#Namespaces: (#ExternalSecrets.Namespace): _

View File

@@ -0,0 +1,33 @@
package holos
import (
"encoding/yaml"
ks "sigs.k8s.io/kustomize/api/types"
)
(#Kubernetes & {Name: "external-secrets-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"
_Kustomization: ks.#Kustomization & {
apiVersion: "kustomize.config.k8s.io/v1beta1"
kind: "Kustomization"
resources: [
// Kustomize the intermediate build plan resources.
BuildPlanResources,
// Mix-in external resources.
"https://raw.githubusercontent.com/external-secrets/external-secrets/v\(#ExternalSecrets.Version)/deploy/crds/bundle.yaml",
]
}
// 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,50 @@
package holos
import (
"encoding/yaml"
ks "sigs.k8s.io/kustomize/api/types"
)
// Patch the the build plan output.
_Kustomization: patches: [for x in KustomizePatches {x}]
#KustomizePatches: [ArbitraryLabel=string]: ks.#Patch
let KustomizePatches = #KustomizePatches & {
let Patch = [{
op: "replace"
path: "/spec/conversion/webhook/clientConfig/service/name"
value: "external-secrets-webhook"
}, {
op: "replace"
path: "/spec/conversion/webhook/clientConfig/service/namespace"
value: "external-secrets"
}]
clustersecretstores: {
target: {
group: "apiextensions.k8s.io"
version: "v1"
kind: "CustomResourceDefinition"
name: "clustersecretstores.external-secrets.io"
}
patch: yaml.Marshal(Patch)
}
externalsecrets: {
target: {
group: "apiextensions.k8s.io"
version: "v1"
kind: "CustomResourceDefinition"
name: "externalsecrets.external-secrets.io"
}
patch: yaml.Marshal(Patch)
}
secretstores: {
target: {
group: "apiextensions.k8s.io"
version: "v1"
kind: "CustomResourceDefinition"
name: "secretstores.external-secrets.io"
}
patch: yaml.Marshal(Patch)
}
}

View File

@@ -0,0 +1,15 @@
package holos
_Chart: {
Name: "external-secrets"
Version: "0.10.3"
Namespace: "external-secrets"
Repo: name: "external-secrets"
Repo: url: "https://charts.external-secrets.io"
Values: installCRDs: false
}
// Produce a helm chart build plan.
(#Helm & _Chart).BuildPlan

View File

@@ -0,0 +1,6 @@
{
"name": "external-secrets",
"short": "safer secret management",
"long": "https://external-secrets.io",
"version": "0.10.3"
}

View File

@@ -4,7 +4,7 @@ package holos
for Fleet in #Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name)/gateway-api": {
path: "components/gateway-api"
path: "projects/platform/components/gateway-api"
cluster: Cluster.name
}
}

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,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,45 +0,0 @@
package holos
// #Istio represents platform wide configuration
#Istio: {
Version: "1.23.1"
System: Namespace: "istio-system"
Gateway: Namespace: "istio-ingress"
// Constrain Helm values for safer, easier upgrades and consistency across
// platform components.
Values: global: istioNamespace: System.Namespace
// Configure ambient mode
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
}
}
}

View File

@@ -0,0 +1,24 @@
package holos
// #Istio represents platform wide configuration
// Manage istio on workload clusters
for Cluster in #Fleets.workload.clusters {
#Platform: Components: {
"\(Cluster.name)/istio-base": {
path: "projects/platform/components/istio/base"
cluster: Cluster.name
}
"\(Cluster.name)/istiod": {
path: "projects/platform/components/istio/istiod"
cluster: Cluster.name
}
"\(Cluster.name)/istio-cni": {
path: "projects/platform/components/istio/cni"
cluster: Cluster.name
}
"\(Cluster.name)/istio-ztunnel": {
path: "projects/platform/components/istio/ztunnel"
cluster: Cluster.name
}
}
}

View File

@@ -0,0 +1,17 @@
package holos
// #Istio represents platform wide configuration
#Istio: {
Version: "1.23.1"
System: Namespace: "istio-system"
// Constrain Helm values for safer, easier upgrades and consistency across
// platform components.
Values: global: istioNamespace: System.Namespace
// Configure ambient mode
Values: profile: "ambient"
}
// Register the Namespaces
#Namespaces: (#Istio.System.Namespace): _

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

@@ -0,0 +1,48 @@
package holos
import (
"encoding/yaml"
ks "sigs.k8s.io/kustomize/api/types"
)
// 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 BuildPlanOutputManifest = "build-plan-output-manifest.yaml"
// Patch istio so it's not constantly out of sync in ArgoCD
let Kustomization = ks.#Kustomization & {
apiVersion: "kustomize.config.k8s.io/v1beta1"
kind: "Kustomization"
// Kustomize the build plan output.
resources: [BuildPlanOutputManifest]
// Patch the the build plan output.
patches: [for x in KustomizePatches {x}]
}
#KustomizePatches: [ArbitraryLabel=string]: ks.#Patch
let KustomizePatches = #KustomizePatches & {
validator: {
target: {
group: "admissionregistration.k8s.io"
version: "v1"
kind: "ValidatingWebhookConfiguration"
name: "istiod-default-validator"
}
let Patch = [{
op: "replace"
path: "/webhooks/0/failurePolicy"
value: "Fail"
}]
patch: yaml.Marshal(Patch)
}
}
// Generate a kustomization.yaml directly from CUE so we can provide the correct
// version.
spec: components: helmChartList: [{
// intermediate build plan resources to kustomize. Necessary to activate the
// kustomization post-rendering step in holos.
kustomize: resourcesFile: BuildPlanOutputManifest
kustomize: kustomizeFiles: "kustomization.yaml": yaml.Marshal(Kustomization)
}]

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

@@ -0,0 +1,61 @@
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "istio-gateway"
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,48 @@
package holos
import (
"encoding/yaml"
ks "sigs.k8s.io/kustomize/api/types"
)
// 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 BuildPlanOutputManifest = "build-plan-output-manifest.yaml"
// Patch istio so it's not constantly out of sync in ArgoCD
let Kustomization = ks.#Kustomization & {
apiVersion: "kustomize.config.k8s.io/v1beta1"
kind: "Kustomization"
// Kustomize the build plan output.
resources: [BuildPlanOutputManifest]
// Patch the the build plan output.
patches: [for x in KustomizePatches {x}]
}
#KustomizePatches: [ArbitraryLabel=string]: ks.#Patch
let KustomizePatches = #KustomizePatches & {
validator: {
target: {
group: "admissionregistration.k8s.io"
version: "v1"
kind: "ValidatingWebhookConfiguration"
name: "istio-validator-istio-system"
}
let Patch = [{
op: "replace"
path: "/webhooks/0/failurePolicy"
value: "Fail"
}]
patch: yaml.Marshal(Patch)
}
}
// Generate a kustomization.yaml directly from CUE so we can provide the correct
// version.
spec: components: helmChartList: [{
// intermediate build plan resources to kustomize. Necessary to activate the
// kustomization post-rendering step in holos.
kustomize: resourcesFile: BuildPlanOutputManifest
kustomize: kustomizeFiles: "kustomization.yaml": yaml.Marshal(Kustomization)
}]

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

@@ -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"
}

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