@intentius/behold 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demos.json +9 -0
- package/dist/cli.js +5 -2
- package/example-flux-estate/README.md +41 -0
- package/example-flux-estate/app-a/chant.config.ts +18 -0
- package/example-flux-estate/app-a/manifests/app.yaml +56 -0
- package/example-flux-estate/app-a/package.json +13 -0
- package/example-flux-estate/app-a/src/app.ts +35 -0
- package/example-flux-estate/app-a/tsconfig.json +1 -0
- package/example-flux-estate/app-b/chant.config.ts +20 -0
- package/example-flux-estate/app-b/manifests/app.yaml +54 -0
- package/example-flux-estate/app-b/package.json +13 -0
- package/example-flux-estate/app-b/src/app.ts +37 -0
- package/example-flux-estate/app-b/tsconfig.json +1 -0
- package/example-flux-estate/control-plane/chant.config.ts +19 -0
- package/example-flux-estate/control-plane/package.json +13 -0
- package/example-flux-estate/control-plane/src/flux.ts +51 -0
- package/example-flux-estate/control-plane/tsconfig.json +1 -0
- package/example-flux-estate/package-lock.json +1949 -0
- package/example-flux-estate/package.json +10 -0
- package/example-flux-estate/scripts/estate-down.sh +19 -0
- package/example-flux-estate/scripts/estate-up.sh +61 -0
- package/package.json +2 -1
package/demos.json
CHANGED
|
@@ -17,6 +17,15 @@
|
|
|
17
17
|
"setup": "bash scripts/local/local-up.sh",
|
|
18
18
|
"serve": { "local": true, "env": "local" }
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
"name": "flux-estate",
|
|
22
|
+
"description": "A GitOps estate: a Flux control plane (GitRepository + Kustomizations) plus two app projects, served as one composed estate — cross-stack sourceRef edges, estate-wide drift, and the namespace-mismatch note on purpose (app-b uses targetNamespace). k3d + Flux, no cloud. scripts/estate-down.sh removes the cluster.",
|
|
23
|
+
"source": "bundled",
|
|
24
|
+
"dir": "example-flux-estate",
|
|
25
|
+
"requires": ["docker", "k3d", "kubectl"],
|
|
26
|
+
"setup": "bash scripts/estate-up.sh",
|
|
27
|
+
"serve": { "env": "local", "dirs": ["control-plane", "app-a", "app-b"] }
|
|
28
|
+
},
|
|
20
29
|
{
|
|
21
30
|
"name": "fountain",
|
|
22
31
|
"description": "The mature estate: self-hosted fountain (a real app) on a throwaway k3d cluster — tiers (try the ha tier picker), seams, drift, runtime Pods. Clones INTENTIUS/fountain-ops; ~5 minutes, mostly image pulls. `just down` in the clone removes the cluster.",
|
package/dist/cli.js
CHANGED
|
@@ -2593,7 +2593,7 @@ function namespaceMismatchNote(nodes) {
|
|
|
2593
2593
|
const k8s = nodes.filter((n) => n?.lexicon === "k8s");
|
|
2594
2594
|
if (k8s.length === 0) return void 0;
|
|
2595
2595
|
const pending = k8s.filter((n) => n.attrs?._status === "accent" && !CLUSTER_SCOPED.has(n.kind ?? ""));
|
|
2596
|
-
if (pending.length <
|
|
2596
|
+
if (pending.length < 2) return void 0;
|
|
2597
2597
|
if (pending.some((n) => typeof n.attrs?.metadata?.namespace === "string" && n.attrs.metadata.namespace)) return void 0;
|
|
2598
2598
|
if (!k8s.some((n) => n.attrs?._status === "good")) return void 0;
|
|
2599
2599
|
return `${pending.length} pending k8s objects declare no metadata.namespace \u2014 if a controller stamps it at apply time (e.g. Flux's targetNamespace), the live read looked in "default", not where they run`;
|
|
@@ -4742,6 +4742,8 @@ function loadDemoRegistry(pkgRoot) {
|
|
|
4742
4742
|
}
|
|
4743
4743
|
if (!Array.isArray(d.requires) || d.requires.some((r) => typeof r !== "string")) return false;
|
|
4744
4744
|
if (!d.serve || typeof d.serve !== "object") return false;
|
|
4745
|
+
if (d.serve.dirs !== void 0 && (!Array.isArray(d.serve.dirs) || d.serve.dirs.some((x) => typeof x !== "string") || !d.serve.dirs.length))
|
|
4746
|
+
return false;
|
|
4745
4747
|
return true;
|
|
4746
4748
|
});
|
|
4747
4749
|
}
|
|
@@ -5173,7 +5175,8 @@ async function runDemo(rest) {
|
|
|
5173
5175
|
}
|
|
5174
5176
|
process.stdout.write(`behold demo ${entry.name} \u2192 serving. Blue = declared; Deploy turns it green.
|
|
5175
5177
|
`);
|
|
5176
|
-
const
|
|
5178
|
+
const serveDirs = entry.serve.dirs?.length ? entry.serve.dirs.map((d) => join13(target, d)) : [target];
|
|
5179
|
+
const serveArgs = ["serve", ...serveDirs, "--port", String(port)];
|
|
5177
5180
|
if (entry.serve.local) serveArgs.push("--local");
|
|
5178
5181
|
if (entry.serve.env) serveArgs.push("--env", entry.serve.env);
|
|
5179
5182
|
await run3(serveArgs);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# flux-estate — behold's GitOps estate demo (#211)
|
|
2
|
+
|
|
3
|
+
Three chant projects served as one composed estate:
|
|
4
|
+
|
|
5
|
+
- **control-plane/** — the Flux machinery: a `GitRepository` pointing at
|
|
6
|
+
behold's own public repo and one `Kustomization` per app. The reconcilers
|
|
7
|
+
deploy the apps; this project never applies a workload itself.
|
|
8
|
+
- **app-a/** — a small web workload with explicit `metadata.namespace` on
|
|
9
|
+
every object: the fully-resolved half.
|
|
10
|
+
- **app-b/** — the same workload with **no** namespace anywhere: the control
|
|
11
|
+
plane's `targetNamespace` stamps it at apply time. Idiomatic Flux, and the
|
|
12
|
+
deliberate exhibit of behold's namespace-mismatch note (behold#192) — a
|
|
13
|
+
plain live read scopes to `default`, finds nothing, and behold explains the
|
|
14
|
+
all-pending paint instead of letting it read as "not deployed".
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npx @intentius/behold demo flux-estate
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
That stands up a throwaway k3d cluster (`behold-flux-demo`), installs Flux's
|
|
21
|
+
controllers straight from the pinned release manifest (no `flux` CLI needed),
|
|
22
|
+
applies the control plane, waits for the reconcilers to deploy both apps from
|
|
23
|
+
this repo, and serves the three projects composed. What to look at:
|
|
24
|
+
|
|
25
|
+
- The **estate**: per-project boundary boxes, and the `sourceRef` edges wiring
|
|
26
|
+
Kustomization → GitRepository across stacks.
|
|
27
|
+
- The **overlay** (env `local`): app-a green, the control plane's CRs green,
|
|
28
|
+
app-b pending **with the note explaining why**.
|
|
29
|
+
- The **runtime tier** on the control plane alone
|
|
30
|
+
(`behold serve control-plane --env local`, zoom: runtime): the workloads
|
|
31
|
+
Flux deployed, attributed back to the declaring Kustomization via its
|
|
32
|
+
labels (chant#1549).
|
|
33
|
+
|
|
34
|
+
The app `manifests/` are committed `chant build` output — Flux syncs them
|
|
35
|
+
from GitHub `main`, so changes to an app's source need a rebuild
|
|
36
|
+
(`npm run build` in the app) and a merge before the cluster follows. To
|
|
37
|
+
verify an unmerged branch: `BEHOLD_FLUX_REF=<branch> bash scripts/estate-up.sh`
|
|
38
|
+
patches the live `GitRepository` (the declared source stays `main`).
|
|
39
|
+
|
|
40
|
+
`bash scripts/estate-down.sh` deletes the cluster and restores your previous
|
|
41
|
+
kubectl context.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChantConfig } from "@intentius/chant";
|
|
2
|
+
import type { K8sChantConfig } from "@intentius/chant-lexicon-k8s";
|
|
3
|
+
|
|
4
|
+
// App project A. Deployed by the control plane's Flux Kustomization, never by
|
|
5
|
+
// this project — its committed manifests/ (chant build output) are what Flux
|
|
6
|
+
// syncs from the repo. behold serves it as part of the estate; the live
|
|
7
|
+
// overlay reads the cluster through the same binding as every other member.
|
|
8
|
+
export default {
|
|
9
|
+
lexicons: ["k8s"],
|
|
10
|
+
sourceDir: "src",
|
|
11
|
+
environments: ["local"],
|
|
12
|
+
ownership: { stack: "app-a", env: "local" },
|
|
13
|
+
k8s: {
|
|
14
|
+
profiles: {
|
|
15
|
+
local: { context: "k3d-behold-flux-demo" },
|
|
16
|
+
},
|
|
17
|
+
} satisfies K8sChantConfig,
|
|
18
|
+
} satisfies ChantConfig;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: app-a
|
|
5
|
+
namespace: app-a
|
|
6
|
+
labels:
|
|
7
|
+
app.kubernetes.io/managed-by: chant
|
|
8
|
+
chant.intentius.io/stack: app-a
|
|
9
|
+
chant.intentius.io/env: local
|
|
10
|
+
app: app-a
|
|
11
|
+
spec:
|
|
12
|
+
replicas: 1
|
|
13
|
+
selector:
|
|
14
|
+
matchLabels:
|
|
15
|
+
app: app-a
|
|
16
|
+
template:
|
|
17
|
+
metadata:
|
|
18
|
+
labels:
|
|
19
|
+
app: app-a
|
|
20
|
+
spec:
|
|
21
|
+
containers:
|
|
22
|
+
- name: web
|
|
23
|
+
image: nginxinc/nginx-unprivileged:1.27-alpine
|
|
24
|
+
ports:
|
|
25
|
+
- containerPort: 8080
|
|
26
|
+
securityContext:
|
|
27
|
+
runAsNonRoot: true
|
|
28
|
+
runAsUser: 101
|
|
29
|
+
allowPrivilegeEscalation: false
|
|
30
|
+
capabilities:
|
|
31
|
+
drop:
|
|
32
|
+
- ALL
|
|
33
|
+
resources:
|
|
34
|
+
requests:
|
|
35
|
+
cpu: '25m'
|
|
36
|
+
memory: '32Mi'
|
|
37
|
+
limits:
|
|
38
|
+
cpu: '100m'
|
|
39
|
+
memory: '64Mi'
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
apiVersion: v1
|
|
43
|
+
kind: Service
|
|
44
|
+
metadata:
|
|
45
|
+
name: app-a
|
|
46
|
+
namespace: app-a
|
|
47
|
+
labels:
|
|
48
|
+
app.kubernetes.io/managed-by: chant
|
|
49
|
+
chant.intentius.io/stack: app-a
|
|
50
|
+
chant.intentius.io/env: local
|
|
51
|
+
spec:
|
|
52
|
+
selector:
|
|
53
|
+
app: app-a
|
|
54
|
+
ports:
|
|
55
|
+
- port: 80
|
|
56
|
+
targetPort: 8080
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "behold-example-flux-app-a",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "App project A: declares its workload WITH explicit namespaces — the fully-resolved half of the estate.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "chant build src -o manifests/app.yaml --format yaml"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@intentius/chant": "^0.41.20",
|
|
11
|
+
"@intentius/chant-lexicon-k8s": "^0.41.20"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// App A: one small web workload, namespace declared EXPLICITLY on every
|
|
2
|
+
// object. Contrast app-b, which leaves namespace to the control plane's
|
|
3
|
+
// targetNamespace — the two apps together show both halves of the Flux
|
|
4
|
+
// namespace story (behold#192).
|
|
5
|
+
import { Deployment, Service } from "@intentius/chant-lexicon-k8s";
|
|
6
|
+
|
|
7
|
+
const labels = { app: "app-a" };
|
|
8
|
+
const image = "nginxinc/nginx-unprivileged:1.27-alpine";
|
|
9
|
+
|
|
10
|
+
export const deployment = new Deployment({
|
|
11
|
+
metadata: { name: "app-a", namespace: "app-a", labels },
|
|
12
|
+
spec: {
|
|
13
|
+
replicas: 1,
|
|
14
|
+
selector: { matchLabels: labels },
|
|
15
|
+
template: {
|
|
16
|
+
metadata: { labels },
|
|
17
|
+
spec: {
|
|
18
|
+
containers: [
|
|
19
|
+
{
|
|
20
|
+
name: "web",
|
|
21
|
+
image,
|
|
22
|
+
ports: [{ containerPort: 8080 }],
|
|
23
|
+
securityContext: { runAsNonRoot: true, runAsUser: 101, allowPrivilegeEscalation: false, capabilities: { drop: ["ALL"] } },
|
|
24
|
+
resources: { requests: { cpu: "25m", memory: "32Mi" }, limits: { cpu: "100m", memory: "64Mi" } },
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const service = new Service({
|
|
33
|
+
metadata: { name: "app-a", namespace: "app-a" },
|
|
34
|
+
spec: { selector: labels, ports: [{ port: 80, targetPort: 8080 }] },
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, "noEmit": true }, "include": ["src/**/*", "ops/**/*", "chant.config.ts"] }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChantConfig } from "@intentius/chant";
|
|
2
|
+
import type { K8sChantConfig } from "@intentius/chant-lexicon-k8s";
|
|
3
|
+
|
|
4
|
+
// App project B — the targetNamespace half of the estate: its objects declare
|
|
5
|
+
// no metadata.namespace (see src/app.ts), so the control plane's
|
|
6
|
+
// Kustomization stamps `app-b` at apply time. That is idiomatic Flux, AND it
|
|
7
|
+
// means a plain live read scopes to `default` and finds nothing — behold's
|
|
8
|
+
// namespace-mismatch note (behold#192) names exactly this, on purpose, in
|
|
9
|
+
// this demo.
|
|
10
|
+
export default {
|
|
11
|
+
lexicons: ["k8s"],
|
|
12
|
+
sourceDir: "src",
|
|
13
|
+
environments: ["local"],
|
|
14
|
+
ownership: { stack: "app-b", env: "local" },
|
|
15
|
+
k8s: {
|
|
16
|
+
profiles: {
|
|
17
|
+
local: { context: "k3d-behold-flux-demo" },
|
|
18
|
+
},
|
|
19
|
+
} satisfies K8sChantConfig,
|
|
20
|
+
} satisfies ChantConfig;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: app-b
|
|
5
|
+
labels:
|
|
6
|
+
app.kubernetes.io/managed-by: chant
|
|
7
|
+
chant.intentius.io/stack: app-b
|
|
8
|
+
chant.intentius.io/env: local
|
|
9
|
+
app: app-b
|
|
10
|
+
spec:
|
|
11
|
+
replicas: 1
|
|
12
|
+
selector:
|
|
13
|
+
matchLabels:
|
|
14
|
+
app: app-b
|
|
15
|
+
template:
|
|
16
|
+
metadata:
|
|
17
|
+
labels:
|
|
18
|
+
app: app-b
|
|
19
|
+
spec:
|
|
20
|
+
containers:
|
|
21
|
+
- name: web
|
|
22
|
+
image: nginxinc/nginx-unprivileged:1.27-alpine
|
|
23
|
+
ports:
|
|
24
|
+
- containerPort: 8080
|
|
25
|
+
securityContext:
|
|
26
|
+
runAsNonRoot: true
|
|
27
|
+
runAsUser: 101
|
|
28
|
+
allowPrivilegeEscalation: false
|
|
29
|
+
capabilities:
|
|
30
|
+
drop:
|
|
31
|
+
- ALL
|
|
32
|
+
resources:
|
|
33
|
+
requests:
|
|
34
|
+
cpu: '25m'
|
|
35
|
+
memory: '32Mi'
|
|
36
|
+
limits:
|
|
37
|
+
cpu: '100m'
|
|
38
|
+
memory: '64Mi'
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
apiVersion: v1
|
|
42
|
+
kind: Service
|
|
43
|
+
metadata:
|
|
44
|
+
name: app-b
|
|
45
|
+
labels:
|
|
46
|
+
app.kubernetes.io/managed-by: chant
|
|
47
|
+
chant.intentius.io/stack: app-b
|
|
48
|
+
chant.intentius.io/env: local
|
|
49
|
+
spec:
|
|
50
|
+
selector:
|
|
51
|
+
app: app-b
|
|
52
|
+
ports:
|
|
53
|
+
- port: 80
|
|
54
|
+
targetPort: 8080
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "behold-example-flux-app-b",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "App project B: declares NO metadata.namespace — Flux's targetNamespace stamps it at apply time (the behold#192 shape).",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "chant build src -o manifests/app.yaml --format yaml"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@intentius/chant": "^0.41.20",
|
|
11
|
+
"@intentius/chant-lexicon-k8s": "^0.41.20"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// App B: same small workload as app-a, with NO metadata.namespace anywhere —
|
|
2
|
+
// the control plane's Kustomization stamps targetNamespace: app-b at apply
|
|
3
|
+
// time. Idiomatic Flux (that's what the field is for), and the deliberate
|
|
4
|
+
// exhibit of behold's namespace-mismatch note (behold#192): a plain live read
|
|
5
|
+
// scopes to `default`, finds nothing, and behold explains the all-pending
|
|
6
|
+
// paint instead of letting it read as "not deployed".
|
|
7
|
+
import { Deployment, Service } from "@intentius/chant-lexicon-k8s";
|
|
8
|
+
|
|
9
|
+
const labels = { app: "app-b" };
|
|
10
|
+
const image = "nginxinc/nginx-unprivileged:1.27-alpine";
|
|
11
|
+
|
|
12
|
+
export const deployment = new Deployment({
|
|
13
|
+
metadata: { name: "app-b", labels },
|
|
14
|
+
spec: {
|
|
15
|
+
replicas: 1,
|
|
16
|
+
selector: { matchLabels: labels },
|
|
17
|
+
template: {
|
|
18
|
+
metadata: { labels },
|
|
19
|
+
spec: {
|
|
20
|
+
containers: [
|
|
21
|
+
{
|
|
22
|
+
name: "web",
|
|
23
|
+
image,
|
|
24
|
+
ports: [{ containerPort: 8080 }],
|
|
25
|
+
securityContext: { runAsNonRoot: true, runAsUser: 101, allowPrivilegeEscalation: false, capabilities: { drop: ["ALL"] } },
|
|
26
|
+
resources: { requests: { cpu: "25m", memory: "32Mi" }, limits: { cpu: "100m", memory: "64Mi" } },
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const service = new Service({
|
|
35
|
+
metadata: { name: "app-b" },
|
|
36
|
+
spec: { selector: labels, ports: [{ port: 80, targetPort: 8080 }] },
|
|
37
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, "noEmit": true }, "include": ["src/**/*", "ops/**/*", "chant.config.ts"] }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ChantConfig } from "@intentius/chant";
|
|
2
|
+
import type { K8sChantConfig } from "@intentius/chant-lexicon-k8s";
|
|
3
|
+
|
|
4
|
+
// The estate's control plane: it declares the Flux machinery (GitRepository +
|
|
5
|
+
// one Kustomization per app), and the reconcilers deploy the app projects —
|
|
6
|
+
// this project never applies a workload itself. Bound to the demo's own
|
|
7
|
+
// cluster (scripts/estate-up.sh creates it) so a live read can never observe
|
|
8
|
+
// whatever kubectl context happens to be ambient (chant#1100).
|
|
9
|
+
export default {
|
|
10
|
+
lexicons: ["k8s"],
|
|
11
|
+
sourceDir: "src",
|
|
12
|
+
environments: ["local"],
|
|
13
|
+
ownership: { stack: "flux-control-plane", env: "local" },
|
|
14
|
+
k8s: {
|
|
15
|
+
profiles: {
|
|
16
|
+
local: { context: "k3d-behold-flux-demo" },
|
|
17
|
+
},
|
|
18
|
+
} satisfies K8sChantConfig,
|
|
19
|
+
} satisfies ChantConfig;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "behold-example-flux-control-plane",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "The estate's control plane: the Flux CRs (GitRepository + Kustomizations) that deploy the app projects.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "chant build src -o dist/control-plane.yaml --format yaml"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@intentius/chant": "^0.41.20",
|
|
11
|
+
"@intentius/chant-lexicon-k8s": "^0.41.20"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// The control plane, GitOps-style: Flux reconcilers deploy the app projects
|
|
2
|
+
// FROM THIS REPO. The GitRepository points at behold's own public repo; each
|
|
3
|
+
// Kustomization applies one app project's committed manifests into that app's
|
|
4
|
+
// namespace via targetNamespace — which is why app-b's objects declare no
|
|
5
|
+
// metadata.namespace (see ../../app-b/src/app.ts): Flux stamps it at apply
|
|
6
|
+
// time. That is the normal Flux estate shape, and exactly the shape behold's
|
|
7
|
+
// namespace-mismatch note (behold#192) exists to explain.
|
|
8
|
+
//
|
|
9
|
+
// scripts/estate-up.sh applies the BUILT form of this project (chant build →
|
|
10
|
+
// dist/control-plane.yaml) once, after installing Flux; from then on the
|
|
11
|
+
// reconcilers own the apps.
|
|
12
|
+
import { Namespace, GitRepository, Kustomization } from "@intentius/chant-lexicon-k8s";
|
|
13
|
+
|
|
14
|
+
// The app namespaces are control-plane concerns: a Kustomization's
|
|
15
|
+
// targetNamespace must already exist — Flux does not create it.
|
|
16
|
+
export const nsAppA = new Namespace({ metadata: { name: "app-a" } });
|
|
17
|
+
export const nsAppB = new Namespace({ metadata: { name: "app-b" } });
|
|
18
|
+
|
|
19
|
+
export const source = new GitRepository({
|
|
20
|
+
metadata: { name: "behold", namespace: "flux-system" },
|
|
21
|
+
spec: {
|
|
22
|
+
interval: "1m",
|
|
23
|
+
url: "https://github.com/INTENTIUS/behold",
|
|
24
|
+
// main is where the committed manifests live once merged. Verifying a
|
|
25
|
+
// not-yet-merged branch: estate-up.sh patches the LIVE object's ref when
|
|
26
|
+
// BEHOLD_FLUX_REF is set — the declared source stays main.
|
|
27
|
+
ref: { branch: "main" },
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const appA = new Kustomization({
|
|
32
|
+
metadata: { name: "app-a", namespace: "flux-system" },
|
|
33
|
+
spec: {
|
|
34
|
+
interval: "1m",
|
|
35
|
+
prune: true,
|
|
36
|
+
targetNamespace: "app-a",
|
|
37
|
+
sourceRef: { kind: "GitRepository", name: "behold" },
|
|
38
|
+
path: "./example-flux-estate/app-a/manifests",
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const appB = new Kustomization({
|
|
43
|
+
metadata: { name: "app-b", namespace: "flux-system" },
|
|
44
|
+
spec: {
|
|
45
|
+
interval: "1m",
|
|
46
|
+
prune: true,
|
|
47
|
+
targetNamespace: "app-b",
|
|
48
|
+
sourceRef: { kind: "GitRepository", name: "behold" },
|
|
49
|
+
path: "./example-flux-estate/app-b/manifests",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, "noEmit": true }, "include": ["src/**/*", "ops/**/*", "chant.config.ts"] }
|