@intentius/chant-lexicon-k8s 0.1.15 → 0.1.17

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "5ba1d1b3a933fa0a69af686d9b421bfeabc9393796b9a0edda924dc33ac4f505",
4
+ "manifest.json": "81c85a3d21213a3ec333100bb65bd5df47009fbb2e55f2d0a519b511b3dbdfef",
5
5
  "meta.json": "b16aba17feef7b62df4057b714b51e34f88330a843d77e3904ea207d6bb073c5",
6
6
  "types/index.d.ts": "be4a0a86c911d4407a22f1c252850d35d87c1234fac46eec8a0aebee248d60f5",
7
7
  "rules/argo-appset-single-project.ts": "afa9f310753aa2d475f35012b13135b2dfaebed2a35d44edbe185ebc07673674",
@@ -32,7 +32,7 @@
32
32
  "rules/wk8207.ts": "e82dbf47e20fc186a105069b5923a8532553f236c58178332f9264f39ac31390",
33
33
  "rules/wk8208.ts": "0e9d654fa70f9ee91de4711df43689fcee4fde831ce0eb0081fdc4753632e9dd",
34
34
  "rules/wk8209.ts": "617324b7988a7c842502c9e76388412c5855dcd321e40a2df6039c9faf87ac47",
35
- "rules/wk8301.ts": "12321c2b217db4a1f8842844e0d9875def589e54056dd66d6c0f4a65e50e1213",
35
+ "rules/wk8301.ts": "b7293376340ae511d6bec1691356558c38e2d42f5823e599125fdce1ddeefea6",
36
36
  "rules/wk8302.ts": "3e8e336e72618b543c3208f9b2b7a582b4535d3d284481cc6c77812c35812e71",
37
37
  "rules/wk8303.ts": "fdf8b072063359d2e654b1e810491738316eae01e85f9d18df1c341578caf2a6",
38
38
  "rules/wk8304.ts": "fd98b1bd1e62713b29af5fbb8e45d8ddf2b8b751eab1819caa9ea813efb9e54d",
@@ -50,5 +50,5 @@
50
50
  "skills/chant-k8s-aks.md": "e18f0e2b055f72cd7a37deaf258d7027c2d4d3e286e8fd4975b27a1f981a3ad9",
51
51
  "skills/chant-k8s-argo.md": "b1a0b826559d8c5033a479c5781efaf650320f0aee4419d8841170bd3393cea5"
52
52
  },
53
- "composite": "bcfebf986465fc20d2904a353b4ca041477fd94e63814d417c1eeba29488c2a0"
53
+ "composite": "44045fb12b92ec20c40832608226bdf313032c40080a56f777fb01861c4bb969"
54
54
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k8s",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "K8s",
6
6
  "intrinsics": [],
@@ -1,9 +1,14 @@
1
1
  /**
2
2
  * WK8301: Probes Required
3
3
  *
4
- * Containers should have both livenessProbe and readinessProbe configured.
5
- * Without probes, Kubernetes cannot detect unhealthy containers or know
6
- * when a container is ready to receive traffic.
4
+ * Containers that expose a port should have both livenessProbe and
5
+ * readinessProbe configured. Without probes, Kubernetes cannot detect
6
+ * unhealthy containers or know when a container is ready to receive traffic.
7
+ *
8
+ * Containers that declare no port (queue/Temporal workers, batch consumers)
9
+ * are exempt: they take no inbound traffic, so there is no endpoint to
10
+ * HTTP-probe and no readiness signal for a Service to gate on. Flagging them
11
+ * would force a placeholder exec probe on a correct, port-less pattern.
7
12
  */
8
13
 
9
14
  import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
@@ -29,6 +34,9 @@ export const wk8301: PostSynthCheck = {
29
34
  const resourceName = manifest.metadata?.name ?? manifest.kind;
30
35
 
31
36
  for (const container of containers) {
37
+ // No declared port → no inbound traffic → nothing to HTTP-probe.
38
+ if (!container.ports || container.ports.length === 0) continue;
39
+
32
40
  const missing: string[] = [];
33
41
  if (!container.livenessProbe) missing.push("livenessProbe");
34
42
  if (!container.readinessProbe) missing.push("readinessProbe");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-k8s",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Kubernetes lexicon for chant — declarative IaC in TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -393,7 +393,7 @@ Post-synth checks run against the serialized YAML after build.
393
393
  | Rule | Description |
394
394
  |------|-------------|
395
395
  | WK8201 | Container missing resource limits |
396
- | WK8301 | Container missing health probes (skips Jobs/CronJobs) |
396
+ | WK8301 | Port-serving container missing health probes (skips Jobs/CronJobs and port-less workers) |
397
397
  | WK8302 | Single replica Deployment |
398
398
  | WK8303 | HA Deployment without PodDisruptionBudget |
399
399
 
@@ -854,7 +854,7 @@ spec:
854
854
  // ── WK8301: Probes required ────────────────────────────────────────
855
855
 
856
856
  describe("WK8301: Probes required", () => {
857
- test("flags container without probes", () => {
857
+ test("flags port-serving container without probes", () => {
858
858
  const ctx = makeCtx(JSON.stringify({
859
859
  apiVersion: "apps/v1",
860
860
  kind: "Deployment",
@@ -862,7 +862,9 @@ describe("WK8301: Probes required", () => {
862
862
  spec: {
863
863
  template: {
864
864
  spec: {
865
- containers: [{ name: "app", image: "app:1.0" }],
865
+ containers: [
866
+ { name: "app", image: "app:1.0", ports: [{ containerPort: 8080 }] },
867
+ ],
866
868
  },
867
869
  },
868
870
  },
@@ -872,6 +874,24 @@ describe("WK8301: Probes required", () => {
872
874
  expect(diags[0].checkId).toBe("WK8301");
873
875
  });
874
876
 
877
+ test("skips port-less worker Deployment (no inbound traffic to probe)", () => {
878
+ const ctx = makeCtx(JSON.stringify({
879
+ apiVersion: "apps/v1",
880
+ kind: "Deployment",
881
+ metadata: { name: "worker" },
882
+ spec: {
883
+ template: {
884
+ spec: {
885
+ // A queue/Temporal worker — long-running, no port, no probes by design.
886
+ containers: [{ name: "worker", image: "worker:1.0" }],
887
+ },
888
+ },
889
+ },
890
+ }));
891
+ const diags = wk8301.check(ctx);
892
+ expect(diags.length).toBe(0);
893
+ });
894
+
875
895
  test("passes with both probes", () => {
876
896
  const ctx = makeCtx(JSON.stringify({
877
897
  apiVersion: "apps/v1",
@@ -884,6 +904,7 @@ describe("WK8301: Probes required", () => {
884
904
  {
885
905
  name: "app",
886
906
  image: "app:1.0",
907
+ ports: [{ containerPort: 8080 }],
887
908
  livenessProbe: { httpGet: { path: "/healthz", port: 8080 } },
888
909
  readinessProbe: { httpGet: { path: "/readyz", port: 8080 } },
889
910
  },
@@ -1,9 +1,14 @@
1
1
  /**
2
2
  * WK8301: Probes Required
3
3
  *
4
- * Containers should have both livenessProbe and readinessProbe configured.
5
- * Without probes, Kubernetes cannot detect unhealthy containers or know
6
- * when a container is ready to receive traffic.
4
+ * Containers that expose a port should have both livenessProbe and
5
+ * readinessProbe configured. Without probes, Kubernetes cannot detect
6
+ * unhealthy containers or know when a container is ready to receive traffic.
7
+ *
8
+ * Containers that declare no port (queue/Temporal workers, batch consumers)
9
+ * are exempt: they take no inbound traffic, so there is no endpoint to
10
+ * HTTP-probe and no readiness signal for a Service to gate on. Flagging them
11
+ * would force a placeholder exec probe on a correct, port-less pattern.
7
12
  */
8
13
 
9
14
  import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
@@ -29,6 +34,9 @@ export const wk8301: PostSynthCheck = {
29
34
  const resourceName = manifest.metadata?.name ?? manifest.kind;
30
35
 
31
36
  for (const container of containers) {
37
+ // No declared port → no inbound traffic → nothing to HTTP-probe.
38
+ if (!container.ports || container.ports.length === 0) continue;
39
+
32
40
  const missing: string[] = [];
33
41
  if (!container.livenessProbe) missing.push("livenessProbe");
34
42
  if (!container.readinessProbe) missing.push("readinessProbe");