Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fb6afe8d5 | ||
|
|
d6f89052d9 | ||
|
|
e4aa7f5994 | ||
|
|
6e4c65cb6c | ||
|
|
4f091677e2 | ||
|
|
0c05df1162 | ||
|
|
64a745fd34 | ||
|
|
490f91f580 | ||
|
|
79b065cda8 | ||
|
|
0fa6047552 | ||
|
|
11ecc0cc3a | ||
|
|
a62e4ba117 | ||
|
|
07fe667f30 | ||
|
|
3ad994cbb9 | ||
|
|
b3d9bd32af | ||
|
|
d398b49d7f | ||
|
|
12179a6991 | ||
|
|
fee472bb66 |
@@ -5,6 +5,7 @@
|
||||
"mdx"
|
||||
],
|
||||
"words": [
|
||||
"acmesolver",
|
||||
"acraccesstokens",
|
||||
"admissionregistration",
|
||||
"alertmanager",
|
||||
@@ -53,6 +54,7 @@
|
||||
"CODEOWNERS",
|
||||
"configmap",
|
||||
"configmapargs",
|
||||
"connectrpc",
|
||||
"cookiesecret",
|
||||
"coredns",
|
||||
"corev",
|
||||
@@ -77,6 +79,7 @@
|
||||
"entgo",
|
||||
"envoyfilter",
|
||||
"envoyfilters",
|
||||
"errdetails",
|
||||
"errgroup",
|
||||
"etcdsnapshotfiles",
|
||||
"externalsecret",
|
||||
@@ -93,6 +96,7 @@
|
||||
"generationbehavior",
|
||||
"generatorargs",
|
||||
"generatoroptions",
|
||||
"genproto",
|
||||
"ggnpl",
|
||||
"ghaction",
|
||||
"githubaccesstokens",
|
||||
@@ -100,6 +104,7 @@
|
||||
"godoc",
|
||||
"golangci",
|
||||
"gomarkdoc",
|
||||
"googleapis",
|
||||
"goreleaser",
|
||||
"gotypesalias",
|
||||
"grpcreflect",
|
||||
@@ -157,6 +162,7 @@
|
||||
"logfmt",
|
||||
"mattn",
|
||||
"mccutchen",
|
||||
"metav",
|
||||
"mindmap",
|
||||
"mktemp",
|
||||
"msqbn",
|
||||
@@ -202,6 +208,7 @@
|
||||
"poddisruptionbudget",
|
||||
"poddisruptionbudgets",
|
||||
"podinfo",
|
||||
"podmonitor",
|
||||
"portmapping",
|
||||
"postgrescluster",
|
||||
"privs",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,37 +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"
|
||||
// highlight-next-line
|
||||
Namespace: #Migration.Namespace
|
||||
_Helm: #Helm & {
|
||||
// highlight-next-line
|
||||
Name: "podinfo"
|
||||
// highlight-next-line
|
||||
Namespace: _Migration.Namespace
|
||||
|
||||
Chart: {
|
||||
version: "6.6.2"
|
||||
repository: {
|
||||
name: "podinfo"
|
||||
url: "https://stefanprodan.github.io/podinfo"
|
||||
}
|
||||
}
|
||||
Chart: {
|
||||
version: "6.6.2"
|
||||
repository: {
|
||||
name: "podinfo"
|
||||
url: "https://stefanprodan.github.io/podinfo"
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
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>
|
||||
@@ -403,16 +396,16 @@ component, `podinfo/podinfo.cue`, but `holos` doesn't enforce this convention.
|
||||
**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 20-21**: 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 27**: 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
|
||||
@@ -463,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>
|
||||
@@ -492,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>
|
||||
@@ -501,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
|
||||
@@ -561,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>
|
||||
@@ -578,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
|
||||
@@ -605,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:
|
||||
@@ -621,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
|
||||
@@ -630,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
|
||||
@@ -650,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:
|
||||
@@ -714,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>
|
||||
@@ -730,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
|
||||
@@ -777,9 +797,9 @@ 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.
|
||||
@@ -791,17 +811,15 @@ Go ahead and create this file (if it hasn't been created previously) with the fo
|
||||
```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">
|
||||
@@ -810,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 + "." + #Organization.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.
|
||||
@@ -861,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].
|
||||
@@ -928,10 +948,10 @@ 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
|
||||
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/workload/components/httproutes/httproutes.gen.yaml
|
||||
+++ b/deploy/clusters/workload/components/httproutes/httproutes.gen.yaml
|
||||
--- 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
|
||||
@@ -961,7 +981,6 @@ index 06f7c91..349e070 100644
|
||||
+ - path:
|
||||
+ type: PathPrefix
|
||||
+ value: /
|
||||
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -1044,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
|
||||
@@ -1054,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
|
||||
@@ -1126,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
|
||||
@@ -1146,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
|
||||
@@ -1192,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
|
||||
@@ -1243,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
|
||||
@@ -1266,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
|
||||
@@ -1284,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
|
||||
@@ -1296,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
|
||||
@@ -1319,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
|
||||
@@ -1327,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
|
||||
@@ -1360,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
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
---
|
||||
description: Learn how Holos adds valuable features to Helm and Kustomize.
|
||||
slug: /guides/helm
|
||||
title: Helm
|
||||
description: Learn how Holos implements the rendered manifest pattern with Helm, Kustomize, and CUE.
|
||||
sidebar_position: 150
|
||||
---
|
||||
|
||||
<head>
|
||||
<meta property="og:title" content="Helm Guide | Holos" />
|
||||
<meta property="og:image" content="https://holos.run/img/cards/guides-helm-2.png" />
|
||||
</head>
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import Admonition from '@theme/Admonition';
|
||||
@@ -455,8 +461,9 @@ values into both charts to configure them in lock step.
|
||||
|
||||
<Tabs groupId="740ABBEB-7A03-4B53-9CD5-4B8C5680172F">
|
||||
<TabItem value="projects/blackbox.schema.cue" label="Blackbox Schema">
|
||||
```txt
|
||||
projects/blackbox.schema.cue
|
||||
```bash
|
||||
mkdir -p projects
|
||||
touch projects/blackbox.schema.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -492,9 +499,7 @@ Add the CUE configuration to manage the prometheus Helm Chart component.
|
||||
|
||||
```bash
|
||||
mkdir -p projects/platform/components/prometheus
|
||||
```
|
||||
```txt
|
||||
projects/platform/components/prometheus/prometheus.cue
|
||||
touch projects/platform/components/prometheus/prometheus.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -521,8 +526,9 @@ the platform directory.
|
||||
|
||||
<Tabs groupId="FF5FF6C6-181D-4071-8BCF-5C8E0663C028">
|
||||
<TabItem value="platform/prometheus.cue" label="Platform">
|
||||
```txt
|
||||
platform/prometheus.cue
|
||||
```bash
|
||||
mkdir -p platform
|
||||
touch platform/prometheus.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -547,8 +553,8 @@ holos render platform ./platform
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
cached prometheus 25.27.0
|
||||
rendered prometheus for cluster local in 1.900449291s
|
||||
rendered platform in 1.900581125s
|
||||
rendered prometheus for cluster local in 1.600449291s
|
||||
rendered platform in 1.600581125s
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="deploy/clusters/local/components/prometheus/prometheus.gen.yaml" label="prometheus.gen.yaml">
|
||||
@@ -2035,9 +2041,7 @@ Add the CUE configuration to manage the blackbox Helm Chart component.
|
||||
|
||||
```bash
|
||||
mkdir -p projects/platform/components/blackbox
|
||||
```
|
||||
```txt
|
||||
projects/platform/components/blackbox/blackbox.cue
|
||||
touch projects/platform/components/blackbox/blackbox.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -2064,8 +2068,9 @@ _Helm: #Helm & {
|
||||
Register the blackbox chart with the platform by adding the following file to
|
||||
the platform directory.
|
||||
|
||||
```txt
|
||||
platform/blackbox.cue
|
||||
```bash
|
||||
mkdir -p platform
|
||||
touch platform/blackbox.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -4162,12 +4167,8 @@ lock step.
|
||||
|
||||
<Tabs groupId="B3A011D0-2D13-4DA8-B963-92115E734085">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output" default>
|
||||
```diff
|
||||
patch -p1 <<EOF
|
||||
--- a/projects/platform/components/blackbox/values.cue
|
||||
+++ b/projects/platform/components/blackbox/values.cue
|
||||
@@ -2,6 +2,9 @@ package holos
|
||||
@@ -4180,15 +4181,15 @@ git diff
|
||||
global: {
|
||||
//# Global image registry to use if it needs to be overriden for some specific use cases (e.g local registries, custom images, ...)
|
||||
//#
|
||||
@@ -196,7 +196,7 @@ _Helm: {
|
||||
annotations: {}
|
||||
labels: {}
|
||||
type: "ClusterIP"
|
||||
- port: 9115
|
||||
+ port: _blackbox.port
|
||||
ipDualStack: {
|
||||
enabled: false
|
||||
ipFamilies: ["IPv6", "IPv4"]
|
||||
@@ -193,7 +196,7 @@ _Helm: {
|
||||
annotations: {}
|
||||
labels: {}
|
||||
type: "ClusterIP"
|
||||
- port: 9115
|
||||
+ port: _blackbox.port
|
||||
ipDualStack: {
|
||||
enabled: false
|
||||
ipFamilies: ["IPv6", "IPv4"]
|
||||
--- a/projects/platform/components/prometheus/values.cue
|
||||
+++ b/projects/platform/components/prometheus/values.cue
|
||||
@@ -1084,7 +1084,7 @@ _Helm: {
|
||||
@@ -4200,6 +4201,13 @@ git diff
|
||||
}, {
|
||||
source_labels: ["__param_target"]
|
||||
target_label: "instance"
|
||||
EOF
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output" default>
|
||||
```txt
|
||||
patching file 'projects/platform/components/blackbox/values.cue'
|
||||
patching file 'projects/platform/components/prometheus/values.cue'
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -4492,12 +4500,8 @@ render platform` command fails immediately with a clear validation error.
|
||||
|
||||
<Tabs groupId="BFCF4FCA-33EB-45D8-8D36-CDD80E54C819">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```diff
|
||||
patch -p1 <<EOF
|
||||
--- a/projects/blackbox.schema.cue
|
||||
+++ b/projects/blackbox.schema.cue
|
||||
@@ -10,6 +10,6 @@ package holos
|
||||
@@ -4508,7 +4512,12 @@ git diff
|
||||
+ host: "this is not valid"
|
||||
port: 6115
|
||||
}
|
||||
|
||||
EOF
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
patching file 'projects/blackbox.schema.cue'
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -4533,6 +4542,13 @@ could not run: could not render component: exit status 1 at builder/v1alpha4/bui
|
||||
|
||||

|
||||
|
||||
Undo the invalid change.
|
||||
|
||||
```bash
|
||||
git restore projects/blackbox.schema.cue
|
||||
rm -f projects/blackbox.schema.cue.orig
|
||||
```
|
||||
|
||||
### Httpbin Kustomization
|
||||
|
||||
We need to manage [httpbin] so we can achieve the goal of probing a simple
|
||||
@@ -4550,10 +4566,7 @@ components.
|
||||
<TabItem value="projects/platform/components/httpbin/httpbin.cue" label="Component">
|
||||
```bash
|
||||
mkdir -p projects/platform/components/httpbin
|
||||
```
|
||||
|
||||
```txt
|
||||
projects/platform/components/httpbin/httpbin.cue
|
||||
touch projects/platform/components/httpbin/httpbin.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -4589,7 +4602,8 @@ Register the component with the platform.
|
||||
<Tabs groupId="CBD42BC2-38C3-46E2-9F4D-B21D8E909BAC">
|
||||
<TabItem value="platform/httpbin.cue" label="Platform">
|
||||
```txt
|
||||
platform/httpbin.cue
|
||||
mkdir -p platform
|
||||
touch platform/httpbin.cue
|
||||
```
|
||||
```cue showLineNumbers
|
||||
package holos
|
||||
@@ -4759,6 +4773,7 @@ deployment.apps/httpbin created
|
||||
Port forward to the prometheus web interface.
|
||||
|
||||
```bash
|
||||
kubectl wait --for=condition=Available deployment/prometheus-server --timeout=300s
|
||||
kubectl -n default port-forward svc/prometheus-server 8081:80
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
@@ -107,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
|
||||
@@ -169,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
|
||||
@@ -187,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
|
||||
@@ -257,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
|
||||
@@ -295,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
|
||||
@@ -303,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.
|
||||
|
||||
@@ -316,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.
|
||||
@@ -327,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
|
||||
```
|
||||
@@ -339,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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -390,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.
|
||||
:::
|
||||
@@ -430,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
|
||||
@@ -451,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
|
||||
@@ -466,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
|
||||
@@ -499,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">
|
||||
@@ -650,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
|
||||
|
||||
@@ -3,9 +3,16 @@ 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
|
||||
---
|
||||
|
||||
I’m excited to share Holos, a Go command line tool we developed to make it
|
||||
<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.
|
||||
|
||||
123
doc/website/blog/2024-10-28-why-cue.md
Normal 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.
|
||||
>
|
||||
> CUE’s 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.
|
||||
BIN
doc/website/static/img/cards/announcing-holos.png
Normal file
|
After Width: | Height: | Size: 596 KiB |
BIN
doc/website/static/img/cards/background.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
doc/website/static/img/cards/guides-helm-2.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
doc/website/static/img/cards/guides-helm.png
Normal file
|
After Width: | Height: | Size: 521 KiB |
BIN
doc/website/static/img/cards/launch.jpg
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
doc/website/static/img/cards/technical-overview.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
doc/website/static/img/cards/why-cue.png
Normal file
|
After Width: | Height: | Size: 486 KiB |
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package holos
|
||||
import api "github.com/holos-run/holos/api/author/v1alpha4"
|
||||
|
||||
// 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"
|
||||
@@ -11,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
|
||||
}
|
||||
@@ -31,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) != ""
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
3
|
||||
|
||||