@intentius/chant-lexicon-k8s 0.124.31 → 0.124.32
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/dist/actions/apps.js +18 -0
- package/dist/actions/batch.js +6 -0
- package/dist/actions/core.js +48 -0
- package/dist/actions/index.js +13 -0
- package/dist/actions/networking.js +11 -0
- package/dist/actions/rbac.js +8 -0
- package/dist/api/classify.js +123 -0
- package/dist/api/connect.js +62 -0
- package/dist/api/fake-cluster.js +175 -0
- package/dist/api/operation-surface.d.ts.map +1 -1
- package/dist/api/operation-surface.js +109 -0
- package/dist/api/owner-chain.js +100 -0
- package/dist/api/sweep-types.js +35 -0
- package/dist/behaviour-kinds.js +82 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +146 -0
- package/dist/codegen/generate-cli.js +30 -0
- package/dist/codegen/generate-lexicon.js +74 -0
- package/dist/codegen/generate-list-map-keys.js +88 -0
- package/dist/codegen/generate-operations.js +53 -0
- package/dist/codegen/generate-typescript.js +124 -0
- package/dist/codegen/generate.js +173 -0
- package/dist/codegen/naming.js +174 -0
- package/dist/codegen/package.js +36 -0
- package/dist/codegen/patches.js +88 -0
- package/dist/codegen/typecheck.js +4 -0
- package/dist/codegen/versions.js +41 -0
- package/dist/components/argo-app.js +51 -0
- package/dist/components/builders.js +22 -0
- package/dist/components/capability-plugin.js +31 -0
- package/dist/components/flux-reconcile.js +61 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +18 -0
- package/dist/components/kubectl-apply.d.ts +83 -1
- package/dist/components/kubectl-apply.d.ts.map +1 -1
- package/dist/components/kubectl-apply.js +274 -0
- package/dist/components/kustomize-apply.js +25 -0
- package/dist/composites/adot-collector.js +184 -0
- package/dist/composites/agic-ingress.js +85 -0
- package/dist/composites/aks-external-dns-agent.js +146 -0
- package/dist/composites/alb-ingress.js +86 -0
- package/dist/composites/argo-app.js +199 -0
- package/dist/composites/autoscaled-service.js +174 -0
- package/dist/composites/azure-disk-storage-class.js +47 -0
- package/dist/composites/azure-file-storage-class.js +48 -0
- package/dist/composites/azure-monitor-collector.js +176 -0
- package/dist/composites/batch-job.js +139 -0
- package/dist/composites/catalog.js +4110 -0
- package/dist/composites/cockroachdb-cluster.js +371 -0
- package/dist/composites/cockroachdb-region-stack.js +369 -0
- package/dist/composites/config-connector-context.js +40 -0
- package/dist/composites/configured-app.js +135 -0
- package/dist/composites/cron-schedule.js +38 -0
- package/dist/composites/cron-workload.js +109 -0
- package/dist/composites/ebs-storage-class.js +54 -0
- package/dist/composites/efs-storage-class.js +46 -0
- package/dist/composites/external-dns-agent.js +122 -0
- package/dist/composites/filestore-storage-class.js +49 -0
- package/dist/composites/fluent-bit-agent.js +157 -0
- package/dist/composites/flux-app.js +156 -0
- package/dist/composites/gce-ingress.js +83 -0
- package/dist/composites/gce-pd-storage-class.js +49 -0
- package/dist/composites/gke-external-dns-agent.js +129 -0
- package/dist/composites/gke-fluent-bit-agent.js +165 -0
- package/dist/composites/gke-gateway.js +91 -0
- package/dist/composites/gke-otel-collector.js +94 -0
- package/dist/composites/index.js +51 -0
- package/dist/composites/inference-service.js +76 -0
- package/dist/composites/irsa-service-account.js +77 -0
- package/dist/composites/member-defaults.js +14 -0
- package/dist/composites/metrics-server.js +181 -0
- package/dist/composites/model.js +92 -0
- package/dist/composites/monitored-service.js +152 -0
- package/dist/composites/namespace-env.js +114 -0
- package/dist/composites/network-isolated-app.js +124 -0
- package/dist/composites/node-agent.js +149 -0
- package/dist/composites/operator-stack.js +268 -0
- package/dist/composites/otel-collector-agent.js +142 -0
- package/dist/composites/otel-collector-gateway.js +216 -0
- package/dist/composites/otel-collector-node.js +176 -0
- package/dist/composites/otel-collector-rbac.js +115 -0
- package/dist/composites/otel-collector-shape.js +128 -0
- package/dist/composites/otel-collector.js +115 -0
- package/dist/composites/otel-operator-collector.js +123 -0
- package/dist/composites/ray-cluster.js +378 -0
- package/dist/composites/ray-job.js +136 -0
- package/dist/composites/ray-service.js +178 -0
- package/dist/composites/secure-ingress.js +100 -0
- package/dist/composites/security-context.js +1 -0
- package/dist/composites/sidecar-app.js +105 -0
- package/dist/composites/stateful-app.js +111 -0
- package/dist/composites/vllm-serving-runtime.js +114 -0
- package/dist/composites/web-app.js +157 -0
- package/dist/composites/worker-pool.js +167 -0
- package/dist/composites/workload-identity-sa.js +81 -0
- package/dist/composites/workload-identity-service-account.js +77 -0
- package/dist/config-schema.js +72 -0
- package/dist/config.js +59 -0
- package/dist/coverage.js +27 -0
- package/dist/crd/crd-sources.js +615 -0
- package/dist/crd/loader.js +181 -0
- package/dist/crd/oci-chart.js +144 -0
- package/dist/crd/parser.js +382 -0
- package/dist/crd/project-codegen.js +273 -0
- package/dist/crd/types.js +7 -0
- package/dist/deep-observe-hooks.js +306 -0
- package/dist/deep-observe.js +234 -0
- package/dist/default-labels.js +87 -0
- package/dist/describe-resources.js +699 -0
- package/dist/describe-stack-status.js +99 -0
- package/dist/detect.js +11 -0
- package/dist/effect-receipt-row.js +205 -0
- package/dist/export-resources.js +39 -0
- package/dist/generated/index.js +1092 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/group-namespace.js +96 -0
- package/dist/import/embedded.js +197 -0
- package/dist/import/generator.js +288 -0
- package/dist/import/live-export.js +85 -0
- package/dist/import/parser.js +204 -0
- package/dist/import/testdata/embedded/fixtures.js +60 -0
- package/dist/include/entity.js +78 -0
- package/dist/include/resolve.js +170 -0
- package/dist/index.js +59 -0
- package/dist/integrity.json +3 -3
- package/dist/kube/apply.js +90 -0
- package/dist/kube/connect.js +46 -0
- package/dist/kube/delete.js +138 -0
- package/dist/kube/describe.js +169 -0
- package/dist/kube/events.js +132 -0
- package/dist/kube/flags.js +91 -0
- package/dist/kube/get.js +159 -0
- package/dist/kube/group.js +123 -0
- package/dist/kube/logs.js +82 -0
- package/dist/kube/project.js +94 -0
- package/dist/kube/render.js +227 -0
- package/dist/kube/source.js +122 -0
- package/dist/kube/target.js +63 -0
- package/dist/kube/testing.js +28 -0
- package/dist/kube/top.js +99 -0
- package/dist/kube/verdict.js +72 -0
- package/dist/kube/wait.js +129 -0
- package/dist/kustomize/render.js +73 -0
- package/dist/kustomize/rendered-entity.js +67 -0
- package/dist/kustomize/root.js +68 -0
- package/dist/lint/audit-catalog.js +61 -0
- package/dist/lint/audit-lineage.js +118 -0
- package/dist/lint/post-synth/argo-helpers.js +36 -0
- package/dist/lint/post-synth/argo002.js +31 -0
- package/dist/lint/post-synth/argo003.js +53 -0
- package/dist/lint/post-synth/argo005.js +54 -0
- package/dist/lint/post-synth/crd-schema-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/crd-schema-helpers.js +214 -0
- package/dist/lint/post-synth/flux002.js +56 -0
- package/dist/lint/post-synth/flux003.js +50 -0
- package/dist/lint/post-synth/index.js +104 -0
- package/dist/lint/post-synth/k8s-helpers.js +186 -0
- package/dist/lint/post-synth/monitoring-selection-helpers.js +163 -0
- package/dist/lint/post-synth/otel-placement-helpers.js +293 -0
- package/dist/lint/post-synth/sops-helpers.js +43 -0
- package/dist/lint/post-synth/wk8005.js +44 -0
- package/dist/lint/post-synth/wk8006.js +56 -0
- package/dist/lint/post-synth/wk8041.js +60 -0
- package/dist/lint/post-synth/wk8042.js +36 -0
- package/dist/lint/post-synth/wk8101.js +52 -0
- package/dist/lint/post-synth/wk8102.js +30 -0
- package/dist/lint/post-synth/wk8103.js +33 -0
- package/dist/lint/post-synth/wk8104.js +58 -0
- package/dist/lint/post-synth/wk8105.js +33 -0
- package/dist/lint/post-synth/wk8201.js +44 -0
- package/dist/lint/post-synth/wk8202.js +34 -0
- package/dist/lint/post-synth/wk8203.js +34 -0
- package/dist/lint/post-synth/wk8204.js +71 -0
- package/dist/lint/post-synth/wk8205.js +38 -0
- package/dist/lint/post-synth/wk8207.js +33 -0
- package/dist/lint/post-synth/wk8208.js +33 -0
- package/dist/lint/post-synth/wk8209.js +33 -0
- package/dist/lint/post-synth/wk8301.js +49 -0
- package/dist/lint/post-synth/wk8302.js +34 -0
- package/dist/lint/post-synth/wk8303.js +68 -0
- package/dist/lint/post-synth/wk8304.js +58 -0
- package/dist/lint/post-synth/wk8305.js +96 -0
- package/dist/lint/post-synth/wk8306.js +38 -0
- package/dist/lint/post-synth/wk8401.js +86 -0
- package/dist/lint/post-synth/wk8402.js +31 -0
- package/dist/lint/post-synth/wk8403.js +49 -0
- package/dist/lint/post-synth/wk8404.js +36 -0
- package/dist/lint/post-synth/wk8405.js +65 -0
- package/dist/lint/post-synth/wk8406.js +50 -0
- package/dist/lint/post-synth/wk8407.js +58 -0
- package/dist/lint/post-synth/wk8501.js +36 -0
- package/dist/lint/post-synth/wk8502.js +35 -0
- package/dist/lint/post-synth/wk8503.js +164 -0
- package/dist/lint/post-synth/wk8504.js +20 -0
- package/dist/lint/post-synth/wk8505.js +31 -0
- package/dist/lint/post-synth/wk8601.js +40 -0
- package/dist/lint/post-synth/wk8602.js +120 -0
- package/dist/lint/post-synth/wk8603.js +63 -0
- package/dist/lint/post-synth/wk8604.js +31 -0
- package/dist/lint/post-synth/wk8605.js +124 -0
- package/dist/lint/post-synth/wk8606.js +22 -0
- package/dist/lint/post-synth/wk8701.js +31 -0
- package/dist/lint/post-synth/wk8702.js +37 -0
- package/dist/lint/post-synth/wk8703.js +31 -0
- package/dist/lint/post-synth/wk8704.js +135 -0
- package/dist/lint/post-synth/wk8705.js +38 -0
- package/dist/lint/rules/argo-appset-single-project.js +56 -0
- package/dist/lint/rules/argo-ast.js +94 -0
- package/dist/lint/rules/argo-automated-prune.js +59 -0
- package/dist/lint/rules/flux-source-ref-pin.js +44 -0
- package/dist/lint/rules/hardcoded-namespace.js +57 -0
- package/dist/lint/rules/latest-image-tag.js +103 -0
- package/dist/lint/rules/missing-resource-limits.js +85 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +57 -0
- package/dist/manifest-entity.js +71 -0
- package/dist/manifest.json +1 -1
- package/dist/micro-time.js +49 -0
- package/dist/op/activities/apply-diff.d.ts +31 -0
- package/dist/op/activities/apply-diff.d.ts.map +1 -0
- package/dist/op/activities/apply-diff.js +79 -0
- package/dist/op/activities/argo.js +98 -0
- package/dist/op/activities/ensure-secret.js +38 -0
- package/dist/op/activities/index.js +51 -0
- package/dist/op/activities/kubectl.d.ts +64 -0
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/op/activities/kubectl.js +517 -0
- package/dist/op/activities/wait-for-ready.js +229 -0
- package/dist/op/builders.js +68 -0
- package/dist/package-cli.js +21 -0
- package/dist/patch/json-patch.js +187 -0
- package/dist/patch/rendered-patch.js +94 -0
- package/dist/plugin.js +741 -0
- package/dist/project-kinds.js +56 -0
- package/dist/receipt-store.js +216 -0
- package/dist/rules/crd-schema-helpers.ts +2 -1
- package/dist/secret-labels.js +33 -0
- package/dist/secret-store.js +116 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +578 -0
- package/dist/sops/encrypted-secret-file.js +194 -0
- package/dist/sops/entity.js +32 -0
- package/dist/spec/fetch.js +58 -0
- package/dist/spec/parse.js +622 -0
- package/dist/subscribe-changes.js +168 -0
- package/dist/teardown.js +197 -0
- package/dist/telemetry-release.js +86 -0
- package/dist/validate-cli.js +17 -0
- package/dist/validate.js +47 -0
- package/dist/variables.js +34 -0
- package/dist/whoami.js +109 -0
- package/package.json +12 -12
- package/src/api/operation-surface.ts +2 -1
- package/src/codegen/package.ts +2 -2
- package/src/components/index.ts +3 -0
- package/src/components/kubectl-apply-plan.k3d.e2e.test.ts +127 -0
- package/src/components/kubectl-apply.test.ts +262 -0
- package/src/components/kubectl-apply.ts +341 -12
- package/src/deep-observe-hooks.ts +2 -2
- package/src/import/roundtrip-build.test.ts +46 -0
- package/src/lint/post-synth/crd-schema-helpers.ts +2 -1
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/op/activities/apply-diff.ts +87 -0
- package/src/op/activities/kubectl-plan.test.ts +224 -0
- package/src/op/activities/kubectl.ts +204 -16
- package/src/serializer.ts +2 -1
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubernetes lexicon plugin.
|
|
3
|
+
*
|
|
4
|
+
* Provides serializer, template detection, code generation,
|
|
5
|
+
* lint rules, and LSP/MCP integration for Kubernetes manifests.
|
|
6
|
+
*/
|
|
7
|
+
import { compositeCatalog } from "./composites/catalog.js";
|
|
8
|
+
import { k8sBehaviourKinds } from "./behaviour-kinds.js";
|
|
9
|
+
import { kubeCommandGroup } from "./kube/group.js";
|
|
10
|
+
import { detectTemplate } from "./detect.js";
|
|
11
|
+
import { postSynthChecks as postSynthCheckList } from "./lint/post-synth/index.js";
|
|
12
|
+
import { k8sAuditCatalog } from "./lint/audit-catalog.js";
|
|
13
|
+
import { createSkillsLoader, createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
|
|
14
|
+
import { k8sSerializer } from "./serializer.js";
|
|
15
|
+
import { hardcodedNamespaceRule } from "./lint/rules/hardcoded-namespace.js";
|
|
16
|
+
import { latestImageTagRule } from "./lint/rules/latest-image-tag.js";
|
|
17
|
+
import { missingResourceLimitsRule } from "./lint/rules/missing-resource-limits.js";
|
|
18
|
+
import { argoAutomatedPruneRule } from "./lint/rules/argo-automated-prune.js";
|
|
19
|
+
import { argoAppSetSingleProjectRule } from "./lint/rules/argo-appset-single-project.js";
|
|
20
|
+
import { fluxSourceRefPinRule } from "./lint/rules/flux-source-ref-pin.js";
|
|
21
|
+
import { k8sCompletions } from "./lsp/completions.js";
|
|
22
|
+
import { k8sHover } from "./lsp/hover.js";
|
|
23
|
+
import { K8sParser } from "./import/parser.js";
|
|
24
|
+
import { K8sGenerator } from "./import/generator.js";
|
|
25
|
+
import { k8sDeepNormalizationHooks } from "./deep-observe-hooks.js";
|
|
26
|
+
import { LABEL_OWNERSHIP_KEYS } from "@intentius/chant/ownership";
|
|
27
|
+
import { k8sConfigSchema } from "./config-schema.js";
|
|
28
|
+
import { renderKustomizeRoots } from "./kustomize/root.js";
|
|
29
|
+
import { encryptedSecretBuildRoot } from "./sops/encrypted-secret-file.js";
|
|
30
|
+
import { k8sProjectCodegen } from "./crd/project-codegen.js";
|
|
31
|
+
import { includeBuildRoot } from "./include/resolve.js";
|
|
32
|
+
export const k8sPlugin = {
|
|
33
|
+
behaviourKinds: k8sBehaviourKinds,
|
|
34
|
+
name: "k8s",
|
|
35
|
+
ownershipChannel: { keys: LABEL_OWNERSHIP_KEYS, reads: ["describeResources", "observeResourcesDeep", "exportResources"] },
|
|
36
|
+
configSchema: k8sConfigSchema,
|
|
37
|
+
auditCatalog: () => k8sAuditCatalog,
|
|
38
|
+
serializer: k8sSerializer,
|
|
39
|
+
// Self-upgrade: where the pinned Kubernetes schema version lives + its upstream (#685).
|
|
40
|
+
upstreamPin: {
|
|
41
|
+
file: "src/spec/fetch.ts",
|
|
42
|
+
pattern: /export const K8S_SCHEMA_VERSION\s*=\s*"([^"]+)"/,
|
|
43
|
+
replace: (v, line) => line.replace(/export const K8S_SCHEMA_VERSION\s*=\s*"[^"]+"/, `export const K8S_SCHEMA_VERSION = "${v}"`),
|
|
44
|
+
upstream: { owner: "kubernetes", repo: "kubernetes", kind: "releases" },
|
|
45
|
+
},
|
|
46
|
+
// chant #1078/#1079 — the command-group seam's tenant. `kube` mounts the
|
|
47
|
+
// terminal surface over the typed client: kubectl-compatible reads (get,
|
|
48
|
+
// describe, logs, events, top, wait), chant's own additions (source, the
|
|
49
|
+
// `get` verdict column, -o chant), and gated writes (apply, delete) that
|
|
50
|
+
// route through the exact same machinery the Op activities use — never a
|
|
51
|
+
// parallel implementation. See ./kube/group.ts for the full verb list;
|
|
52
|
+
// this plugin only mounts it.
|
|
53
|
+
commands() {
|
|
54
|
+
return kubeCommandGroup();
|
|
55
|
+
},
|
|
56
|
+
lintRules() {
|
|
57
|
+
return [
|
|
58
|
+
hardcodedNamespaceRule,
|
|
59
|
+
latestImageTagRule,
|
|
60
|
+
missingResourceLimitsRule,
|
|
61
|
+
argoAutomatedPruneRule,
|
|
62
|
+
argoAppSetSingleProjectRule,
|
|
63
|
+
fluxSourceRefPinRule,
|
|
64
|
+
];
|
|
65
|
+
},
|
|
66
|
+
postSynthChecks() {
|
|
67
|
+
return postSynthCheckList;
|
|
68
|
+
},
|
|
69
|
+
// Typed classes for the project's own CRDs (`k8s.crds`), written by
|
|
70
|
+
// `chant generate` and checked for drift by every build. See
|
|
71
|
+
// ./crd/project-codegen.ts.
|
|
72
|
+
projectCodegen() {
|
|
73
|
+
return k8sProjectCodegen();
|
|
74
|
+
},
|
|
75
|
+
// #1548 piece 3 — kustomization dirs declared as build roots. Each entry in
|
|
76
|
+
// `k8s.kustomize.roots` renders at build time (same injectable runner as
|
|
77
|
+
// the kustomize-apply capability: `kustomize build`, `kubectl kustomize`
|
|
78
|
+
// fallback) and the documents join the build as verbatim manifest entities:
|
|
79
|
+
// serialized with ownership stamping, checked post-synth, observed by
|
|
80
|
+
// `lifecycle diff --live`. See ./kustomize/root.ts.
|
|
81
|
+
//
|
|
82
|
+
// The same hook also resolves committed-encrypted `declareSecret()`
|
|
83
|
+
// declarations: it reads the ciphertext each one names and contributes it
|
|
84
|
+
// as a verbatim sidecar entity (see ./sops/encrypted-secret-file.ts), and
|
|
85
|
+
// `k8sInclude()` declarations: it reads or fetches each declared YAML and
|
|
86
|
+
// contributes its documents as verbatim manifest entities (see
|
|
87
|
+
// ./include/resolve.ts). All three read at the one sanctioned impure seam.
|
|
88
|
+
async buildRoots(ctx) {
|
|
89
|
+
const entities = new Map();
|
|
90
|
+
const warnings = [];
|
|
91
|
+
const roots = ctx.config.k8s?.kustomize?.roots ?? [];
|
|
92
|
+
if (roots.length > 0) {
|
|
93
|
+
const rendered = await renderKustomizeRoots({ projectRoot: ctx.projectRoot, roots });
|
|
94
|
+
for (const [name, entity] of rendered.entities)
|
|
95
|
+
entities.set(name, entity);
|
|
96
|
+
warnings.push(...rendered.warnings);
|
|
97
|
+
}
|
|
98
|
+
const included = await includeBuildRoot(ctx);
|
|
99
|
+
for (const [name, entity] of included.entities)
|
|
100
|
+
entities.set(name, entity);
|
|
101
|
+
const encrypted = await encryptedSecretBuildRoot(ctx);
|
|
102
|
+
for (const [name, entity] of encrypted.entities)
|
|
103
|
+
entities.set(name, entity);
|
|
104
|
+
warnings.push(...(encrypted.warnings ?? []));
|
|
105
|
+
return { entities, warnings };
|
|
106
|
+
},
|
|
107
|
+
// K8s YAML has no template interpolation functions like CloudFormation's
|
|
108
|
+
// Fn::Sub or GitLab's !reference. Cross-resource references are handled by
|
|
109
|
+
// the AttrRef system in the serializer (resolves to metadata.name).
|
|
110
|
+
// ConfigMap/Secret valueFrom references are expressed as plain property
|
|
111
|
+
// values, not intrinsics.
|
|
112
|
+
intrinsics() {
|
|
113
|
+
return [];
|
|
114
|
+
},
|
|
115
|
+
initTemplates(template) {
|
|
116
|
+
if (template === "microservice") {
|
|
117
|
+
return {
|
|
118
|
+
src: {
|
|
119
|
+
"infra.ts": `import { Deployment, Service, HorizontalPodAutoscaler, PodDisruptionBudget, Container, Probe, ResourceRequirements } from "@intentius/chant-lexicon-k8s";
|
|
120
|
+
|
|
121
|
+
export const deployment = new Deployment({
|
|
122
|
+
metadata: { name: "my-service", labels: { "app.kubernetes.io/name": "my-service" } },
|
|
123
|
+
spec: {
|
|
124
|
+
replicas: 2,
|
|
125
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-service" } },
|
|
126
|
+
template: {
|
|
127
|
+
metadata: { labels: { "app.kubernetes.io/name": "my-service" } },
|
|
128
|
+
spec: {
|
|
129
|
+
containers: [
|
|
130
|
+
new Container({
|
|
131
|
+
name: "app",
|
|
132
|
+
image: "my-service:latest",
|
|
133
|
+
ports: [{ containerPort: 8080, name: "http" }],
|
|
134
|
+
resources: new ResourceRequirements({
|
|
135
|
+
limits: { cpu: "500m", memory: "256Mi" },
|
|
136
|
+
requests: { cpu: "100m", memory: "128Mi" },
|
|
137
|
+
}),
|
|
138
|
+
livenessProbe: new Probe({ httpGet: { path: "/healthz", port: 8080 }, initialDelaySeconds: 10 }),
|
|
139
|
+
readinessProbe: new Probe({ httpGet: { path: "/readyz", port: 8080 }, initialDelaySeconds: 5 }),
|
|
140
|
+
}),
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
export const service = new Service({
|
|
148
|
+
metadata: { name: "my-service", labels: { "app.kubernetes.io/name": "my-service" } },
|
|
149
|
+
spec: {
|
|
150
|
+
selector: { "app.kubernetes.io/name": "my-service" },
|
|
151
|
+
ports: [{ port: 80, targetPort: 8080, protocol: "TCP", name: "http" }],
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export const hpa = new HorizontalPodAutoscaler({
|
|
156
|
+
metadata: { name: "my-service" },
|
|
157
|
+
spec: {
|
|
158
|
+
scaleTargetRef: { apiVersion: "apps/v1", kind: "Deployment", name: "my-service" },
|
|
159
|
+
minReplicas: 2,
|
|
160
|
+
maxReplicas: 10,
|
|
161
|
+
metrics: [{ type: "Resource", resource: { name: "cpu", target: { type: "Utilization", averageUtilization: 70 } } }],
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
export const pdb = new PodDisruptionBudget({
|
|
166
|
+
metadata: { name: "my-service" },
|
|
167
|
+
spec: {
|
|
168
|
+
minAvailable: 1,
|
|
169
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-service" } },
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
`,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (template === "stateful") {
|
|
177
|
+
return {
|
|
178
|
+
src: {
|
|
179
|
+
"infra.ts": `import { StatefulSet, Service } from "@intentius/chant-lexicon-k8s";
|
|
180
|
+
|
|
181
|
+
export const statefulSet = new StatefulSet({
|
|
182
|
+
metadata: { name: "my-db", labels: { "app.kubernetes.io/name": "my-db" } },
|
|
183
|
+
spec: {
|
|
184
|
+
serviceName: "my-db",
|
|
185
|
+
replicas: 3,
|
|
186
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-db" } },
|
|
187
|
+
template: {
|
|
188
|
+
metadata: { labels: { "app.kubernetes.io/name": "my-db" } },
|
|
189
|
+
spec: {
|
|
190
|
+
containers: [
|
|
191
|
+
{
|
|
192
|
+
name: "db",
|
|
193
|
+
image: "postgres:16",
|
|
194
|
+
ports: [{ containerPort: 5432, name: "postgres" }],
|
|
195
|
+
volumeMounts: [{ name: "data", mountPath: "/var/lib/postgresql/data" }],
|
|
196
|
+
env: [
|
|
197
|
+
{ name: "POSTGRES_DB", value: "mydb" },
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
volumeClaimTemplates: [
|
|
204
|
+
{
|
|
205
|
+
metadata: { name: "data" },
|
|
206
|
+
spec: {
|
|
207
|
+
accessModes: ["ReadWriteOnce"],
|
|
208
|
+
resources: { requests: { storage: "10Gi" } },
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
export const service = new Service({
|
|
216
|
+
metadata: { name: "my-db", labels: { "app.kubernetes.io/name": "my-db" } },
|
|
217
|
+
spec: {
|
|
218
|
+
selector: { "app.kubernetes.io/name": "my-db" },
|
|
219
|
+
ports: [{ port: 5432, targetPort: 5432, name: "postgres" }],
|
|
220
|
+
clusterIP: "None",
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
`,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// Default template — Deployment + Service
|
|
228
|
+
return {
|
|
229
|
+
src: {
|
|
230
|
+
"infra.ts": `import { Deployment, Service, Container, Probe } from "@intentius/chant-lexicon-k8s";
|
|
231
|
+
|
|
232
|
+
export const deployment = new Deployment({
|
|
233
|
+
metadata: { name: "my-app", labels: { "app.kubernetes.io/name": "my-app" } },
|
|
234
|
+
spec: {
|
|
235
|
+
replicas: 2,
|
|
236
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-app" } },
|
|
237
|
+
template: {
|
|
238
|
+
metadata: { labels: { "app.kubernetes.io/name": "my-app" } },
|
|
239
|
+
spec: {
|
|
240
|
+
containers: [
|
|
241
|
+
new Container({
|
|
242
|
+
name: "app",
|
|
243
|
+
image: "my-app:latest",
|
|
244
|
+
ports: [{ containerPort: 8080, name: "http" }],
|
|
245
|
+
livenessProbe: new Probe({ httpGet: { path: "/healthz", port: 8080 } }),
|
|
246
|
+
readinessProbe: new Probe({ httpGet: { path: "/readyz", port: 8080 } }),
|
|
247
|
+
}),
|
|
248
|
+
],
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
export const service = new Service({
|
|
255
|
+
metadata: { name: "my-app", labels: { "app.kubernetes.io/name": "my-app" } },
|
|
256
|
+
spec: {
|
|
257
|
+
selector: { "app.kubernetes.io/name": "my-app" },
|
|
258
|
+
ports: [{ port: 80, targetPort: 8080, protocol: "TCP", name: "http" }],
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
`,
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
detectTemplate,
|
|
266
|
+
completionProvider(ctx) {
|
|
267
|
+
return k8sCompletions(ctx);
|
|
268
|
+
},
|
|
269
|
+
hoverProvider(ctx) {
|
|
270
|
+
return k8sHover(ctx);
|
|
271
|
+
},
|
|
272
|
+
templateParser() {
|
|
273
|
+
return new K8sParser();
|
|
274
|
+
},
|
|
275
|
+
templateGenerator() {
|
|
276
|
+
return new K8sGenerator();
|
|
277
|
+
},
|
|
278
|
+
async docs(options) {
|
|
279
|
+
const { generateDocs } = await import("./codegen/docs.js");
|
|
280
|
+
await generateDocs(options);
|
|
281
|
+
},
|
|
282
|
+
async generate(options) {
|
|
283
|
+
const { generate, writeGeneratedFiles } = await import("./codegen/generate.js");
|
|
284
|
+
const { dirname } = await import("path");
|
|
285
|
+
const { fileURLToPath } = await import("url");
|
|
286
|
+
const result = await generate({ verbose: options?.verbose ?? true });
|
|
287
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
288
|
+
writeGeneratedFiles(result, pkgDir);
|
|
289
|
+
console.error(`Generated ${result.resources} resources, ${result.properties} property types, ${result.enums} enums`);
|
|
290
|
+
if (result.warnings.length > 0) {
|
|
291
|
+
console.error(`${result.warnings.length} warnings`);
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
async validate(options) {
|
|
295
|
+
const { validate } = await import("./validate.js");
|
|
296
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
297
|
+
const result = await validate();
|
|
298
|
+
printValidationResult(result);
|
|
299
|
+
},
|
|
300
|
+
async coverage(options) {
|
|
301
|
+
const { analyzeK8sCoverage } = await import("./coverage.js");
|
|
302
|
+
await analyzeK8sCoverage({
|
|
303
|
+
verbose: options?.verbose,
|
|
304
|
+
minOverall: options?.minOverall,
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
async package(options) {
|
|
308
|
+
const { packageLexicon } = await import("./codegen/package.js");
|
|
309
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
310
|
+
const { join, dirname } = await import("path");
|
|
311
|
+
const { fileURLToPath } = await import("url");
|
|
312
|
+
const { spec, stats } = await packageLexicon({ verbose: options?.verbose, force: options?.force });
|
|
313
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
314
|
+
const distDir = join(pkgDir, "dist");
|
|
315
|
+
writeBundleSpec(spec, distDir);
|
|
316
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
317
|
+
},
|
|
318
|
+
composites() {
|
|
319
|
+
return compositeCatalog;
|
|
320
|
+
},
|
|
321
|
+
mcpTools() {
|
|
322
|
+
return [createDiffTool(k8sSerializer, "Compare current build output against previous output for Kubernetes manifests", "k8s")];
|
|
323
|
+
},
|
|
324
|
+
mcpResources() {
|
|
325
|
+
return [
|
|
326
|
+
createCatalogResource(import.meta.url, "Kubernetes Resource Catalog", "JSON list of all supported Kubernetes resource types", "lexicon-k8s.json", "k8s"),
|
|
327
|
+
{
|
|
328
|
+
uri: "examples/basic-deployment",
|
|
329
|
+
name: "Basic Deployment Example",
|
|
330
|
+
description: "A basic Kubernetes Deployment with Service",
|
|
331
|
+
mimeType: "text/typescript",
|
|
332
|
+
async handler() {
|
|
333
|
+
return `import { Deployment, Service, Container, Probe } from "@intentius/chant-lexicon-k8s";
|
|
334
|
+
|
|
335
|
+
export const deployment = new Deployment({
|
|
336
|
+
metadata: { name: "my-app", labels: { "app.kubernetes.io/name": "my-app" } },
|
|
337
|
+
spec: {
|
|
338
|
+
replicas: 2,
|
|
339
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-app" } },
|
|
340
|
+
template: {
|
|
341
|
+
metadata: { labels: { "app.kubernetes.io/name": "my-app" } },
|
|
342
|
+
spec: {
|
|
343
|
+
containers: [
|
|
344
|
+
new Container({
|
|
345
|
+
name: "app",
|
|
346
|
+
image: "my-app:1.0",
|
|
347
|
+
ports: [{ containerPort: 8080, name: "http" }],
|
|
348
|
+
livenessProbe: new Probe({ httpGet: { path: "/healthz", port: 8080 } }),
|
|
349
|
+
readinessProbe: new Probe({ httpGet: { path: "/readyz", port: 8080 } }),
|
|
350
|
+
}),
|
|
351
|
+
],
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
export const service = new Service({
|
|
358
|
+
metadata: { name: "my-app" },
|
|
359
|
+
spec: {
|
|
360
|
+
selector: { "app.kubernetes.io/name": "my-app" },
|
|
361
|
+
ports: [{ port: 80, targetPort: 8080, name: "http" }],
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
`;
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
];
|
|
368
|
+
},
|
|
369
|
+
skills: createSkillsLoader(import.meta.url, [
|
|
370
|
+
{
|
|
371
|
+
file: "chant-k8s.md",
|
|
372
|
+
name: "chant-k8s",
|
|
373
|
+
description: "Kubernetes manifest lifecycle — scaffold, generate, lint, build, apply, troubleshoot, rollback",
|
|
374
|
+
triggers: [
|
|
375
|
+
{ type: "file-pattern", value: "**/*.k8s.ts" },
|
|
376
|
+
{ type: "file-pattern", value: "**/k8s/**/*.ts" },
|
|
377
|
+
{ type: "context", value: "kubernetes" },
|
|
378
|
+
{ type: "context", value: "k8s" },
|
|
379
|
+
{ type: "context", value: "kubectl" },
|
|
380
|
+
{ type: "context", value: "deployment" },
|
|
381
|
+
{ type: "context", value: "pod" },
|
|
382
|
+
{ type: "context", value: "composite" },
|
|
383
|
+
{ type: "context", value: "autoscaled" },
|
|
384
|
+
{ type: "context", value: "workerpool" },
|
|
385
|
+
{ type: "context", value: "namespace-env" },
|
|
386
|
+
{ type: "context", value: "node-agent" },
|
|
387
|
+
],
|
|
388
|
+
preConditions: [
|
|
389
|
+
"chant CLI is installed (chant --version succeeds)",
|
|
390
|
+
"kubectl is configured and can access the cluster",
|
|
391
|
+
"Project has chant source files in src/",
|
|
392
|
+
],
|
|
393
|
+
postConditions: [
|
|
394
|
+
"All pods are in Running state",
|
|
395
|
+
"No CrashLoopBackOff or Error pods",
|
|
396
|
+
],
|
|
397
|
+
parameters: [],
|
|
398
|
+
examples: [
|
|
399
|
+
{
|
|
400
|
+
title: "Basic deployment",
|
|
401
|
+
description: "Create a Deployment with Service",
|
|
402
|
+
input: "Create a web app deployment",
|
|
403
|
+
output: `new Deployment({
|
|
404
|
+
metadata: { name: "my-app", labels: { "app.kubernetes.io/name": "my-app" } },
|
|
405
|
+
spec: {
|
|
406
|
+
replicas: 2,
|
|
407
|
+
selector: { matchLabels: { "app.kubernetes.io/name": "my-app" } },
|
|
408
|
+
template: {
|
|
409
|
+
metadata: { labels: { "app.kubernetes.io/name": "my-app" } },
|
|
410
|
+
spec: {
|
|
411
|
+
containers: [{
|
|
412
|
+
name: "app",
|
|
413
|
+
image: "my-app:1.0",
|
|
414
|
+
ports: [{ containerPort: 8080 }],
|
|
415
|
+
}],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
})`,
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
title: "Deploy to cluster",
|
|
423
|
+
description: "Build and apply manifests",
|
|
424
|
+
input: "Deploy my app to the cluster",
|
|
425
|
+
output: `chant build src/ --output manifests.yaml
|
|
426
|
+
kubectl apply -f manifests.yaml --dry-run=server
|
|
427
|
+
kubectl apply -f manifests.yaml
|
|
428
|
+
kubectl rollout status deployment/my-app`,
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
title: "AutoscaledService composite",
|
|
432
|
+
description: "Production HTTP service with HPA, PDB, and zone spreading",
|
|
433
|
+
input: "Create an autoscaled API service",
|
|
434
|
+
output: `import { AutoscaledService } from "@intentius/chant-lexicon-k8s";
|
|
435
|
+
|
|
436
|
+
const { deployment, service, hpa, pdb } = AutoscaledService({
|
|
437
|
+
name: "api",
|
|
438
|
+
image: "api:1.0",
|
|
439
|
+
port: 8080,
|
|
440
|
+
maxReplicas: 10,
|
|
441
|
+
cpuRequest: "100m",
|
|
442
|
+
memoryRequest: "128Mi",
|
|
443
|
+
topologySpread: true,
|
|
444
|
+
});`,
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
title: "BatchJob composite",
|
|
448
|
+
description: "One-shot batch job with RBAC",
|
|
449
|
+
input: "Run a database migration job",
|
|
450
|
+
output: `import { BatchJob } from "@intentius/chant-lexicon-k8s";
|
|
451
|
+
|
|
452
|
+
const { job, serviceAccount, role, roleBinding } = BatchJob({
|
|
453
|
+
name: "db-migrate",
|
|
454
|
+
image: "api:1.0",
|
|
455
|
+
command: ["python", "manage.py", "migrate"],
|
|
456
|
+
backoffLimit: 3,
|
|
457
|
+
ttlSecondsAfterFinished: 3600,
|
|
458
|
+
});`,
|
|
459
|
+
},
|
|
460
|
+
],
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
file: "chant-k8s-patterns.md",
|
|
464
|
+
name: "chant-k8s-patterns",
|
|
465
|
+
description: "Advanced K8s patterns — sidecars, observability, TLS, network isolation, config/secret mounting",
|
|
466
|
+
triggers: [
|
|
467
|
+
{ type: "context", value: "sidecar" },
|
|
468
|
+
{ type: "context", value: "init-container" },
|
|
469
|
+
{ type: "context", value: "prometheus" },
|
|
470
|
+
{ type: "context", value: "cert-manager" },
|
|
471
|
+
{ type: "context", value: "tls" },
|
|
472
|
+
{ type: "context", value: "network-policy" },
|
|
473
|
+
{ type: "context", value: "canary" },
|
|
474
|
+
{ type: "context", value: "blue-green" },
|
|
475
|
+
{ type: "context", value: "configmap-mount" },
|
|
476
|
+
{ type: "context", value: "secret-mount" },
|
|
477
|
+
],
|
|
478
|
+
preConditions: [
|
|
479
|
+
"chant CLI is installed (chant --version succeeds)",
|
|
480
|
+
"kubectl is configured and can access the cluster",
|
|
481
|
+
],
|
|
482
|
+
postConditions: [
|
|
483
|
+
"Pattern resources are deployed and functional",
|
|
484
|
+
],
|
|
485
|
+
parameters: [],
|
|
486
|
+
examples: [
|
|
487
|
+
{
|
|
488
|
+
title: "Sidecar with envoy proxy",
|
|
489
|
+
description: "Deploy an app with an Envoy sidecar",
|
|
490
|
+
input: "Add an envoy sidecar proxy to my API",
|
|
491
|
+
output: `import { SidecarApp } from "@intentius/chant-lexicon-k8s";
|
|
492
|
+
|
|
493
|
+
const { deployment, service } = SidecarApp({
|
|
494
|
+
name: "api",
|
|
495
|
+
image: "api:1.0",
|
|
496
|
+
port: 8080,
|
|
497
|
+
sidecars: [{ name: "envoy", image: "envoyproxy/envoy:v1.28", ports: [{ containerPort: 9901 }] }],
|
|
498
|
+
});`,
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
title: "Monitored service with alerts",
|
|
502
|
+
description: "Deploy a service with Prometheus monitoring and alerting",
|
|
503
|
+
input: "Set up monitoring for my API with error rate alerts",
|
|
504
|
+
output: `import { MonitoredService } from "@intentius/chant-lexicon-k8s";
|
|
505
|
+
|
|
506
|
+
const { deployment, service, serviceMonitor, prometheusRule } = MonitoredService({
|
|
507
|
+
name: "api",
|
|
508
|
+
image: "api:1.0",
|
|
509
|
+
metricsPort: 9090,
|
|
510
|
+
alertRules: [{ name: "HighErrorRate", expr: 'rate(http_errors[5m]) > 0.1', severity: "critical" }],
|
|
511
|
+
});`,
|
|
512
|
+
},
|
|
513
|
+
],
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
file: "chant-k8s-deployment-strategies.md",
|
|
517
|
+
name: "chant-k8s-deployment-strategies",
|
|
518
|
+
description: "Kubernetes deployment strategies, stateful workloads, RBAC, and networking patterns",
|
|
519
|
+
triggers: [
|
|
520
|
+
{ type: "context", value: "deployment strategy" },
|
|
521
|
+
{ type: "context", value: "statefulset" },
|
|
522
|
+
{ type: "context", value: "rbac" },
|
|
523
|
+
{ type: "context", value: "network policy" },
|
|
524
|
+
{ type: "context", value: "rolling update" },
|
|
525
|
+
{ type: "context", value: "blue green" },
|
|
526
|
+
],
|
|
527
|
+
parameters: [],
|
|
528
|
+
examples: [
|
|
529
|
+
{
|
|
530
|
+
title: "Blue/Green Deployment",
|
|
531
|
+
input: "Set up a blue/green deployment for my app",
|
|
532
|
+
output: "import { WebApp } from \"@intentius/chant-lexicon-k8s\";\n\nconst blue = WebApp({ name: \"app-blue\", image: \"app:1.0\" });\nconst green = WebApp({ name: \"app-green\", image: \"app:2.0\" });",
|
|
533
|
+
},
|
|
534
|
+
],
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
file: "chant-k8s-security.md",
|
|
538
|
+
name: "chant-k8s-security",
|
|
539
|
+
description: "Kubernetes pod security, image scanning, network policies, and secrets management",
|
|
540
|
+
triggers: [
|
|
541
|
+
{ type: "context", value: "k8s security" },
|
|
542
|
+
{ type: "context", value: "pod security" },
|
|
543
|
+
{ type: "context", value: "image security" },
|
|
544
|
+
{ type: "context", value: "k8s secrets" },
|
|
545
|
+
{ type: "context", value: "security context" },
|
|
546
|
+
],
|
|
547
|
+
parameters: [],
|
|
548
|
+
examples: [
|
|
549
|
+
{
|
|
550
|
+
title: "Hardened Container",
|
|
551
|
+
input: "Create a hardened container with security context",
|
|
552
|
+
output: "WebApp({ name: \"api\", image: \"api:1.0\", securityContext: { runAsNonRoot: true, readOnlyRootFilesystem: true, capabilities: { drop: [\"ALL\"] } } })",
|
|
553
|
+
},
|
|
554
|
+
],
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
file: "chant-k8s-eks.md",
|
|
558
|
+
name: "chant-k8s-eks",
|
|
559
|
+
description: "EKS-specific Kubernetes composites — IRSA, ALB, EBS/EFS, Fluent Bit, ExternalDNS, ADOT",
|
|
560
|
+
triggers: [
|
|
561
|
+
{ type: "context", value: "eks composites" },
|
|
562
|
+
{ type: "context", value: "irsa" },
|
|
563
|
+
{ type: "context", value: "alb ingress" },
|
|
564
|
+
{ type: "context", value: "ebs storage" },
|
|
565
|
+
{ type: "context", value: "karpenter" },
|
|
566
|
+
],
|
|
567
|
+
parameters: [],
|
|
568
|
+
examples: [
|
|
569
|
+
{
|
|
570
|
+
title: "IRSA ServiceAccount",
|
|
571
|
+
input: "Create an IRSA ServiceAccount for my app",
|
|
572
|
+
output: "import { IrsaServiceAccount } from \"@intentius/chant-lexicon-k8s\";\n\nconst { serviceAccount } = IrsaServiceAccount({ name: \"app-sa\", iamRoleArn: \"arn:aws:iam::123456789012:role/app-role\" });",
|
|
573
|
+
},
|
|
574
|
+
],
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
file: "chant-k8s-gke.md",
|
|
578
|
+
name: "chant-k8s-gke",
|
|
579
|
+
description: "GKE-specific Kubernetes composites — Workload Identity, GCE PD, Filestore, FluentBit, OTel, ExternalDNS, Gateway",
|
|
580
|
+
triggers: [
|
|
581
|
+
{ type: "context", value: "gke composites" },
|
|
582
|
+
{ type: "context", value: "workload identity gke" },
|
|
583
|
+
{ type: "context", value: "config connector k8s" },
|
|
584
|
+
],
|
|
585
|
+
parameters: [],
|
|
586
|
+
examples: [
|
|
587
|
+
{
|
|
588
|
+
title: "GKE Workload Identity",
|
|
589
|
+
input: "Create a ServiceAccount with GKE Workload Identity",
|
|
590
|
+
output: "import { WorkloadIdentityServiceAccount } from \"@intentius/chant-lexicon-k8s\";\n\nconst { serviceAccount } = WorkloadIdentityServiceAccount({ name: \"app-sa\", gcpServiceAccountEmail: \"app@project.iam.gserviceaccount.com\" });",
|
|
591
|
+
},
|
|
592
|
+
],
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
file: "chant-k8s-aks.md",
|
|
596
|
+
name: "chant-k8s-aks",
|
|
597
|
+
description: "AKS-specific Kubernetes composites — Workload Identity, AGIC, Azure Disk/File, ExternalDNS, Azure Monitor",
|
|
598
|
+
triggers: [
|
|
599
|
+
{ type: "context", value: "aks composites" },
|
|
600
|
+
{ type: "context", value: "workload identity aks" },
|
|
601
|
+
{ type: "context", value: "agic ingress" },
|
|
602
|
+
],
|
|
603
|
+
parameters: [],
|
|
604
|
+
examples: [
|
|
605
|
+
{
|
|
606
|
+
title: "AKS Workload Identity",
|
|
607
|
+
input: "Create a ServiceAccount with AKS Workload Identity",
|
|
608
|
+
output: "import { AksWorkloadIdentityServiceAccount } from \"@intentius/chant-lexicon-k8s\";\n\nconst { serviceAccount } = AksWorkloadIdentityServiceAccount({ name: \"app-sa\", clientId: \"12345678-abcd-1234-abcd-123456789012\" });",
|
|
609
|
+
},
|
|
610
|
+
],
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
file: "chant-k8s-argo.md",
|
|
614
|
+
name: "chant-k8s-argo",
|
|
615
|
+
description: "Argo CD composites — ArgoAppFor, ArgoAppSetForRegions, AppProject scoping, cluster registration, and how a deploy splits between Argo and a chant Op",
|
|
616
|
+
triggers: [
|
|
617
|
+
{ type: "context", value: "argo" },
|
|
618
|
+
{ type: "context", value: "argo cd" },
|
|
619
|
+
{ type: "context", value: "argocd" },
|
|
620
|
+
{ type: "context", value: "gitops" },
|
|
621
|
+
{ type: "context", value: "application" },
|
|
622
|
+
{ type: "context", value: "applicationset" },
|
|
623
|
+
{ type: "context", value: "appproject" },
|
|
624
|
+
{ type: "context", value: "reconcile" },
|
|
625
|
+
],
|
|
626
|
+
parameters: [],
|
|
627
|
+
examples: [
|
|
628
|
+
{
|
|
629
|
+
title: "Application from a build target",
|
|
630
|
+
description: "Reconcile a Chant build target with Argo CD",
|
|
631
|
+
input: "Deploy my api target through Argo CD",
|
|
632
|
+
output: "import { ArgoAppFor } from \"@intentius/chant-lexicon-k8s\";\n\nexport const api = ArgoAppFor(\"api\", {\n repo: \"https://github.com/acme/infra\",\n path: \"dist/api\",\n destination: { server: \"https://kubernetes.default.svc\", namespace: \"api\" },\n});",
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
title: "Per-region ApplicationSet",
|
|
636
|
+
description: "Fan one app out across regional clusters",
|
|
637
|
+
input: "Deploy crdb to east, central, and west clusters via Argo",
|
|
638
|
+
output: "import { ArgoAppSetForRegions } from \"@intentius/chant-lexicon-k8s\";\n\nexport const crdb = ArgoAppSetForRegions(\n [\"east\", \"central\", \"west\"],\n (region) => ({ server: servers[region], namespace: `crdb-${region}`, path: `dist/${region}` }),\n { name: \"crdb\", repo: \"https://github.com/acme/infra\", project: \"crdb\" },\n);",
|
|
639
|
+
},
|
|
640
|
+
],
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
file: "chant-k8s-flux.md",
|
|
644
|
+
name: "chant-k8s-flux",
|
|
645
|
+
description: "Flux CD composites — FluxGitSource + FluxAppFor, the one-source-many-apps shape, dependsOn ordering, the FLUX rules, and the flux-reconcile deploy step",
|
|
646
|
+
triggers: [
|
|
647
|
+
{ type: "context", value: "flux" },
|
|
648
|
+
{ type: "context", value: "fluxcd" },
|
|
649
|
+
{ type: "context", value: "flux cd" },
|
|
650
|
+
{ type: "context", value: "gitops" },
|
|
651
|
+
{ type: "context", value: "gitrepository" },
|
|
652
|
+
{ type: "context", value: "kustomization" },
|
|
653
|
+
{ type: "context", value: "source-controller" },
|
|
654
|
+
{ type: "context", value: "kustomize-controller" },
|
|
655
|
+
{ type: "context", value: "reconcile" },
|
|
656
|
+
],
|
|
657
|
+
parameters: [],
|
|
658
|
+
examples: [
|
|
659
|
+
{
|
|
660
|
+
title: "Source + Kustomization from a build target",
|
|
661
|
+
description: "Reconcile a Chant build target with Flux",
|
|
662
|
+
input: "Deploy my app through Flux",
|
|
663
|
+
output: "import { FluxGitSource, FluxAppFor } from \"@intentius/chant-lexicon-k8s\";\n\nexport const source = FluxGitSource(\"infra\", {\n url: \"https://github.com/acme/infra\",\n branch: \"main\",\n});\n\nexport const app = FluxAppFor(\"app\", {\n source,\n path: \"./dist/apps/app\",\n dependsOn: [\"platform\"],\n});",
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
title: "One source, many apps",
|
|
667
|
+
description: "The multi-app repo shape — one GitRepository shared by every Kustomization",
|
|
668
|
+
input: "Reconcile platform, api, and web from one repo with ordering",
|
|
669
|
+
output: "import { FluxGitSource, FluxAppFor } from \"@intentius/chant-lexicon-k8s\";\n\nconst source = FluxGitSource(\"infra\", { url: \"https://github.com/acme/infra\" });\n\nexport const platform = FluxAppFor(\"platform\", { source, path: \"./dist/platform\" });\nexport const api = FluxAppFor(\"api\", { source, path: \"./dist/apps/api\", dependsOn: [\"platform\"] });\nexport const web = FluxAppFor(\"web\", { source, path: \"./dist/apps/web\", dependsOn: [\"platform\", \"api\"] });",
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
},
|
|
673
|
+
]),
|
|
674
|
+
async describeResources(options) {
|
|
675
|
+
const { describeResources } = await import("./describe-resources.js");
|
|
676
|
+
return describeResources(options);
|
|
677
|
+
},
|
|
678
|
+
/**
|
|
679
|
+
* Who chant would act as in this cluster, before it acts (#1982) — the
|
|
680
|
+
* connector's own context/credential resolution plus the API server's
|
|
681
|
+
* `SelfSubjectReview`, reported through the same connect path the read uses
|
|
682
|
+
* so the cluster named is the cluster read. Implementation in ./whoami.ts.
|
|
683
|
+
*/
|
|
684
|
+
async describeIdentity(options) {
|
|
685
|
+
const { describeIdentity } = await import("./whoami.js");
|
|
686
|
+
return describeIdentity(options);
|
|
687
|
+
},
|
|
688
|
+
// Env teardown (#1222): enumeration + execution over the marker label
|
|
689
|
+
// selector (managed-by + stack + env), through the same typed client the
|
|
690
|
+
// prune uses. Execution deletes namespaces last. See ./teardown.ts.
|
|
691
|
+
async teardownOwned(options) {
|
|
692
|
+
const { teardownOwned } = await import("./teardown.js");
|
|
693
|
+
return teardownOwned(options);
|
|
694
|
+
},
|
|
695
|
+
async executeTeardown(options) {
|
|
696
|
+
const { executeTeardown } = await import("./teardown.js");
|
|
697
|
+
return executeTeardown(options);
|
|
698
|
+
},
|
|
699
|
+
/**
|
|
700
|
+
* Deploy-unit presence + health for `chant components status --live`
|
|
701
|
+
* (#1495 piece 3): a Kubernetes deploy unit is the label selector chant's
|
|
702
|
+
* own serializer stamps, so this reads back
|
|
703
|
+
* `app.kubernetes.io/managed-by=chant, chant.intentius.io/stack=<stack>`
|
|
704
|
+
* and rolls readiness up from the matching workloads' controllers.
|
|
705
|
+
*/
|
|
706
|
+
async describeStackStatus(options) {
|
|
707
|
+
const { describeStackStatus } = await import("./describe-stack-status.js");
|
|
708
|
+
return describeStackStatus(options);
|
|
709
|
+
},
|
|
710
|
+
async exportResources(options) {
|
|
711
|
+
const { exportResources } = await import("./export-resources.js");
|
|
712
|
+
return exportResources(options);
|
|
713
|
+
},
|
|
714
|
+
/**
|
|
715
|
+
* The change signal (#1981). A Watch on every declared kind, reported as a
|
|
716
|
+
* bare `onChange()` that wakes an operator tick early. Nothing a frame
|
|
717
|
+
* carries reaches the tick: the seam has no payload, and the tick that runs
|
|
718
|
+
* is the tick the timer would have run. Kubernetes is the one substrate
|
|
719
|
+
* chant reaches whose change stream needs nothing deployed into the observed
|
|
720
|
+
* cluster; see the verdict table in the operator guide. Implementation in
|
|
721
|
+
* ./subscribe-changes.ts, dynamically imported for the same reason
|
|
722
|
+
* describeResources is.
|
|
723
|
+
*/
|
|
724
|
+
async subscribeChanges(options) {
|
|
725
|
+
const { subscribeChanges } = await import("./subscribe-changes.js");
|
|
726
|
+
return subscribeChanges(options);
|
|
727
|
+
},
|
|
728
|
+
// Property-level live drift via SSA managed-fields (#1076, epic #1073).
|
|
729
|
+
// The reader lives in ./deep-observe.ts, loaded only through this dynamic
|
|
730
|
+
// import — same reason describeResources/exportResources are — so the API
|
|
731
|
+
// client never becomes reachable from the build path (chant #1074,
|
|
732
|
+
// examples/k8s-client-boundary.test.ts). deepNormalizationHooks is plain
|
|
733
|
+
// data with no client dependency (./deep-observe-hooks.ts) and is imported
|
|
734
|
+
// statically above, because core applies it to the *declared* tree whether
|
|
735
|
+
// or not a live read ever happens.
|
|
736
|
+
async observeResourcesDeep(options) {
|
|
737
|
+
const { observeResourcesDeepK8s } = await import("./deep-observe.js");
|
|
738
|
+
return observeResourcesDeepK8s(options);
|
|
739
|
+
},
|
|
740
|
+
deepNormalizationHooks: k8sDeepNormalizationHooks,
|
|
741
|
+
};
|