Compare commits

..

10 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
27 changed files with 2468 additions and 52 deletions

View File

@@ -5,25 +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",
@@ -40,16 +49,22 @@
"devicecode",
"dnsmasq",
"dscacheutil",
"ecrauthorizationtokens",
"entgo",
"envoyfilters",
"errgroup",
"etcdsnapshotfiles",
"externalsecret",
"externalsecrets",
"fctr",
"fieldmaskpb",
"flushcache",
"gatewayclasses",
"gcraccesstokens",
"gendoc",
"ggnpl",
"ghaction",
"githubaccesstokens",
"gitops",
"godoc",
"golangci",
@@ -57,6 +72,9 @@
"grpcreflect",
"grpcroutes",
"grpcurl",
"healthz",
"helmchartconfigs",
"helmcharts",
"holos",
"holoslogger",
"horizontalpodautoscaler",
@@ -70,6 +88,7 @@
"jeffmccune",
"jetstack",
"Jsonnet",
"kfbh",
"killall",
"kubeadm",
"kubeconfig",
@@ -79,6 +98,7 @@
"kustomize",
"ldflags",
"leaderelection",
"ledgerwriter",
"libnss",
"loadbalancer",
"mattn",
@@ -102,6 +122,7 @@
"pipefail",
"PKCE",
"platformconnect",
"podcli",
"poddisruptionbudget",
"podinfo",
"portmapping",
@@ -110,9 +131,11 @@
"protojson",
"proxyconfigs",
"Pulumi",
"pushsecrets",
"putenv",
"qjbp",
"quickstart",
"readyz",
"referencegrant",
"referencegrants",
"requestauthentications",
@@ -121,14 +144,17 @@
"ropc",
"seccomp",
"SECRETKEY",
"secretstore",
"secretstores",
"serverlb",
"serverside",
"serviceaccount",
"servicebindings",
"serviceentries",
"spanid",
"spiffe",
"startupapicheck",
"statefulset",
"stefanprodan",
"structpb",
"subjectaccessreviews",
@@ -143,7 +169,9 @@
"Tokener",
"Traceid",
"traefik",
"transactionhistory",
"uibutton",
"unstage",
"untar",
"Upsert",
"urandom",
@@ -152,6 +180,7 @@
"userdata",
"userservice",
"validatingwebhookconfiguration",
"vaultdynamicsecrets",
"virtualservices",
"wasmplugins",
"workloadentries",

View File

@@ -161,3 +161,22 @@ type Platform struct {
// platform operators to define.
Domain string `cue:"string | *\"holos.localhost\""`
}
// Organization represents organizational metadata useful across the platform.
type Organization struct {
Name string
DisplayName string
}
// 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

@@ -17,6 +17,8 @@ Package v1alpha3 contains CUE definitions intended as convenience wrappers aroun
- [type Helm](<#Helm>)
- [type Kubernetes](<#Kubernetes>)
- [type Kustomize](<#Kustomize>)
- [type Organization](<#Organization>)
- [type OrganizationStrict](<#OrganizationStrict>)
- [type Platform](<#Platform>)
- [type StandardFleets](<#StandardFleets>)
@@ -172,6 +174,35 @@ type Kustomize struct {
}
```
<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]$\" & !~ \" \""`
}
```
<a name="Platform"></a>
## type Platform {#Platform}

View File

@@ -4,8 +4,697 @@ 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
:::warning
Under construction.
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

@@ -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: 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

@@ -410,7 +410,7 @@ before going further.
:::
> In its simplest form, CUE looks a lot like JSON. This is because CUE is a
superset of JSON. Or, put differently: all valid JSON is CUE.
superset of JSON. Or, put differently: all valid JSON is CUE[^1].
>
> 1. C-style comments are allowed
> 2. field names without special characters don't need to be quoted
@@ -763,3 +763,5 @@ Helm charts or Deployments and manage it with Holos.
[core]: /docs/api/core/v1alpha3/
[Deploy a Service]: /docs/guides/deploy-a-service/
[Manage a Project]: /docs/guides/manage-a-project/
[^1]: [The Basics of CUE](https://cuelang.org/docs/tour/basics/json-superset/)

View File

@@ -6,15 +6,111 @@ slug: /
# Introduction
Welcome to Holos. Holos is an open source tool to manage software development
platforms safely, easily, and consistently.
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.
Our documentation is organized into [Guides] and the [API Reference].
## Documentation
:::tip
Please start with the [Quickstart] guide to learn who Holos is for, what
problems it solves, and if it can solve problems you have.
:::
- [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

@@ -4,7 +4,7 @@ import type * as Preset from '@docusaurus/preset-classic';
const config: Config = {
title: 'Holos',
tagline: 'The Holistic Platform Manager',
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

@@ -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 platform wide changes before the
change is made.
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

@@ -10,6 +10,18 @@
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. */
:root {
--ifm-link-color: #268bd2;

View File

@@ -17,20 +17,32 @@ 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 Kubernetes configuration manifests, including Helm
and Kustomize. These features make the experience of integrating
software 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
className="button button--secondary button--lg"
to="docs/quickstart">
Get Started
</Link>
<span className={styles.divider}></span>
<Link
className="button button--primary button--lg"
to="docs/">
Learn More
</Link>
<span className={styles.divider}></span>
</div>
</div>
</div >
</header >
);
}

View File

@@ -181,3 +181,24 @@ import (
// platform operators to define.
Domain: string & (string | *"holos.localhost")
}
// Organization represents organizational metadata useful across the platform.
#Organization: {
Name: string
DisplayName: string
}
// OrganizationStrict represents organizational metadata useful across the
// platform. This is an example of using CUE regular expressions to constrain
// and validate configuration.
#OrganizationStrict: {
#Organization
// 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 & (=~"^[a-z][0-9a-z-]{1,61}[0-9a-z]$" & !~"--")
// DisplayName represents the human readable organization name.
DisplayName: string & (=~"^[0-9A-Za-z][0-9A-Za-z ]{2,61}[0-9A-Za-z]$" & !~" ")
}

View File

@@ -2,8 +2,13 @@ package holos
import api "github.com/holos-run/holos/api/author/v1alpha3"
#Platform: api.#Platform
#Fleets: api.#StandardFleets
// Define the default organization name
#Organization: DisplayName: string | *"Bank of Holos"
#Organization: Name: string | *"bank-of-holos"
#Organization: api.#OrganizationStrict
#Platform: api.#Platform
#Fleets: api.#StandardFleets
_ComponentConfig: {
Resources: #Resources

View File

@@ -4,5 +4,5 @@ deps:
- remote: buf.build
owner: bufbuild
repository: protovalidate
commit: a6c49f84cc0f4e038680d390392e2ab0
digest: shake256:3deb629c655e469d87c58babcfbed403275a741fb4a269366c4fd6ea9db012cf562a1e64819508d73670c506f96d01f724c43bc97b44e2e02aa6e8bbdd160ab2
commit: 5a7b106cbb87462d9a8c9ffecdbd2e38
digest: shake256:2f7efa5a904668219f039d4f6eeb51e871f8f7f5966055a10663cba335bd65f76cac84da3fa758ab7b5dcb489ec599521390ce3951d119fb56df1fc2def16bb0

View File

@@ -1 +1 @@
2
3