Compare commits

...

33 Commits

Author SHA1 Message Date
Jeff McCune
6fb6afe8d5 v0.97.3 2024-10-31 21:04:22 -07:00
Jeff McCune
d6f89052d9 website: update helm guide to apply patches (#291)
Updated the helm guide to apply patches while still showing the diff in
the documentation markdown.  The only gotcha is it creates orig files.
2024-10-31 20:54:57 -07:00
Jeff McCune
e4aa7f5994 website: update change-a-service to use hidden fields (#291)
Use _Foo instead of #Foo to hold concrete values.
2024-10-31 20:25:40 -07:00
Jeff McCune
6e4c65cb6c website: update deploy-a-service to use hidden fields (#291)
Use _Foo instead of #Foo to hold concrete values.
2024-10-31 20:13:17 -07:00
Jeff McCune
4f091677e2 website: update quickstart for v1alpha4 hidden fields (#291) 2024-10-31 16:35:41 -07:00
Jeff McCune
0c05df1162 website: update technical overview with consistent fields (#291) 2024-10-31 11:30:20 -07:00
Jeff McCune
64a745fd34 v1alpha4: use hidden fields consistently (#291)
Previously it wasn't clear for users if platform wide structs should be
definitions or hidden fields in CUE.  They should be hidden fields when
they contain data and definitions when they define a schema.

This patch updates the generate platform v1alpha4 subcommand to use the
correct field names consistently for clarity.
2024-10-31 10:45:47 -07:00
Jeff McCune
490f91f580 cli: hide unsupported commands (#289)
Use a simple feature flag system that checks env vars if a feature is
enabled.
2024-10-31 10:04:01 -07:00
Jeff McCune
79b065cda8 website: add open graph image for helm guide try 6 2024-10-30 12:23:18 -07:00
Jeff McCune
0fa6047552 website: add open graph image for helm guide try 5 2024-10-30 12:20:19 -07:00
Jeff McCune
11ecc0cc3a website: add open graph image for helm guide try 4 2024-10-30 12:04:39 -07:00
Jeff McCune
a62e4ba117 website: add open graph image for helm guide try 3 2024-10-30 11:56:01 -07:00
Jeff McCune
07fe667f30 website: add open graph image for helm guide try 2 2024-10-30 11:40:39 -07:00
Jeff McCune
3ad994cbb9 website: add open graph image for helm guide 2024-10-30 11:26:54 -07:00
Jeff McCune
b3d9bd32af website: add why cue for configuration blog post
This is going to be one of the first questions we get.
2024-10-28 21:30:11 -07:00
Jeff McCune
d398b49d7f website: fix head title tag try 2
The open graph title was still showing up poorly, docusaurus generates
it with the Holos | Holos repetition, so we need to override it.
2024-10-28 14:37:43 -07:00
Jeff McCune
12179a6991 website: fix head title tag and social card
Generate the social card manually from https://www.opengraph.xyz/
Override the page title tag, otherwise it shows up as "Announcing Holos
| Holos" in social links, which is weird.
2024-10-28 14:07:40 -07:00
Jeff McCune
fee472bb66 website: add stock social card for annoucement 2024-10-28 13:31:10 -07:00
Jeff McCune
c6a13059f3 v0.97.1 2024-10-28 11:12:55 -07:00
Jeff McCune
ff3eb896f3 webite: put ois logo back
Until we get a better logo.
2024-10-28 10:46:59 -07:00
Jeff McCune
70f70ae6b9 website: fix launch announcement 2024-10-28 10:45:43 -07:00
Jeff McCune
2580ec1c5f website: fix order of api references
The api references are in reverse order and don't have good descriptions
in the index listings.  This patch adds front matter to each generated
document to order them correctly and add a nice description.
2024-10-27 20:43:54 -07:00
Jeff McCune
4fa99e0faa website: add helm prometheus blackbox httpbin guide
The purpose of this guide is to demonstrate how holos offers value
above and beyond helm and kustomize alone.
2024-10-27 19:48:42 -07:00
Jeff McCune
7341d25483 website: add at proto did for bsky 2024-10-25 14:26:42 -07:00
Jeff McCune
3074b3a241 website: add discord invite link 2024-10-24 10:27:37 -07:00
Jeff McCune
9a5e7869c6 v1alpha4: omit the platform model if empty
The platform model distracts from getting started:

  cue export --out yaml ./platform

  kind: Platform
  apiVersion: v1alpha4
  metadata:
    name: default
  spec:
    components:
      - name: prometheus
        component: projects/platform/components/prometheus
        cluster: local
        model: {}

With this patch it's absent by default.
2024-10-23 13:46:58 -07:00
Jeff McCune
1064ceba31 v1alpha4: manage a single workload cluster named local by default
Manage a single cluster by default after generating the platform.
Assume it's a local cluster for use with the guides.
2024-10-23 13:42:46 -07:00
Jeff McCune
4bccaa3710 v1alpha4: _Platform not #Platform for component registration
`_Platform` is a hidden field representing the platform components,
`#Platform` defines the schema of the hidden field.
2024-10-23 13:33:28 -07:00
Jeff McCune
95efae1343 docs: update rendered manifest figure in technical overview
It's too wide with KubeAPI, take it out.
2024-10-20 10:11:57 -07:00
Jeff McCune
ba88125877 v1alpha4: enable config map generator for Kustomize
Without this patch it's difficult to mix in a plain file as a config
map.  This is necessary for the use case of using a Job to generate a
secret in-cluster.  We want a plain shell script to be carried through
and transformed into the job.

We already have the KustomizeConfig fields to support this, they just
weren't wired up to the #Kustomization component kind.

I didn't check if it's wired up to Helm and Kustomize for expedience.
They may be missing there as well.
2024-10-19 10:57:37 -07:00
Jeff McCune
d12c1a0c11 Merge pull request #284 from holos-run/gl/deploy-a-service-v4alpha-update
Update deploy-a-service guide for Author API v1alpha4
2024-10-18 20:35:51 -07:00
Jeff McCune
d56d3400a7 docs: replace tabs in deploy-a-service guide 2024-10-18 20:33:54 -07:00
Gary Larizza
4f0f9dced5 Update deploy-a-service guide for Author API v1alpha4
PROBLEM:

Version v1alpha4 of the Author API has been updated with backwards
incompatible changes, and the deploy-a-service guide uses code from
version v1alpha3.

SOLUTION:

Update any code, links, and data that is out of date, and then run
through the guide to make sure it works locally.

OUTCOME:

The instructions in the deploy-a-service guide will work successfully
with version v1alpha4 of the Author API.
2024-10-18 15:21:56 -07:00
73 changed files with 6336 additions and 789 deletions

View File

@@ -5,36 +5,56 @@
"mdx"
],
"words": [
"acmesolver",
"acraccesstokens",
"admissionregistration",
"alertmanager",
"alertmanagers",
"anthos",
"apiextensions",
"apimachinery",
"apiobjects",
"apiservers",
"applicationset",
"applicationsets",
"appproject",
"appprojects",
"argoproj",
"argumentless",
"authcode",
"authorizationpolicies",
"authorizationpolicy",
"authpolicy",
"authproxy",
"authroutes",
"automount",
"automounting",
"autoscaler",
"balancereader",
"blackbox",
"buildplan",
"builtinpluginloadingoptions",
"cadvisor",
"cainjector",
"CAROOT",
"certificaterequest",
"certificaterequests",
"certificatesigningrequests",
"clsx",
"clusterexternalsecret",
"clusterexternalsecrets",
"clusterissuer",
"clusterissuers",
"clusterrole",
"clusterrolebinding",
"clustersecretstore",
"clustersecretstores",
"clusterwide",
"CNCF",
"CODEOWNERS",
"configmap",
"configmapargs",
"connectrpc",
"cookiesecret",
"coredns",
"corev",
@@ -42,99 +62,166 @@
"crds",
"creds",
"crossplane",
"crunchydata",
"cuecontext",
"cuelang",
"customresourcedefinition",
"daemonset",
"deploymentruntimeconfig",
"destinationrule",
"destinationrules",
"devicecode",
"dnsmasq",
"dscacheutil",
"ecrauthorizationtokens",
"edns",
"endpointslices",
"entgo",
"envoyfilter",
"envoyfilters",
"errdetails",
"errgroup",
"etcdsnapshotfiles",
"externalsecret",
"externalsecrets",
"fctr",
"fieldmaskpb",
"fieldspec",
"flushcache",
"fullname",
"gatewayclass",
"gatewayclasses",
"gcraccesstokens",
"gendoc",
"generationbehavior",
"generatorargs",
"generatoroptions",
"genproto",
"ggnpl",
"ghaction",
"githubaccesstokens",
"gitops",
"godoc",
"golangci",
"gomarkdoc",
"googleapis",
"goreleaser",
"gotypesalias",
"grpcreflect",
"grpcroute",
"grpcroutes",
"grpcurl",
"healthchecks",
"healthz",
"helmchartargs",
"helmchartconfigs",
"helmcharts",
"Hiera",
"holos",
"holoslogger",
"horizontalpodautoscaler",
"horizontalpodautoscalers",
"Hostaliases",
"Hostnames",
"htpasswd",
"httpbin",
"httproute",
"httproutes",
"iampolicygenerator",
"Infima",
"intstr",
"isatty",
"istiod",
"jbrx",
"jeffmccune",
"jetstack",
"jiralert",
"Jsonnet",
"kfbh",
"killall",
"kubeadm",
"kubeconfig",
"kubelet",
"kubelogin",
"kubernetesobjects",
"Kustomization",
"Kustomizations",
"kustomize",
"kustomizebuild",
"kvpairsources",
"labeldrop",
"labelmap",
"ldflags",
"leaderelection",
"ledgerwriter",
"libnss",
"limitranges",
"livez",
"loadbalancer",
"loadrestrictions",
"logfmt",
"mattn",
"mccutchen",
"metav",
"mindmap",
"mktemp",
"msqbn",
"mtls",
"Multicluster",
"mutatingwebhookconfiguration",
"mutatingwebhookconfigurations",
"mxcl",
"myhostname",
"myRegistrKeySecretName",
"mysecret",
"nameofclusterrole",
"nameserver",
"namespacedname",
"ndots",
"networkpolicies",
"nodename",
"nolint",
"oauthproxy",
"objectmap",
"objectmeta",
"organizationconnect",
"orgid",
"otelconnect",
"overriden",
"Parentspanid",
"patchstrategicmerge",
"pcjc",
"peerauthentication",
"peerauthentications",
"persistentvolumeclaim",
"persistentvolumeclaims",
"persistentvolumes",
"pflag",
"pgadmin",
"pgupgrade",
"pipefail",
"PKCE",
"platformconnect",
"pluginconfig",
"pluginrestrictions",
"podcli",
"poddisruptionbudget",
"poddisruptionbudgets",
"podinfo",
"podmonitor",
"portmapping",
"postgrescluster",
"privs",
"prometheuses",
"promhttp",
"protobuf",
"protojson",
"providerconfig",
"proxyconfig",
"proxyconfigs",
"Pulumi",
"pushgateway",
"pushsecret",
"pushsecrets",
"putenv",
"qjbp",
@@ -143,11 +230,19 @@
"readyz",
"referencegrant",
"referencegrants",
"Registr",
"replacementfield",
"replicasets",
"replicationcontrollers",
"requestauthentication",
"requestauthentications",
"resourcequotas",
"retryable",
"rolebinding",
"rootfs",
"ropc",
"seccomp",
"secretargs",
"SECRETKEY",
"secretstore",
"secretstores",
@@ -156,29 +251,47 @@
"serviceaccount",
"servicebindings",
"serviceentries",
"serviceentry",
"servicemonitor",
"somevalue",
"SOMEVAR",
"sortoptions",
"spanid",
"spiffe",
"stackdriver",
"startupapicheck",
"statefulset",
"statefulsets",
"stefanprodan",
"storageclasses",
"streamwatcher",
"struct",
"structpb",
"subcharts",
"subjectaccessreviews",
"svclb",
"sysfs",
"systemconnect",
"tablewriter",
"templatable",
"thanos",
"Tiltfile",
"timestamppb",
"Timoni",
"tlsclientconfig",
"tokencache",
"Tokener",
"tolerations",
"Traceid",
"traefik",
"transactionhistory",
"tsdb",
"typemeta",
"udev",
"uibutton",
"unstage",
"untar",
"upbound",
"Upsert",
"urandom",
"usecases",
@@ -186,11 +299,18 @@
"userdata",
"userservice",
"validatingwebhookconfiguration",
"validatingwebhookconfigurations",
"vaultdynamicsecrets",
"virtualservice",
"virtualservices",
"volumeattachments",
"wasmplugin",
"wasmplugins",
"workloadentries",
"workloadentry",
"workloadgroup",
"workloadgroups",
"yournamespace",
"zerolog",
"zitadel",
"ztunnel"

View File

@@ -0,0 +1,4 @@
---
description: Simplified abstraction to generate core v1alpha3 components.
sidebar_position: 997
---

View File

@@ -0,0 +1,4 @@
---
description: Simplified abstraction to generate core v1alpha4 build plans.
sidebar_position: 996
---

View File

@@ -0,0 +1,4 @@
---
description: Core v1alpha4 schema for advanced use cases.
sidebar_position: 998
---

View File

@@ -0,0 +1,4 @@
---
description: Core v1alpha3 schema for advanced use cases.
sidebar_position: 997
---

View File

@@ -0,0 +1,4 @@
---
description: Core v1alpha2 schema for advanced use cases.
sidebar_position: 996
---

View File

@@ -365,7 +365,7 @@ type Component struct {
// Model represents the platform model holos gets from from the
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
// Injected as the tag "holos_model".
Model map[string]any `json:"model"`
Model map[string]any `json:"model,omitempty"`
// Tags represents cue @tag variables injected into the holos render component
// command from the holos render platform command. Tags with a "holos_"
// prefix are reserved for use by the Holos Authors.

View File

@@ -1,3 +1,7 @@
---
description: Simplified abstraction to generate core v1alpha3 components.
sidebar_position: 997
---
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# v1alpha3

View File

@@ -1,3 +1,7 @@
---
description: Simplified abstraction to generate core v1alpha4 build plans.
sidebar_position: 996
---
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# v1alpha4

View File

@@ -1,3 +1,7 @@
---
description: Core v1alpha4 schema for advanced use cases.
sidebar_position: 998
---
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# v1alpha2

View File

@@ -1,3 +1,7 @@
---
description: Core v1alpha3 schema for advanced use cases.
sidebar_position: 997
---
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# v1alpha3

View File

@@ -1,3 +1,7 @@
---
description: Core v1alpha2 schema for advanced use cases.
sidebar_position: 996
---
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
# v1alpha4
@@ -234,7 +238,7 @@ type Component struct {
// Model represents the platform model holos gets from from the
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
// Injected as the tag "holos_model".
Model map[string]any `json:"model"`
Model map[string]any `json:"model,omitempty"`
// Tags represents cue @tag variables injected into the holos render component
// command from the holos render platform command. Tags with a "holos_"
// prefix are reserved for use by the Holos Authors.

View File

@@ -80,33 +80,62 @@ The bank front end web service is managed by the
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">
<TabItem value="schema.cue" label="schema.cue">
```cue showLineNumbers
package holos
import api "github.com/holos-run/holos/api/author/v1alpha3"
import api "github.com/holos-run/holos/api/author/v1alpha4"
// 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
// Define the default organization name.
_Organization: api.#OrganizationStrict & {
DisplayName: string | *"Bank of Holos"
Name: string | *"bank-of-holos"
Domain: string | *"holos.localhost"
}
#Helm: api.#Helm & _ComponentConfig
#Kustomize: api.#Kustomize & _ComponentConfig
#Kubernetes: api.#Kubernetes & _ComponentConfig
// Projects represents a way to organize components into projects with owners.
// https://holos.run/docs/api/author/v1alpha4/#Projects
_Projects: api.#Projects
#ArgoConfig: api.#ArgoConfig & {
ClusterName: _ClusterName
// ArgoConfig represents the configuration of ArgoCD Application resources for
// each component.
// https://holos.run/docs/api/author/v1alpha4/#ArgoConfig
_ArgoConfig: api.#ArgoConfig
#ComponentConfig: api.#ComponentConfig & {
Name: _Tags.name
Component: _Tags.component
Cluster: _Tags.cluster
ArgoConfig: _ArgoConfig & {
if _Tags.project != "no-project" {
AppProject: _Tags.project
}
}
Resources: #Resources
// Mix in project labels if the project is defined by the platform.
if _Tags.project != "no-project" {
CommonLabels: _Projects[_Tags.project].CommonLabels
}
}
// https://holos.run/docs/api/author/v1alpha4/#Kubernetes
#Kubernetes: close({
#ComponentConfig
api.#Kubernetes
})
// https://holos.run/docs/api/author/v1alpha4/#Kustomize
#Kustomize: close({
#ComponentConfig
api.#Kustomize
})
// https://holos.run/docs/api/author/v1alpha4/#Helm
#Helm: close({
#ComponentConfig
api.#Helm
})
```
</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">
@@ -117,215 +146,214 @@ package holos
(#Kubernetes & Objects).BuildPlan
let Objects = {
Name: "bank-frontend"
Namespace: #BankOfHolos.Frontend.Namespace
Name: "bank-frontend"
Namespace: _BankOfHolos.Frontend.Namespace
// Ensure resources go in the correct namespace
Resources: [_]: [_]: metadata: namespace: 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}]
}
}
// 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"
}
},
]
}
}
}
}
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: _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
}
// Allow HTTPRoutes in the ingress gateway namespace to reference Services
// in this namespace.
ReferenceGrant: grant: _ReferenceGrant & {
metadata: namespace: Namespace
}
// Include shared resources
#BankOfHolos.Resources
}
// Include shared resources
_BankOfHolos.Resources
}
}
```
</TabItem>
</Tabs>
Line 6 of the `schema.gen.cue` file defines the _default_ value for
`#Organization.DisplayName` by using `string | *"..."`. In CUE, the `*`
Line 7 of the `schema.cue` file defines the _default_ value for
`_Organization.DisplayName` by using `string | *"..."`. In CUE, the `*`
asterisk character denotes a [default value].
Line 78 of the `bank-frontend.cue` file refers to `#Organization.DisplayName` to
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 value for
`#Organization.DisplayName` at the root of the configuration. Create
`_Organization.DisplayName` at the root of the configuration. Create
`projects/organization.cue` with the following content.
<Tabs groupId="B386181F-EBE7-469D-8CB5-37631067669B">
@@ -333,7 +361,7 @@ Let's change the name of the bank by defining a new value for
```cue showLineNumbers
package holos
#Organization: DisplayName: "The Holistic-Bank"
_Organization: DisplayName: "The Holistic-Bank"
```
</TabItem>
</Tabs>
@@ -348,18 +376,11 @@ 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
could not run: could not marshal json projects/platform/components/istio/cni: cue: marshal error: _Organization.DisplayName: 2 errors in empty disjunction: (and 2 more errors) at internal/builder/builder.go:63
_Organization.DisplayName: _Organization.DisplayName: 2 errors in empty disjunction: (and 2 more errors)
could not run: could not marshal json projects/platform/components/argocd/crds: cue: marshal error: _Organization.DisplayName: 2 errors in empty disjunction: (and 2 more errors) at internal/builder/builder.go:63
_Organization.DisplayName: _Organization.DisplayName: 2 errors in empty disjunction: (and 2 more errors)
could not run: could not render component: exit status 1 at builder/v1alpha4/builder.go:95
```
</TabItem>
</Tabs>
@@ -386,7 +407,7 @@ Let's try again, this time replacing the hyphen with a space.
```cue showLineNumbers
package holos
#Organization: DisplayName: "The Holistic Bank"
_Organization: DisplayName: "The Holistic Bank"
```
</TabItem>
</Tabs>

View File

@@ -94,8 +94,8 @@ an ArgoCD Application or Flux Kustomization.
consistently add common labels.
:::tip
[ComponentFields] in the Author API describes the fields common to all kinds of
component.
[ComponentConfig] in the Author API describes the fields common to all kinds of
components.
:::
We'll start with a [Helm] component to deploy the service, then compare it to a
@@ -130,23 +130,23 @@ package holos
// Platform wide definitions
// highlight-next-line
#Migration: Namespace: "migration"
_Migration: Namespace: "migration"
// Register namespaces
// highlight-next-line
#Namespaces: (#Migration.Namespace): _
_Namespaces: (_Migration.Namespace): _
// Register projects
// highlight-next-line
#AppProjects: migration: _
_AppProjects: migration: _
```
</TabItem>
</Tabs>
Each of the highlighted lines has a specific purpose.
- Line 4 defines the `#Migration` CUE struct. The team that currently owns the
migration project defines this struct.
- Line 4 defines the `_Migration` hidden field. The team owning the migration
project manages this struct.
- Line 7 registers the namespace with the `namespaces` component owned by the
platform team. The `_` value indicates the value is defined elsewhere in CUE.
In this case, the platform team defines what a Namespace is.
@@ -208,9 +208,9 @@ 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/local/components/app-projects/app-projects.gen.yaml
// highlight-next-line
modified: deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
modified: deploy/clusters/local/components/namespaces/namespaces.gen.yaml
Untracked files:
(use "git add <file>..." to include in what will be committed)
@@ -230,15 +230,14 @@ git diff deploy
</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
diff --git a/deploy/clusters/local/components/app-projects/app-projects.gen.yaml b/deploy/clusters/local/components/app-projects/app-projects.gen.yaml
index bdc8371..42cb01a 100644
--- a/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
+++ b/deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
--- a/deploy/clusters/local/components/app-projects/app-projects.gen.yaml
+++ b/deploy/clusters/local/components/app-projects/app-projects.gen.yaml
@@ -50,6 +50,23 @@ spec:
sourceRepos:
- '*'
---
+# Source: CUE apiObjects.AppProject.migration
+apiVersion: argoproj.io/v1alpha1
+kind: AppProject
+metadata:
@@ -255,19 +254,17 @@ index bdc8371..42cb01a 100644
+ sourceRepos:
+ - '*'
+---
# Source: CUE apiObjects.AppProject.platform
apiVersion: argoproj.io/v1alpha1
kind: AppProject
diff --git a/deploy/clusters/workload/components/namespaces/namespaces.gen.yaml b/deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
diff --git a/deploy/clusters/local/components/namespaces/namespaces.gen.yaml b/deploy/clusters/local/components/namespaces/namespaces.gen.yaml
index de96ab9..7ddd870 100644
--- a/deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
+++ b/deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
--- a/deploy/clusters/local/components/namespaces/namespaces.gen.yaml
+++ b/deploy/clusters/local/components/namespaces/namespaces.gen.yaml
@@ -62,3 +62,11 @@ metadata:
kubernetes.io/metadata.name: istio-system
kind: Namespace
apiVersion: v1
+---
+# Source: CUE apiObjects.Namespace.migration
+metadata:
+ name: migration
+ labels:
@@ -351,33 +348,33 @@ import ks "sigs.k8s.io/kustomize/api/types"
// Produce a helm chart build plan.
// highlight-next-line
(#Helm & Chart).BuildPlan
_Helm.BuildPlan
let Chart = {
// highlight-next-line
Name: "podinfo"
Version: "6.6.2"
// highlight-next-line
Namespace: #Migration.Namespace
_Helm: #Helm & {
// highlight-next-line
Name: "podinfo"
// highlight-next-line
Namespace: _Migration.Namespace
// Necessary to ensure the resources go to the correct namespace.
// highlight-next-line
EnableKustomizePostProcessor: true
// highlight-next-line
KustomizeFiles: "kustomization.yaml": ks.#Kustomization & {
namespace: Namespace
}
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
Repo: name: "podinfo"
Repo: url: "https://stefanprodan.github.io/podinfo"
KustomizeConfig: Kustomization: ks.#Kustomization & {
// highlight-next-line
namespace: Namespace
}
// Allow the platform team to route traffic into our namespace.
// highlight-next-line
Resources: ReferenceGrant: grant: #ReferenceGrant & {
metadata: namespace: Namespace
}
// Allow the platform team to route traffic into our namespace.
Resources: ReferenceGrant: grant: _ReferenceGrant & {
// highlight-next-line
metadata: namespace: Namespace
}
}
```
</TabItem>
</Tabs>
@@ -396,19 +393,19 @@ Name as the sub-directory name when it writes the rendered manifest into
`deploy/`. Normally this name also matches the directory and file name of the
component, `podinfo/podinfo.cue`, but `holos` doesn't enforce this convention.
**Line 11**: We use the same namespace we registered with the `namespaces`
**Line 10**: We use the same namespace we registered with the `namespaces`
component as the value we pass to Helm. This is a good example of Holos
offering safety and consistency with CUE, if we change the value of
`#Migration.Namespace`, multiple components stay consistent.
`_Migration.Namespace`, multiple components stay consistent.
**Lines 14-15**: Unfortunately, the Helm chart doesn't set the
**Lines 21**: Unfortunately, the Helm chart doesn't set the
`metadata.namespace` field for the resources it generates, which creates a
security problem. The resources will be created in the wrong namespace. We
don't want to modify the upstream chart because it creates a maintenance burden.
We solve the problem by having Holos post-process the Helm output with
Kustomize. This ensures all resources go into the correct namespace.
**Lines 23**: The migration team grants the platform team permission to route
**Lines 26**: The migration team grants the platform team permission to route
traffic into the `migration` Namespace using a [ReferenceGrant].
:::note
@@ -459,11 +456,12 @@ following content.
package holos
// Manage on workload clusters only
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name)/podinfo": {
path: "projects/migration/components/podinfo"
cluster: Cluster.name
}
for Cluster in _Fleets.workload.clusters {
_Platform: Components: "\(Cluster.name)/podinfo": {
name: "podinfo"
component: "projects/migration/components/podinfo"
cluster: Cluster.name
}
}
```
</TabItem>
@@ -488,7 +486,7 @@ package holos
// Assign ArgoCD Applications to the migration AppProject
// highlight-next-line
#ArgoConfig: AppProject: #AppProjects.migration.metadata.name
_ArgoConfig: AppProject: _AppProjects.migration.metadata.name
```
</TabItem>
</Tabs>
@@ -497,7 +495,7 @@ This file provides consistency and safety in a number of ways:
1. All components under `projects/migration/` will automatically have their
ArgoCD Application assigned to the migration `AppProject`.
2. `holos render platform` errors out if `#AppProjects.migration` is not
2. `holos render platform` errors out if `_AppProjects.migration` is not
defined, we defined it in `projects/migration.cue`
3. The platform team is responsible for managing the `AppProject` resource
itself, the team doing the migration refers to the `metadata.name` field defined
@@ -557,14 +555,14 @@ git status
</TabItem>
<TabItem value="output" label="Output">
```txt
On branch main
On branch jeff/291-consistent-fields
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: deploy/clusters/workload/components/podinfo/podinfo.gen.yaml
new file: deploy/clusters/workload/gitops/podinfo.application.gen.yaml
new file: platform/migration-podinfo.cue
new file: projects/migration/app-project.cue
new file: projects/migration/components/podinfo/podinfo.cue
new file: deploy/clusters/local/components/podinfo/podinfo.gen.yaml
new file: deploy/clusters/local/gitops/podinfo.gen.yaml
new file: platform/migration-podinfo.cue
new file: projects/migration/app-project.cue
new file: projects/migration/components/podinfo/podinfo.cue
```
</TabItem>
</Tabs>
@@ -574,25 +572,26 @@ in a new manifest for the Helm output along with an ArgoCD Application for
GitOps. Here's what they look like:
<Tabs groupId="0F2B3066-B57F-466E-A27F-A603C1803E11">
<TabItem value="deploy/clusters/workload/gitops/podinfo.application.gen.yaml" label="podinfo.application.gen.yaml">
<TabItem value="deploy/clusters/local/gitops/podinfo.gen.yaml" label="podinfo.gen.yaml">
```yaml showLineNumbers
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
labels:
holos.run/component.name: podinfo
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
# highlight-next-line
project: migration
source:
path: ./deploy/clusters/workload/components/podinfo
path: deploy/clusters/local/components/podinfo
repoURL: https://github.com/holos-run/bank-of-holos
targetRevision: main
```
</TabItem>
<TabItem value="deploy/clusters/workload/components/podinfo/podinfo.gen.yaml" label="podinfo.gen.yaml">
<TabItem value="deploy/clusters/local/components/podinfo/podinfo.gen.yaml" label="podinfo.gen.yaml">
```yaml showLineNumbers
apiVersion: v1
kind: Service
@@ -601,9 +600,10 @@ metadata:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: podinfo
app.kubernetes.io/version: 6.6.2
argocd.argoproj.io/instance: podinfo
helm.sh/chart: podinfo-6.6.2
holos.run/component.name: podinfo
name: podinfo
# highlight-next-line
namespace: migration
spec:
ports:
@@ -617,6 +617,8 @@ spec:
targetPort: grpc
selector:
app.kubernetes.io/name: podinfo
argocd.argoproj.io/instance: podinfo
holos.run/component.name: podinfo
type: ClusterIP
---
apiVersion: apps/v1
@@ -626,15 +628,18 @@ metadata:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: podinfo
app.kubernetes.io/version: 6.6.2
argocd.argoproj.io/instance: podinfo
helm.sh/chart: podinfo-6.6.2
holos.run/component.name: podinfo
name: podinfo
# highlight-next-line
namespace: migration
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: podinfo
argocd.argoproj.io/instance: podinfo
holos.run/component.name: podinfo
strategy:
rollingUpdate:
maxUnavailable: 1
@@ -646,6 +651,8 @@ spec:
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/name: podinfo
argocd.argoproj.io/instance: podinfo
holos.run/component.name: podinfo
spec:
containers:
- command:
@@ -710,6 +717,23 @@ spec:
volumes:
- emptyDir: {}
name: data
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
labels:
argocd.argoproj.io/instance: podinfo
holos.run/component.name: podinfo
name: istio-ingress
namespace: migration
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: istio-ingress
to:
- group: ""
kind: Service
```
</TabItem>
</Tabs>
@@ -726,10 +750,10 @@ git commit -m 'register the migration project podinfo component with the platfor
</TabItem>
<TabItem value="output" label="Output">
```txt
[main] register the migration project podinfo component with the platform
5 files changed, 167 insertions(+)
create mode 100644 deploy/clusters/workload/components/podinfo/podinfo.gen.yaml
create mode 100644 deploy/clusters/workload/gitops/podinfo.application.gen.yaml
[main 31197e2] register the migration project podinfo component with the platform
5 files changed, 205 insertions(+)
create mode 100644 deploy/clusters/local/components/podinfo/podinfo.gen.yaml
create mode 100644 deploy/clusters/local/gitops/podinfo.gen.yaml
create mode 100644 platform/migration-podinfo.cue
create mode 100644 projects/migration/app-project.cue
create mode 100644 projects/migration/components/podinfo/podinfo.cue
@@ -773,31 +797,29 @@ platform as a whole. Bank of Holos uses [HTTPRoute] routes from the new Gateway
API. The company the bank acquired uses older Ingress resources from earlier
Kubernetes versions.
The platform team at the bank defines a `#HTTPRoutes` struct for other teams at
the bank to register with. The `#HTTPRoutes` struct is similar to the
`#Namespaces` and `#AppProjects` structs we've already seen.
The platform team at the bank defines a `_HTTPRoutes` struct for other teams at
the bank to register with. The `_HTTPRoutes` struct is similar to the
`_Namespaces` and `_AppProjects` structs we've already seen.
As a member of the migration team, we'll add the file
`projects/migration-routes.cue` to expose the service we're migrating.
Go ahead and create this file with the following content.
Go ahead and create this file (if it hasn't been created previously) with the following content.
<Tabs groupId="6F9044EC-1737-4926-BD07-455536BA6573">
<TabItem value="projects/migration-routes.cue" label="projects/migration-routes.cue">
```cue showLineNumbers
package holos
let Podinfo = {
podinfo: {
port: 9898
namespace: #Migration.Namespace
}
}
// Route migration-podinfo.example.com to port 9898 of Service podinfo in the
// migration namespace.
// highlight-next-line
#HTTPRoutes: "migration-podinfo": _backendRefs: Podinfo
_HTTPRoutes: "migration-podinfo": _backendRefs: {
podinfo: {
port: 9898
namespace: _Migration.Namespace
}
}
```
</TabItem>
<TabItem value="projects/httproutes.cue" label="projects/httproutes.cue">
@@ -806,44 +828,45 @@ 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.
// Struct containing HTTPRoute configurations. These resources are managed in
// the istio-ingress namespace. Other components define the routes they need
// close to the root of configuration.
_HTTPRoutes: #HTTPRoutes
// #HTTPRoutes defines the schema of managed HTTPRoute resources for the
// platform.
#HTTPRoutes: {
// For the guides, we simplify this down to a flat namespace.
// highlight-next-line
[Name=string]: v1.#HTTPRoute & {
let HOST = Name + "." + #Platform.Domain
// For the guides, we simplify this down to a flat namespace.
[Name=string]: v1.#HTTPRoute & {
let HOST = Name + "." + _Organization.Domain
// highlight-next-line
_backendRefs: [NAME=string]: {
name: NAME
namespace: string
port: number | *80
}
_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: "/"}}]
// highlight-next-line
backendRefs: [for x in _backendRefs {x}]
},
]
}
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}]
},
]
}
}
```
</TabItem>
</Tabs>
In this file we're adding a field to the `#HTTPRoutes` struct the platform team
In this file we're adding a field to the `_HTTPRoutes` struct the platform team
defined for us.
You might be wondering how we knew all of these fields to put into this file.
@@ -857,8 +880,9 @@ The most important things the migration team takes away from this file are:
1. The platform team requires a `gateway.networking.k8s.io/httproute/v1`
`HTTPRoute`.
2. Line 13 uses a [hidden field] so we can provide backend references as a struct instead of a list.
3. Line 30 uses a [comprehension] to convert the struct to a list.
2. Line 17 uses a [hidden field] so we can provide backend references as a
struct instead of a list.
3. Line 34 uses a [comprehension] to convert the struct to a list.
We can look up the spec for the fields we need to provide in the Gateway API
reference documentation for [HTTPRoute].
@@ -924,39 +948,39 @@ git diff
</TabItem>
<TabItem value="output" label="Output">
```diff
diff --git a/deploy/clusters/workload/components/httproutes/httproutes.gen.yaml b/deploy/clusters/workload/components/httproutes/httproutes.gen.yaml
index 4b476da..a150015 100644
--- a/deploy/clusters/workload/components/httproutes/httproutes.gen.yaml
+++ b/deploy/clusters/workload/components/httproutes/httproutes.gen.yaml
@@ -46,3 +46,27 @@ spec:
- name: frontend
namespace: bank-frontend
port: 80
diff --git a/deploy/clusters/local/components/httproutes/httproutes.gen.yaml b/deploy/clusters/local/components/httproutes/httproutes.gen.yaml
index 06f7c91..349e070 100644
--- a/deploy/clusters/local/components/httproutes/httproutes.gen.yaml
+++ b/deploy/clusters/local/components/httproutes/httproutes.gen.yaml
@@ -47,3 +47,28 @@ spec:
- path:
type: PathPrefix
value: /
+---
+# Source: CUE apiObjects.HTTPRoute.migration-podinfo
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: migration-podinfo
+ namespace: istio-ingress
+ labels:
+ app: migration-podinfo
+ argocd.argoproj.io/instance: httproutes
+ holos.run/component.name: httproutes
+ name: migration-podinfo
+ namespace: istio-ingress
+spec:
+ hostnames:
+ - migration-podinfo.holos.localhost
+ - migration-podinfo.holos.localhost
+ parentRefs:
+ - name: default
+ namespace: istio-ingress
+ - name: default
+ namespace: istio-ingress
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ backendRefs:
+ - name: podinfo
+ port: 9898
+ namespace: migration
+ - backendRefs:
+ - name: podinfo
+ namespace: migration
+ port: 9898
+ matches:
+ - path:
+ type: PathPrefix
+ value: /
```
</TabItem>
</Tabs>
@@ -1039,7 +1063,7 @@ in the `bank-of-holos` repository after resetting your cluster following the
</TabItem>
<TabItem value="output" label="Output">
```txt
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/namespaces/namespaces.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/namespaces/namespaces.gen.yaml
namespace/argocd serverside-applied
namespace/bank-backend serverside-applied
namespace/bank-frontend serverside-applied
@@ -1049,17 +1073,17 @@ namespace/external-secrets serverside-applied
namespace/istio-ingress serverside-applied
namespace/istio-system serverside-applied
namespace/migration serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/argocd-crds/argocd-crds.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/argocd-crds/argocd-crds.gen.yaml
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/gateway-api/gateway-api.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/gateway-api/gateway-api.gen.yaml
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
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/external-secrets-crds/external-secrets-crds.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/external-secrets-crds/external-secrets-crds.gen.yaml
customresourcedefinition.apiextensions.k8s.io/acraccesstokens.generators.external-secrets.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/clusterexternalsecrets.external-secrets.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/clustersecretstores.external-secrets.io serverside-applied
@@ -1121,7 +1145,7 @@ customresourcedefinition.apiextensions.k8s.io/wasmplugins.extensions.istio.io co
customresourcedefinition.apiextensions.k8s.io/webhooks.generators.external-secrets.io condition met
customresourcedefinition.apiextensions.k8s.io/workloadentries.networking.istio.io condition met
customresourcedefinition.apiextensions.k8s.io/workloadgroups.networking.istio.io condition met
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/external-secrets/external-secrets.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/external-secrets/external-secrets.gen.yaml
serviceaccount/external-secrets-cert-controller serverside-applied
serviceaccount/external-secrets serverside-applied
serviceaccount/external-secrets-webhook serverside-applied
@@ -1141,7 +1165,7 @@ deployment.apps/external-secrets serverside-applied
deployment.apps/external-secrets-webhook serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/secretstore-validate serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/externalsecret-validate serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/cert-manager/cert-manager.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/cert-manager/cert-manager.gen.yaml
serviceaccount/cert-manager-cainjector serverside-applied
serviceaccount/cert-manager serverside-applied
serviceaccount/cert-manager-webhook serverside-applied
@@ -1187,11 +1211,11 @@ deployment.apps/cert-manager serverside-applied
deployment.apps/cert-manager-webhook serverside-applied
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/local-ca/local-ca.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/local-ca/local-ca.gen.yaml
clusterissuer.cert-manager.io/local-ca serverside-applied
+ kubectl wait --for=condition=Ready clusterissuer/local-ca --timeout=30s
clusterissuer.cert-manager.io/local-ca condition met
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/argocd/argocd.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/argocd/argocd.gen.yaml
serviceaccount/argocd-application-controller serverside-applied
serviceaccount/argocd-applicationset-controller serverside-applied
serviceaccount/argocd-notifications-controller serverside-applied
@@ -1238,13 +1262,13 @@ deployment.apps/argocd-server serverside-applied
statefulset.apps/argocd-application-controller serverside-applied
job.batch/argocd-redis-secret-init serverside-applied
referencegrant.gateway.networking.k8s.io/istio-ingress serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/app-projects/app-projects.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/app-projects/app-projects.gen.yaml
appproject.argoproj.io/bank-backend serverside-applied
appproject.argoproj.io/bank-frontend serverside-applied
appproject.argoproj.io/bank-security serverside-applied
appproject.argoproj.io/migration serverside-applied
appproject.argoproj.io/platform serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-base/istio-base.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/istio-base/istio-base.gen.yaml
customresourcedefinition.apiextensions.k8s.io/authorizationpolicies.security.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/destinationrules.networking.istio.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/envoyfilters.networking.istio.io serverside-applied
@@ -1261,7 +1285,7 @@ customresourcedefinition.apiextensions.k8s.io/workloadentries.networking.istio.i
customresourcedefinition.apiextensions.k8s.io/workloadgroups.networking.istio.io serverside-applied
serviceaccount/istio-reader-service-account serverside-applied
validatingwebhookconfiguration.admissionregistration.k8s.io/istiod-default-validator serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/istiod/istiod.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/istiod/istiod.gen.yaml
serviceaccount/istiod serverside-applied
role.rbac.authorization.k8s.io/istiod serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-reader-clusterrole-istio-system serverside-applied
@@ -1279,7 +1303,7 @@ poddisruptionbudget.policy/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
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-cni/istio-cni.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/istio-cni/istio-cni.gen.yaml
serviceaccount/istio-cni serverside-applied
configmap/istio-cni-config serverside-applied
clusterrole.rbac.authorization.k8s.io/istio-cni serverside-applied
@@ -1291,20 +1315,20 @@ clusterrolebinding.rbac.authorization.k8s.io/istio-cni-ambient serverside-applie
daemonset.apps/istio-cni-node serverside-applied
+ kubectl wait --for=condition=Ready pod -l k8s-app=istio-cni-node --timeout=300s -n istio-system
pod/istio-cni-node-7kfbh condition met
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-ztunnel/istio-ztunnel.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/istio-ztunnel/istio-ztunnel.gen.yaml
serviceaccount/ztunnel serverside-applied
daemonset.apps/ztunnel serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/istio-gateway/istio-gateway.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/istio-gateway/istio-gateway.gen.yaml
certificate.cert-manager.io/gateway-cert serverside-applied
gateway.gateway.networking.k8s.io/default serverside-applied
serviceaccount/default-istio serverside-applied
+ kubectl wait --for=condition=Ready pod -l istio.io/gateway-name=default --timeout=300s -n istio-ingress
pod/default-istio-54598d985b-69wmr condition met
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/httproutes/httproutes.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/httproutes/httproutes.gen.yaml
httproute.gateway.networking.k8s.io/argocd serverside-applied
httproute.gateway.networking.k8s.io/bank serverside-applied
httproute.gateway.networking.k8s.io/migration-podinfo serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-secrets/bank-secrets.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-secrets/bank-secrets.gen.yaml
configmap/jwt-key-writer serverside-applied
job.batch/jwt-key-writer serverside-applied
role.rbac.authorization.k8s.io/jwt-key-reader serverside-applied
@@ -1314,7 +1338,7 @@ rolebinding.rbac.authorization.k8s.io/jwt-key-writer serverside-applied
serviceaccount/jwt-key-writer serverside-applied
+ kubectl wait --for=condition=complete job.batch/jwt-key-writer -n bank-security --timeout=300s
job.batch/jwt-key-writer condition met
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-backend-config/bank-backend-config.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-backend-config/bank-backend-config.gen.yaml
configmap/demo-data-config serverside-applied
configmap/environment-config serverside-applied
configmap/service-api-config serverside-applied
@@ -1322,30 +1346,30 @@ externalsecret.external-secrets.io/jwt-key serverside-applied
referencegrant.gateway.networking.k8s.io/istio-ingress serverside-applied
secretstore.external-secrets.io/bank-security serverside-applied
serviceaccount/bank-of-holos serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-accounts-db/bank-accounts-db.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-accounts-db/bank-accounts-db.gen.yaml
configmap/accounts-db-config serverside-applied
service/accounts-db serverside-applied
statefulset.apps/accounts-db serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-ledger-db/bank-ledger-db.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-ledger-db/bank-ledger-db.gen.yaml
configmap/ledger-db-config serverside-applied
service/ledger-db serverside-applied
statefulset.apps/ledger-db serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-contacts/bank-contacts.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-contacts/bank-contacts.gen.yaml
deployment.apps/contacts serverside-applied
service/contacts serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-balance-reader/bank-balance-reader.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-balance-reader/bank-balance-reader.gen.yaml
deployment.apps/balancereader serverside-applied
service/balancereader serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-userservice/bank-userservice.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-userservice/bank-userservice.gen.yaml
deployment.apps/userservice serverside-applied
service/userservice serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-ledger-writer/bank-ledger-writer.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-ledger-writer/bank-ledger-writer.gen.yaml
deployment.apps/ledgerwriter serverside-applied
service/ledgerwriter serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-transaction-history/bank-transaction-history.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-transaction-history/bank-transaction-history.gen.yaml
deployment.apps/transactionhistory serverside-applied
service/transactionhistory serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/components/bank-frontend/bank-frontend.gen.yaml
+ kubectl apply --server-side=true -f deploy/clusters/local/components/bank-frontend/bank-frontend.gen.yaml
configmap/demo-data-config serverside-applied
configmap/environment-config serverside-applied
configmap/service-api-config serverside-applied
@@ -1355,7 +1379,7 @@ referencegrant.gateway.networking.k8s.io/istio-ingress serverside-applied
secretstore.external-secrets.io/bank-security serverside-applied
service/frontend serverside-applied
serviceaccount/bank-of-holos serverside-applied
+ kubectl apply --server-side=true -f deploy/clusters/workload/gitops
+ kubectl apply --server-side=true -f deploy/clusters/local/gitops
application.argoproj.io/app-projects serverside-applied
application.argoproj.io/argocd-crds serverside-applied
application.argoproj.io/argocd serverside-applied
@@ -1428,10 +1452,10 @@ for some time.
[Quickstart]: /docs/quickstart/
[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
[Helm]: /docs/api/author/v1alpha4/#Helm
[Kubernetes]: /docs/api/author/v1alpha4/#Kubernetes
[Kustomize]: /docs/api/author/v1alpha4/#Kustomize
[ComponentConfig]: /docs/api/author/v1alpha4/#ComponentConfig
[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

View File

@@ -1,15 +0,0 @@
---
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

4808
doc/md/guides/helm.mdx Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -1,20 +0,0 @@
---
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

@@ -1,20 +0,0 @@
---
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

@@ -72,7 +72,7 @@ go install github.com/holos-run/holos/cmd/holos@latest
</TabItem>
<TabItem value="output" label="Output">
```txt
go: downloading github.com/holos-run/holos v0.95.1
go: downloading github.com/holos-run/holos v0.97.2
```
</TabItem>
</Tabs>
@@ -138,12 +138,10 @@ workflow.
```cue showLineNumbers
package holos
#ArgoConfig: {
Enabled: true
// highlight-next-line
RepoURL: "https://github.com/holos-run/bank-of-holos"
_ArgoConfig: {
Enabled: true
RepoURL: "https://github.com/jeffmccune/bank-of-holos"
}
```
</TabItem>
</Tabs>
@@ -154,16 +152,17 @@ Change the RepoURL to the URL of your fork. For example:
<TabItem value="command" label="projects/argocd-config.cue">
```diff showLineNumbers
diff --git a/projects/argocd-config.cue b/projects/argocd-config.cue
index 5264f48..0214e99 100644
index 1291a31..ff3bbfb 100644
--- a/projects/argocd-config.cue
+++ b/projects/argocd-config.cue
@@ -2,5 +2,5 @@ package holos
#ArgoConfig: {
Enabled: true
- RepoURL: "https://github.com/holos-run/bank-of-holos"
+ RepoURL: "https://github.com/jeffmccune/bank-of-holos"
_ArgoConfig: {
Enabled: true
- RepoURL: "https://github.com/holos-run/bank-of-holos"
+ RepoURL: "https://github.com/jeffmccune/bank-of-holos"
}
```
</TabItem>
</Tabs>
@@ -228,38 +227,36 @@ git status
</TabItem>
<TabItem value="output" label="Output">
```txt
On branch main
Your branch is up to date with 'origin/main'.
On branch jeff/291-consistent-fields
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)
modified: deploy/clusters/workload/gitops/app-projects.gen.yaml
modified: deploy/clusters/workload/gitops/argocd-crds.gen.yaml
modified: deploy/clusters/workload/gitops/argocd.gen.yaml
modified: deploy/clusters/workload/gitops/bank-accounts-db.gen.yaml
modified: deploy/clusters/workload/gitops/bank-backend-config.gen.yaml
modified: deploy/clusters/workload/gitops/bank-balance-reader.gen.yaml
modified: deploy/clusters/workload/gitops/bank-contacts.gen.yaml
modified: deploy/clusters/workload/gitops/bank-frontend.gen.yaml
modified: deploy/clusters/workload/gitops/bank-ledger-db.gen.yaml
modified: deploy/clusters/workload/gitops/bank-ledger-writer.gen.yaml
modified: deploy/clusters/workload/gitops/bank-secrets.gen.yaml
modified: deploy/clusters/workload/gitops/bank-transaction-history.gen.yaml
modified: deploy/clusters/workload/gitops/bank-userservice.gen.yaml
modified: deploy/clusters/workload/gitops/cert-manager.gen.yaml
modified: deploy/clusters/workload/gitops/external-secrets-crds.gen.yaml
modified: deploy/clusters/workload/gitops/external-secrets.gen.yaml
modified: deploy/clusters/workload/gitops/gateway-api.gen.yaml
modified: deploy/clusters/workload/gitops/httproutes.gen.yaml
modified: deploy/clusters/workload/gitops/istio-base.gen.yaml
modified: deploy/clusters/workload/gitops/istio-cni.gen.yaml
modified: deploy/clusters/workload/gitops/istio-gateway.gen.yaml
modified: deploy/clusters/workload/gitops/istio-ztunnel.gen.yaml
modified: deploy/clusters/workload/gitops/istiod.gen.yaml
modified: deploy/clusters/workload/gitops/local-ca.gen.yaml
modified: deploy/clusters/workload/gitops/namespaces.gen.yaml
modified: projects/argocd-config.cue
modified: deploy/clusters/local/gitops/app-projects.gen.yaml
modified: deploy/clusters/local/gitops/argocd-crds.gen.yaml
modified: deploy/clusters/local/gitops/argocd.gen.yaml
modified: deploy/clusters/local/gitops/bank-accounts-db.gen.yaml
modified: deploy/clusters/local/gitops/bank-backend-config.gen.yaml
modified: deploy/clusters/local/gitops/bank-balance-reader.gen.yaml
modified: deploy/clusters/local/gitops/bank-contacts.gen.yaml
modified: deploy/clusters/local/gitops/bank-frontend.gen.yaml
modified: deploy/clusters/local/gitops/bank-ledger-db.gen.yaml
modified: deploy/clusters/local/gitops/bank-ledger-writer.gen.yaml
modified: deploy/clusters/local/gitops/bank-secrets.gen.yaml
modified: deploy/clusters/local/gitops/bank-transaction-history.gen.yaml
modified: deploy/clusters/local/gitops/bank-userservice.gen.yaml
modified: deploy/clusters/local/gitops/cert-manager.gen.yaml
modified: deploy/clusters/local/gitops/external-secrets-crds.gen.yaml
modified: deploy/clusters/local/gitops/external-secrets.gen.yaml
modified: deploy/clusters/local/gitops/gateway-api.gen.yaml
modified: deploy/clusters/local/gitops/httproutes.gen.yaml
modified: deploy/clusters/local/gitops/istio-base.gen.yaml
modified: deploy/clusters/local/gitops/istio-cni.gen.yaml
modified: deploy/clusters/local/gitops/istio-gateway.gen.yaml
modified: deploy/clusters/local/gitops/istio-ztunnel.gen.yaml
modified: deploy/clusters/local/gitops/istiod.gen.yaml
modified: deploy/clusters/local/gitops/local-ca.gen.yaml
modified: deploy/clusters/local/gitops/namespaces.gen.yaml
modified: projects/argocd-config.cue
no changes added to commit (use "git add" and/or "git commit -a")
```
@@ -272,22 +269,23 @@ the changed `spec.source.repoURL` field.
<Tabs groupId="665E5402-FB42-4975-B654-3922EE73EE07">
<TabItem value="command" label="Command">
```bash
git diff deploy/clusters/workload/gitops/bank-frontend.gen.yaml
git diff deploy/clusters/local/gitops/bank-frontend.gen.yaml
```
</TabItem>
<TabItem value="output" label="Output">
```diff showLineNumbers
diff --git a/deploy/clusters/workload/gitops/bank-frontend.gen.yaml b/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
index 3a3dec0..22e21bb 100644
--- a/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
+++ b/deploy/clusters/workload/gitops/bank-frontend.gen.yaml
diff --git a/deploy/clusters/local/gitops/bank-frontend.gen.yaml b/deploy/clusters/local/gitops/bank-frontend.gen.yaml
index e07d5ea..14cc71c 100644
--- a/deploy/clusters/local/gitops/bank-frontend.gen.yaml
+++ b/deploy/clusters/local/gitops/bank-frontend.gen.yaml
@@ -11,5 +11,5 @@ spec:
project: default
project: bank-frontend
source:
path: deploy/clusters/workload/components/bank-frontend
path: deploy/clusters/local/components/bank-frontend
- repoURL: https://github.com/holos-run/bank-of-holos
+ repoURL: https://github.com/jeffmccune/bank-of-holos
targetRevision: main
```
</TabItem>
</Tabs>
@@ -407,14 +405,14 @@ files for now, they behave the same as these two.
package holos
// Manage the Component on every Cluster in the Platform
for Fleet in #Fleets {
for Fleet in _Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name):argocd-crds": {
_Platform: Components: "\(Cluster.name):argocd-crds": {
name: "argocd-crds"
component: "projects/platform/components/argocd/crds"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name):argocd": {
_Platform: Components: "\(Cluster.name):argocd": {
name: "argocd"
component: "projects/platform/components/argocd/argocd"
cluster: Cluster.name
@@ -428,14 +426,14 @@ for Fleet in #Fleets {
package holos
// Manage the component on every cluster in the platform
for Fleet in #Fleets {
for Fleet in _Fleets {
for Cluster in Fleet.clusters {
#Platform: Components: "\(Cluster.name):external-secrets-crds": {
_Platform: Components: "\(Cluster.name):external-secrets-crds": {
name: "external-secrets-crds"
component: "projects/platform/components/external-secrets-crds"
cluster: Cluster.name
}
#Platform: Components: "\(Cluster.name):external-secrets": {
_Platform: Components: "\(Cluster.name):external-secrets": {
name: "external-secrets"
component: "projects/platform/components/external-secrets"
cluster: Cluster.name
@@ -488,7 +486,7 @@ understand how the rest of the CUE files in the platform directory behave.
:::tip
Each CUE file in the platform directory adds components to the
`#Platform.Components` struct.
`_Platform.Components` struct.
:::
The final file in the directory is responsible for producing the Platform spec.
@@ -501,17 +499,17 @@ package holos
import api "github.com/holos-run/holos/api/author/v1alpha4"
#Platform: api.#Platform & {
Name: "guide"
_Platform: api.#Platform & {
Name: "default"
}
// Render a Platform resource for holos to process
#Platform.Resource
_Platform.Resource
```
</TabItem>
</Tabs>
This file provides the value of the `#Platform.Resource` field, the platform
This file provides the value of the `_Platform.Resource` field, the platform
spec, to `holos`.
Let's take a look at that Output value:
@@ -527,29 +525,84 @@ cue export --out yaml ./platform
kind: Platform
apiVersion: v1alpha4
metadata:
name: guide
name: default
spec:
components: # This is a trimmed list for readability.
components:
- name: httproutes
component: projects/platform/components/httproutes
cluster: local
- name: istio-gateway
component: projects/platform/components/istio/gateway
cluster: local
- name: istio-base
component: projects/platform/components/istio/base
cluster: local
- name: istiod
component: projects/platform/components/istio/istiod
cluster: local
- name: istio-cni
component: projects/platform/components/istio/cni
cluster: local
- name: istio-ztunnel
component: projects/platform/components/istio/ztunnel
cluster: local
- name: app-projects
component: projects/platform/components/app-projects
cluster: local
- name: argocd-crds
component: projects/platform/components/argocd/crds
cluster: local
- name: argocd
component: projects/platform/components/argocd/argocd
cluster: local
- name: bank-secrets
component: projects/bank-of-holos/security/components/bank-secrets
cluster: workload
model: {}
cluster: local
- name: bank-frontend
component: projects/bank-of-holos/frontend/components/bank-frontend
cluster: workload
model: {}
cluster: local
- name: bank-backend-config
component: projects/bank-of-holos/backend/components/bank-backend-config
cluster: workload
model: {}
cluster: local
- name: bank-accounts-db
component: projects/bank-of-holos/backend/components/bank-accounts-db
cluster: workload
model: {}
cluster: local
- name: bank-userservice
component: projects/bank-of-holos/backend/components/bank-userservice
cluster: workload
model: {}
cluster: local
- name: bank-ledger-db
component: projects/bank-of-holos/backend/components/bank-ledger-db
cluster: local
- name: bank-ledger-writer
component: projects/bank-of-holos/backend/components/bank-ledger-writer
cluster: local
- name: bank-balance-reader
component: projects/bank-of-holos/backend/components/bank-balance-reader
cluster: local
- name: bank-transaction-history
component: projects/bank-of-holos/backend/components/bank-transaction-history
cluster: local
- name: bank-contacts
component: projects/bank-of-holos/backend/components/bank-contacts
cluster: local
- name: cert-manager
component: projects/platform/components/cert-manager
cluster: local
- name: external-secrets-crds
component: projects/platform/components/external-secrets-crds
cluster: local
- name: external-secrets
component: projects/platform/components/external-secrets
cluster: local
- name: gateway-api
component: projects/platform/components/gateway-api
cluster: local
- name: local-ca
component: projects/platform/components/local-ca
cluster: local
- name: namespaces
component: projects/platform/components/namespaces
cluster: local
```
</TabItem>
</Tabs>
@@ -600,23 +653,26 @@ start working with the cert-manager component.
package holos
// Produce a helm chart build plan.
(#Helm & Chart).BuildPlan
_HelmChart.BuildPlan
let Chart = {
_HelmChart: #Helm & {
Name: "cert-manager"
Namespace: #CertManager.Namespace
Namespace: _CertManager.Namespace
Chart: {
version: #CertManager.Version
version: _CertManager.Version
repository: {
name: "jetstack"
url: "https://charts.jetstack.io"
}
}
EnableHooks: true
Values: {
installCRDs: true
Values: #Values & {
crds: enabled: true
startupapicheck: enabled: false
// https://github.com/cert-manager/cert-manager/issues/6716
global: leaderElection: namespace: Namespace
}
}
```
@@ -625,14 +681,19 @@ let Chart = {
```cue showLineNumbers
package holos
// Platform wide configuration
#CertManager: {
Version: "1.15.3"
Version: string
Namespace: string
}
// Platform wide configuration
_CertManager: {
Version: "v1.16.1"
Namespace: "cert-manager"
}
// Register the namespace
#Namespaces: (#CertManager.Namespace): _
_Namespaces: (_CertManager.Namespace): _
```
</TabItem>
</Tabs>
@@ -640,15 +701,13 @@ package holos
This file introduces a few new concepts.
1. Line 4 indicates this component produces a BuildPlan that wraps a Helm Chart.
2. On line 6 `let` binds a name to an expression for the current scope. The
current file in this case.
3. Notice Chart is referenced on line 4 before it's bound on line 6. **Order is
irrelevant in CUE**. Complex changes are simpler and easier when we don't have
to think about order.
4. The chart version and namespace are defined in a different file closer to the
root, `projects/cert-manager.cue`
5. We define Helm values in CUE to take advantage of strong type checking and
manage multiple Helm charts consistently with platform wide values.
2. Notice `_HelmChart` is referenced on line 4 before it's defined on line 6.
**Order is irrelevant in CUE**. Complex changes are simpler and easier when we
don't have to think about order.
3. Line 8 and 11: The chart version and namespace are defined in a different
file closer to the root, `projects/cert-manager.cue`
4. Line 19: Helm values are defined in CUE to take advantage of strong type
checking and manage multiple Helm charts consistently with the same values.
Let's take a look at the BuildPlan that results from the CUE configuration
described above.
@@ -675,16 +734,280 @@ spec:
helm:
chart:
name: cert-manager
version: 1.15.3
version: v1.16.1
release: cert-manager
repository:
name: jetstack
url: https://charts.jetstack.io
values:
installCRDs: true
global:
imagePullSecrets: []
commonLabels: {}
priorityClassName: ""
rbac:
create: true
aggregateClusterRoles: true
podSecurityPolicy:
enabled: false
useAppArmor: true
logLevel: 2
leaderElection:
namespace: cert-manager
installCRDs: false
crds:
enabled: true
keep: true
replicaCount: 1
strategy: {}
podDisruptionBudget:
enabled: false
featureGates: ""
maxConcurrentChallenges: 60
image:
repository: quay.io/jetstack/cert-manager-controller
pullPolicy: IfNotPresent
clusterResourceNamespace: ""
namespace: ""
serviceAccount:
create: true
automountServiceAccountToken: true
enableCertificateOwnerRef: false
config: {}
dns01RecursiveNameservers: ""
dns01RecursiveNameserversOnly: false
disableAutoApproval: false
approveSignerNames:
- issuers.cert-manager.io/*
- clusterissuers.cert-manager.io/*
extraArgs: []
extraEnv: []
resources: {}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
volumes: []
volumeMounts: []
podLabels: {}
hostAliases: []
nodeSelector:
kubernetes.io/os: linux
ingressShim: {}
affinity: {}
tolerations: []
topologySpreadConstraints: []
livenessProbe:
enabled: true
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
successThreshold: 1
failureThreshold: 8
enableServiceLinks: false
prometheus:
enabled: true
servicemonitor:
enabled: false
prometheusInstance: default
targetPort: 9402
path: /metrics
interval: 60s
scrapeTimeout: 30s
labels: {}
annotations: {}
honorLabels: false
endpointAdditionalProperties: {}
podmonitor:
enabled: false
prometheusInstance: default
path: /metrics
interval: 60s
scrapeTimeout: 30s
labels: {}
annotations: {}
honorLabels: false
endpointAdditionalProperties: {}
webhook:
replicaCount: 1
timeoutSeconds: 30
config: {}
strategy: {}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
podDisruptionBudget:
enabled: false
validatingWebhookConfiguration:
namespaceSelector:
matchExpressions:
- key: cert-manager.io/disable-validation
operator: NotIn
values:
- "true"
mutatingWebhookConfiguration:
namespaceSelector: {}
extraArgs: []
extraEnv: []
featureGates: ""
resources: {}
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 60
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 1
nodeSelector:
kubernetes.io/os: linux
affinity: {}
tolerations: []
topologySpreadConstraints: []
podLabels: {}
serviceLabels: {}
serviceIPFamilyPolicy: ""
serviceIPFamilies: []
image:
repository: quay.io/jetstack/cert-manager-webhook
pullPolicy: IfNotPresent
serviceAccount:
create: true
automountServiceAccountToken: true
securePort: 10250
hostNetwork: false
serviceType: ClusterIP
url: {}
networkPolicy:
enabled: false
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0
egress:
- ports:
- port: 80
protocol: TCP
- port: 443
protocol: TCP
- port: 53
protocol: TCP
- port: 53
protocol: UDP
- port: 6443
protocol: TCP
to:
- ipBlock:
cidr: 0.0.0.0/0
volumes: []
volumeMounts: []
enableServiceLinks: false
cainjector:
enabled: true
replicaCount: 1
config: {}
strategy: {}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
podDisruptionBudget:
enabled: false
extraArgs: []
extraEnv: []
featureGates: ""
resources: {}
nodeSelector:
kubernetes.io/os: linux
affinity: {}
tolerations: []
topologySpreadConstraints: []
podLabels: {}
serviceLabels: {}
image:
repository: quay.io/jetstack/cert-manager-cainjector
pullPolicy: IfNotPresent
serviceAccount:
create: true
automountServiceAccountToken: true
volumes: []
volumeMounts: []
enableServiceLinks: false
acmesolver:
image:
repository: quay.io/jetstack/cert-manager-acmesolver
pullPolicy: IfNotPresent
startupapicheck:
enabled: false
enableHooks: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
timeout: 1m
backoffLimit: 4
jobAnnotations:
helm.sh/hook: post-install
helm.sh/hook-weight: "1"
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
extraArgs:
- -v
extraEnv: []
resources: {}
nodeSelector:
kubernetes.io/os: linux
affinity: {}
tolerations: []
podLabels: {}
image:
repository: quay.io/jetstack/cert-manager-startupapicheck
pullPolicy: IfNotPresent
rbac:
annotations:
helm.sh/hook: post-install
helm.sh/hook-weight: "-5"
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
serviceAccount:
create: true
annotations:
helm.sh/hook: post-install
helm.sh/hook-weight: "-5"
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
automountServiceAccountToken: true
volumes: []
volumeMounts: []
enableServiceLinks: false
extraObjects: []
creator: helm
enabled: true
enableHooks: true
namespace: cert-manager
- kind: Resources
output: resources.gen.yaml
@@ -711,6 +1034,7 @@ spec:
namespace: cert-manager
commonLabels:
holos.run/component.name: cert-manager
argocd.argoproj.io/instance: cert-manager
resources:
- combined.gen.yaml
- artifact: clusters/no-cluster/gitops/cert-manager.gen.yaml
@@ -728,7 +1052,7 @@ spec:
spec:
destination:
server: https://kubernetes.default.svc
project: default
project: platform
source:
path: deploy/clusters/no-cluster/components/cert-manager
repoURL: https://github.com/jeffmccune/bank-of-holos

View File

@@ -42,9 +42,9 @@ graph TB
Kustomize[<a href="#component">Kustomize</a>]
CUE[<a href="#component">CUE</a>]
Cluster --> Platform
Fleet --> Cluster
Component --> Fleet
Fleet --> Platform
Cluster --> Fleet
Component --> Cluster
Helm --> Component
Kustomize --> Component
CUE --> Component

View File

@@ -8,7 +8,7 @@ sidebar_position: 900
## Community Support
You can ask questions in our community forums in [GitHub Discussions](https://github.com/holos-run/holos/discussions) or [Google Groups](https://groups.google.com/g/holos-discuss).
You can ask questions in our community forums in [GitHub Discussions](https://github.com/holos-run/holos/discussions), [Discord](https://discord.gg/JgDVbNpye7), or [Google Groups](https://groups.google.com/g/holos-discuss).
## Commercial Support and Services

View File

@@ -1,8 +1,14 @@
---
slug: technical-overview
title: Technical Overview
description: Learn how Holos makes it easier for platform teams to integrate software into their platform.
---
<head>
<meta property="og:title" content="Technical Overview | Holos" />
<meta property="og:image" content="/img/cards/technical-overview.png" />
</head>
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';
@@ -45,7 +51,7 @@ Go command line tool leveraging [CUE] to fill this gap.
```mermaid
---
title: Figure 1 - v1alpha4 Render Pipeline
title: Figure 1 - v1alpha4 Rendered Manifest Pipeline
---
graph LR
Platform[<a href="/docs/api/author/v1alpha4/#Platform">Platform</a>]
@@ -60,18 +66,19 @@ graph LR
ResourcesArtifact[<a href="/docs/api/core/v1alpha4/#artifact">Resources<br/>Artifact</a>]
GitOpsArtifact[<a href="/docs/api/core/v1alpha4/#artifact">GitOps<br/>Artifact</a>]
Generator[<a href="/docs/api/core/v1alpha4/#generators">Generator</a>]
Transformer[<a href="/docs/api/core/v1alpha4/#transformer">Transformer</a>]
Generators[<a href="/docs/api/core/v1alpha4/#generators">Generators</a>]
Transformers[<a href="/docs/api/core/v1alpha4/#transformer">Transformers</a>]
Files[Manifest<br/>Files]
Platform --> Component
Component --> Helm --> BuildPlan
Component --> Kubernetes --> BuildPlan
Component --> Kustomize --> BuildPlan
BuildPlan --> ResourcesArtifact --> Generator
BuildPlan --> GitOpsArtifact --> Generator
BuildPlan --> ResourcesArtifact --> Generators
BuildPlan --> GitOpsArtifact --> Generators
Generator --> Transformer --> Files --> KubeAPI
Generators --> Transformers --> Files
```
## Use Case
@@ -106,7 +113,7 @@ The development team registers their experimental project, creatively named
package holos
// The development team registers a project name.
#Projects: experiment: {
_Projects: experiment: {
// The project owner must be named.
Owner: Name: "dev-team"
// Expose Service podinfo at https://podinfo.example.com
@@ -168,9 +175,9 @@ The fully rendered manifests are written into the `deploy/` directory organized
by cluster and component for GitOps.
<Tabs groupId="07FBE14E-E9EA-437B-9FA1-C6D8806524AD">
<TabItem value="deploy/clusters/overview/components/namespaces/namespaces.gen.yaml" label="namespaces">
<TabItem value="deploy/clusters/local/components/namespaces/namespaces.gen.yaml" label="namespaces">
```
cat deploy/clusters/overview/components/namespaces/namespaces.gen.yaml
cat deploy/clusters/local/components/namespaces/namespaces.gen.yaml
```
```yaml showLineNumbers
apiVersion: v1
@@ -186,9 +193,9 @@ metadata:
name: experiment
```
</TabItem>
<TabItem value="deploy/clusters/overview/components/projects/projects.gen.yaml" label="projects">
<TabItem value="deploy/clusters/local/components/projects/projects.gen.yaml" label="projects">
```
cat deploy/clusters/overview/components/projects/projects.gen.yaml
cat deploy/clusters/local/components/projects/projects.gen.yaml
```
```yaml showLineNumbers
apiVersion: rbac.authorization.k8s.io/v1
@@ -256,9 +263,9 @@ spec:
kind: Service
```
</TabItem>
<TabItem value="deploy/clusters/overview/components/httproutes/httproutes.gen.yaml" label="httproutes">
<TabItem value="deploy/clusters/local/components/httproutes/httproutes.gen.yaml" label="httproutes">
```
cat deploy/clusters/overview/components/httproutes/httproutes.gen.yaml
cat deploy/clusters/local/components/httproutes/httproutes.gen.yaml
```
```yaml showLineNumbers
apiVersion: gateway.networking.k8s.io/v1
@@ -294,7 +301,7 @@ spec:
The rendered manifests are derived from the project registration information by
definitions implemented by the platform team. The [Author API] provides a
[Project] schema, but does not define an implementation. The platform team
implements the [Project] schema by writing a `#Projects` definition to manage
implements the [Project] schema by adding a `_Projects` struct to manage
resources according to bank policies.
:::important
@@ -302,7 +309,7 @@ The Author API is intended as a convenient, ergonomic reference for component
authors. Definitions **are not** confined to the Author API.
:::
The following example shows how the platform team wrote the `#Projects`
The following example shows how the platform team wrote the `_Projects`
definition to derive the Namespace from the project registration provided by the
dev team.
@@ -315,8 +322,8 @@ projects/platform/components/namespaces/namespaces.cue
package holos
_Kubernetes: #Kubernetes & {
Name: "namespaces"
Resources: Namespace: #Namespaces
Name: "namespaces"
Resources: Namespace: _Namespaces
}
// Produce a kubernetes objects build plan.
@@ -326,7 +333,7 @@ _Kubernetes.BuildPlan
1. This is the namespaces component which manages a collection of Namespace resources derived from the project registration data shown in the second tab.
2. Line 5 manages a Namespace for each value of the `#Namespaces` struct. See the second tab for how the platform team defines this structure.
</TabItem>
<TabItem value="projects/projects.cue" label="#Projects Definition">
<TabItem value="projects/projects.cue" label="Projects Definition">
```txt
projects/projects.cue
```
@@ -338,42 +345,42 @@ import api "github.com/holos-run/holos/api/author/v1alpha4"
// Projects defines the structure other teams register with to manage project
// resources. The platform team defines the schema, development teams provide
// the values.
#Projects: api.#Projects & {
[NAME=string]: {
Name: NAME
// The platform team requires the development teams to indicate an owner of
// the project.
Owner: Name: string
// The default value for the owner email address is derived from the owner
// name, but development teams can provide a different email address if
// needed.
Owner: Email: string | *"sg-\(Owner.Name)@\(#Organization.Domain)"
// The platform team constrains the project to a single namespace.
Namespaces: close({(NAME): Name: NAME})
// The platform team constrains the exposed services to the project
// namespace.
Hostnames: [HOST=string]: {
Name: HOST
Namespace: Namespaces[NAME].Name
Service: HOST
Port: number | *80
}
_Projects: api.#Projects & {
[NAME=string]: {
Name: NAME
// The platform team requires the development teams to indicate an owner of
// the project.
Owner: Name: string
// The default value for the owner email address is derived from the owner
// name, but development teams can provide a different email address if
// needed.
Owner: Email: string | *"sg-\(Owner.Name)@\(_Organization.Domain)"
// The platform team constrains the project to a single namespace.
Namespaces: close({(NAME): Name: NAME})
// The platform team constrains the exposed services to the project
// namespace.
Hostnames: [HOST=string]: {
Name: HOST
Namespace: Namespaces[NAME].Name
Service: HOST
Port: number | *80
}
CommonLabels: {
"\(#Organization.Domain)/project.name": Name
"\(#Organization.Domain)/owner.name": Owner.Name
"\(#Organization.Domain)/owner.email": Owner.Email
}
}
CommonLabels: {
"\(_Organization.Domain)/project.name": Name
"\(_Organization.Domain)/owner.name": Owner.Name
"\(_Organization.Domain)/owner.email": Owner.Email
}
}
}
for Project in #Projects {
// Register project namespaces with the namespaces component.
#Namespaces: {
for Namespace in Project.Namespaces {
(Namespace.Name): metadata: labels: Project.CommonLabels
}
}
for Project in _Projects {
// Register project namespaces with the namespaces component.
_Namespaces: {
for Namespace in Project.Namespaces {
(Namespace.Name): metadata: labels: Project.CommonLabels
}
}
}
```
@@ -389,20 +396,20 @@ for Project in #Projects {
</Tabs>
The RoleBinding, SecretScore, and ReferenceGrant are managed in the
[projects](https://github.com/holos-run/bank-of-holos/blob/v0.2.0/examples/tech-overview/projects/platform/components/projects/projects.cue)
[projects](https://github.com/holos-run/bank-of-holos/blob/v0.4.1/examples/tech-overview/projects/platform/components/projects/projects.cue)
component, similar to the previous namespaces example.
The HTTPRoute is managed separately in the
[httproutes](https://github.com/holos-run/bank-of-holos/blob/v0.2.0/examples/tech-overview/projects/platform/components/httproutes/httproutes.cue)
[httproutes](https://github.com/holos-run/bank-of-holos/blob/v0.4.1/examples/tech-overview/projects/platform/components/httproutes/httproutes.cue)
component.
All components are registered with the platform in the
[platform](https://github.com/holos-run/bank-of-holos/tree/v0.2.0/examples/tech-overview/platform)
[platform](https://github.com/holos-run/bank-of-holos/tree/v0.4.1/examples/tech-overview/platform)
directory.
:::important
Multiple components, potentially owned by different teams, derive fully rendered
resources from the same three project values. The dev team added these three
values to the `#Projects` definition. The platform team wrote the definition to
values to the `_Projects` struct. The platform team wrote the definition to
integrate software according to bank policies. CUE powers this _unified_
platform configuration model.
:::
@@ -429,14 +436,14 @@ package holos
_HelmChart.BuildPlan
_HelmChart: #Helm & {
Name: "podinfo"
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
Name: "podinfo"
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
}
```
This file represents a Helm chart component to add to the platform. The second
@@ -450,13 +457,13 @@ platform/podinfo.cue
package holos
// Manage the component on every workload Cluster, but not management clusters.
for Cluster in #Fleets.workload.clusters {
#Platform: Components: "\(Cluster.name):podinfo": {
name: "podinfo"
component: "projects/experiment/components/podinfo"
cluster: Cluster.name
tags: project: "experiment"
}
for Cluster in _Fleets.workload.clusters {
_Platform: Components: "\(Cluster.name):podinfo": {
name: "podinfo"
component: "projects/experiment/components/podinfo"
cluster: Cluster.name
tags: project: "experiment"
}
}
```
This file registers the component with the platform. When the platform is
@@ -465,7 +472,7 @@ across the platform.
</TabItem>
</Tabs>
The project tag associates the `#Platform` component with the correct entry in the `#Projects` struct.
The project tag links the component to the same field of the `_Projects` struct.
:::important
You can add your own key=value tags in your platform specification to inject
@@ -498,7 +505,7 @@ rendered platform in 195.90275ms
<Tabs groupId="77BF500B-105A-4AB4-A615-DEC19F501AE1">
<TabItem value="command" label="Command">
```bash
cat deploy/clusters/overview/components/podinfo/podinfo.gen.yaml
cat deploy/clusters/local/components/podinfo/podinfo.gen.yaml
```
</TabItem>
<TabItem value="output" label="Output">
@@ -649,7 +656,7 @@ platform team added a constraint to the project so all Helm charts are post
processed with Kustomize to add these common labels. The platform team
accomplishes this by adding a constraint in the project directory. This can be
seen in
[schema.cue](https://github.com/holos-run/bank-of-holos/blob/v0.2.0/schema.cue#L35-L40)
[schema.cue](https://github.com/holos-run/bank-of-holos/blob/v0.4.1/schema.cue#L35-L38)
where the platform team configures all component kinds for the platform.
We've covered how the platform team provides a golden path for development teams

View File

@@ -1,94 +0,0 @@
---
slug: holos-platform-manager
title: Holos Platform Manager
authors: [jeff]
tags: [holos]
---
## Introducing Holos
Im excited to announce Holos, a tool designed to help engineering teams
manage their software development platforms built on the Kubernetes resource
model.
:::tip
For a hands-on introduction, check out our [Quickstart] Guide.
:::
<!-- truncate -->
### The Backstory
In our roles at [Open Infrastructure Services], and earlier at Puppet, we helped
many companies automate infrastructure management. In 2017, we had the
opportunity to work with Twitter to improve their configuration management
system. This opportunity gave us insight into the challenges of managing a
large-scale platform with multiple engineering teams. Our work involved
everything from observability systems to application deployment workflows and of
course, managing the core infrastructure.
This experience demonstrated the value of platform engineering. As the pandemic
hit, I began thinking about what a fully cloud-native platform might look like
using the Kubernetes resource model. Around the same time, I came across the
Hacker News post, “[Why Are We Templating YAML]?”, which sparked a good
discussion. It was clear I wasnt alone in my frustration with managing YAML
files and ensuring clear, predictable changes before merging them into
production.
A common pain point and theme is the complexity of working with nested YAML
configurations, especially with tools like ArgoCD and Helm. The lack of a
standard for rendering YAML templates makes it difficult to see what changes are
actually being applied to the Kubernetes API. This often results in trial and
error, costly blue-green deployments, and hours of debugging.
During the pandemic, I began experimenting with a tool to address this issue,
drawing on lessons from our work at Twitter. The key problems we aimed to solve
are:
- **Lack of visibility**: Engineers struggled to foresee the impact of small changes.
- **Large blast radius**: Small changes affected global systems, with no way to limit the impact.
- **Incomplete tooling**: While processes were in place, the right information wasnt surfaced at the right time.
We built several iterations of a reference platform based on Kubernetes,
initially focusing on fully rendering manifests into plain files—a pattern now
called the [rendered manifests pattern]. Over time, we realized we were spending
most of our time maintaining bash scripts and YAML templates. This led back to
the question: Why are we templating YAML? What _should_ replace templates?
We'd previously seen a colleague use CUE effectively to generate large scale
configurations for Envoy, and ran into CUE again when we worked on a project
involving Dagger, but I still hadn't taken a deep look at CUE.
At the end of 2023, I decided to dive deep with [CUE]. I quickly came to
appreciate CUEs unified approach where **order is irrelevant**. Before CUE, we
handled configuration data in a hierarchy with a precedence ordering, similar to
how we handled data in Puppet with Hiera. CUE's promise of no longer needing to
think about ordering and precedence rules held, alleviating a large cognitive
burden when dealing with complex configurations. CUE quickly allowed me to
replace the unmaintainable bash scripts and complex Helm templates, simplifying
our workflow.
### Enter Holos
Holos adds CUE as a well-specified integration layer over tools like Helm,
Kustomize, ArgoCD, and Crossplane. With Holos, we can now efficiently integrate
upstream Helm charts and Kustomize bases into our platform without the
complexity of templates and scripts. This has also made it easy for one team to
define "golden paths" that other teams can follow—like automatically configuring
namespaces and security policies when dev teams start new projects.
We've found Holos incredibly useful and hope you do too. Let us know your
thoughts!
[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/
[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
[Holos]: https://holos.run/
[Quickstart]: /docs/quickstart/
[rendered manifests pattern]: https://akuity.io/blog/the-rendered-manifests-pattern/

View File

@@ -0,0 +1,125 @@
---
slug: announcing-holos
title: Announcing Holos
authors: [jeff]
tags: [holos, launch]
image: /img/cards/announcing-holos.png
description: Holistically manage Helm and Kustomize with CUE
---
<head>
<title>Announcing Holos</title>
<meta property="og:title" content="Announcing Holos" />
</head>
I'm excited to share Holos, a Go command line tool we developed to make it
easier to manage a platform built on Kubernetes. Holos implements the rendered
manifests pattern as a data pipeline to fully render manifests generated from
[Helm], [Kustomize], or [CUE] in a holistic way.
[Helm]: https://helm.sh/
[Kustomize]: https://kustomize.io/
[CUE]: https://cuelang.org/
```mermaid
---
title: Rendered Manifest Pipeline
---
graph LR
Platform[<a href="/docs/api/author/v1alpha4/#Platform">Platform</a>]
Component[<a href="/docs/api/author/v1alpha4/#ComponentConfig">Components</a>]
Helm[<a href="/docs/api/author/v1alpha4/#Helm">Helm</a>]
Kustomize[<a href="/docs/api/author/v1alpha4/#Kustomize">Kustomize</a>]
Kubernetes[<a href="/docs/api/author/v1alpha4/#Kubernetes">Kubernetes</a>]
BuildPlan[<a href="/docs/api/core/v1alpha4/#buildplan">BuildPlan</a>]
ResourcesArtifact[<a href="/docs/api/core/v1alpha4/#artifact">Resources<br/>Artifact</a>]
GitOpsArtifact[<a href="/docs/api/core/v1alpha4/#artifact">GitOps<br/>Artifact</a>]
Generators[<a href="/docs/api/core/v1alpha4/#generators">Generators</a>]
Transformers[<a href="/docs/api/core/v1alpha4/#transformer">Transformers</a>]
Files[Manifest<br/>Files]
Platform --> Component
Component --> Helm --> BuildPlan
Component --> Kubernetes --> BuildPlan
Component --> Kustomize --> BuildPlan
BuildPlan --> ResourcesArtifact --> Generators
BuildPlan --> GitOpsArtifact --> Generators
Generators --> Transformers --> Files
```
<!-- truncate -->
At the start of the pandemic I was migrating our platform from VMs managed by
Puppet to Kubernetes. My primary goal was to build an observability system
similar to what we had when we managed Puppet at Twitter prior to the
acquisition. I started building the observability system with the official
[prometheus community charts], but quickly ran into issues where the
individual charts didnt work with each other. I was frustrated with how
complicated and difficult to configure these charts were. They werent well
integrated, so I switched to the [kube-prometheus-stack] umbrella chart which
attempts to solve this integration problem.
The umbrella chart got us further, as long as we didnt stray too far from the
default values, but we quickly ran into operational challenges. Upgrading the
chart introduced breaking changes we couldnt see until they were applied,
causing incidents. We needed to manage secrets securely so we mixed in
ExternalSecrets with many of the charts. We decided to handle these
customizations by implementing the [rendered manifests pattern] using scripts in
our CI pipeline.
These scripts got us further, but we found them costly to maintain.
Teammates needed to be careful to execute them with the same context they were
executed in CI. We realized we were reinventing Hiera to manage a hierarchy of
helm values.yaml files to inject into multiple charts.
At this point I started looking for a more holistic solution to this problem of
integrating multiple charts together. We saw the value in the rendered
manifests pattern, but we couldnt find an agreed upon implementation. We built
a Go command line tool to implement the pattern as a data pipeline. Id been
thinking about the comments from the [Why are we templating YAML] posts and
wondering what an answer to this question would look like.
The Go command line tool was an incremental improvement over the CI scripts, but
we still didnt have a good way to handle the data values. We were still
templating YAML which didnt catch errors early enough. It was too easy to
render invalid resources Kubernetes rejected, causing deployment problems. I
searched for a solution to manage helm values, something like Hiera which we
knew well from Puppet, but not hierarchical because we knew it was important to
trace where config values came from in an outage. A few HN comments mentioned
CUE, and an engineer we worked with at Twitter used CUE to configure Envoy at
scale, so I gave it a try. I quickly appreciated how CUE provides both strong
type checking and validation of constraints, unifies all configuration data, and
provides clarity into where values originate from.
Take a look at Holos if youre looking to implement the rendered manifests
pattern or cant shake that feeling it should be easier to integrate third party
software into Kubernetes like we felt.
1. [Helm Guide] Walks through how we solved the challenges we faced with the prometheus Helm charts.
2. [Quickstart] Works through how a platform team can define golden paths for other teams using CUE.
3. [Author API] provides an ergonomic way to work with Helm, Kustomize, and CUE resources.
[Helm Guide]: /docs/guides/helm/
[Guides]: /docs/guides/
[API Reference]: /docs/api/
[Quickstart]: /docs/quickstart/
[Author API]: /docs/api/author/
[Core API]: /docs/api/core/
[Open Infrastructure Services]: https://openinfrastructure.co/
[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
[Holos]: https://holos.run/
[Quickstart]: /docs/quickstart/
[Helm]: https://helm.sh/
[Kustomize]: https://kustomize.io/
[CUE]: https://cuelang.org/
[rendered manifests pattern]: https://akuity.io/blog/the-rendered-manifests-pattern/
[prometheus community charts]: https://github.com/prometheus-community/helm-charts
[kube-prometheus-stack]: https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack

View File

@@ -0,0 +1,123 @@
---
slug: why-cue-for-configuration
title: Why CUE for Configuration
authors: [jeff]
tags: [holos, cue]
image: /img/cards/why-cue.png
description: Why we use CUE for configuration in Holos
date: 2024-10-28T16:00
---
We selected [CUE](https://cuelang.org/) as the configuration language in Holos
for a number of reasons described in this post. The process was a combination
of process by elimination and the unique way CUE _unifies_ configuration.
<!-- truncate -->
We evaluated a number of domain specific and general purpose languages before
deciding on CUE. The CUE website, GitHub issues, and Marcel's videos do a great
job of explaining most of these reasons, so I'll summarize and cite them here.
## DSL or GPL
The first decision was if we should use a turing complete general purpose
language, or a domain specific language (DSL). We decided to use a DSL because
we knew from hard won experience configuration with general purpose languages
invites too many problems over time.
1. Configuration easily becomes non-deterministic, especially when remote procedure calls are involved.
2. Many general purpose languages support type checking, but few support constraints and validation of data. We must write our own validation logic which often means validation happens haphazardly, if at all.
3. Data is usually mutable, making it difficult to know where an output value came from.
4. Configuration code is read much more frequently, and at more critical times like an outage, than it's written. I felt this pain and I don't want anyone using Holos to feel that way.
For these reasons we sought a domain specific language that focused on
simplicity, readability, and data validation. This quote from Marcel got my attention focused on CUE.
> I would argue that for configuration languages maintainability and readability are more important even than for programming languages, because they are ofter viewed by a larger group, often need to be changed in emergency conditions, and also as they are supposed to convey a certain contract. Most configuration languages, like GCL (my own doing), are more like scripting languages, making it easier to crank out definitions of large swats of data compactly, but being harder to comprehend and modify later.
Source: [Comparisons between CUE, Jsonnet, Shall, OPA, etc.](https://github.com/cuelang/cue/discussions/669#discussioncomment-306811)
## Other DSLs
### Template Engines
Template engines are not exactly a domain specific language, but they're
similar. We already used Go templates in Helm to produce YAML, and previously
used Jinja2 and ERB templates extensively for configuration tasks.
The fundamental problem with text template engines is that they manipulate text,
not data. As a result, output is often rendered without error or indication the
configuration is invalid until it is applied to the live system. Errors need
to be handled faster and earlier, ideally immediately as we're writing in our
editor.
For these reasons we can set aside all tools based on text templating.
### Jsonnet
Marcel and the CUE website explain this much better than I can. We used Jsonnet
to configure the kubernetes prometheus stack and experienced Jsonnet's lack of
validation features first hand.
> Like Jsonnet, CUE is a superset of JSON. They also are both influenced by GCL. CUE, in turn is influenced by Jsonnet. This may give the semblance that the languages are very similar. At the core, though, they are very different.
>
> CUEs focus is data validation whereas Jsonnet focuses on data templating (boilerplate removal). Jsonnet was not designed with validation in mind.
>
> Jsonnet and GCL can be quite powerful at reducing boilerplate. The goal of CUE is not to be better at boilerplate removal than Jsonnet or GCL. CUE was designed to be an answer to two major shortcomings of these approaches: complexity and lack of typing. Jsonnet reduces some of the complexities of GCL, but largely falls into the same category. For CUE, the tradeoff was to add typing and reduce complexity (for humans and machines), at the expense of giving up flexibility.
Source: [CUE Configuration Use Case - Jsonnet / GCL](https://cuelang.org/docs/concept/configuration-use-case/#jsonnet-gcl)
Marcel answered this question in more depth earlier:
> Jsonnet is based on BCL, an internal language at Google. It fixes a few things relative to BCL, but is mostly the same. This means it copies the biggest mistakes of BCL. Even though BCL is still widely used at Google, its issues are clear. It was just that the alternatives weren't that much better.
>
> There are a myriad of issues with BCL (and Jsonnet and pretty much all of its descendants), but I will mention a couple:
>
> 1. Most notably, the basic operation of composition of BCL/Jsonnet, inheritance, is not commutative and idempotent in the general case. In other words, order matters. This makes it, for humans, hard to track where values are coming from. But also, it makes it very complicated, if not impossible, to do any kind of automation. The complexity of inheritance is compounded by the fact that values can enter an object from one of several directions (super, overlay, etc.), and the order in which this happens matters. The basic operation of CUE is commutative, associative and idempotent. This order independence helps both humans and machines. The resulting model is much less complex.
> 2. Typing: most of the BCL offshoots do not allow for schema definitions. This makes it hard to detect any kind of typos or user errors. For a large code bases, no one will question a requirement to have a compiled/typed language. Why should we not require the same kind of rigor for data? Some offshoots of BCL internal to Google and also external have tried to address this a bit, but none quite satisfactory. In CUE types and values are the same thing. This makes things both easier than schema-based languages (less concepts to learn), but also more powerful. It allows for intuitive but also precise typing.
>
> There are many other issues, like handling cycles, unprincipled workarounds for hermeticity, poor tooling and so forth that make BCL and offsprings often awkward.
>
> So why CUE? Configuration is still largely an unsolved problem. We have tried using code to generate configs, or hybrid languages, but that often results in a mess. Using generators on databases doesn't allow keeping it sync with revision control. Simpler approaches like HCL and Kustomize recognize the complexity issue by removing a lot of it, but then sometimes become too weak, and actually also reintroduce some of this complexity with overlays (a poor man's inheritance, if you will, but with some of the same negative consequences). Other forms of removing complexity, for instance by just introducing simpler forms/ abstraction layers of configuration, may work within certain context but are domain-specific and relatively hard to maintain.
>
> So inheritance-based languages, for all its flaws, were the best we had. The idea behind CUE is to recognize that a declarative language is the best approach for many (not all) configuration problems, but to tackle the fundamental issues of these languages.
>
> The idea for CUE is actually not new. It was invented about 30 years ago and has been in use and further developed since that time in the field of computational linguistics, where the concept is used to encode entire lexicons as well as very detailed grammars of human languages. If you think about it, these are huge configurations that are often maintained by both computer scientists and linguists. You can see this as a proof of concept that large-scale, declarative configuration for a highly complex domain can work.
>
> CUE is a bit different from the languages used in linguistics and more tailored to the general configuration issue as we've seen it at Google. But under the hood it adheres strictly to the concepts and principles of these approaches and we have been careful not to make the same mistakes made in BCL (which then were copied in all its offshoots). It also means that CUE can benefit from 30 years of research on this topic. For instance, under the hood, CUE uses a first-order unification algorithm, allowing us to build template extractors based on anti-unification (see issue #7 and #15), something that is not very meaningful or even possible with languages like BCL and Jsonnet.
Source: [how CUE differs from jsonnet](https://github.com/cuelang/cue/issues/33#issuecomment-483615374)
### Dhall
> Dhall addresses some of the issues of GCL and Jsonnet (like lack of typing), but lacks the detailed typing of CUE. But it still misses the most important property of CUE: its model of composability. Some of the benefits are explained in the above link. Conceptually, CUE is an aspect-oriented and constraint-based language. It allows you to specify fine-grained constraints on what are valid values. These constraints then double as templates, allowing to remove boilerplate often with the same efficacy as inheritance, even if it works very differently.
Source [Comparisons between CUE, Jsonnet, Dhall, OPA, etc.](https://github.com/cuelang/cue/discussions/669#discussioncomment-306811)
### Rego (OPA)
> CUE also can be used for policy specification, like Rego (OPA).CUE unifies values, types, and constraints in a single continuum. As it is a constraint-based language first and foremost, it is well suited for defining policy. It is less developed in that area than Rego, but it I expect it will ultimately be better suited for policy. Note that Rego is based on Datalog, which is more of a query language at hart, giving it quite a different feel for defining policy than CUE. Both are logic programming languages, though, and share many of the same properties.
Source [Comparisons between CUE, Jsonnet, Dhall, OPA, etc.](https://github.com/cuelang/cue/discussions/669#discussioncomment-306811)
### PKL
I didn't look deeply into [Pkl](https://github.com/apple/pkl) primarily because
CUE, like Holos, is written in Go. It was straight forward to integrate CUE
into Holos.
### HCL
I have extensive experience with HCL and found it challenging to work with at medium to large scales.
See also: [CUE Configuration Use Case - HCL](https://cuelang.org/docs/concept/configuration-use-case/#hcl)
## Editor Integration
CUE has good support today for Visual Studio Code, and better support coming,
see the [CUE LSP Roadmap](https://github.com/orgs/cue-lang/projects/15)
## Additional Resources
The video [Large-Scale Engineering of Configuration with Unification (Marcel van
Lohuizen)](https://www.youtube.com/watch?v=jSRXobu1jHk) motivated me to go
deeper and invest significant time into CUE.

View File

@@ -116,6 +116,11 @@ const config: Config = {
label: 'GitHub',
position: 'right',
},
{
href: 'https://discord.gg/JgDVbNpye7',
label: 'Discord',
position: 'right',
},
],
},
footer: {
@@ -150,8 +155,8 @@ const config: Config = {
href: '/docs/support',
},
{
label: 'Announcements List',
href: 'https://groups.google.com/g/holos-announce',
label: 'Discord',
href: 'https://discord.gg/JgDVbNpye7',
},
{
label: 'Discussion List',

View File

@@ -0,0 +1 @@
did:plc:7jly72mfd42u4fj4mfyovxqz

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

View File

@@ -0,0 +1,4 @@
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="90" fill="#FDF6E3" stroke="#073642" stroke-width="4" />
<text x="50%" y="50%" text-anchor="middle" fill="#073642" font-size="96" dy=".35em" font-family="Arial, sans-serif" font-weight="bold">H</text>
</svg>

After

Width:  |  Height:  |  Size: 306 B

View File

@@ -0,0 +1,4 @@
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="90" stroke="#FDF6E3" fill="#073642" stroke-width="4" />
<text x="50%" y="50%" text-anchor="middle" fill="#FDF6E3" font-size="96" dy=".35em" font-family="Arial, sans-serif" font-weight="bold">H</text>
</svg>

After

Width:  |  Height:  |  Size: 306 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 605.044 336.948" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Logo" vectornator:layerName="Logo">
<g opacity="1">
<path d="M591.109 167.89C580.229 111.687 546.936 77.6261 491.282 65.5687C433.469 53.0447 384.362 69.3554 342.802 110.398C310.616 142.185 278.709 174.259 246.482 205.995C225.922 226.226 205.922 247.343 179.109 259.626C149.202 273.334 119.469 272.37 93.4157 251.847C66.8557 230.91 61.2157 201.791 69.349 169.809C81.5757 121.787 138.509 102.695 182.402 131.721C187.656 135.193 192.829 138.787 198.149 142.406C200.682 140.009 202.496 138.35 204.242 136.622C224.509 116.598 244.109 95.8634 265.162 76.7034C293.082 51.2821 325.909 36.9234 364.469 39.9821C377.656 41.0274 390.656 44.4154 406.242 47.1781C374.122 16.6794 338.802 2.73806 296.776 9.35939C257.362 15.5701 226.149 36.7381 199.789 65.6101C193.602 72.3927 188.029 74.0394 179.256 70.7394C168.722 66.7727 158.376 64.2394 148.229 63.0127L148.229 63.0087C148.216 63.0074 148.189 63.0074 148.176 63.0061C148.056 62.9914 147.936 62.9714 147.816 62.9581C147.802 62.9687 147.802 62.9767 147.789 62.9874C21.4957 55.3727 9.17567 165.405 9.17567 165.405C-2.58433 286.525 80.029 311.302 80.029 311.302L80.069 311.302C90.0823 315.263 100.456 318.062 111.029 320.229L111.042 320.25C111.042 320.25 112.962 320.745 116.509 321.295C117.456 321.47 118.402 321.653 119.349 321.819C119.376 321.781 119.402 321.745 119.416 321.706C138.362 324.111 187.416 325.538 246.122 289.946C246.242 289.951 246.376 289.939 246.496 289.95C284.176 252.225 321.882 214.525 359.722 176.97C377.829 159.006 394.296 138.981 418.056 127.409C455.242 109.302 501.269 117.934 522.642 147.982C539.616 171.834 541.616 197.893 529.402 223.943C516.682 251.057 493.776 265.733 464.016 266.622C423.082 267.846 382.082 267.358 341.122 267.277C332.309 267.259 325.469 269.946 319.336 276.357C306.549 289.741 293.216 302.61 280.202 315.782C278.402 317.595 275.269 320.245 272.429 323.437C276.522 323.878 281.362 324.021 283.762 324.023C330.429 324.065 377.096 324.385 423.762 323.905C446.856 323.666 470.549 324.903 492.896 320.317C561.376 306.267 604.602 237.579 591.109 167.89" fill="#fdf6e3" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M202.896 194.097C202.896 228.629 174.909 256.622 140.376 256.622C105.842 256.622 77.8423 228.629 77.8423 194.097C77.8423 159.565 105.842 131.57 140.376 131.57C174.909 131.57 202.896 159.565 202.896 194.097" fill="#fdf6e3" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 605.044 336.948" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<g id="Logo" vectornator:layerName="Logo">
<g opacity="1">
<path d="M591.109 167.89C580.229 111.687 546.936 77.6261 491.282 65.5687C433.469 53.0447 384.362 69.3554 342.802 110.398C310.616 142.185 278.709 174.259 246.482 205.995C225.922 226.226 205.922 247.343 179.109 259.626C149.202 273.334 119.469 272.37 93.4157 251.847C66.8557 230.91 61.2157 201.791 69.349 169.809C81.5757 121.787 138.509 102.695 182.402 131.721C187.656 135.193 192.829 138.787 198.149 142.406C200.682 140.009 202.496 138.35 204.242 136.622C224.509 116.598 244.109 95.8634 265.162 76.7034C293.082 51.2821 325.909 36.9234 364.469 39.9821C377.656 41.0274 390.656 44.4154 406.242 47.1781C374.122 16.6794 338.802 2.73806 296.776 9.35939C257.362 15.5701 226.149 36.7381 199.789 65.6101C193.602 72.3927 188.029 74.0394 179.256 70.7394C168.722 66.7727 158.376 64.2394 148.229 63.0127L148.229 63.0087C148.216 63.0074 148.189 63.0074 148.176 63.0061C148.056 62.9914 147.936 62.9714 147.816 62.9581C147.802 62.9687 147.802 62.9767 147.789 62.9874C21.4957 55.3727 9.17567 165.405 9.17567 165.405C-2.58433 286.525 80.029 311.302 80.029 311.302L80.069 311.302C90.0823 315.263 100.456 318.062 111.029 320.229L111.042 320.25C111.042 320.25 112.962 320.745 116.509 321.295C117.456 321.47 118.402 321.653 119.349 321.819C119.376 321.781 119.402 321.745 119.416 321.706C138.362 324.111 187.416 325.538 246.122 289.946C246.242 289.951 246.376 289.939 246.496 289.95C284.176 252.225 321.882 214.525 359.722 176.97C377.829 159.006 394.296 138.981 418.056 127.409C455.242 109.302 501.269 117.934 522.642 147.982C539.616 171.834 541.616 197.893 529.402 223.943C516.682 251.057 493.776 265.733 464.016 266.622C423.082 267.846 382.082 267.358 341.122 267.277C332.309 267.259 325.469 269.946 319.336 276.357C306.549 289.741 293.216 302.61 280.202 315.782C278.402 317.595 275.269 320.245 272.429 323.437C276.522 323.878 281.362 324.021 283.762 324.023C330.429 324.065 377.096 324.385 423.762 323.905C446.856 323.666 470.549 324.903 492.896 320.317C561.376 306.267 604.602 237.579 591.109 167.89" fill="#142831" fill-rule="nonzero" opacity="1" stroke="none"/>
<path d="M202.896 194.097C202.896 228.629 174.909 256.622 140.376 256.622C105.842 256.622 77.8423 228.629 77.8423 194.097C77.8423 159.565 105.842 131.57 140.376 131.57C174.909 131.57 202.896 159.565 202.896 194.097" fill="#142831" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,5 +1,12 @@
#! /bin/bash
#
tmpdir="$(mktemp -d)"
finish() {
rm -rf "$tmpdir"
}
trap finish EXIT
set -euo pipefail
# Generate the documentation for the package the calls go:generate
@@ -10,8 +17,5 @@ gomarkdoc --output "doc/md/${package%/}.md" "./${package}"
# Fix heading anchors by making them explicit
# Refer to https://docusaurus.io/docs/markdown-features/toc#heading-ids
stamp=$RANDOM
# sed 's/^## type /## /' "doc/md/${package%/}.md" > "doc/md/${package%/}.md.${stamp}"
sed -E 's/## type ([A-Za-z0-9_]+)/## type \1 {#\1}/' "doc/md/${package%/}.md" > "doc/md/${package%/}.md.${stamp}"
mv "doc/md/${package%/}.md.${stamp}" "doc/md/${package%/}.md"
sed -E 's/## type ([A-Za-z0-9_]+)/## type \1 {#\1}/' "doc/md/${package%/}.md" > "${tmpdir}/doc.md"
cat "./${package%%/}/header.yaml" "${tmpdir}/doc.md" > "doc/md/${package%/}.md"

View File

@@ -43,8 +43,9 @@ func makeBuildRunFunc(cfg *client.Config) command.RunFunc {
}
// New returns the build subcommand for the root command
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("build DIRECTORY")
cmd.Hidden = !feature.Flag(holos.BuildFeature)
cmd.Args = cobra.ExactArgs(1)
cmd.Short = "write kubernetes manifests to standard output"
cmd.Example = " holos build components/argo/crds"

View File

@@ -12,9 +12,10 @@ import (
)
// New returns the create command for the cli
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("create")
cmd.Short = "create resources"
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Flags().SortFlags = false
cmd.RunE = func(c *cobra.Command, args []string) error {
return c.Usage()

View File

@@ -11,8 +11,9 @@ import (
)
// New returns the command for the cli
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("delete")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Aliases = []string{"destroy"}
cmd.Short = "delete resources"
cmd.Flags().SortFlags = false

View File

@@ -14,14 +14,14 @@ import (
)
// New returns a new generate command.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("generate")
cmd.Aliases = []string{"gen"}
cmd.Short = "generate local resources"
cmd.Args = cobra.NoArgs
cmd.AddCommand(NewPlatform(cfg))
cmd.AddCommand(NewComponent())
cmd.AddCommand(NewComponent(feature))
return cmd
}
@@ -48,9 +48,10 @@ func NewPlatform(cfg *holos.Config) *cobra.Command {
}
// NewComponent returns a command to generate a holos component
func NewComponent() *cobra.Command {
func NewComponent(feature holos.Flagger) *cobra.Command {
cmd := command.New("component")
cmd.Short = "generate a component from an embedded schematic"
cmd.Hidden = !feature.Flag(holos.GenerateComponentFeature)
for _, name := range generate.Components("v1alpha3") {
cmd.AddCommand(makeSchematicCommand("v1alpha3", name))

View File

@@ -16,8 +16,10 @@ import (
)
// New returns the get command for the cli.
func New(hc *holos.Config) *cobra.Command {
func New(hc *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("get")
// not supported as of v0.97
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "get resources"
cmd.Aliases = []string{"list"}
cmd.Flags().SortFlags = false

View File

@@ -10,8 +10,9 @@ import (
)
// New returns the kv root command for the cli
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("kv")
cmd.Hidden = !feature.Flag(holos.SecretsFeature)
cmd.Short = "work with secrets in the provisioner cluster"
cmd.Flags().SortFlags = false
cmd.RunE = func(c *cobra.Command, args []string) error {

View File

@@ -13,8 +13,9 @@ import (
)
// New returns a new login command.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("login")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "log in by caching credentials"
var printClaims bool

View File

@@ -11,8 +11,9 @@ import (
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("logout")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "log out by deleting cached credentials"
cmd.RunE = func(c *cobra.Command, args []string) error {
if err := os.RemoveAll(token.CacheDir); err != nil {

View File

@@ -18,7 +18,8 @@ func MakeMain(options ...holos.Option) func() int {
cfg := holos.New(options...)
slog.SetDefault(cfg.Logger())
ctx := context.Background()
if err := New(cfg).ExecuteContext(ctx); err != nil {
feature := &holos.EnvFlagger{}
if err := New(cfg, feature).ExecuteContext(ctx); err != nil {
return HandleError(ctx, err, cfg)
}
return 0

View File

@@ -25,10 +25,10 @@ func newConfig() (*config, *flag.FlagSet) {
}
// New returns the preflight command for the root command.
func New(hc *holos.Config) *cobra.Command {
func New(hc *holos.Config, feature holos.Flagger) *cobra.Command {
cfg, flagSet := newConfig()
cmd := command.New("preflight")
cmd.Hidden = !feature.Flag(holos.PreflightFeature)
cmd.Short = "run holos preflight checks"
cmd.Flags().AddGoFlagSet(flagSet)
cmd.RunE = makePreflightRunFunc(hc, cfg)

View File

@@ -14,8 +14,9 @@ import (
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("pull")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "pull resources from holos server"
cmd.Args = cobra.NoArgs

View File

@@ -14,9 +14,10 @@ import (
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("push")
cmd.Short = "push resources to holos server"
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Args = cobra.NoArgs
config := client.NewConfig(cfg)

View File

@@ -10,8 +10,9 @@ import (
)
// New returns a new register command.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("register")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "rpc UserService.RegisterUser"
cmd.Long = "register with holos server"
cmd.Args = cobra.NoArgs

View File

@@ -22,10 +22,10 @@ import (
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("render")
cmd.Args = cobra.NoArgs
cmd.Short = "render platforms and components into the deploy/ directory"
cmd.Short = "render platforms and components to manifest files"
cmd.AddCommand(NewComponent(cfg))
cmd.AddCommand(NewPlatform(cfg))
return cmd
@@ -35,7 +35,7 @@ func New(cfg *holos.Config) *cobra.Command {
func NewComponent(cfg *holos.Config) *cobra.Command {
cmd := command.New("component DIRECTORY")
cmd.Args = cobra.ExactArgs(1)
cmd.Short = "render specific components"
cmd.Short = "render a platform component"
cmd.Example = " holos render component --inject holos_cluster=aws2 ./components/monitoring/kube-prometheus-stack"
cmd.Flags().AddGoFlagSet(cfg.WriteFlagSet())
cmd.Flags().AddGoFlagSet(cfg.ClusterFlagSet())

View File

@@ -35,7 +35,7 @@ import (
var helpLong string
// New returns a new root *cobra.Command for command line execution.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
rootCmd := &cobra.Command{
Use: "holos",
Short: "holos manages a holistic integrated software development platform",
@@ -67,36 +67,37 @@ func New(cfg *holos.Config) *cobra.Command {
rootCmd.PersistentFlags().AddGoFlagSet(cfg.LogFlagSet())
// subcommands
rootCmd.AddCommand(build.New(cfg))
rootCmd.AddCommand(render.New(cfg))
rootCmd.AddCommand(get.New(cfg))
rootCmd.AddCommand(create.New(cfg))
rootCmd.AddCommand(destroy.New(cfg))
rootCmd.AddCommand(preflight.New(cfg))
rootCmd.AddCommand(login.New(cfg))
rootCmd.AddCommand(logout.New(cfg))
rootCmd.AddCommand(token.New(cfg))
rootCmd.AddCommand(generate.New(cfg))
rootCmd.AddCommand(register.New(cfg))
rootCmd.AddCommand(pull.New(cfg))
rootCmd.AddCommand(push.New(cfg))
rootCmd.AddCommand(newOrgCmd())
rootCmd.AddCommand(build.New(cfg, feature))
rootCmd.AddCommand(render.New(cfg, feature))
rootCmd.AddCommand(get.New(cfg, feature))
rootCmd.AddCommand(create.New(cfg, feature))
rootCmd.AddCommand(destroy.New(cfg, feature))
rootCmd.AddCommand(preflight.New(cfg, feature))
rootCmd.AddCommand(login.New(cfg, feature))
rootCmd.AddCommand(logout.New(cfg, feature))
rootCmd.AddCommand(token.New(cfg, feature))
rootCmd.AddCommand(generate.New(cfg, feature))
rootCmd.AddCommand(register.New(cfg, feature))
rootCmd.AddCommand(pull.New(cfg, feature))
rootCmd.AddCommand(push.New(cfg, feature))
rootCmd.AddCommand(newOrgCmd(feature))
// Maybe not needed?
rootCmd.AddCommand(txtar.New(cfg))
// Deprecated, remove?
rootCmd.AddCommand(kv.New(cfg))
rootCmd.AddCommand(kv.New(cfg, feature))
// Server
rootCmd.AddCommand(server.New(cfg))
rootCmd.AddCommand(server.New(cfg, feature))
return rootCmd
}
func newOrgCmd() (cmd *cobra.Command) {
func newOrgCmd(feature holos.Flagger) (cmd *cobra.Command) {
cmd = command.New("orgid")
cmd.Short = "print the current context org id."
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
cc := holos.NewClientContext(ctx)

View File

@@ -14,7 +14,7 @@ import (
func newCommand() (*cobra.Command, *bytes.Buffer) {
var b1, b2 bytes.Buffer
// discard stdout for now, it's a bunch of usage messages.
cmd := New(holos.New(holos.Stdout(&b1), holos.Stderr(&b2)))
cmd := New(holos.New(holos.Stdout(&b1), holos.Stderr(&b2)), &holos.EnvFlagger{})
return cmd, &b2
}
@@ -90,7 +90,7 @@ func TestInvalidArgs(t *testing.T) {
}
for _, args := range invalidArgs {
var b bytes.Buffer
cmd := New(holos.New(holos.Stdout(&b)))
cmd := New(holos.New(holos.Stdout(&b)), &holos.EnvFlagger{})
cmd.SetArgs(args)
err := cmd.Execute()
if err == nil {
@@ -115,7 +115,7 @@ func TestLoggerFromContext(t *testing.T) {
func TestVersion(t *testing.T) {
var b bytes.Buffer
cmd := New(holos.New(holos.Stdout(&b)))
cmd := New(holos.New(holos.Stdout(&b)), &holos.EnvFlagger{})
cmd.SetOut(&b)
cmd.SetArgs([]string{"--version"})
if err := cmd.Execute(); err != nil {

View File

@@ -77,7 +77,7 @@ func cmdHolos(ts *testscript.TestScript, neg bool, args []string) {
holos.Stderr(ts.Stderr()),
)
cmd := cli.New(cfg)
cmd := cli.New(cfg, &holos.EnvFlagger{})
cmd.SetArgs(args)
err := cmd.Execute()

View File

@@ -13,8 +13,9 @@ import (
)
// New returns a new login command.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := command.New("token")
cmd.Hidden = !feature.Flag(holos.ServerFeature)
cmd.Short = "write id token to stdout"
cmd.Long = "Useful with curl / grpcurl -H $(holos token)"

View File

@@ -392,7 +392,7 @@ package v1alpha4
// Model represents the platform model holos gets from from the
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
// Injected as the tag "holos_model".
model: {...} @go(Model,map[string]any)
model?: {...} @go(Model,map[string]any)
// Tags represents cue @tag variables injected into the holos render component
// command from the holos render platform command. Tags with a "holos_"

View File

@@ -59,18 +59,33 @@ import (
artifact: "\(_path)/\(Name).gen.yaml"
let ResourcesOutput = "resources.gen.yaml"
let IntermediateOutput = "combined.gen.yaml"
generators: [{
kind: "Resources"
output: ResourcesOutput
resources: Resources
}]
generators: [
{
kind: "Resources"
output: ResourcesOutput
resources: Resources
},
for x in KustomizeConfig.Files {
kind: "File"
output: x.Source
file: source: x.Source
},
for x in KustomizeConfig.Resources {
kind: "File"
output: x.Source
file: source: x.Source
},
]
transformers: [
core.#Transformer & {
kind: "Kustomize"
inputs: [ResourcesOutput]
inputs: [for x in generators {x.output}]
output: IntermediateOutput
kustomize: kustomization: KustomizeConfig.Kustomization & {
resources: inputs
resources: [
ResourcesOutput,
for x in KustomizeConfig.Resources {x.Source},
]
}
},
_Transformer & {

View File

@@ -1,16 +1,19 @@
package platforms
// TODO: Remove env GODEBUG=gotypesalias=0 when cue 0.11 is released and used.
// See: https://github.com/cue-lang/cue/issues/3539
//go:generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/v1alpha1
//go:generate cue get go github.com/holos-run/holos/api/v1alpha1/...
//go:generate env GODEBUG=gotypesalias=0 cue get go github.com/holos-run/holos/api/v1alpha1/...
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/core
//go:generate cue get go github.com/holos-run/holos/api/core/...
//go:generate env GODEBUG=gotypesalias=0 cue get go github.com/holos-run/holos/api/core/...
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/meta
//go:generate cue get go github.com/holos-run/holos/api/meta/...
//go:generate env GODEBUG=gotypesalias=0 cue get go github.com/holos-run/holos/api/meta/...
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/author
//go:generate cue get go github.com/holos-run/holos/api/author/...
//go:generate env GODEBUG=gotypesalias=0 cue get go github.com/holos-run/holos/api/author/...
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object
//go:generate cue import ../../../service/holos/object/v1alpha1/object.proto -o cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object/v1alpha1/object.proto_gen.cue -I ../../../proto -f

View File

@@ -0,0 +1,8 @@
package holos
import api "github.com/holos-run/holos/api/author/v1alpha4"
// Manage a workload cluster named local for use with the guides.
_Fleets: api.#StandardFleets & {
workload: clusters: local: _
}

View File

@@ -2,9 +2,9 @@ package holos
import api "github.com/holos-run/holos/api/author/v1alpha4"
#Platform: api.#Platform & {
Name: "guide"
_Platform: api.#Platform & {
Name: "default"
}
// Render a Platform resource for holos to process
#Platform.Resource
_Platform.Resource

View File

@@ -2,11 +2,8 @@ package holos
import api "github.com/holos-run/holos/api/author/v1alpha4"
// Manage a workload cluster named workload for use with the guides.
#Fleets: api.#StandardFleets
// Define the default organization name.
#Organization: api.#OrganizationStrict & {
_Organization: api.#OrganizationStrict & {
DisplayName: string | *"Bank of Holos"
Name: string | *"bank-of-holos"
Domain: string | *"holos.localhost"
@@ -14,18 +11,18 @@ import api "github.com/holos-run/holos/api/author/v1alpha4"
// Projects represents a way to organize components into projects with owners.
// https://holos.run/docs/api/author/v1alpha4/#Projects
#Projects: api.#Projects
_Projects: api.#Projects
// ArgoConfig represents the configuration of ArgoCD Application resources for
// each component.
// https://holos.run/docs/api/author/v1alpha4/#ArgoConfig
#ArgoConfig: api.#ArgoConfig
_ArgoConfig: api.#ArgoConfig
#ComponentConfig: api.#ComponentConfig & {
Name: _Tags.name
Component: _Tags.component
Cluster: _Tags.cluster
ArgoConfig: #ArgoConfig & {
ArgoConfig: _ArgoConfig & {
if _Tags.project != "no-project" {
AppProject: _Tags.project
}
@@ -34,7 +31,7 @@ import api "github.com/holos-run/holos/api/author/v1alpha4"
// Mix in project labels if the project is defined by the platform.
if _Tags.project != "no-project" {
CommonLabels: #Projects[_Tags.project].CommonLabels
CommonLabels: _Projects[_Tags.project].CommonLabels
}
}

View File

@@ -2,6 +2,7 @@ package holos
import (
"fmt"
"os"
"strings"
)
@@ -25,3 +26,23 @@ func (i *StringSlice) Set(value string) error {
}
return nil
}
type feature string
const BuildFeature = feature("BUILD")
const ServerFeature = feature("SERVER")
const PreflightFeature = feature("PREFLIGHT")
const GenerateComponentFeature = feature("GENERATE_COMPONENT")
const SecretsFeature = feature("SECRETS")
// Flagger is the interface to check if an experimental feature is enabled.
type Flagger interface {
Flag(name feature) bool
}
type EnvFlagger struct{}
func (e *EnvFlagger) Flag(name feature) bool {
envVar := "HOLOS_FEATURE_" + strings.ToUpper(string(name))
return os.Getenv(envVar) != ""
}

View File

@@ -26,11 +26,12 @@ import (
var helpLong string
// New builds a root cobra command with flags linked to the Config field.
func New(cfg *holos.Config) *cobra.Command {
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
cmd := &cobra.Command{
Use: "server",
Short: "run the holos server",
Long: helpLong,
Use: "server",
Short: "run the holos server",
Hidden: !feature.Flag(holos.ServerFeature),
Long: helpLong,
// We handle our own errors.
SilenceUsage: true,
SilenceErrors: true,

View File

@@ -1 +1 @@
0
3