Compare commits

...

59 Commits

Author SHA1 Message Date
Jeff McCune
6a47edbc3d guides: Add Change Service Guide (#253)
This patch also adds Organization to the Author API as an example of a
regular expression constraint.
2024-09-23 19:54:46 -07:00
Jeff McCune
67d00f1dd4 website: get rid of What is Holos? on landing page 2024-09-23 14:08:09 -07:00
Jeff McCune
bfa02cd6ed website: introduction (#258) 2024-09-23 13:45:28 -07:00
Jeff McCune
2d8ca474f3 website: Landing Page 3 (#256) 2024-09-23 10:08:25 -07:00
Jeff McCune
c7cd6f5190 website: Landing Page 2 (#256) 2024-09-20 17:14:34 -07:00
Jeff McCune
21e3e6f5e4 website: Landing Page 1 (#256) 2024-09-20 14:57:40 -07:00
Jeff McCune
16a4f89c2f doc: clarify story in the deploy a service guide pass 2
Focus on the migration team and platform team.
2024-09-20 11:12:41 -07:00
Jeff McCune
f15dea5ee7 doc: clarify story in the deploy a service guide
Focus on the migration team and platform team.
2024-09-20 11:02:41 -07:00
Jeff McCune
a3bbadd1f5 doc: apply manifests for deploy a service guide
This gets us through to the end with podinfo deployed.  Need to tell the
story of the migration team a bit better though, working with the
platform team to expose the service.
2024-09-20 09:42:00 -07:00
Jeff McCune
30cbb0d537 doc: add deploy a service guide
Covers wrapping a helm chart with a Holos Component.
2024-09-19 21:31:45 -07:00
Jeff McCune
6041fd4d76 website: fix broken links 2024-09-19 09:51:27 -07:00
Jeff McCune
fec1de0004 website: holistic platform manager social card 2024-09-19 09:49:56 -07:00
Jeff McCune
6ad24a6eec package: rename schema api to author api (#248)
Schema API is unclear, Author API is more clear the API is intended for
component authors.
2024-09-19 08:51:01 -07:00
Jeff McCune
57dedc6450 website: clean up placeholders 2024-09-19 08:30:31 -07:00
Jeff McCune
8d2a9dd659 quickstart: re-focus on core concepts 2024-09-18 17:24:44 -07:00
Jeff McCune
e3c53f5655 website: tweak features on landing page for clarity 2024-09-18 13:44:44 -07:00
Jeff McCune
3b833cdacd website: update landing page to focus on platform management
Instead of package management.
2024-09-18 13:41:36 -07:00
Jeff McCune
31d1086345 render: shorten the component rendered in the output
It's too long for documentation.  Shorten it for clarity.

Result:

```
❯ holos render platform ./platform
rendered bank-accounts-db for cluster workload in 160.7245ms
rendered bank-ledger-db for cluster workload in 162.465625ms
rendered bank-userservice for cluster workload in 166.150417ms
rendered bank-ledger-writer for cluster workload in 168.075459ms
rendered bank-balance-reader for cluster workload in 172.492292ms
rendered bank-backend-config for cluster workload in 198.117916ms
rendered bank-secrets for cluster workload in 223.200042ms
rendered gateway for cluster workload in 124.841917ms
rendered httproutes for cluster workload in 131.86625ms
rendered bank-contacts for cluster workload in 154.463792ms
rendered bank-transaction-history for cluster workload in 159.968208ms
rendered bank-frontend for cluster workload in 325.24425ms
rendered app-projects for cluster workload in 110.577916ms
rendered ztunnel for cluster workload in 137.502792ms
rendered cni for cluster workload in 209.993375ms
rendered cert-manager for cluster workload in 172.933834ms
rendered external-secrets for cluster workload in 135.759792ms
rendered local-ca for cluster workload in 98.026708ms
rendered istiod for cluster workload in 403.050833ms
rendered argocd for cluster workload in 294.663167ms
rendered gateway-api for cluster workload in 228.47875ms
rendered namespaces for cluster workload in 113.586916ms
rendered base for cluster workload in 533.76675ms
rendered external-secrets-crds for cluster workload in 529.053375ms
rendered crds for cluster workload in 931.180458ms
rendered platform in 1.248310167s
```

Previously:

```
❯ holos render platform ./platform
rendered projects/bank-of-holos/backend/components/bank-ledger-db for cluster workload in 158.534875ms
rendered projects/bank-of-holos/backend/components/bank-accounts-db for cluster workload in 159.836166ms
rendered projects/bank-of-holos/backend/components/bank-userservice for cluster workload in 160.360667ms
rendered projects/bank-of-holos/backend/components/bank-balance-reader for cluster workload in 169.478584ms
rendered projects/bank-of-holos/backend/components/bank-ledger-writer for cluster workload in 169.437833ms
rendered projects/bank-of-holos/backend/components/bank-backend-config for cluster workload in 182.089333ms
rendered projects/bank-of-holos/security/components/bank-secrets for cluster workload in 196.502792ms
rendered projects/platform/components/istio/gateway for cluster workload in 122.273083ms
rendered projects/bank-of-holos/frontend/components/bank-frontend for cluster workload in 307.573584ms
rendered projects/platform/components/httproutes for cluster workload in 149.631583ms
rendered projects/bank-of-holos/backend/components/bank-contacts for cluster workload in 153.529708ms
rendered projects/bank-of-holos/backend/components/bank-transaction-history for cluster workload in 165.375667ms
rendered projects/platform/components/app-projects for cluster workload in 107.253958ms
rendered projects/platform/components/istio/ztunnel for cluster workload in 137.22275ms
rendered projects/platform/components/istio/cni for cluster workload in 233.980958ms
rendered projects/platform/components/cert-manager for cluster workload in 171.966958ms
rendered projects/platform/components/external-secrets for cluster workload in 134.207792ms
rendered projects/platform/components/istio/istiod for cluster workload in 403.19ms
rendered projects/platform/components/local-ca for cluster workload in 97.544708ms
rendered projects/platform/components/argocd/argocd for cluster workload in 289.577208ms
rendered projects/platform/components/gateway-api for cluster workload in 218.290458ms
rendered projects/platform/components/namespaces for cluster workload in 109.534125ms
rendered projects/platform/components/istio/base for cluster workload in 526.32525ms
rendered projects/platform/components/external-secrets-crds for cluster workload in 523.7495ms
rendered projects/platform/components/argocd/crds for cluster workload in 1.002546375s
rendered platform in 1.312824333s
```
2024-09-17 11:40:14 -07:00
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
207 changed files with 12462 additions and 2101 deletions

View File

@@ -5,22 +5,34 @@
"mdx"
],
"words": [
"acraccesstokens",
"admissionregistration",
"anthos",
"apiextensions",
"applicationset",
"applicationsets",
"appproject",
"appprojects",
"argoproj",
"authcode",
"authorizationpolicies",
"authpolicy",
"authproxy",
"authroutes",
"balancereader",
"buildplan",
"cainjector",
"CAROOT",
"certificaterequests",
"certificatesigningrequests",
"clsx",
"clusterexternalsecrets",
"clusterissuer",
"clusterissuers",
"clusterrole",
"clusterrolebinding",
"clustersecretstores",
"CNCF",
"configmap",
"cookiesecret",
"coredns",
@@ -37,15 +49,22 @@
"devicecode",
"dnsmasq",
"dscacheutil",
"ecrauthorizationtokens",
"entgo",
"envoyfilters",
"errgroup",
"etcdsnapshotfiles",
"externalsecret",
"externalsecrets",
"fctr",
"fieldmaskpb",
"flushcache",
"gatewayclasses",
"gcraccesstokens",
"gendoc",
"ggnpl",
"ghaction",
"githubaccesstokens",
"gitops",
"godoc",
"golangci",
@@ -53,16 +72,23 @@
"grpcreflect",
"grpcroutes",
"grpcurl",
"healthz",
"helmchartconfigs",
"helmcharts",
"holos",
"holoslogger",
"horizontalpodautoscaler",
"httpbin",
"httproute",
"httproutes",
"Infima",
"isatty",
"istiod",
"jbrx",
"jeffmccune",
"jetstack",
"Jsonnet",
"kfbh",
"killall",
"kubeadm",
"kubeconfig",
@@ -71,12 +97,16 @@
"Kustomizations",
"kustomize",
"ldflags",
"leaderelection",
"ledgerwriter",
"libnss",
"loadbalancer",
"mattn",
"mccutchen",
"mindmap",
"mktemp",
"msqbn",
"mtls",
"Multicluster",
"mutatingwebhookconfiguration",
"mxcl",
@@ -86,11 +116,13 @@
"orgid",
"otelconnect",
"Parentspanid",
"pcjc",
"peerauthentications",
"pflag",
"pipefail",
"PKCE",
"platformconnect",
"podcli",
"poddisruptionbudget",
"podinfo",
"portmapping",
@@ -99,24 +131,33 @@
"protojson",
"proxyconfigs",
"Pulumi",
"pushsecrets",
"putenv",
"qjbp",
"quickstart",
"readyz",
"referencegrant",
"referencegrants",
"requestauthentications",
"retryable",
"rolebinding",
"ropc",
"seccomp",
"SECRETKEY",
"secretstore",
"secretstores",
"serverlb",
"serverside",
"serviceaccount",
"servicebindings",
"serviceentries",
"spanid",
"spiffe",
"startupapicheck",
"statefulset",
"stefanprodan",
"structpb",
"subjectaccessreviews",
"svclb",
"systemconnect",
"tablewriter",
@@ -128,14 +169,18 @@
"Tokener",
"Traceid",
"traefik",
"transactionhistory",
"uibutton",
"unstage",
"untar",
"Upsert",
"urandom",
"usecases",
"userconnect",
"userdata",
"userservice",
"validatingwebhookconfiguration",
"vaultdynamicsecrets",
"virtualservices",
"wasmplugins",
"workloadentries",

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,27 @@ 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\""`
}
// 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
// Organization represents organizational metadata useful across the platform.
type Organization struct {
Name string
DisplayName string
}
// 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
// OrganizationStrict represents organizational metadata useful across the
// platform. This is an example of using CUE regular expressions to constrain
// and validate configuration.
type OrganizationStrict struct {
Organization `json:",inline"`
// Name represents the organization name as a resource name. Must be 63
// characters or less. Must start with a letter. May contain non-repeating
// hyphens, letters, and numbers. Must end with a letter or number.
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
// DisplayName represents the human readable organization name.
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
}

View File

@@ -1,5 +1,5 @@
import DocCardList from '@theme/DocCardList';
# Schema API
# Author API
<DocCardList />

View File

@@ -3,7 +3,7 @@
# v1alpha3
```go
import "github.com/holos-run/holos/api/schema/v1alpha3"
import "github.com/holos-run/holos/api/author/v1alpha3"
```
Package v1alpha3 contains CUE definitions intended as convenience wrappers around the core data types defined in package core. The purpose of these wrappers is to make life easier for platform engineers by reducing boiler plate code and generating component build plans in a consistent manner.
@@ -12,10 +12,13 @@ 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>)
- [type Kustomize](<#Kustomize>)
- [type Organization](<#Organization>)
- [type OrganizationStrict](<#OrganizationStrict>)
- [type Platform](<#Platform>)
- [type StandardFleets](<#StandardFleets>)
@@ -43,6 +46,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 +67,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 +105,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 +145,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 +155,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 +168,38 @@ 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
<a name="Organization"></a>
## type Organization {#Organization}
Organization represents organizational metadata useful across the platform.
```go
type Organization struct {
Name string
DisplayName string
}
```
<a name="OrganizationStrict"></a>
## type OrganizationStrict {#OrganizationStrict}
OrganizationStrict represents organizational metadata useful across the platform. This is an example of using CUE regular expressions to constrain and validate configuration.
```go
type OrganizationStrict struct {
Organization `json:",inline"`
// Name represents the organization name as a resource name. Must be 63
// characters or less. Must start with a letter. May contain non-repeating
// hyphens, letters, and numbers. Must end with a letter or number.
Name string `cue:"=~ \"^[a-z][0-9a-z-]{1,61}[0-9a-z]$\" & !~ \"--\""`
// DisplayName represents the human readable organization name.
DisplayName string `cue:"=~ \"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$\" & !~ \" \""`
}
```
@@ -185,6 +220,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\""`
}
```

View File

@@ -0,0 +1,724 @@
---
description: Try Holos with this quick start guide.
slug: /archive/2024-09-15-quickstart
sidebar_position: 100
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
# Quickstart
In this guide, you'll experience how Holos makes the process of operating a
Platform safer, easier, and more consistent. We'll use Holos to manage a
vendor-provided Helm chart as a Component. Next, we'll mix in our own custom
resources to manage the Component with GitOps. Finally, you'll see how Holos
makes it safer and easier to maintain software over time by surfacing the exact
changes that will be applied when upgrading the vendor's chart to a new version,
before they are actually made.
The [Concepts](/docs/concepts) page defines capitalized terms such as Platform
and Component.
## What you'll need {#requirements}
You'll need the following tools installed to complete this guide.
1. [holos](/docs/install) - to build the Platform.
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos Components that
wrap upstream Helm charts.
Optionally, if you'd like to apply the rendered manifests to a real Cluster,
first complete the [Local Cluster Guide](/docs/guides/local-cluster).
## Install Holos
Install Holos with the following command or other methods listed on the
[Installation](/docs/install/) page.
```bash
go install github.com/holos-run/holos/cmd/holos@latest
```
## Create a Git Repository
Start by initializing an empty Git repository. Holos operates on local files
stored in a Git repository.
<Tabs groupId="init">
<TabItem value="command" label="Command">
```bash
mkdir holos-quickstart
cd holos-quickstart
git init
```
</TabItem>
<TabItem value="output" label="Output">
```txt
Initialized empty Git repository in /holos-quickstart/.git/
```
</TabItem>
</Tabs>
This guide assumes you will run commands from the root directory of the Git
repository unless stated otherwise.
## Generate the Platform {#Generate-Platform}
Generate the Platform code in the repository root. A Platform refers to the
entire set of software holistically integrated to provide a software development
platform for your organization. In this guide, the Platform will include a
single Component to demonstrate how the concepts fit together.
```bash
holos generate platform quickstart
```
Commit the generated platform config to the repository.
<Tabs groupId="commit-platform">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "holos generate platform quickstart - $(holos --version)"
```
</TabItem>
<TabItem value="output" label="Output">
```txt
[main (root-commit) 0b17b7f] holos generate platform quickstart
213 files changed, 72349 insertions(+)
...
```
</TabItem>
</Tabs>
## Generate a Component {#generate-component}
The platform you generated is currently empty. Run the following command to
generate the CUE code that defines a Helm Component.
<Tabs groupId="gen-podinfo">
<TabItem value="command" label="Command">
```bash
holos generate component podinfo --component-version 6.6.1
```
</TabItem>
<TabItem value="output" label="Output">
```txt
generated component
```
</TabItem>
</Tabs>
The --component-version 6.6.1 flag intentionally installs an older release.
You'll see how Holos assists with software upgrades later in this guide.
The generate component command creates two files: a leaf file,
`components/podinfo/podinfo.gen.cue`, and a root file, `podinfo.gen.cue`. Holos
leverages the fact that [order is
irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/) in CUE to
register the component with the Platform by adding a file to the root of the Git
repository. The second file defines the component in the leaf component
directory.
<Tabs groupId="podinfo-files">
<TabItem value="components/podinfo/podinfo.gen.cue" label="Leaf">
`components/podinfo/podinfo.gen.cue`
```cue showLineNumbers
package holos
// Produce a helm chart build plan.
(#Helm & Chart).Output
let Chart = {
Name: "podinfo"
Version: "6.6.1"
Namespace: "default"
Repo: name: "podinfo"
Repo: url: "https://stefanprodan.github.io/podinfo"
Values: {}
}
```
</TabItem>
<TabItem value="podinfo.gen.cue" label="Root">
`podinfo.gen.cue`
```cue showLineNumbers
package holos
// Manage podinfo on workload clusters only
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name)/podinfo": {
path: "components/podinfo"
cluster: Cluster.name
}
}
```
</TabItem>
</Tabs>
In this example, we provide the minimal information needed to manage the Helm
chart: the name, version, Kubernetes namespace for deployment, and the chart
repository location.
This chart deploys cleanly without any values provided, but we include an empty
Values struct to show how Holos improves consistency and safety in Helm by
leveraging the strong type-checking in CUE. You can safely pass shared values,
such as the organizations domain name, to all Components across all clusters in
the Platform by defining them at the root of the configuration.
Commit the generated component config to the repository.
<Tabs groupId="commit-component">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "holos generate component podinfo - $(holos --version)"
```
</TabItem>
<TabItem value="output" label="Output">
```txt
[main cc0e90c] holos generate component podinfo
2 files changed, 24 insertions(+)
create mode 100644 components/podinfo/podinfo.gen.cue
create mode 100644 podinfo.gen.cue
```
</TabItem>
</Tabs>
## Render the Component
You can render individual components without adding them to a Platform, which is
helpful when developing a new component.
<Tabs groupId="render-podinfo">
<TabItem value="command" label="Command">
```bash
holos render component ./components/podinfo --cluster-name=default
```
</TabItem>
<TabItem value="output" label="Output">
```txt
cached
rendered podinfo
```
</TabItem>
</Tabs>
First, the command caches the Helm chart locally to speed up subsequent
renderings. Then, the command runs Helm to produce the output and writes it into
the deploy directory.
<Tabs groupId="tree-podinfo">
<TabItem value="command" label="Command">
```bash
tree deploy
```
</TabItem>
<TabItem value="output" label="Output">
```txt
deploy
└── clusters
└── default
└── components
└── podinfo
└── podinfo.gen.yaml
5 directories, 1 file
```
</TabItem>
</Tabs>
The component deploys to one cluster named `default`. In practice, the same
component is often deployed to multiple clusters, such as `east` and `west` to
provide redundancy and increase availability.
:::tip
This example is equivalent to running `helm template` on the chart and saving
the output to a file. Holos simplifies this task, making it safer and more
consistent when managing many charts.
:::
## Mix in an ArgoCD Application
We've seen how Holos works with Helm, but we haven't yet explored how Holos
makes it easier to consistently and safely manage all of the software in a
Platform.
Holos allows you to easily mix in resources that differentiate your Platform.
We'll use this feature to mix in an ArgoCD [Application][application] to manage
the podinfo Component with GitOps. We'll define this configuration in a way that
can be automatically and consistently reused across all future Components added
to the Platform.
Create a new file named `argocd.cue` in the root of your Git repository with the
following contents:
<Tabs groupId="argocd-config">
<TabItem value="command" label="argocd.cue">
```cue showLineNumbers
package holos
#ArgoConfig: {
Enabled: true
RepoURL: "https://github.com/holos-run/holos-quickstart-guide"
}
```
</TabItem>
</Tabs>
:::tip
If you plan to apply the rendered output to a real cluster, change the
`example.com` RepoURL to the URL of the Git repository you created in this
guide. You don't need to change the example if you're just exploring Holos by
inspecting the rendered output without applying it to a live cluster.
:::
With this file in place, render the component again.
<Tabs groupId="render-podinfo-argocd">
<TabItem value="command" label="Command">
```bash
holos render component ./components/podinfo --cluster-name=default
```
</TabItem>
<TabItem value="output" label="Output">
```txt
wrote deploy file
rendered gitops/podinfo
rendered podinfo
```
</TabItem>
</Tabs>
Holos uses the locally cached chart to improve performance and reliability. It
then renders the Helm template output along with an ArgoCD Application resource
for GitOps.
:::tip
By defining the ArgoCD configuration at the root, we again take advantage of the
fact that [order is
irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/) in CUE.
:::
Defining the configuration at the root ensures all future leaf Components take
the ArgoCD configuration and render an Application manifest for GitOps
management.
<Tabs groupId="tree-podinfo-argocd">
<TabItem value="command" label="Command">
```bash
tree deploy
```
</TabItem>
<TabItem value="output" label="Output">
```txt
deploy
└── clusters
└── default
├── components
│   └── podinfo
│   └── podinfo.gen.yaml
└── gitops
└── podinfo.application.gen.yaml
6 directories, 2 files
```
</TabItem>
</Tabs>
Notice the new `podinfo.application.gen.yaml` file created by enabling ArgoCD in
the Helm component. The Application resource in the file looks like this:
<Tabs groupId="podinfo-application">
<TabItem value="file" label="podinfo.application.gen.yaml">
```yaml showLineNumbers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
path: ./deploy/clusters/default/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main
```
</TabItem>
</Tabs>
:::tip
Holos generates a similar Application resource for every additional Component
added to your Platform.
:::
Finally, add and commit the results to your Platform's Git repository.
<Tabs groupId="commit-argo">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "holos render component ./components/podinfo --cluster-name=default"
```
</TabItem>
<TabItem value="output" label="Output">
```txt
[main f95cef1] holos render component ./components/podinfo --cluster-name=default
3 files changed, 134 insertions(+)
create mode 100644 argocd.cue
create mode 100644 deploy/clusters/default/components/podinfo/podinfo.gen.yaml
create mode 100644 deploy/clusters/default/gitops/podinfo.application.gen.yaml
```
</TabItem>
</Tabs>
In this section, we learned how Holos simplifies mixing resources into
Components, like an ArgoCD Application. Holos ensures consistency by managing an
Application resource for every Component added to the Platform through the
configuration you define in `argocd.cue` at the root of the repository.
## Define Workload Clusters {#workload-clusters}
We've generated a Component to manage podinfo and integrated it with our
Platform, but rendering the Platform doesn't render podinfo. Podinfo isn't
rendered because we haven't assigned any Clusters to the workload Fleet.
Define two new clusters, `east` and `west`, and assign them to the workload
Fleet. Create a new file named `clusters.cue` in the root of your Git repository
with the following contents:
<Tabs groupId="clusters">
<TabItem value="clusters.cue" label="clusters.cue">
```cue showLineNumbers
package holos
// Define two workload clusters for disaster recovery.
#Fleets: workload: clusters: {
// In CUE _ indicates values are defined elsewhere.
east: _
west: _
}
```
</TabItem>
</Tabs>
This example shows how Holos simplifies configuring multiple clusters with
similar configuration by grouping them into a Fleet.
:::tip
Fleets help segment a group of Clusters into one leader and multiple followers
by designating one cluster as the primary. Holos makes it safer, easier, and
more consistent to reconfigure which cluster is the primary. The primary can be
set to automatically restore persistent data from backups, while non-primary
clusters can be configured to automatically replicate from the primary.
Automatic database backup, restore, and streaming replication is an advanced
topic enabled by Cloud Native PG and CUE. Check back for a guide on this and
other Day 2 operations topics.
:::
## Render the Platform {#render-platform}
Render the Platform to render the podinfo Component for each of the workload
clusters.
<Tabs groupId="render-platform">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt
rendered components/podinfo for cluster west in 99.480792ms
rendered components/podinfo for cluster east in 99.882667ms
```
</TabItem>
</Tabs>
The render platform command iterates over every Cluster in the Fleet and renders
each Component assigned to the Fleet. Notice the two additional subdirectories
created under the deploy directory, one for each cluster: `east` and `west`.
<Tabs groupId="tree-platform">
<TabItem value="command" label="Command">
```bash
tree deploy
```
</TabItem>
<TabItem value="output" label="Output">
```txt
deploy
└── clusters
├── default
│   ├── components
│   │   └── podinfo
│   │   └── podinfo.gen.yaml
│   └── gitops
│   └── podinfo.application.gen.yaml
# highlight-next-line
├── east
│   ├── components
│   │   └── podinfo
│   │   └── podinfo.gen.yaml
│   └── gitops
│   └── podinfo.application.gen.yaml
# highlight-next-line
└── west
├── components
│   └── podinfo
│   └── podinfo.gen.yaml
└── gitops
└── podinfo.application.gen.yaml
14 directories, 6 files
```
</TabItem>
</Tabs>
Holos ensures consistency and safety by defining the ArgoCD Application once,
with strong type checking, at the configuration root.
New Application resources are automatically generated for the `east` and `west`
workload Clusters.
<Tabs groupId="applications">
<TabItem value="east" label="east">
`deploy/clusters/east/gitops/podinfo.application.gen.yaml`
```yaml showLineNumbers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
# highlight-next-line
path: ./deploy/clusters/east/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main
```
</TabItem>
<TabItem value="west" label="west">
`deploy/clusters/west/gitops/podinfo.application.gen.yaml`
```yaml showLineNumbers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
# highlight-next-line
path: ./deploy/clusters/west/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main
```
</TabItem>
<TabItem value="default" label="default">
`deploy/clusters/default/gitops/podinfo.application.gen.yaml`
```yaml showLineNumbers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
# highlight-next-line
path: ./deploy/clusters/default/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main
```
</TabItem>
</Tabs>
Add and commit the rendered Platform and workload Clusters.
<Tabs groupId="commit-render-platform">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m "holos render platform ./platform - $(holos --version)"
```
</TabItem>
<TabItem value="output" label="Output">
```txt
[main 5aebcf5] holos render platform ./platform - 0.93.2
5 files changed, 263 insertions(+)
create mode 100644 clusters.cue
create mode 100644 deploy/clusters/east/components/podinfo/podinfo.gen.yaml
create mode 100644 deploy/clusters/east/gitops/podinfo.application.gen.yaml
create mode 100644 deploy/clusters/west/components/podinfo/podinfo.gen.yaml
create mode 100644 deploy/clusters/west/gitops/podinfo.application.gen.yaml
```
</TabItem>
</Tabs>
## Upgrade a Helm Chart
Holos is designed to ease the burden of Day 2 operations. With Holos, upgrading
software, integrating new software, and making safe platform-wide configuration
changes become easier.
Let's upgrade the podinfo Component to see how this works in practice. First,
update the Component version field to the latest upstream Helm chart version.
<Tabs groupId="gen-podinfo">
<TabItem value="command" label="Command">
```bash
holos generate component podinfo --component-version 6.6.2
```
</TabItem>
<TabItem value="output" label="Output">
```txt
generated component
```
</TabItem>
</Tabs>
Remove the cached chart version.
<Tabs groupId="gen-podinfo">
<TabItem value="command" label="Command">
```bash
rm -rf components/podinfo/vendor
```
</TabItem>
</Tabs>
Now re-render the Platform.
<Tabs groupId="render-platform2">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt
rendered components/podinfo for cluster east in 327.10475ms
rendered components/podinfo for cluster west in 327.796541ms
```
</TabItem>
</Tabs>
Notice we're still using the upstream chart without modifying it. The Holos
component wraps around the chart to mix in additional resources and integrate
the component with the broader Platform.
## Visualize the Changes
Holos makes it easier to see exactly what changes are made and which resources
will be applied to the API server. By design, Holos operates on local files,
leaving the task of applying them to ecosystem tools like `kubectl` and ArgoCD.
This allows platform operators to inspect changes during code review, or before
committing the change at all.
For example, using `git diff`, we see that the only functional change when
upgrading this Helm chart is the deployment of a new container image tag to each
cluster. Additionally, we can roll out this change gradually by applying it to
the east cluster first, then to the west cluster, limiting the potential blast
radius of a problematic change.
<Tabs groupId="git-diff">
<TabItem value="command" label="Command">
```bash
git diff deploy/clusters/east
```
</TabItem>
<TabItem value="output" label="Output">
```diff showLineNumbers
diff --git a/deploy/clusters/east/components/podinfo/podinfo.gen.yaml b/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
index 7cc3332..8c1647d 100644
--- a/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
+++ b/deploy/clusters/east/components/podinfo/podinfo.gen.yaml
@@ -5,9 +5,9 @@ kind: Service
metadata:
name: podinfo
labels:
- helm.sh/chart: podinfo-6.6.1
+ helm.sh/chart: podinfo-6.6.2
app.kubernetes.io/name: podinfo
- app.kubernetes.io/version: "6.6.1"
+ app.kubernetes.io/version: "6.6.2"
app.kubernetes.io/managed-by: Helm
spec:
type: ClusterIP
@@ -29,9 +29,9 @@ kind: Deployment
metadata:
name: podinfo
labels:
- helm.sh/chart: podinfo-6.6.1
+ helm.sh/chart: podinfo-6.6.2
app.kubernetes.io/name: podinfo
- app.kubernetes.io/version: "6.6.1"
+ app.kubernetes.io/version: "6.6.2"
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
@@ -53,7 +53,7 @@ spec:
terminationGracePeriodSeconds: 30
containers:
- name: podinfo
# highlight-next-line
- image: "ghcr.io/stefanprodan/podinfo:6.6.1"
# highlight-next-line
+ image: "ghcr.io/stefanprodan/podinfo:6.6.2"
imagePullPolicy: IfNotPresent
command:
- ./podinfo
```
</TabItem>
</Tabs>
:::tip
Holos is designed to surface the _fully rendered_ manifests intended for the
Kubernetes API server, making it easier to see and reason about platform-wide
configuration changes.
:::
## Recap {#recap}
In this quickstart guide, we learned how Holos makes it easier, safer, and more
consistent to manage a Platform composed of multiple Clusters and upstream Helm
charts.
We covered how to:
1. Generate a Git repository for the Platform config.
2. Wrap the unmodified upstream podinfo Helm chart into a Component.
3. Render an individual Component.
4. Mix-in your Platform's unique resources to all Components. For example, ArgoCD Application resources.
5. Define multiple similar, but not identical, workload clusters.
6. Render the manifests for the entire Platform with the `holos render platform` command.
7. Upgrade a Helm chart to the latest version as an important Day 2 task.
8. Visualize and surface the details of planned changes Platform wide.
## Dive Deeper
If you'd like to dive deeper, check out the [Schema API][schema] and [Core
API][core] reference docs. The main difference between the schema and core
packages is that the schema is used by users to write refined CUE, while the
core package is what the schema produces for `holos` to execute. Users rarely
need to interact with the Core API when on the happy path, but can use the core
package as an escape hatch when the happy path doesn't go where you want.
[application]: https://argo-cd.readthedocs.io/en/stable/user-guide/application-specification/
[schema]: /docs/api/author/v1alpha3/
[core]: /docs/api/core/v1alpha3/

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -2,4 +2,23 @@ import DocCardList from '@theme/DocCardList';
# Guides
## Start with the [Quickstart] guide
The guides are organized as a progression. We'll use Holos to manage a
fictional bank's platform, the Bank of Holos in each of the guides. In doing so
we'll take the time to explain the foundational concepts of Holos.
1. [Quickstart] covers the foundational concepts of Holos.
2. [Deploy a Service] explains how to deploy a containerized service using an
existing Helm chart. This guide then explains how to deploy a similar service
safely and consistently with CUE instead of Helm.
3. [Change a Service] covers the day two task of making configuration changes to
deployed services safely and consistently.
---
<DocCardList />
[Quickstart]: /docs/quickstart/
[Deploy a Service]: /docs/guides/deploy-a-service/
[Change a Service]: /docs/guides/change-a-service/

View File

@@ -0,0 +1,700 @@
---
description: Change a service on your platform.
slug: /guides/change-a-service
sidebar_position: 300
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
# Change a Service
In this guide we'll explore how Holos helps the frontend development team at the
[Bank of Holos] reconfigures a service they've already deployed. In doing so,
we'll see how simple configuration configuration changes are safer with type
checking, and how rendering the complete platform provides clear visibility into
changes.
We'll build on the concepts we learned in the [Quickstart] and [Deploy a
Service] guides.
## What you'll need {#requirements}
Like our other guides, this guide is intended to be useful without needing to
run the commands. If you'd like to render the platform and apply the manifests
to a real Cluster, complete the [Local Cluster
Guide](/docs/guides/local-cluster) before this guide.
You'll need the following tools installed to run the commands in this guide.
1. [holos](/docs/install) - to build the Platform.
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos Components that
wrap Helm charts.
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to render Holos
Components that render with Kustomize.
If you plan to apply the changes we make, you may delete and re-create your
local platform with the following commands.
```bash
./scripts/reset-cluster
```
Then apply the current manifests with:
```bash
./scripts/apply
```
## Fork the Git Repository
If you haven't already done so, [fork the Bank of
Holos](https://github.com/holos-run/bank-of-holos/fork) then clone the
repository to your local machine.
<Tabs groupId="git-clone">
<TabItem value="command" label="Command">
```bash
# Change YourName
git clone https://github.com/YourName/bank-of-holos
cd bank-of-holos
```
</TabItem>
<TabItem value="output" label="Output">
```txt
Cloning into 'bank-of-holos'...
remote: Enumerating objects: 1177, done.
remote: Counting objects: 100% (1177/1177), done.
remote: Compressing objects: 100% (558/558), done.
remote: Total 1177 (delta 394), reused 1084 (delta 303), pack-reused 0 (from 0)
Receiving objects: 100% (1177/1177), 2.89 MiB | 6.07 MiB/s, done.
Resolving deltas: 100% (394/394), done.
```
</TabItem>
</Tabs>
Run the rest of the commands in this guide from the root of the repository.
## Rename the Bank
Let's imagine the bank recently re-branded from The Bank of Holos to The
Holistic Bank. The software development team responsible for the front end
website needs to update the branding accordingly.
Let's explore how Holos catches errors early, before they land in production,
then guides the team to the correct place to make a change.
The bank front end web service is managed by the
`projects/bank-of-holos/frontend/components/bank-frontend/` component which
refers to the organization display name in `schema.gen.cue`.
<Tabs groupId="F5B546EB-566F-4B83-84C3-C55B40F55555">
<TabItem value="schema.gen.cue" label="schema.gen.cue">
```cue showLineNumbers
package holos
import api "github.com/holos-run/holos/api/author/v1alpha3"
// Define the default organization name
// highlight-next-line
#Organization: DisplayName: string | *"Bank of Holos"
#Organization: Name: string | *"bank-of-holos"
#Organization: api.#OrganizationStrict
#Platform: api.#Platform
#Fleets: api.#StandardFleets
_ComponentConfig: {
Resources: #Resources
ArgoConfig: #ArgoConfig
}
#Helm: api.#Helm & _ComponentConfig
#Kustomize: api.#Kustomize & _ComponentConfig
#Kubernetes: api.#Kubernetes & _ComponentConfig
#ArgoConfig: api.#ArgoConfig & {
ClusterName: _ClusterName
}
```
</TabItem>
<TabItem value="projects/bank-of-holos/frontend/components/bank-frontend/bank-frontend.cue" label="projects/bank-of-holos/frontend/components/bank-frontend/bank-frontend.cue">
```cue showLineNumbers
package holos
// Produce a kubernetes objects build plan.
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "bank-frontend"
Namespace: #BankOfHolos.Frontend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: Namespace
// https://github.com/GoogleCloudPlatform/bank-of-anthos/blob/release/v0.6.5/kubernetes-manifests/frontend.yaml
Resources: {
Service: frontend: {
metadata: name: "frontend"
metadata: labels: {
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
selector: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
_ports: http: {
name: "http"
port: 80
targetPort: 8080
protocol: "TCP"
}
ports: [for x in _ports {x}]
}
}
Deployment: frontend: {
metadata: name: "frontend"
metadata: labels: {
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
selector: matchLabels: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
template: {
metadata: labels: {
app: "frontend"
application: "bank-of-holos"
environment: "development"
team: "frontend"
tier: "web"
}
spec: {
securityContext: {
seccompProfile: type: "RuntimeDefault"
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
}
serviceAccountName: "bank-of-holos"
terminationGracePeriodSeconds: 5
containers: [{
env: [{
name: "BANK_NAME"
// highlight-next-line
value: #Organization.DisplayName
}, {
name: "ENV_PLATFORM"
value: "local"
}, {
name: "VERSION"
value: "v0.6.5"
}, {
name: "PORT"
value: "8080"
}, {
name: "ENABLE_TRACING"
value: "false"
}, {
name: "SCHEME"
value: "https"
}, {
name: "LOG_LEVEL"
value: "info"
}, {
name: "DEFAULT_USERNAME"
valueFrom: configMapKeyRef: {
key: "DEMO_LOGIN_USERNAME"
name: "demo-data-config"
}
}, {
name: "DEFAULT_PASSWORD"
valueFrom: configMapKeyRef: {
key: "DEMO_LOGIN_PASSWORD"
name: "demo-data-config"
}
}, {
name: "REGISTERED_OAUTH_CLIENT_ID"
valueFrom: configMapKeyRef: {
key: "DEMO_OAUTH_CLIENT_ID"
name: "oauth-config"
optional: true
}
}, {
name: "ALLOWED_OAUTH_REDIRECT_URI"
valueFrom: configMapKeyRef: {
key: "DEMO_OAUTH_REDIRECT_URI"
name: "oauth-config"
optional: true
}
}]
envFrom: [{
configMapRef: name: "environment-config"
}, {
configMapRef: name: "service-api-config"
}]
image: "us-central1-docker.pkg.dev/bank-of-anthos-ci/bank-of-anthos/frontend:v0.6.5@sha256:d72050f70d12383e4434ad04d189b681dc625f696087ddf0b5df641645c9dafa"
livenessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 60
periodSeconds: 15
timeoutSeconds: 30
}
name: "front"
readinessProbe: {
httpGet: {
path: "/ready"
port: 8080
}
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 10
}
resources: {
limits: {
cpu: "250m"
memory: "128Mi"
}
requests: {
cpu: "100m"
memory: "64Mi"
}
}
securityContext: {
allowPrivilegeEscalation: false
capabilities: drop: ["all"]
privileged: false
readOnlyRootFilesystem: true
}
volumeMounts: [{
mountPath: "/tmp"
name: "tmp"
}, {
mountPath: "/tmp/.ssh"
name: "publickey"
readOnly: true
}]
}]
volumes: [
{
emptyDir: {}
name: "tmp"
},
{
name: "publickey"
secret: {
items: [{key: "jwtRS256.key.pub", path: "publickey"}]
secretName: "jwt-key"
}
},
]
}
}
}
}
// Allow HTTPRoutes in the ingress gateway namespace to reference Services
// in this namespace.
ReferenceGrant: grant: #ReferenceGrant & {
metadata: namespace: Namespace
}
// Include shared resources
#BankOfHolos.Resources
}
}
```
</TabItem>
</Tabs>
Line 6 of the schema cue file defines the _default_ display name by using
`string | *"..."`. In CUE, the asterisk denotes a [default value].
Line 78 of the bank-frontend cue file refers to `#Organization.DisplayName` to
configure the front end web container.
Let's change the name of the bank by defining a new name at the root of the
configuration. Create `projects/organization.cue` with the following content.
<Tabs groupId="B386181F-EBE7-469D-8CB5-37631067669B">
<TabItem value="projects/organization.cue" label="projects/organization.cue">
```cue showLineNumbers
package holos
#Organization: DisplayName: "The Holistic-Bank"
```
</TabItem>
</Tabs>
Let's render the platform and see if this changes the name.
<Tabs groupId="A014333C-3271-4C22-87E6-2B7BF898EA3E">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt
#Organization.DisplayName: 2 errors in empty disjunction:
#Organization.DisplayName: conflicting values "Bank of Holos" and "The Holistic-Bank":
/bank-of-holos/projects/organization.cue:3:29
/bank-of-holos/schema.gen.cue:6:39
// highlight-next-line
#Organization.DisplayName: invalid value "The Holistic-Bank" (out of bound =~"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$"):
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:203:25
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:188:15
/bank-of-holos/cue.mod/gen/github.com/holos-run/holos/api/author/v1alpha3/definitions_go_gen.cue:203:15
/bank-of-holos/projects/organization.cue:3:29
/bank-of-holos/schema.gen.cue:6:29
could not run: could not render component: exit status 1 at internal/render/platform.go:50
```
</TabItem>
</Tabs>
Whoops, the development team defined a value that isn't allowed by the
configuration. Someone else in the organization placed a [constraint] on the
configuration to ensure the display name contains only letters, numbers, and
spaces.
:::tip
CUE provides clear visibility where to start looking to resolve conflicts. Each
file and line number listed is a place the `#Organization.DisplayName` field is
defined.
:::
Let's try again, this time replacing the hyphen with a space.
<Tabs groupId="F93B34FA-C0C6-4793-A32F-DAD094403208">
<TabItem value="projects/organization.cue" label="projects/organization.cue">
```cue showLineNumbers
package holos
#Organization: DisplayName: "The Holistic Bank"
```
</TabItem>
</Tabs>
<Tabs groupId="5FD68778-476A-4F82-8817-71CEE205216E">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt
rendered bank-ledger-db for cluster workload in 139.863625ms
rendered bank-accounts-db for cluster workload in 151.74875ms
rendered bank-balance-reader for cluster workload in 154.356083ms
rendered bank-ledger-writer for cluster workload in 161.209541ms
rendered bank-userservice for cluster workload in 163.373417ms
rendered bank-backend-config for cluster workload in 179.271208ms
rendered bank-secrets for cluster workload in 204.35625ms
rendered gateway for cluster workload in 118.707583ms
rendered httproutes for cluster workload in 140.981541ms
rendered bank-transaction-history for cluster workload in 156.066875ms
rendered bank-frontend for cluster workload in 300.102292ms
rendered bank-contacts for cluster workload in 159.89625ms
rendered cni for cluster workload in 150.754458ms
rendered istiod for cluster workload in 222.922625ms
rendered app-projects for cluster workload in 118.422792ms
rendered ztunnel for cluster workload in 142.840625ms
rendered cert-manager for cluster workload in 190.938834ms
rendered base for cluster workload in 340.679416ms
rendered local-ca for cluster workload in 107.120334ms
rendered external-secrets for cluster workload in 145.020834ms
rendered argocd for cluster workload in 299.690917ms
rendered namespaces for cluster workload in 115.862334ms
rendered gateway-api for cluster workload in 225.783833ms
rendered external-secrets-crds for cluster workload in 339.741166ms
rendered crds for cluster workload in 421.849041ms
rendered platform in 718.015959ms
```
</TabItem>
</Tabs>
Great, the platform rendered successfully so we know the display name is valid
according to the constraints. Let's see if the new display name value updated
the configuration for the bank frontend.
<Tabs groupId="6C068651-2061-4262-BE1E-7BB3E7EB66CB">
<TabItem value="command" label="Command">
```bash
git status
```
</TabItem>
<TabItem value="output" label="Output">
```txt
On branch main
Your branch and 'jeffmccune/main' have diverged,
and have 2 and 4 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
// highlight-next-line
modified: deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
modified: deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
Untracked files:
(use "git add <file>..." to include in what will be committed)
projects/organization.cue
no changes added to commit (use "git add" and/or "git commit -a")
```
</TabItem>
</Tabs>
<Tabs groupId="4A20831E-461B-4EDE-8F6E-E73C3AEC12DB">
<TabItem value="command" label="Command">
```bash
git diff
```
</TabItem>
<TabItem value="output" label="Output">
```diff
diff --git a/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml b/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
index 7914756..250c660 100644
--- a/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
+++ b/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
@@ -9,7 +9,7 @@ spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
- description: Holos managed AppProject for Bank of Holos
+ description: Holos managed AppProject for The Holistic Bank
destinations:
- namespace: '*'
server: '*'
@@ -26,7 +26,7 @@ spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
- description: Holos managed AppProject for Bank of Holos
+ description: Holos managed AppProject for The Holistic Bank
destinations:
- namespace: '*'
server: '*'
@@ -43,7 +43,7 @@ spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
- description: Holos managed AppProject for Bank of Holos
+ description: Holos managed AppProject for The Holistic Bank
destinations:
- namespace: '*'
server: '*'
@@ -60,7 +60,7 @@ spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
- description: Holos managed AppProject for Bank of Holos
+ description: Holos managed AppProject for The Holistic Bank
destinations:
- namespace: '*'
server: '*'
diff --git a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
index dae6f93..d41516b 100644
--- a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
+++ b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
@@ -71,7 +71,7 @@ spec:
containers:
- env:
- name: BANK_NAME
- value: Bank of Holos
+ value: The Holistic Bank
- name: ENV_PLATFORM
value: local
- name: VERSION
```
</TabItem>
</Tabs>
The new display name changed the frontend container, but it _also_ affected the
app-projects component. Submitting a pull request would trigger a code review
from the platform engineering team who manages the app-projects component.
Let's see how to narrow the change down to limit the scope to the bank's user
facing services. All of these serves are managed under
`projects/bank-of-holos/` Move the `organization.cue` file we created into this
folder to limit the scope of configuration to the the components contained within.
```bash
mv projects/organization.cue projects/bank-of-holos/
```
Render the platform and review what changed.
<Tabs groupId="0FFEC244-B59B-4136-9C82-837985DC2AB8">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```txt
rendered bank-ledger-db for cluster workload in 163.814917ms
rendered bank-accounts-db for cluster workload in 163.960208ms
rendered bank-userservice for cluster workload in 164.1625ms
rendered bank-ledger-writer for cluster workload in 169.185291ms
rendered bank-balance-reader for cluster workload in 174.5455ms
rendered bank-backend-config for cluster workload in 178.092125ms
rendered bank-secrets for cluster workload in 202.305334ms
rendered gateway for cluster workload in 122.81725ms
rendered httproutes for cluster workload in 134.121084ms
rendered bank-contacts for cluster workload in 146.4185ms
rendered bank-frontend for cluster workload in 311.35425ms
rendered bank-transaction-history for cluster workload in 160.103ms
rendered cni for cluster workload in 145.762083ms
rendered istiod for cluster workload in 216.0065ms
rendered app-projects for cluster workload in 117.684333ms
rendered ztunnel for cluster workload in 144.555292ms
rendered cert-manager for cluster workload in 178.247917ms
rendered base for cluster workload in 336.679ms
rendered external-secrets for cluster workload in 142.21825ms
rendered local-ca for cluster workload in 101.249ms
rendered argocd for cluster workload in 280.54525ms
rendered namespaces for cluster workload in 106.822042ms
rendered gateway-api for cluster workload in 200.459791ms
rendered external-secrets-crds for cluster workload in 470.125833ms
rendered crds for cluster workload in 844.388666ms
rendered platform in 1.154937084s
```
</TabItem>
</Tabs>
<Tabs groupId="DE4FEEE5-FC53-48A6-BC6F-D0EA1DBFD00C">
<TabItem value="command" label="Command">
```bash
git diff
```
</TabItem>
<TabItem value="output" label="Output">
```diff
diff --git a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
index dae6f93..d41516b 100644
--- a/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
+++ b/deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
@@ -71,7 +71,7 @@ spec:
containers:
- env:
- name: BANK_NAME
- value: Bank of Holos
+ value: The Holistic Bank
- name: ENV_PLATFORM
value: local
- name: VERSION
```
</TabItem>
</Tabs>
Great! This time, the only manifest affected is our `bank-frontend.gen.yaml`.
The `BANK_NAME` environment variable will change as we expected.
Let's commit and push this change and see if it works in the platform.
<Tabs groupId="435D9C60-F841-4CF1-A947-506422E6BAC9">
<TabItem value="command" label="Command">
```bash
git add .
git commit -m 'frontend: rename bank to The Holistic Bank'
git push
```
</TabItem>
<TabItem value="output" label="Output">
```txt
[main fda74ec] frontend: rename bank to The Holistic Bank
2 files changed, 4 insertions(+), 1 deletion(-)
create mode 100644 projects/bank-of-holos/organization.cue
```
</TabItem>
</Tabs>
Now that we've pushed the change, let's apply the change to the platform.
## Apply the Change
Once we've pushed the change, navigate to the [bank-frontend GitOps
Application](https://argocd.holos.localhost/applications/argocd/bank-frontend?view=tree&resource=).
We can see the Deployment needs to sync to the desired state we just pushed.
![bank-frontend out of sync](./img/change-a-service-out-of-sync.png)
Clicking on the frontend Deployment, we see the diff with the change we expect.
![bank-frontend diff](./img/change-a-service-diff.png)
Sync the change, ArgoCD applies the desired configuration state to the cluster
and Kubernetes handles rolling out the updated Deployment resource.
![bank-frontend progressing](./img/change-a-service-progressing.png)
Soon, the deployment finishes and the component is in sync again.
![bank-frontend in sync](./img/change-a-service-in-sync.png)
Finally, let's see if the name actually changed on the website. Navigate to
https://bank.holos.localhost/.
![bank-frontend login page](./img/change-a-service-login-page.png)
Great! We successfully made our change and successfully applied the changed
configuration to the platform.
- We saw how multiple teams are could be impacted by defining configuration at
the `projects/` path.
- We scoped our change to only affect components within the
`projects/bank-of-holos/` path, limiting the impact on other teams.
- We saw how CUE can be used to constrain values in Holos, increasing safety.
- We saw how CUE surfaces the file and line number of _every_ place to look for
where a value is defined, making it faster and easier to troubleshoot problems..
Thanks for taking the time to work through this guide.
[Quickstart]: /docs/quickstart/
[Deploy a Service]: /docs/guides/deploy-a-service/
[Change a Service]: /docs/guides/change-a-service/
[Helm]: /docs/api/author/v1alpha3/#Helm
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize
[ComponentFields]: /docs/api/author/v1alpha3/#ComponentFields
[platform-files]: /docs/quickstart/#how-platform-rendering-works
[AppProject]: https://argo-cd.readthedocs.io/en/stable/user-guide/projects/
[unification operator]: https://cuelang.org/docs/reference/spec/#unification
[code-owners]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
[Kustomization API]: https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v5.2/api/types/kustomization.go#L34
[cue import]: https://cuelang.org/docs/reference/command/cue-help-import/
[cue get go]: https://cuelang.org/docs/concept/how-cue-works-with-go/
[timoni-crds]: https://timoni.sh/cue/module/custom-resources/
[HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute/?h=filter
[Ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
[hidden field]: https://cuelang.org/docs/tour/references/hidden/
[comprehension]: https://cuelang.org/docs/reference/spec/#comprehensions
[code owners]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
[ReferenceGrant]: https://gateway-api.sigs.k8s.io/api-types/referencegrant/
[Local Cluster Guide]: /docs/guides/local-cluster
[Bank of Holos]: https://github.com/holos-run/bank-of-holos
[default value]: https://cuelang.org/docs/tour/types/defaults/
[constraint]: https://cuelang.org/docs/tour/basics/constraints/

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

@@ -0,0 +1,15 @@
---
description: Helm Component
slug: /guides/helm-component
sidebar_position: 400
---
# Helm Component
The [Deploy a Service](/docs/guides/deploy-a-service/) guide is the best guide
we have on wrapping a Helm chart in a Holos Component. The [Helm] section of
the Author API may also be useful.
[Helm]: /docs/api/author/v1alpha3/#Helm
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 KiB

View File

@@ -0,0 +1,20 @@
---
description: Kubernetes Component
slug: /guides/kubernetes-component
sidebar_position: 500
---
# Kubernetes Component
:::warning
TODO
:::
This is a placeholder for a guide for managing Kubernetes resources directly
from a Holos Component with strong type checking.
In the meantime, please refer to the [Kubernetes] section of the Author API.
[Helm]: /docs/api/author/v1alpha3/#Helm
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize

View File

@@ -0,0 +1,20 @@
---
description: Wrap a Kustomize Kustomization in a Holos Component.
slug: /guides/kustomize-component
sidebar_position: 600
---
# Kustomize Component
:::warning
TODO
:::
This is a placeholder for a guide on wrapping a Kustomize Kustomization base
with a Holos component.
In the meantime, please refer to the [Kustomize] section of the Author API.
[Helm]: /docs/api/author/v1alpha3/#Helm
[Kubernetes]: /docs/api/author/v1alpha3/#Kubernetes
[Kustomize]: /docs/api/author/v1alpha3/#Kustomize

View File

@@ -1,7 +1,7 @@
---
description: Build a local Cluster to use with these guides.
slug: /guides/local-cluster
sidebar_position: 300
sidebar_position: 999
---
import Tabs from '@theme/Tabs';
@@ -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">

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,112 @@ slug: /
# Introduction
:::warning TODO
See [introduction](https://github.com/facebook/docusaurus/blob/main/website/docs/introduction.mdx?plain=1)
:::
Welcome to Holos. Holos is an open source tool to manage software development
platforms safely, easily, and consistently. We built Holos to help engineering
teams work more efficiently together by empowering them to build golden paths
and paved roads for other teams to leverage for quicker delivery.
## Documentation
- [Guides] are organized into example use-cases of how Holos helps engineering
teams at the fictional Bank of Holos deliver business value on the bank's
platform.
- The [API Reference] is a technical reference for when you're writing CUE code to define your platform.
## Backstory
At [Open Infrastructure Services], each of us has helped dozens of companies
build and operate their software development platform over the course of our
career. During the U.S. presidential election just before the pandemic our
second largest client, Twitter, had a global outage lasting the better part of a
day. At the time, we were helping the core infrastructure team by managing
their production configuration management system so the team could focus on
delivering key objectives for the business. In this position, we had a front
row seat into what happened that day.
One of Twitter's employees, a close friend of ours and engineer on the team,
landed a trivial one line change to the firewall configuration. Less than 30
minutes later literally everything was down. The one line change, which passed
code review and seemed harmless, resulted in the host firewall reverting to the
default state on hundreds of thousands of servers. All connections to all
servers globally were blocked and dropped. Except SSH, thankfully. At least
one Presidential candidate complained loudly.
This incident led us to deeply consider a few key problems about Twitter's
software development platform, problems which made their way all the way up to
the board of directors to solve.
1. **Lack of Visibility** - There was no way to see clearly the impact a simple one-line
change could have on the platform. This lack of visibility made it difficult
for engineers to reason about changes they were writing and reviewing.
2. **Large Blast Radius** - All changes, no matter how small or large, affected the
entire global fleet within 30 minutes. Twitter needed a way to cap the
potential blast radius to prevent global outages.
3. **Incomplete Tooling** - Twitter had the correct processes in place, but
their tooling didn't support their process. The one line change was tested and
peer reviewed prior to landing, but the tooling didn't surface the information
they needed when they needed it.
Over the next few years we built features for Twitter's configuration management
system that solved each of these problems. At the same time, I started
exploring my curiosity of what these solutions would look like in the context of
Kubernetes and cloud native software instead of a traditional configuration
management context.
As Google Cloud partners, we had the opportunity to work with Google's largest
customers and learn how they built their software development platforms on
Kubernetes. Over the course of the pandemic, we built a software development
platform made largely in the same way, taking off the shelf CNCF projects like
ArgoCD, the Kubernetes Prometheus Stack, Istio, Cert Manager, External Secrets
Operator, etc... and integrating them into a holistic software development
platform. We started with the packaging recommended by the upstream project.
Helm was and still is the most common distribution method, but many projects
also provided plain yaml, kustomize bases, or sometimes even jsonnet in the case
of the prometheus community. We then wrote scripts to mix-in the resources we
needed to integrate each piece of software with the platform as a whole. For
example, we often passed Helm's output to Kustomize to add common labels or fix
bugs in the upstream chart, like missing namespace fields. We wrote umbrella
charts to mix in Ingress, HTTPRoute, and ExternalSecret resources to the vendor
provided chart.
We viewed these scripts as necessary glue to assemble and fasten the components
together into a platform, but we were never fully satisfied with them. Umbrella
charts became difficult to maintain once there were multiple environments,
regions, and cloud providers in the platform. Nested for loops in yaml
templates created significant friction and were a challenge to troubleshoot
because they obfuscated what was happening. The scripts, too, made it difficult
to see what was happening, when, and fix issues in them that affected all
components in the platform.
Despite the makeshift scripts and umbrella charts, the overall approach had a
significant advantage. The scripts always produced fully rendered manifests
stored in plain text files. We committed these files to version control and
used ArgoCD to apply them. The ability to make a one-line change, render the
whole platform, then see clearly what changed platform-wide resulted in less
time spent troubleshooting and fewer errors making their way to production.
For awhile, we lived with the scripts and charts. I couldn't stop thinking
about the [Why are we templating
YAML?](https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=https%3A%2F%2Fleebriggs.co.uk%2Fblog%2F2019%2F02%2F07%2Fwhy-are-we-templating-yaml&sort=byDate&type=story)
post on Hacker News though. I was curious what it would look like to replace
our scripts and umbrella charts with something that helped address the 3 main
problems Twitter experienced.
After doing quite a bit of digging and talking with folks, I found
[CUE](https://cuelang.org). I took our scripts and charts and re-wrote the same
functionality we needed from the glue-layer in Go and CUE. The result is a new
tool, `holos`, built to complement Helm, Kustomize, and JSonnet, but not replace
them. Holos leverages CUE to make it easier and safer for teams to define
golden paths and paved roads without having to write bespoke, makeshift scripts
or template text.
Thanks for reading this far, give Holos a try locally with out [Quickstart]
guide.
[Guides]: /docs/guides/
[API Reference]: /docs/api/
[Quickstart]: /docs/quickstart/
[CUE]: https://cuelang.org/
[Author API]: /docs/api/author/
[Core API]: /docs/api/core/
[Open Infrastructure Services]: https://openinfrastructure.co/

View File

@@ -2,4 +2,12 @@ import DocCardList from '@theme/DocCardList';
# Get Started
## Start with the [Quickstart] guide
---
These documents provide additional context to supplement the [Quickstart] guide.
<DocCardList />
[Quickstart]: /docs/quickstart/

View File

@@ -6,65 +6,10 @@ sidebar_position: 300
# Comparison
:::tip
Holos is designed to complement and improve, not replace, existing tools in the
cloud native ecosystem.
:::
## Helm
### Chart Users
Describe how things are different when using an upstream helm chart.
### Chart Authors
Describe how things are different when writing a new helm chart.
## Kustomize
TODO
## ArgoCD
TODO
## Flux
TODO
## Timoni
| Aspect | Timoni | Holos | Comment |
| ---------- | -------------------- | -------------------- | ---------------------------------------------------------------------------------------- |
| Language | CUE | CUE | Like Holos, Timoni is also built on CUE. |
| Artifact | OCI Image | Plain YAML Files | The Holos Authors find plain files easier to work with and reason about than OCI images. |
| Outputs to | OCI Image Repository | Local Git repository | Holos is designed for use with existing GitOps tools. |
| Concept | Module | Component | A Timoni Module is analogous to a Holos Component. |
| Concept | Bundle | Platform | A Timoni Bundle is somewhat similar, but smaller in scope to a Holos Platform. |
:::important
The Holos Authors are deeply grateful to Stefan and Timoni for the capability of
importing Kubernetes custom resource definitions into CUE. Without this
functionality, much of the Kubernetes ecosystem would be more difficult to
manage in CUE and therefore in Holos.
:::
## KubeVela
1. Also built on CUE.
2. Intended to create an Application abstraction.
3. Holos prioritizes composition over abstraction.
4. An abstraction of an Application acts as a filter that removes all but the lowest common denominator functionality. The Holos Authors have found this filtering effect to create excessive friction for software developers.
5. Holos focuses instead on composition to empower developers and platform engineers to leverage the unique features and functionality of their software and platform.
## Pulumi
TODO
## Jsonnet
TODO

View File

@@ -4,7 +4,7 @@ import type * as Preset from '@docusaurus/preset-classic';
const config: Config = {
title: 'Holos',
tagline: 'The Holistic Package Manager for Cloud Native Applications',
tagline: 'Holos helps you manage your software development platform safely and easily.',
favicon: 'img/favicon.ico',
// Set the production url of your site here
@@ -12,6 +12,7 @@ const config: Config = {
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/',
// trailing slash is necessary for Cloudflare pages.
trailingSlash: true,
// GitHub pages deployment config.
@@ -65,7 +66,7 @@ const config: Config = {
blogSidebarTitle: "All posts",
feedOptions: {
type: 'all',
copyright: `Copyright © ${new Date().getFullYear()}, The Holos Authors.`,
copyright: `Copyright © ${new Date().getFullYear()}, The Holos Authors`,
},
showReadingTime: false,
},

View File

@@ -44,14 +44,14 @@ const sidebars: SidebarsConfig = {
link: { type: 'doc', id: 'api' },
items: [
{
label: 'Schema API',
label: 'Author API',
type: 'category',
link: { type: 'doc', id: 'api/schema' },
link: { type: 'doc', id: 'api/author' },
collapsed: true,
items: [
{
type: 'autogenerated',
dirName: 'api/schema',
dirName: 'api/author',
},
]
},

View File

@@ -8,53 +8,58 @@ type FeatureItem = {
description: JSX.Element;
};
// TODO: Consider focusing on the three pillars of Safe, Easy, Consistent.
// We don't focus on features, but rather problems and solutions.
const FeatureList: FeatureItem[] = [
{
title: 'Kustomize Helm',
Svg: require('@site/static/img/base00/undraw_together_re_a8x4.svg').default,
title: 'For Platform Engineers',
Svg: require('@site/static/img/base00/undraw_software_engineer_re_tnjc.svg').default,
description: (
<>
Super charge your existing Helm charts by providing well defined,
validated input values, post-processing the output with Kustomize,
and mixing in your own custom resources. All without modifying upstream
charts to alleviate the pain of upgrades.
Spend more time building platform features and less time maintaining
scripts and text templates. Add type checking and validation to your
existing Helm charts and manifests. Define golden paths for teams to
safely spin up new projects without interrupting you. Automatically
manage Namespaces, Certificates, Secrets, Roles, and labels with
strongly typed CUE definitions. Take unmodified, upstream software and
mix-in the resources making your platform unique and valuable.
<br />
<a href="/docs/">Learn More</a>
</>
),
},
{
title: 'Unified Data Model',
Svg: require('@site/static/img/base00/undraw_fitting_pieces_re_nss7.svg').default,
title: 'For Software Developers',
Svg: require('@site/static/img/base00/undraw_through_the_park_lxnl.svg').default,
description: (
<>
Unify all of your platform components into one well-defined, strongly
typed data model with CUE. Holos makes it easier and safer to integrate
seamlessly with software distributed with current and future tools that
produce Kubernetes resource manifests.
Move faster along paved roads provided by your platform and security
teams. Quickly spin up new projects and environments without filing
tickets. Develop where it works best for you, locally or in the cloud.
Deploy your existing Helm charts, Kubernetes manifests, or containers
safely and confidently with strong type checking. Reduce the friction of
integrating your services into your organization's platform.
<br />
<a href="/docs/">Learn More</a>
</>
),
},
{
title: 'Deep Insights',
Svg: require('@site/static/img/base00/undraw_code_review_re_woeb.svg').default,
title: 'For Security Teams',
Svg: require('@site/static/img/base00/undraw_security_on_re_e491.svg').default,
description: (
<>
Reduce risk and increase confidence in your configuration changes.
Holos offers clear visibility into complete resource configuration
<i>before</i> being applied.
Express your security policies as reusable, well defined, typed
configuration. Build guard rails making it easy to develop services
securely. Automatically provision and configure SecretStores,
ExternalSecrets, AuthorizationPolicies, RoleBindings, etc... for project
teams. Gain clear visibility into the complete configuration of the
platform to quickly identify risk and audit your security posture.
Integrate your preferred security tools with the platform.
<br />
<a href="/docs/">Learn More</a>
</>
),
},
{
title: 'Interoperable',
Svg: require('@site/static/img/base00/undraw_version_control_re_mg66.svg').default,
description: (
<>
Holos is designed for compatibility with your preferred tools and
processes, for example git diff and code reviews.
</>
),
},
}
];
function Feature({ title, Svg, description }: FeatureItem) {

View File

@@ -5,9 +5,21 @@
*/
/* Enable wrapping by default for mobile */
pre code {
/* pre code {
white-space: pre-wrap;
overflow-wrap: anywhere;
} */
.hero__title {
text-align: left;
}
.hero__subtitle {
text-align: left;
}
.projectDesc {
text-align: left;
}
/* You can override the default Infima variables here. */

View File

@@ -17,10 +17,16 @@ function HomepageHeader() {
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<p className="projectDesc">
Holos adds CUE's type safety, unified structure, and strong validation
features to your current software packages, including Helm and
Kustomize. These features make the experience of integrating software
packages into a holistic platform a pleasant journey.
Engineering teams spend considerable time and effort gluing software
projects together into a platform. This integration glue is usually
made with bespoke scripts and error prone text templates. This glue
layer is often makeshift, slowing teams down and inviting outages due
to configuration errors.
</p>
<p className="projectDesc">
Holos helps teams deliver value faster by offering a well defined,
safe, and automated integration layer to manage your platform
holistically.
</p>
<div className={styles.buttons}>
<Link
@@ -31,11 +37,12 @@ function HomepageHeader() {
<span className={styles.divider}></span>
<Link
className="button button--primary button--lg"
to="docs/concepts">
to="docs/">
Learn More
</Link>
<span className={styles.divider}></span>
</div>
</div>
</div >
</header >
);
}
@@ -44,8 +51,8 @@ export default function Home(): JSX.Element {
const { siteConfig } = useDocusaurusContext();
return (
<Layout
title={`${siteConfig.title} Package Manager`}
description="Holos adds CUE's type safety, unified structure, and strong validation features to your current software packages, including Helm and Kustomize.">
title={`${siteConfig.title} Platform Manager`}
description="Holos adds CUE's type safety, unified structure, and strong validation features to your Kubernetes configuration manifests, including Helm and Kustomize.">
<HomepageHeader />
<main>
<HomepageFeatures />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 461 KiB

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

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/

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