@intentius/chant-lexicon-k8s 0.124.30 → 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.
Files changed (270) hide show
  1. package/dist/actions/apps.js +18 -0
  2. package/dist/actions/batch.js +6 -0
  3. package/dist/actions/core.js +48 -0
  4. package/dist/actions/index.js +13 -0
  5. package/dist/actions/networking.js +11 -0
  6. package/dist/actions/rbac.js +8 -0
  7. package/dist/api/classify.js +123 -0
  8. package/dist/api/connect.js +62 -0
  9. package/dist/api/fake-cluster.js +175 -0
  10. package/dist/api/operation-surface.d.ts.map +1 -1
  11. package/dist/api/operation-surface.js +109 -0
  12. package/dist/api/owner-chain.js +100 -0
  13. package/dist/api/sweep-types.js +35 -0
  14. package/dist/behaviour-kinds.js +82 -0
  15. package/dist/codegen/docs-cli.js +2 -0
  16. package/dist/codegen/docs.js +146 -0
  17. package/dist/codegen/generate-cli.js +30 -0
  18. package/dist/codegen/generate-lexicon.js +74 -0
  19. package/dist/codegen/generate-list-map-keys.js +88 -0
  20. package/dist/codegen/generate-operations.js +53 -0
  21. package/dist/codegen/generate-typescript.js +124 -0
  22. package/dist/codegen/generate.js +173 -0
  23. package/dist/codegen/naming.js +174 -0
  24. package/dist/codegen/package.js +36 -0
  25. package/dist/codegen/patches.js +88 -0
  26. package/dist/codegen/typecheck.js +4 -0
  27. package/dist/codegen/versions.js +41 -0
  28. package/dist/components/argo-app.js +51 -0
  29. package/dist/components/builders.js +22 -0
  30. package/dist/components/capability-plugin.js +31 -0
  31. package/dist/components/flux-reconcile.js +61 -0
  32. package/dist/components/index.d.ts +1 -1
  33. package/dist/components/index.d.ts.map +1 -1
  34. package/dist/components/index.js +18 -0
  35. package/dist/components/kubectl-apply.d.ts +83 -1
  36. package/dist/components/kubectl-apply.d.ts.map +1 -1
  37. package/dist/components/kubectl-apply.js +274 -0
  38. package/dist/components/kustomize-apply.js +25 -0
  39. package/dist/composites/adot-collector.js +184 -0
  40. package/dist/composites/agic-ingress.js +85 -0
  41. package/dist/composites/aks-external-dns-agent.js +146 -0
  42. package/dist/composites/alb-ingress.js +86 -0
  43. package/dist/composites/argo-app.js +199 -0
  44. package/dist/composites/autoscaled-service.js +174 -0
  45. package/dist/composites/azure-disk-storage-class.js +47 -0
  46. package/dist/composites/azure-file-storage-class.js +48 -0
  47. package/dist/composites/azure-monitor-collector.js +176 -0
  48. package/dist/composites/batch-job.js +139 -0
  49. package/dist/composites/catalog.js +4110 -0
  50. package/dist/composites/cockroachdb-cluster.js +371 -0
  51. package/dist/composites/cockroachdb-region-stack.js +369 -0
  52. package/dist/composites/config-connector-context.js +40 -0
  53. package/dist/composites/configured-app.js +135 -0
  54. package/dist/composites/cron-schedule.js +38 -0
  55. package/dist/composites/cron-workload.js +109 -0
  56. package/dist/composites/ebs-storage-class.js +54 -0
  57. package/dist/composites/efs-storage-class.js +46 -0
  58. package/dist/composites/external-dns-agent.js +122 -0
  59. package/dist/composites/filestore-storage-class.js +49 -0
  60. package/dist/composites/fluent-bit-agent.js +157 -0
  61. package/dist/composites/flux-app.js +156 -0
  62. package/dist/composites/gce-ingress.js +83 -0
  63. package/dist/composites/gce-pd-storage-class.js +49 -0
  64. package/dist/composites/gke-external-dns-agent.js +129 -0
  65. package/dist/composites/gke-fluent-bit-agent.js +165 -0
  66. package/dist/composites/gke-gateway.js +91 -0
  67. package/dist/composites/gke-otel-collector.js +94 -0
  68. package/dist/composites/index.js +51 -0
  69. package/dist/composites/inference-service.js +76 -0
  70. package/dist/composites/irsa-service-account.js +77 -0
  71. package/dist/composites/member-defaults.js +14 -0
  72. package/dist/composites/metrics-server.js +181 -0
  73. package/dist/composites/model.js +92 -0
  74. package/dist/composites/monitored-service.js +152 -0
  75. package/dist/composites/namespace-env.js +114 -0
  76. package/dist/composites/network-isolated-app.js +124 -0
  77. package/dist/composites/node-agent.js +149 -0
  78. package/dist/composites/operator-stack.js +268 -0
  79. package/dist/composites/otel-collector-agent.js +142 -0
  80. package/dist/composites/otel-collector-gateway.js +216 -0
  81. package/dist/composites/otel-collector-node.js +176 -0
  82. package/dist/composites/otel-collector-rbac.js +115 -0
  83. package/dist/composites/otel-collector-shape.js +128 -0
  84. package/dist/composites/otel-collector.js +115 -0
  85. package/dist/composites/otel-operator-collector.js +123 -0
  86. package/dist/composites/ray-cluster.js +378 -0
  87. package/dist/composites/ray-job.js +136 -0
  88. package/dist/composites/ray-service.js +178 -0
  89. package/dist/composites/secure-ingress.js +100 -0
  90. package/dist/composites/security-context.js +1 -0
  91. package/dist/composites/sidecar-app.js +105 -0
  92. package/dist/composites/stateful-app.js +111 -0
  93. package/dist/composites/vllm-serving-runtime.js +114 -0
  94. package/dist/composites/web-app.js +157 -0
  95. package/dist/composites/worker-pool.js +167 -0
  96. package/dist/composites/workload-identity-sa.js +81 -0
  97. package/dist/composites/workload-identity-service-account.js +77 -0
  98. package/dist/config-schema.js +72 -0
  99. package/dist/config.js +59 -0
  100. package/dist/coverage.js +27 -0
  101. package/dist/crd/crd-sources.js +615 -0
  102. package/dist/crd/loader.js +181 -0
  103. package/dist/crd/oci-chart.js +144 -0
  104. package/dist/crd/parser.js +382 -0
  105. package/dist/crd/project-codegen.js +273 -0
  106. package/dist/crd/types.js +7 -0
  107. package/dist/deep-observe-hooks.js +306 -0
  108. package/dist/deep-observe.js +234 -0
  109. package/dist/default-labels.js +87 -0
  110. package/dist/describe-resources.js +699 -0
  111. package/dist/describe-stack-status.js +99 -0
  112. package/dist/detect.js +11 -0
  113. package/dist/effect-receipt-row.js +205 -0
  114. package/dist/export-resources.js +39 -0
  115. package/dist/generated/index.js +1092 -0
  116. package/dist/generated/runtime.js +4 -0
  117. package/dist/group-namespace.js +96 -0
  118. package/dist/import/embedded.js +197 -0
  119. package/dist/import/generator.js +288 -0
  120. package/dist/import/live-export.js +85 -0
  121. package/dist/import/parser.js +204 -0
  122. package/dist/import/testdata/embedded/fixtures.js +60 -0
  123. package/dist/include/entity.js +78 -0
  124. package/dist/include/resolve.js +170 -0
  125. package/dist/index.js +59 -0
  126. package/dist/integrity.json +3 -3
  127. package/dist/kube/apply.js +90 -0
  128. package/dist/kube/connect.js +46 -0
  129. package/dist/kube/delete.js +138 -0
  130. package/dist/kube/describe.js +169 -0
  131. package/dist/kube/events.js +132 -0
  132. package/dist/kube/flags.js +91 -0
  133. package/dist/kube/get.js +159 -0
  134. package/dist/kube/group.js +123 -0
  135. package/dist/kube/logs.js +82 -0
  136. package/dist/kube/project.js +94 -0
  137. package/dist/kube/render.js +227 -0
  138. package/dist/kube/source.js +122 -0
  139. package/dist/kube/target.js +63 -0
  140. package/dist/kube/testing.js +28 -0
  141. package/dist/kube/top.js +99 -0
  142. package/dist/kube/verdict.js +72 -0
  143. package/dist/kube/wait.js +129 -0
  144. package/dist/kustomize/render.js +73 -0
  145. package/dist/kustomize/rendered-entity.js +67 -0
  146. package/dist/kustomize/root.js +68 -0
  147. package/dist/lint/audit-catalog.js +61 -0
  148. package/dist/lint/audit-lineage.js +118 -0
  149. package/dist/lint/post-synth/argo-helpers.js +36 -0
  150. package/dist/lint/post-synth/argo002.js +31 -0
  151. package/dist/lint/post-synth/argo003.js +53 -0
  152. package/dist/lint/post-synth/argo005.js +54 -0
  153. package/dist/lint/post-synth/crd-schema-helpers.d.ts.map +1 -1
  154. package/dist/lint/post-synth/crd-schema-helpers.js +214 -0
  155. package/dist/lint/post-synth/flux002.js +56 -0
  156. package/dist/lint/post-synth/flux003.js +50 -0
  157. package/dist/lint/post-synth/index.js +104 -0
  158. package/dist/lint/post-synth/k8s-helpers.js +186 -0
  159. package/dist/lint/post-synth/monitoring-selection-helpers.js +163 -0
  160. package/dist/lint/post-synth/otel-placement-helpers.js +293 -0
  161. package/dist/lint/post-synth/sops-helpers.js +43 -0
  162. package/dist/lint/post-synth/wk8005.js +44 -0
  163. package/dist/lint/post-synth/wk8006.js +56 -0
  164. package/dist/lint/post-synth/wk8041.js +60 -0
  165. package/dist/lint/post-synth/wk8042.js +36 -0
  166. package/dist/lint/post-synth/wk8101.js +52 -0
  167. package/dist/lint/post-synth/wk8102.js +30 -0
  168. package/dist/lint/post-synth/wk8103.js +33 -0
  169. package/dist/lint/post-synth/wk8104.js +58 -0
  170. package/dist/lint/post-synth/wk8105.js +33 -0
  171. package/dist/lint/post-synth/wk8201.js +44 -0
  172. package/dist/lint/post-synth/wk8202.js +34 -0
  173. package/dist/lint/post-synth/wk8203.js +34 -0
  174. package/dist/lint/post-synth/wk8204.js +71 -0
  175. package/dist/lint/post-synth/wk8205.js +38 -0
  176. package/dist/lint/post-synth/wk8207.js +33 -0
  177. package/dist/lint/post-synth/wk8208.js +33 -0
  178. package/dist/lint/post-synth/wk8209.js +33 -0
  179. package/dist/lint/post-synth/wk8301.js +49 -0
  180. package/dist/lint/post-synth/wk8302.js +34 -0
  181. package/dist/lint/post-synth/wk8303.js +68 -0
  182. package/dist/lint/post-synth/wk8304.js +58 -0
  183. package/dist/lint/post-synth/wk8305.js +96 -0
  184. package/dist/lint/post-synth/wk8306.js +38 -0
  185. package/dist/lint/post-synth/wk8401.js +86 -0
  186. package/dist/lint/post-synth/wk8402.js +31 -0
  187. package/dist/lint/post-synth/wk8403.js +49 -0
  188. package/dist/lint/post-synth/wk8404.js +36 -0
  189. package/dist/lint/post-synth/wk8405.js +65 -0
  190. package/dist/lint/post-synth/wk8406.js +50 -0
  191. package/dist/lint/post-synth/wk8407.js +58 -0
  192. package/dist/lint/post-synth/wk8501.js +36 -0
  193. package/dist/lint/post-synth/wk8502.js +35 -0
  194. package/dist/lint/post-synth/wk8503.js +164 -0
  195. package/dist/lint/post-synth/wk8504.js +20 -0
  196. package/dist/lint/post-synth/wk8505.js +31 -0
  197. package/dist/lint/post-synth/wk8601.js +40 -0
  198. package/dist/lint/post-synth/wk8602.js +120 -0
  199. package/dist/lint/post-synth/wk8603.js +63 -0
  200. package/dist/lint/post-synth/wk8604.js +31 -0
  201. package/dist/lint/post-synth/wk8605.js +124 -0
  202. package/dist/lint/post-synth/wk8606.js +22 -0
  203. package/dist/lint/post-synth/wk8701.js +31 -0
  204. package/dist/lint/post-synth/wk8702.js +37 -0
  205. package/dist/lint/post-synth/wk8703.js +31 -0
  206. package/dist/lint/post-synth/wk8704.js +135 -0
  207. package/dist/lint/post-synth/wk8705.js +38 -0
  208. package/dist/lint/rules/argo-appset-single-project.js +56 -0
  209. package/dist/lint/rules/argo-ast.js +94 -0
  210. package/dist/lint/rules/argo-automated-prune.js +59 -0
  211. package/dist/lint/rules/flux-source-ref-pin.js +44 -0
  212. package/dist/lint/rules/hardcoded-namespace.js +57 -0
  213. package/dist/lint/rules/latest-image-tag.js +103 -0
  214. package/dist/lint/rules/missing-resource-limits.js +85 -0
  215. package/dist/lsp/completions.d.ts.map +1 -1
  216. package/dist/lsp/completions.js +18 -0
  217. package/dist/lsp/hover.d.ts.map +1 -1
  218. package/dist/lsp/hover.js +57 -0
  219. package/dist/manifest-entity.js +71 -0
  220. package/dist/manifest.json +1 -1
  221. package/dist/micro-time.js +49 -0
  222. package/dist/op/activities/apply-diff.d.ts +31 -0
  223. package/dist/op/activities/apply-diff.d.ts.map +1 -0
  224. package/dist/op/activities/apply-diff.js +79 -0
  225. package/dist/op/activities/argo.js +98 -0
  226. package/dist/op/activities/ensure-secret.js +38 -0
  227. package/dist/op/activities/index.js +51 -0
  228. package/dist/op/activities/kubectl.d.ts +64 -0
  229. package/dist/op/activities/kubectl.d.ts.map +1 -1
  230. package/dist/op/activities/kubectl.js +517 -0
  231. package/dist/op/activities/wait-for-ready.js +229 -0
  232. package/dist/op/builders.js +68 -0
  233. package/dist/package-cli.js +21 -0
  234. package/dist/patch/json-patch.js +187 -0
  235. package/dist/patch/rendered-patch.js +94 -0
  236. package/dist/plugin.js +741 -0
  237. package/dist/project-kinds.js +56 -0
  238. package/dist/receipt-store.js +216 -0
  239. package/dist/rules/crd-schema-helpers.ts +2 -1
  240. package/dist/secret-labels.js +33 -0
  241. package/dist/secret-store.js +116 -0
  242. package/dist/serializer.d.ts.map +1 -1
  243. package/dist/serializer.js +578 -0
  244. package/dist/sops/encrypted-secret-file.js +194 -0
  245. package/dist/sops/entity.js +32 -0
  246. package/dist/spec/fetch.js +58 -0
  247. package/dist/spec/parse.js +622 -0
  248. package/dist/subscribe-changes.js +168 -0
  249. package/dist/teardown.js +197 -0
  250. package/dist/telemetry-release.js +86 -0
  251. package/dist/validate-cli.js +17 -0
  252. package/dist/validate.js +47 -0
  253. package/dist/variables.js +34 -0
  254. package/dist/whoami.js +109 -0
  255. package/package.json +12 -12
  256. package/src/api/operation-surface.ts +2 -1
  257. package/src/codegen/package.ts +2 -2
  258. package/src/components/index.ts +3 -0
  259. package/src/components/kubectl-apply-plan.k3d.e2e.test.ts +127 -0
  260. package/src/components/kubectl-apply.test.ts +262 -0
  261. package/src/components/kubectl-apply.ts +341 -12
  262. package/src/deep-observe-hooks.ts +2 -2
  263. package/src/import/roundtrip-build.test.ts +46 -0
  264. package/src/lint/post-synth/crd-schema-helpers.ts +2 -1
  265. package/src/lsp/completions.ts +2 -1
  266. package/src/lsp/hover.ts +2 -1
  267. package/src/op/activities/apply-diff.ts +87 -0
  268. package/src/op/activities/kubectl-plan.test.ts +224 -0
  269. package/src/op/activities/kubectl.ts +204 -16
  270. package/src/serializer.ts +2 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * SecureIngress composite — Ingress + optional cert-manager Certificate.
3
+ *
4
+ * A standalone Ingress with TLS via cert-manager, supporting
5
+ * multiple hosts and paths (unlike the single-path Ingress in WebApp).
6
+ */
7
+ import { Composite, mergeDefaults } from "@intentius/chant";
8
+ import { Ingress, Certificate } from "../generated/index.js";
9
+ /**
10
+ * Create a SecureIngress composite — returns prop objects for
11
+ * an Ingress and optional cert-manager Certificate.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { SecureIngress } from "@intentius/chant-lexicon-k8s";
16
+ *
17
+ * const { ingress, certificate } = SecureIngress({
18
+ * name: "api-ingress",
19
+ * hosts: [
20
+ * {
21
+ * hostname: "api.example.com",
22
+ * paths: [{ path: "/", serviceName: "api", servicePort: 80 }],
23
+ * },
24
+ * ],
25
+ * clusterIssuer: "letsencrypt-prod",
26
+ * ingressClassName: "nginx",
27
+ * });
28
+ * ```
29
+ */
30
+ export const SecureIngress = Composite((props) => {
31
+ const { name, hosts, clusterIssuer, ingressClassName, annotations: extraAnnotations = {}, labels: extraLabels = {}, namespace, defaults: defs, } = props;
32
+ const commonLabels = {
33
+ "app.kubernetes.io/name": name,
34
+ "app.kubernetes.io/managed-by": "chant",
35
+ ...extraLabels,
36
+ };
37
+ const allHostnames = hosts.map((h) => h.hostname);
38
+ const secretName = `${name}-tls`;
39
+ const ingressAnnotations = {
40
+ ...extraAnnotations,
41
+ };
42
+ if (clusterIssuer) {
43
+ ingressAnnotations["cert-manager.io/cluster-issuer"] = clusterIssuer;
44
+ }
45
+ const ingressRules = hosts.map((host) => ({
46
+ host: host.hostname,
47
+ http: {
48
+ paths: host.paths.map((p) => ({
49
+ path: p.path,
50
+ pathType: p.pathType ?? "Prefix",
51
+ backend: {
52
+ service: { name: p.serviceName, port: { number: p.servicePort } },
53
+ },
54
+ })),
55
+ },
56
+ }));
57
+ const hasAnnotations = Object.keys(ingressAnnotations).length > 0;
58
+ const ingress = new Ingress(mergeDefaults({
59
+ metadata: {
60
+ name,
61
+ ...(namespace && { namespace }),
62
+ labels: { ...commonLabels, "app.kubernetes.io/component": "ingress" },
63
+ ...(hasAnnotations && { annotations: ingressAnnotations }),
64
+ },
65
+ spec: {
66
+ ...(ingressClassName && { ingressClassName }),
67
+ rules: ingressRules,
68
+ ...(clusterIssuer && {
69
+ tls: [
70
+ {
71
+ hosts: allHostnames,
72
+ secretName,
73
+ },
74
+ ],
75
+ }),
76
+ },
77
+ }, defs?.ingress));
78
+ const result = { ingress };
79
+ if (clusterIssuer) {
80
+ // A real cert-manager Certificate (the ingress-shim annotation on the Ingress
81
+ // above is also set, so either path issues the cert; the explicit resource
82
+ // makes the cert lifecycle declarable).
83
+ result.certificate = new Certificate(mergeDefaults({
84
+ metadata: {
85
+ name: secretName,
86
+ ...(namespace && { namespace }),
87
+ labels: { ...commonLabels, "app.kubernetes.io/component": "certificate" },
88
+ },
89
+ spec: {
90
+ secretName,
91
+ issuerRef: {
92
+ name: clusterIssuer,
93
+ kind: "ClusterIssuer",
94
+ },
95
+ dnsNames: allHostnames,
96
+ },
97
+ }, defs?.certificate));
98
+ }
99
+ return result;
100
+ }, "SecureIngress");
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,105 @@
1
+ /**
2
+ * SidecarApp composite — multi-container Deployment + Service.
3
+ *
4
+ * Sidecar and init container patterns (envoy proxy, log forwarder,
5
+ * DB migration init). Supports shared volumes between containers.
6
+ */
7
+ import { Composite, mergeDefaults } from "@intentius/chant";
8
+ import { Deployment, Service } from "../generated/index.js";
9
+ /**
10
+ * Create a SidecarApp composite — returns prop objects for
11
+ * a multi-container Deployment and Service.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { SidecarApp } from "@intentius/chant-lexicon-k8s";
16
+ *
17
+ * const { deployment, service } = SidecarApp({
18
+ * name: "api",
19
+ * image: "api:1.0",
20
+ * port: 8080,
21
+ * sidecars: [
22
+ * { name: "envoy", image: "envoyproxy/envoy:v1.28", ports: [{ containerPort: 9901 }] },
23
+ * ],
24
+ * initContainers: [
25
+ * { name: "migrate", image: "api:1.0", command: ["python", "manage.py", "migrate"] },
26
+ * ],
27
+ * sharedVolumes: [{ name: "tmp", emptyDir: {} }],
28
+ * });
29
+ * ```
30
+ */
31
+ export const SidecarApp = Composite((props) => {
32
+ const { name, image, port = 80, replicas = 2, sidecars, initContainers, sharedVolumes, labels: extraLabels = {}, cpuLimit = "500m", memoryLimit = "256Mi", cpuRequest = "100m", memoryRequest = "128Mi", namespace, env, securityContext, defaults: defs, } = props;
33
+ const commonLabels = {
34
+ "app.kubernetes.io/name": name,
35
+ "app.kubernetes.io/managed-by": "chant",
36
+ ...extraLabels,
37
+ };
38
+ // Primary container
39
+ const primaryContainer = {
40
+ name,
41
+ image,
42
+ ports: [{ containerPort: port, name: "http" }],
43
+ resources: {
44
+ limits: { cpu: cpuLimit, memory: memoryLimit },
45
+ requests: { cpu: cpuRequest, memory: memoryRequest },
46
+ },
47
+ ...(env && { env }),
48
+ ...(securityContext && { securityContext }),
49
+ };
50
+ // Sidecar containers
51
+ const sidecarContainers = sidecars.map((sc) => ({
52
+ name: sc.name,
53
+ image: sc.image,
54
+ ...(sc.ports && { ports: sc.ports }),
55
+ ...(sc.resources && { resources: sc.resources }),
56
+ ...(sc.env && { env: sc.env }),
57
+ }));
58
+ // Build volumes from sharedVolumes
59
+ const volumes = sharedVolumes?.map((sv) => {
60
+ if (sv.configMapName) {
61
+ return { name: sv.name, configMap: { name: sv.configMapName } };
62
+ }
63
+ return { name: sv.name, emptyDir: sv.emptyDir ?? {} };
64
+ });
65
+ const podSpec = {
66
+ containers: [primaryContainer, ...sidecarContainers],
67
+ ...(initContainers && {
68
+ initContainers: initContainers.map((ic) => ({
69
+ name: ic.name,
70
+ image: ic.image,
71
+ ...(ic.command && { command: ic.command }),
72
+ ...(ic.args && { args: ic.args }),
73
+ })),
74
+ }),
75
+ ...(volumes && volumes.length > 0 && { volumes }),
76
+ };
77
+ const deployment = new Deployment(mergeDefaults({
78
+ metadata: {
79
+ name,
80
+ ...(namespace && { namespace }),
81
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
82
+ },
83
+ spec: {
84
+ replicas,
85
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
86
+ template: {
87
+ metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
88
+ spec: podSpec,
89
+ },
90
+ },
91
+ }, defs?.deployment));
92
+ const service = new Service(mergeDefaults({
93
+ metadata: {
94
+ name,
95
+ ...(namespace && { namespace }),
96
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
97
+ },
98
+ spec: {
99
+ selector: { "app.kubernetes.io/name": name },
100
+ ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
101
+ type: "ClusterIP",
102
+ },
103
+ }, defs?.service));
104
+ return { deployment, service };
105
+ }, "SidecarApp");
@@ -0,0 +1,111 @@
1
+ /**
2
+ * StatefulApp composite — StatefulSet + headless Service + PVC template.
3
+ *
4
+ * A higher-level construct for deploying stateful applications
5
+ * like databases, caches, and message queues.
6
+ */
7
+ import { Composite, mergeDefaults } from "@intentius/chant";
8
+ import { StatefulSet, Service, PodDisruptionBudget } from "../generated/index.js";
9
+ /**
10
+ * Create a StatefulApp composite — returns prop objects for
11
+ * a StatefulSet and headless Service.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { StatefulApp } from "@intentius/chant-lexicon-k8s";
16
+ *
17
+ * const { statefulSet, service } = StatefulApp({
18
+ * name: "postgres",
19
+ * image: "postgres:16",
20
+ * port: 5432,
21
+ * storageSize: "20Gi",
22
+ * env: [{ name: "POSTGRES_PASSWORD", value: "changeme" }],
23
+ * });
24
+ * ```
25
+ */
26
+ export const StatefulApp = Composite((props) => {
27
+ const { name, image, port = 5432, replicas = 1, storageSize = "10Gi", storageClassName, mountPath = "/data", minAvailable, initContainers, securityContext, terminationGracePeriodSeconds, priorityClassName, labels: extraLabels = {}, cpuLimit = "1", memoryLimit = "1Gi", namespace, env, defaults: defs, } = props;
28
+ const commonLabels = {
29
+ "app.kubernetes.io/name": name,
30
+ "app.kubernetes.io/managed-by": "chant",
31
+ ...extraLabels,
32
+ };
33
+ const container = {
34
+ name,
35
+ image,
36
+ ports: [{ containerPort: port, name: "app" }],
37
+ resources: {
38
+ limits: { cpu: cpuLimit, memory: memoryLimit },
39
+ },
40
+ volumeMounts: [{ name: "data", mountPath }],
41
+ ...(env && { env }),
42
+ ...(securityContext && { securityContext }),
43
+ };
44
+ const podSpec = {
45
+ containers: [container],
46
+ ...(initContainers && {
47
+ initContainers: initContainers.map((ic) => ({
48
+ name: ic.name,
49
+ image: ic.image,
50
+ ...(ic.command && { command: ic.command }),
51
+ ...(ic.args && { args: ic.args }),
52
+ })),
53
+ }),
54
+ ...(terminationGracePeriodSeconds !== undefined && { terminationGracePeriodSeconds }),
55
+ ...(priorityClassName && { priorityClassName }),
56
+ };
57
+ const statefulSet = new StatefulSet(mergeDefaults({
58
+ metadata: {
59
+ name,
60
+ ...(namespace && { namespace }),
61
+ labels: { ...commonLabels, "app.kubernetes.io/component": "database" },
62
+ },
63
+ spec: {
64
+ serviceName: name,
65
+ replicas,
66
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
67
+ template: {
68
+ metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
69
+ spec: podSpec,
70
+ },
71
+ volumeClaimTemplates: [
72
+ {
73
+ metadata: { name: "data" },
74
+ spec: {
75
+ accessModes: ["ReadWriteOnce"],
76
+ ...(storageClassName && { storageClassName }),
77
+ resources: { requests: { storage: storageSize } },
78
+ },
79
+ },
80
+ ],
81
+ },
82
+ }, defs?.statefulSet));
83
+ // Headless service (clusterIP: None) for StatefulSet DNS
84
+ const service = new Service(mergeDefaults({
85
+ metadata: {
86
+ name,
87
+ ...(namespace && { namespace }),
88
+ labels: { ...commonLabels, "app.kubernetes.io/component": "database" },
89
+ },
90
+ spec: {
91
+ selector: { "app.kubernetes.io/name": name },
92
+ ports: [{ port, targetPort: port, protocol: "TCP", name: "app" }],
93
+ clusterIP: "None",
94
+ },
95
+ }, defs?.service));
96
+ const result = { statefulSet, service };
97
+ if (minAvailable !== undefined) {
98
+ result.pdb = new PodDisruptionBudget(mergeDefaults({
99
+ metadata: {
100
+ name,
101
+ ...(namespace && { namespace }),
102
+ labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
103
+ },
104
+ spec: {
105
+ minAvailable,
106
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
107
+ },
108
+ }, defs?.pdb));
109
+ }
110
+ return result;
111
+ }, "StatefulApp");
@@ -0,0 +1,114 @@
1
+ /**
2
+ * VllmServingRuntime composite — KServe ServingRuntime/ClusterServingRuntime
3
+ * running vLLM.
4
+ *
5
+ * Design rule (chant #982, #984): spec-true, not chant-flavored. Props mirror
6
+ * vLLM's real `vllm serve` CLI args — no generic runtime abstraction. KServe's
7
+ * ServingRuntime CRD is the pluggability seam; this composite types vLLM
8
+ * faithfully on top of it, it doesn't invent a wrapper around it.
9
+ *
10
+ * The model itself is not a prop here — an InferenceService (chant #985)
11
+ * references this runtime and supplies storageUri, which KServe mounts at
12
+ * /mnt/models inside the pod. That's the path this composite passes to
13
+ * `vllm serve`.
14
+ */
15
+ import { Composite, mergeDefaults } from "@intentius/chant";
16
+ import { ServingRuntime, ClusterServingRuntime, } from "../generated/index.js";
17
+ /** Build the container args list, in `vllm serve --help` flag order. */
18
+ function buildVllmArgs(props) {
19
+ const { tensorParallelSize, maxModelLen, dtype, quantization, gpuMemoryUtilization, maxNumSeqs, containerArgs = [], } = props;
20
+ const args = [];
21
+ if (tensorParallelSize !== undefined)
22
+ args.push("--tensor-parallel-size", String(tensorParallelSize));
23
+ if (maxModelLen !== undefined)
24
+ args.push("--max-model-len", String(maxModelLen));
25
+ if (dtype !== undefined)
26
+ args.push("--dtype", dtype);
27
+ if (quantization !== undefined)
28
+ args.push("--quantization", quantization);
29
+ if (gpuMemoryUtilization !== undefined)
30
+ args.push("--gpu-memory-utilization", String(gpuMemoryUtilization));
31
+ if (maxNumSeqs !== undefined)
32
+ args.push("--max-num-seqs", String(maxNumSeqs));
33
+ args.push(...containerArgs);
34
+ return args;
35
+ }
36
+ /** Build container resource requests/limits. GPU count maps to nvidia.com/gpu. */
37
+ function buildResources(spec) {
38
+ if (!spec)
39
+ return undefined;
40
+ const base = {};
41
+ if (spec.cpu)
42
+ base.cpu = spec.cpu;
43
+ if (spec.memory)
44
+ base.memory = spec.memory;
45
+ if (spec.gpu)
46
+ base["nvidia.com/gpu"] = String(spec.gpu);
47
+ if (Object.keys(base).length === 0)
48
+ return undefined;
49
+ return { requests: { ...base }, limits: { ...base } };
50
+ }
51
+ /**
52
+ * Create a VllmServingRuntime composite — a KServe ServingRuntime (or, with
53
+ * `clusterScoped: true`, a ClusterServingRuntime) that runs vLLM's OpenAI-
54
+ * compatible server, with vLLM's own flags surfaced as typed props.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { VllmServingRuntime } from "@intentius/chant-lexicon-k8s";
59
+ *
60
+ * const runtime = VllmServingRuntime({
61
+ * name: "vllm-runtime",
62
+ * namespace: "models",
63
+ * image: "vllm/vllm-openai:v0.7.0",
64
+ * tensorParallelSize: 2,
65
+ * maxModelLen: 8192,
66
+ * dtype: "bfloat16",
67
+ * gpuMemoryUtilization: 0.9,
68
+ * resources: { cpu: "8", memory: "32Gi", gpu: 2 },
69
+ * });
70
+ * ```
71
+ */
72
+ export const VllmServingRuntime = Composite((props) => {
73
+ const { name, namespace, clusterScoped = false, image, modelFormat = { name: "vllm", autoSelect: true }, labels: extraLabels = {}, defaults: defs, } = props;
74
+ if (!clusterScoped && !namespace) {
75
+ throw new Error(`VllmServingRuntime("${name}"): namespace is required unless clusterScoped is true.`);
76
+ }
77
+ const commonLabels = {
78
+ "app.kubernetes.io/name": name,
79
+ "app.kubernetes.io/managed-by": "chant",
80
+ "app.kubernetes.io/component": "vllm-serving-runtime",
81
+ ...extraLabels,
82
+ };
83
+ const resources = buildResources(props.resources);
84
+ const spec = {
85
+ supportedModelFormats: [modelFormat],
86
+ containers: [
87
+ {
88
+ name: "kserve-container",
89
+ image,
90
+ command: ["vllm", "serve", "/mnt/models"],
91
+ args: buildVllmArgs(props),
92
+ ports: [{ containerPort: 8000, protocol: "TCP", name: "http1" }],
93
+ ...(resources && { resources }),
94
+ },
95
+ ],
96
+ };
97
+ const servingRuntime = clusterScoped
98
+ ? new ClusterServingRuntime(mergeDefaults({
99
+ metadata: {
100
+ name,
101
+ labels: commonLabels,
102
+ },
103
+ spec,
104
+ }, defs?.servingRuntime))
105
+ : new ServingRuntime(mergeDefaults({
106
+ metadata: {
107
+ name,
108
+ namespace,
109
+ labels: commonLabels,
110
+ },
111
+ spec,
112
+ }, defs?.servingRuntime));
113
+ return { servingRuntime };
114
+ }, "VllmServingRuntime");
@@ -0,0 +1,157 @@
1
+ /**
2
+ * WebApp composite — Deployment + Service + optional Ingress.
3
+ *
4
+ * A higher-level construct for deploying stateless web applications
5
+ * with common defaults (health probes, resource limits, labels).
6
+ */
7
+ import { Composite, mergeDefaults } from "@intentius/chant";
8
+ import { Deployment, Service, Ingress, PodDisruptionBudget } from "../generated/index.js";
9
+ /**
10
+ * Create a WebApp composite — returns declarable instances for
11
+ * a Deployment, Service, and optional Ingress.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { WebApp } from "@intentius/chant-lexicon-k8s";
16
+ *
17
+ * const { deployment, service, ingress } = WebApp({
18
+ * name: "my-app",
19
+ * image: "my-app:1.0",
20
+ * port: 8080,
21
+ * replicas: 3,
22
+ * ingressHost: "my-app.example.com",
23
+ * });
24
+ *
25
+ * export { deployment, service, ingress };
26
+ * ```
27
+ */
28
+ export const WebApp = Composite((props) => {
29
+ const { name, image, port = 80, replicas = 2, labels: extraLabels = {}, cpuLimit = "500m", memoryLimit = "256Mi", cpuRequest = "100m", memoryRequest = "128Mi", namespace, env, initContainers, securityContext, terminationGracePeriodSeconds, priorityClassName, minAvailable, defaults: defs, } = props;
30
+ const commonLabels = {
31
+ "app.kubernetes.io/name": name,
32
+ "app.kubernetes.io/managed-by": "chant",
33
+ ...extraLabels,
34
+ };
35
+ const container = {
36
+ name,
37
+ image,
38
+ ports: [{ containerPort: port, name: "http" }],
39
+ resources: {
40
+ limits: { cpu: cpuLimit, memory: memoryLimit },
41
+ requests: { cpu: cpuRequest, memory: memoryRequest },
42
+ },
43
+ livenessProbe: {
44
+ httpGet: { path: "/", port },
45
+ initialDelaySeconds: 10,
46
+ periodSeconds: 10,
47
+ },
48
+ readinessProbe: {
49
+ httpGet: { path: "/", port },
50
+ initialDelaySeconds: 5,
51
+ periodSeconds: 5,
52
+ },
53
+ ...(env && { env }),
54
+ ...(securityContext && { securityContext }),
55
+ };
56
+ const podSpec = {
57
+ containers: [container],
58
+ ...(initContainers && {
59
+ initContainers: initContainers.map((ic) => ({
60
+ name: ic.name,
61
+ image: ic.image,
62
+ ...(ic.command && { command: ic.command }),
63
+ ...(ic.args && { args: ic.args }),
64
+ })),
65
+ }),
66
+ ...(terminationGracePeriodSeconds !== undefined && { terminationGracePeriodSeconds }),
67
+ ...(priorityClassName && { priorityClassName }),
68
+ };
69
+ const deployment = new Deployment(mergeDefaults({
70
+ metadata: {
71
+ name,
72
+ ...(namespace && { namespace }),
73
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
74
+ },
75
+ spec: {
76
+ replicas,
77
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
78
+ template: {
79
+ metadata: { labels: { "app.kubernetes.io/name": name, ...extraLabels } },
80
+ spec: podSpec,
81
+ },
82
+ },
83
+ }, defs?.deployment));
84
+ const service = new Service(mergeDefaults({
85
+ metadata: {
86
+ name,
87
+ ...(namespace && { namespace }),
88
+ labels: { ...commonLabels, "app.kubernetes.io/component": "server" },
89
+ },
90
+ spec: {
91
+ selector: { "app.kubernetes.io/name": name },
92
+ ports: [{ port: 80, targetPort: port, protocol: "TCP", name: "http" }],
93
+ type: "ClusterIP",
94
+ },
95
+ }, defs?.service));
96
+ const result = { deployment, service };
97
+ if (props.ingressHost) {
98
+ // Build paths — use ingressPaths if provided, otherwise default single "/"
99
+ const paths = props.ingressPaths
100
+ ? props.ingressPaths.map((p) => ({
101
+ path: p.path,
102
+ pathType: p.pathType ?? "Prefix",
103
+ backend: {
104
+ service: {
105
+ name: p.serviceName ?? name,
106
+ port: { number: p.servicePort ?? 80 },
107
+ },
108
+ },
109
+ }))
110
+ : [
111
+ {
112
+ path: "/",
113
+ pathType: "Prefix",
114
+ backend: {
115
+ service: { name, port: { number: 80 } },
116
+ },
117
+ },
118
+ ];
119
+ result.ingress = new Ingress(mergeDefaults({
120
+ metadata: {
121
+ name,
122
+ ...(namespace && { namespace }),
123
+ labels: { ...commonLabels, "app.kubernetes.io/component": "ingress" },
124
+ },
125
+ spec: {
126
+ rules: [
127
+ {
128
+ host: props.ingressHost,
129
+ http: { paths },
130
+ },
131
+ ],
132
+ ...(props.ingressTlsSecret && {
133
+ tls: [
134
+ {
135
+ hosts: [props.ingressHost],
136
+ secretName: props.ingressTlsSecret,
137
+ },
138
+ ],
139
+ }),
140
+ },
141
+ }, defs?.ingress));
142
+ }
143
+ if (minAvailable !== undefined) {
144
+ result.pdb = new PodDisruptionBudget(mergeDefaults({
145
+ metadata: {
146
+ name,
147
+ ...(namespace && { namespace }),
148
+ labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
149
+ },
150
+ spec: {
151
+ minAvailable,
152
+ selector: { matchLabels: { "app.kubernetes.io/name": name } },
153
+ },
154
+ }, defs?.pdb));
155
+ }
156
+ return result;
157
+ }, "WebApp");