@intentius/chant-lexicon-k8s 0.57.0 → 0.58.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/dist/api/sweep-types.d.ts +1 -2
- package/dist/api/sweep-types.d.ts.map +1 -1
- package/dist/composites/operator-stack.d.ts +19 -18
- package/dist/composites/operator-stack.d.ts.map +1 -1
- package/dist/config.d.ts +4 -4
- package/dist/deep-observe-hooks.d.ts +4 -4
- package/dist/deep-observe.d.ts +23 -16
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/export-resources.d.ts +1 -1
- package/dist/integrity.json +3 -3
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-lineage.d.ts +10 -0
- package/dist/lint/audit-lineage.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/argo.d.ts +4 -4
- package/dist/op/activities/argo.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +9 -7
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/kubectl.d.ts +7 -7
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/op/activities/wait-for-ready.d.ts +6 -5
- package/dist/op/activities/wait-for-ready.d.ts.map +1 -1
- package/dist/op/builders.d.ts +13 -13
- package/dist/skills/chant-k8s-argo.md +27 -13
- package/package.json +3 -3
- package/src/api/sweep-types.ts +1 -2
- package/src/composites/composites.test.ts +13 -2
- package/src/composites/operator-stack.ts +22 -20
- package/src/config.ts +4 -4
- package/src/crd/crd-sources.ts +4 -4
- package/src/deep-observe-hooks.ts +4 -4
- package/src/deep-observe.test.ts +219 -46
- package/src/deep-observe.ts +28 -21
- package/src/export-resources.ts +1 -1
- package/src/lint/audit-catalog.ts +5 -1
- package/src/lint/audit-lineage.ts +127 -0
- package/src/op/activities/argo.test.ts +7 -8
- package/src/op/activities/argo.ts +4 -4
- package/src/op/activities/index.ts +9 -7
- package/src/op/activities/kubectl.test.ts +5 -4
- package/src/op/activities/kubectl.ts +52 -67
- package/src/op/activities/wait-for-ready.test.ts +2 -2
- package/src/op/activities/wait-for-ready.ts +7 -7
- package/src/op/builders.ts +13 -13
- package/src/plugin.ts +1 -1
- package/src/serializer.test.ts +26 -0
- package/src/skills/chant-k8s-argo.md +27 -13
package/src/op/builders.ts
CHANGED
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
* earlier step's declared output.
|
|
19
19
|
*
|
|
20
20
|
* `core`'s own `kubectlApply`/`waitForReady`/`ensureSecret` (in
|
|
21
|
-
* `@intentius/chant/op`,
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
21
|
+
* `@intentius/chant/op`, the lexicon-agnostic single-import barrel) are
|
|
22
|
+
* UNCHANGED and produce byte-identical `ActivityStep` output for the same
|
|
23
|
+
* inputs — these are purely additive. Deliberately not swapped into core's
|
|
24
|
+
* barrel: that would make `@intentius/chant` depend on this package (and on
|
|
25
|
+
* helm, for `helmInstall`) at runtime, so a project that never touches
|
|
26
|
+
* Kubernetes would install both just to import anything from `op`. That is
|
|
27
|
+
* exactly the "core stays product-agnostic" property the
|
|
28
28
|
* `op/activities/index.ts` module docs across this repo call out on purpose
|
|
29
|
-
* (activities
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* already depends on; existing `@intentius/chant
|
|
34
|
-
*
|
|
29
|
+
* (activities live in per-product lexicons for this reason; the step-builder
|
|
30
|
+
* layer shouldn't reintroduce the coupling from the other direction). An
|
|
31
|
+
* author who wants the typed surface imports it from here —
|
|
32
|
+
* `@intentius/chant-lexicon-k8s` — which a project using `kubectlApply`
|
|
33
|
+
* already depends on; existing `@intentius/chant/op` imports keep working
|
|
34
|
+
* exactly as before, opting in only if the import is changed.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import {
|
package/src/plugin.ts
CHANGED
|
@@ -632,7 +632,7 @@ const { deployment, service, serviceMonitor, prometheusRule } = MonitoredService
|
|
|
632
632
|
{
|
|
633
633
|
file: "chant-k8s-argo.md",
|
|
634
634
|
name: "chant-k8s-argo",
|
|
635
|
-
description: "Argo CD composites — ArgoAppFor, ArgoAppSetForRegions, AppProject scoping, cluster registration, and
|
|
635
|
+
description: "Argo CD composites — ArgoAppFor, ArgoAppSetForRegions, AppProject scoping, cluster registration, and how a deploy splits between Argo and a chant Op",
|
|
636
636
|
triggers: [
|
|
637
637
|
{ type: "context", value: "argo" },
|
|
638
638
|
{ type: "context", value: "argo cd" },
|
package/src/serializer.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
2
|
import { k8sSerializer } from "./serializer";
|
|
3
3
|
import { DECLARABLE_MARKER } from "@intentius/chant/declarable";
|
|
4
|
+
import { heldElsewhere } from "@intentius/chant";
|
|
4
5
|
import {
|
|
5
6
|
defaultLabels,
|
|
6
7
|
defaultAnnotations,
|
|
@@ -69,6 +70,31 @@ describe("k8sSerializer", () => {
|
|
|
69
70
|
expect(result).toContain("replicas: 2");
|
|
70
71
|
});
|
|
71
72
|
|
|
73
|
+
// #2162 — the honest example the issue names: an HPA owns `spec.replicas`
|
|
74
|
+
// on a Deployment after the first apply. `heldElsewhere()` omits the field
|
|
75
|
+
// from the manifest entirely, every apply, so the API server defaults it
|
|
76
|
+
// once at creation and the HPA is free to write it from there without
|
|
77
|
+
// chant's own apply fighting it back.
|
|
78
|
+
test("a heldElsewhere() replicas field never reaches the manifest", () => {
|
|
79
|
+
const entities = new Map<string, any>();
|
|
80
|
+
entities.set(
|
|
81
|
+
"myApp",
|
|
82
|
+
mockResource("K8s::Apps::Deployment", {
|
|
83
|
+
metadata: { name: "my-app", labels: { app: "my-app" } },
|
|
84
|
+
spec: {
|
|
85
|
+
replicas: heldElsewhere<number>({ by: "hpa", reason: "the autoscaler owns replicas after the first apply" }),
|
|
86
|
+
selector: { matchLabels: { app: "my-app" } },
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const result = k8sSerializer.serialize(entities);
|
|
92
|
+
expect(result).toContain("kind: Deployment");
|
|
93
|
+
expect(result).toContain("selector:");
|
|
94
|
+
expect(result).not.toContain("replicas");
|
|
95
|
+
expect(result).not.toContain("heldElsewhere");
|
|
96
|
+
});
|
|
97
|
+
|
|
72
98
|
test("metadata.name auto-generated from logical name (camelCase→kebab-case)", () => {
|
|
73
99
|
const entities = new Map<string, any>();
|
|
74
100
|
entities.set(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
skill: chant-k8s-argo
|
|
3
|
-
description: Argo CD composites for GitOps reconciliation — ArgoAppFor, ArgoAppSetForRegions, AppProject scoping, cluster registration, and
|
|
3
|
+
description: Argo CD composites for GitOps reconciliation — ArgoAppFor, ArgoAppSetForRegions, AppProject scoping, cluster registration, and how a deploy splits between Argo and a chant Op
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -14,9 +14,9 @@ Chant authors typed infrastructure into manifests. Argo CD continuously reconcil
|
|
|
14
14
|
|---|---|---|
|
|
15
15
|
| **Chant** | Authoring typed infra → manifests | the lexicons |
|
|
16
16
|
| **Argo CD** | Continuously reconciling declarative manifests (the apply layer) | `ArgoAppFor` / `ArgoAppSetForRegions` |
|
|
17
|
-
| **
|
|
17
|
+
| **A chant Op** | Procedural steps Argo can't express: ordering, human gates, one-shot RPCs | an `Op` in the project, plus this lexicon's `waitForArgoSync` |
|
|
18
18
|
|
|
19
|
-
Rule of thumb: **if it's declarative and converges, let Argo reconcile it. If it's a procedure with ordering, gates, or out-of-band steps,
|
|
19
|
+
Rule of thumb: **if it's declarative and converges, let Argo reconcile it. If it's a procedure with ordering, gates, or out-of-band steps, write it as a chant Op and run it from CI or a steward.** Prefer Argo CD over Argo Workflows; the procedural layer stays an Op.
|
|
20
20
|
|
|
21
21
|
## Prerequisites
|
|
22
22
|
|
|
@@ -138,9 +138,9 @@ Produces a `Secret` labelled `argocd.argoproj.io/secret-type: cluster`. After th
|
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
141
|
-
##
|
|
141
|
+
## Splitting a deploy between Argo and an Op
|
|
142
142
|
|
|
143
|
-
When a deploy has both declarative and procedural parts, let each layer own what it's good at. Example
|
|
143
|
+
When a deploy has both declarative and procedural parts, let each layer own what it's good at. Example, the multi-region CockroachDB deploy:
|
|
144
144
|
|
|
145
145
|
| Step | Owner | Why |
|
|
146
146
|
|---|---|---|
|
|
@@ -148,16 +148,30 @@ When a deploy has both declarative and procedural parts, let each layer own what
|
|
|
148
148
|
| Install ESO / operators (Helm) | **Argo** | Declarative Helm source |
|
|
149
149
|
| Apply per-cluster K8s manifests | **Argo** (`ApplicationSet`) | One App per workload cluster |
|
|
150
150
|
| Wait for workloads Healthy | **Argo** (`Health=Healthy`) | Subsumed by Application health |
|
|
151
|
-
| Wait for DNS delegation | **
|
|
152
|
-
| Generate + push TLS certs | **
|
|
153
|
-
| `cockroach init`, configure regions | **
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
| Wait for DNS delegation | **an Op** | Out of band, and a human confirms it |
|
|
152
|
+
| Generate + push TLS certs | **an Op** | One-shot procedure, secrets not in git |
|
|
153
|
+
| `cockroach init`, configure regions | **an Op** | Ordered one-shot RPCs |
|
|
154
|
+
|
|
155
|
+
Argo owns the sync. The Op owns the ordering and the gates: its phases run in
|
|
156
|
+
sequence in one process (`packages/core/src/op/local-executor.ts`), and a `gate`
|
|
157
|
+
step reads the gate ledger, so a run that reaches a gate nobody has approved
|
|
158
|
+
records the pending fact, ends with status `gated` and exits 3. Someone runs
|
|
159
|
+
`chant approve <op> <gate>`, the next run reads the resolution and walks
|
|
160
|
+
through. CI is what runs the Op, on whatever cadence the Op's `schedule`
|
|
161
|
+
names.
|
|
162
|
+
|
|
163
|
+
To make a step wait on Argo, use this lexicon's `waitForArgoSync` activity. It is
|
|
164
|
+
exported from `lexicons/k8s/src/op/activities/index.ts`, and the core activity
|
|
165
|
+
registry resolves it by export name once `k8s` is in the project's `lexicons`.
|
|
166
|
+
Give the step core's `argoSync` profile
|
|
167
|
+
(`packages/core/src/op/activity-profiles.ts`): a 30m timeout, five attempts
|
|
168
|
+
backing off from 10s, and `ArgoSyncFailedError` marked non-retryable so a
|
|
169
|
+
terminally unhealthy Application fails fast instead of polling to the cap.
|
|
156
170
|
|
|
157
171
|
```typescript
|
|
158
|
-
// In
|
|
159
|
-
|
|
160
|
-
//
|
|
172
|
+
// In an Op phase:
|
|
173
|
+
activity("waitForArgoSync", { appName: "east-crdb", namespace: "argocd" }, "argoSync"),
|
|
174
|
+
// Later steps in the phase run once the workloads are Healthy.
|
|
161
175
|
```
|
|
162
176
|
|
|
163
177
|
`waitForArgoSync` is dependency-free — it polls the Application's status (`health=Healthy && sync=Synced`) and never imports the Argo CRD types.
|