@intentius/chant-lexicon-k8s 0.30.0 → 0.32.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/classify.d.ts +65 -0
- package/dist/api/classify.d.ts.map +1 -0
- package/dist/api/connect.d.ts +58 -0
- package/dist/api/connect.d.ts.map +1 -0
- package/dist/api/fake-cluster.d.ts +55 -0
- package/dist/api/fake-cluster.d.ts.map +1 -0
- package/dist/api/operation-surface.d.ts +64 -0
- package/dist/api/operation-surface.d.ts.map +1 -0
- package/dist/api/owner-chain.d.ts +46 -0
- package/dist/api/owner-chain.d.ts.map +1 -0
- package/dist/api/sweep-types.d.ts +17 -0
- package/dist/api/sweep-types.d.ts.map +1 -0
- package/dist/codegen/generate-operations.d.ts +29 -0
- package/dist/codegen/generate-operations.d.ts.map +1 -0
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/crd/parser.d.ts.map +1 -1
- package/dist/crd/types.d.ts +7 -0
- package/dist/crd/types.d.ts.map +1 -1
- package/dist/deep-observe-hooks.d.ts +86 -0
- package/dist/deep-observe-hooks.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +146 -0
- package/dist/deep-observe.d.ts.map +1 -0
- package/dist/describe-resources.d.ts +58 -26
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/export-resources.d.ts +31 -1
- package/dist/export-resources.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/kube/apply.d.ts +26 -0
- package/dist/kube/apply.d.ts.map +1 -0
- package/dist/kube/connect.d.ts +30 -0
- package/dist/kube/connect.d.ts.map +1 -0
- package/dist/kube/delete.d.ts +27 -0
- package/dist/kube/delete.d.ts.map +1 -0
- package/dist/kube/describe.d.ts +19 -0
- package/dist/kube/describe.d.ts.map +1 -0
- package/dist/kube/events.d.ts +34 -0
- package/dist/kube/events.d.ts.map +1 -0
- package/dist/kube/flags.d.ts +40 -0
- package/dist/kube/flags.d.ts.map +1 -0
- package/dist/kube/get.d.ts +21 -0
- package/dist/kube/get.d.ts.map +1 -0
- package/dist/kube/group.d.ts +19 -0
- package/dist/kube/group.d.ts.map +1 -0
- package/dist/kube/logs.d.ts +16 -0
- package/dist/kube/logs.d.ts.map +1 -0
- package/dist/kube/project.d.ts +59 -0
- package/dist/kube/project.d.ts.map +1 -0
- package/dist/kube/render.d.ts +75 -0
- package/dist/kube/render.d.ts.map +1 -0
- package/dist/kube/source.d.ts +19 -0
- package/dist/kube/source.d.ts.map +1 -0
- package/dist/kube/target.d.ts +52 -0
- package/dist/kube/target.d.ts.map +1 -0
- package/dist/kube/testing.d.ts +21 -0
- package/dist/kube/testing.d.ts.map +1 -0
- package/dist/kube/top.d.ts +23 -0
- package/dist/kube/top.d.ts.map +1 -0
- package/dist/kube/verdict.d.ts +45 -0
- package/dist/kube/verdict.d.ts.map +1 -0
- package/dist/kube/wait.d.ts +23 -0
- package/dist/kube/wait.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/index.d.ts +7 -4
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/kubectl.d.ts +120 -2
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/op/activities/wait-for-ready.d.ts +30 -3
- package/dist/op/activities/wait-for-ready.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/spec/parse.d.ts +42 -0
- package/dist/spec/parse.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/api/classify.test.ts +133 -0
- package/src/api/classify.ts +144 -0
- package/src/api/connect.ts +104 -0
- package/src/api/fake-cluster.ts +218 -0
- package/src/api/operation-surface.test.ts +116 -0
- package/src/api/operation-surface.ts +129 -0
- package/src/api/owner-chain.test.ts +171 -0
- package/src/api/owner-chain.ts +144 -0
- package/src/api/sweep-types.ts +36 -0
- package/src/codegen/generate-operations.ts +56 -0
- package/src/codegen/generate.ts +9 -0
- package/src/config.ts +17 -0
- package/src/crd/parser.ts +8 -0
- package/src/crd/types.ts +7 -0
- package/src/deep-observe-hooks.ts +125 -0
- package/src/deep-observe.test.ts +668 -0
- package/src/deep-observe.ts +299 -0
- package/src/describe-resources.test.ts +619 -191
- package/src/describe-resources.ts +218 -117
- package/src/export-resources-io.test.ts +76 -51
- package/src/export-resources.ts +47 -35
- package/src/generated/operations.json +2156 -0
- package/src/kube/apply.test.ts +105 -0
- package/src/kube/apply.ts +101 -0
- package/src/kube/connect.ts +54 -0
- package/src/kube/delete.test.ts +123 -0
- package/src/kube/delete.ts +174 -0
- package/src/kube/describe.test.ts +106 -0
- package/src/kube/describe.ts +195 -0
- package/src/kube/events.test.ts +115 -0
- package/src/kube/events.ts +160 -0
- package/src/kube/flags.test.ts +65 -0
- package/src/kube/flags.ts +114 -0
- package/src/kube/get.test.ts +195 -0
- package/src/kube/get.ts +190 -0
- package/src/kube/group.test.ts +33 -0
- package/src/kube/group.ts +125 -0
- package/src/kube/logs.test.ts +126 -0
- package/src/kube/logs.ts +96 -0
- package/src/kube/project.test.ts +57 -0
- package/src/kube/project.ts +106 -0
- package/src/kube/render.test.ts +142 -0
- package/src/kube/render.ts +252 -0
- package/src/kube/source.test.ts +138 -0
- package/src/kube/source.ts +139 -0
- package/src/kube/target.test.ts +67 -0
- package/src/kube/target.ts +89 -0
- package/src/kube/testing.ts +42 -0
- package/src/kube/top.test.ts +149 -0
- package/src/kube/top.ts +120 -0
- package/src/kube/verdict.test.ts +48 -0
- package/src/kube/verdict.ts +77 -0
- package/src/kube/wait.test.ts +125 -0
- package/src/kube/wait.ts +160 -0
- package/src/lifecycle-integration.test.ts +132 -92
- package/src/op/activities/index.ts +7 -3
- package/src/op/activities/kubectl.test.ts +420 -0
- package/src/op/activities/kubectl.ts +379 -13
- package/src/op/activities/wait-for-ready.test.ts +94 -0
- package/src/op/activities/wait-for-ready.ts +66 -15
- package/src/plugin.test.ts +58 -1
- package/src/plugin.ts +29 -0
- package/src/spec/parse.ts +93 -1
|
@@ -1,34 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cross-lexicon lifecycle integration (#163) — Kubernetes row.
|
|
3
3
|
*
|
|
4
|
-
* Drives the REAL k8sPlugin through core's live-import driver and the
|
|
5
|
-
* path, with the
|
|
4
|
+
* Drives the REAL k8sPlugin through core's live-import driver and the
|
|
5
|
+
* changeset path, with the cluster edge faked at
|
|
6
|
+
* `@kubernetes/client-node`'s request layer (chant #1074, previously at
|
|
7
|
+
* `kubectl`). The plugin's own `describeResources` / `exportResources` are what
|
|
8
|
+
* run; only the socket is replaced, and only a literal kubeconfig is ever read.
|
|
6
9
|
*/
|
|
7
10
|
import { describe, test, expect, vi, beforeEach } from "vitest";
|
|
8
11
|
import { mkdtempSync, rmSync, readdirSync, readFileSync } from "node:fs";
|
|
9
12
|
import { tmpdir } from "node:os";
|
|
10
13
|
import { join } from "node:path";
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The plugin reaches the cluster through `./api/connect`'s default connector,
|
|
17
|
+
* which is the one thing a test must not let run for real: it would read the
|
|
18
|
+
* developer's kubeconfig. Replacing the module swaps in a connector backed by
|
|
19
|
+
* `fakeCluster`, which still builds a real client over a literal kubeconfig.
|
|
20
|
+
*/
|
|
21
|
+
const clusterState: { objects: Record<string, unknown>; fail?: (path: string) => { status: number; body: unknown } | undefined } = {
|
|
22
|
+
objects: {},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
vi.mock("./api/connect", async () => {
|
|
26
|
+
const { fakeCluster } = await import("./api/fake-cluster");
|
|
15
27
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const r = execMock(cmd);
|
|
22
|
-
queueMicrotask(() =>
|
|
23
|
-
r instanceof Error
|
|
24
|
-
? cb(r, { stdout: "", stderr: "" })
|
|
25
|
-
: cb(null, r as { stdout: string; stderr: string }),
|
|
26
|
-
);
|
|
27
|
-
},
|
|
28
|
+
defaultK8sConnector: (options: unknown) =>
|
|
29
|
+
fakeCluster({
|
|
30
|
+
objects: clusterState.objects as never,
|
|
31
|
+
respond: (req) => clusterState.fail?.(req.path),
|
|
32
|
+
}).connector(options as never),
|
|
28
33
|
};
|
|
29
34
|
});
|
|
30
35
|
|
|
31
36
|
const { k8sPlugin } = await import("./plugin");
|
|
37
|
+
const { objectKey } = await import("./api/fake-cluster");
|
|
38
|
+
const { statusBody } = await import("@intentius/chant-k8s-client/testing");
|
|
32
39
|
const { liveImportFromPlugins } = await import("@intentius/chant/cli/commands/import");
|
|
33
40
|
const { buildChangeSet } = await import("@intentius/chant/lifecycle/change-set");
|
|
34
41
|
const { normalizeObservation } = await import("@intentius/chant/observation");
|
|
@@ -42,24 +49,24 @@ const liveDeployment = {
|
|
|
42
49
|
spec: { replicas: 3, selector: { matchLabels: { app: "web" } } },
|
|
43
50
|
};
|
|
44
51
|
|
|
45
|
-
const
|
|
52
|
+
const observedWeb = {
|
|
53
|
+
apiVersion: "apps/v1",
|
|
54
|
+
kind: "Deployment",
|
|
55
|
+
metadata: { name: "web", namespace: "prod", uid: "uid-1" },
|
|
56
|
+
status: { readyReplicas: 3, replicas: 3 },
|
|
57
|
+
};
|
|
46
58
|
|
|
47
59
|
describe("k8s lifecycle integration (#163)", () => {
|
|
48
|
-
beforeEach(() =>
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
clusterState.objects = {};
|
|
62
|
+
clusterState.fail = undefined;
|
|
63
|
+
});
|
|
49
64
|
|
|
50
65
|
test("live-import driver: real exportResources → IR → generated source", async () => {
|
|
51
|
-
|
|
52
|
-
cmd?.includes("get deployment.apps")
|
|
53
|
-
? { stdout: JSON.stringify({ items: [liveDeployment] }), stderr: "" }
|
|
54
|
-
: emptyList,
|
|
55
|
-
);
|
|
66
|
+
clusterState.objects = { [objectKey("apps/v1", "Deployment", "web", "default")]: liveDeployment };
|
|
56
67
|
const output = mkdtempSync(join(tmpdir(), "chant-k8s-li-"));
|
|
57
68
|
try {
|
|
58
|
-
const result = await liveImportFromPlugins([k8sPlugin], {
|
|
59
|
-
environment: "prod",
|
|
60
|
-
output,
|
|
61
|
-
force: true,
|
|
62
|
-
});
|
|
69
|
+
const result = await liveImportFromPlugins([k8sPlugin], { environment: "prod", output, force: true });
|
|
63
70
|
expect(result.success).toBe(true);
|
|
64
71
|
expect(result.generatedFiles.length).toBeGreaterThan(0);
|
|
65
72
|
const all = readdirSync(output)
|
|
@@ -73,17 +80,7 @@ describe("k8s lifecycle integration (#163)", () => {
|
|
|
73
80
|
});
|
|
74
81
|
|
|
75
82
|
test("changeset path: real describeResources → buildChangeSet verdicts", async () => {
|
|
76
|
-
|
|
77
|
-
cmd?.includes("deployment.apps web")
|
|
78
|
-
? {
|
|
79
|
-
stdout: JSON.stringify({
|
|
80
|
-
metadata: { name: "web", namespace: "prod", uid: "uid-1" },
|
|
81
|
-
status: { readyReplicas: 3, replicas: 3 },
|
|
82
|
-
}),
|
|
83
|
-
stderr: "",
|
|
84
|
-
}
|
|
85
|
-
: new Error("not found"),
|
|
86
|
-
);
|
|
83
|
+
clusterState.objects = { [objectKey("apps/v1", "Deployment", "web", "prod")]: observedWeb };
|
|
87
84
|
|
|
88
85
|
const { resources: observedNow } = normalizeObservation(
|
|
89
86
|
await k8sPlugin.describeResources!({
|
|
@@ -97,45 +94,32 @@ describe("k8s lifecycle integration (#163)", () => {
|
|
|
97
94
|
);
|
|
98
95
|
expect(observedNow.web?.type).toBe("K8s::Apps::Deployment");
|
|
99
96
|
|
|
100
|
-
const cs = buildChangeSet("prod", {
|
|
101
|
-
declared: new Set(["webSvc"]),
|
|
102
|
-
observedNow,
|
|
103
|
-
observedThen: undefined,
|
|
104
|
-
});
|
|
97
|
+
const cs = buildChangeSet("prod", { declared: new Set(["webSvc"]), observedNow, observedThen: undefined });
|
|
105
98
|
const byName = Object.fromEntries(cs.entries.map((e) => [e.name, e.action]));
|
|
106
99
|
expect(byName.webSvc).toBe("create");
|
|
107
100
|
expect(byName.web).toBe("adopt");
|
|
108
101
|
|
|
109
|
-
const cs2 = buildChangeSet("prod", {
|
|
110
|
-
declared: new Set(["web"]),
|
|
111
|
-
observedNow,
|
|
112
|
-
observedThen: undefined,
|
|
113
|
-
});
|
|
102
|
+
const cs2 = buildChangeSet("prod", { declared: new Set(["web"]), observedNow, observedThen: undefined });
|
|
114
103
|
expect(cs2.entries.find((e) => e.name === "web")!.action).toBe("noop");
|
|
115
104
|
});
|
|
116
105
|
|
|
117
106
|
/**
|
|
118
|
-
* The #1089 chain, end to end on the real plugin
|
|
119
|
-
*
|
|
120
|
-
*
|
|
107
|
+
* The #1089 chain, end to end on the real plugin. The entity that used to
|
|
108
|
+
* demonstrate it — a CRD with no `KUBECTL_RESOURCE` entry — is no longer a
|
|
109
|
+
* hole, because #1074 removed the map; an RBAC-denied read is what produces
|
|
110
|
+
* a hole now, and it has to survive describe → plan → status the same way.
|
|
121
111
|
*/
|
|
122
|
-
test("tri-state chain: an unreadable
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
status: { readyReplicas: 3, replicas: 3 },
|
|
129
|
-
}),
|
|
130
|
-
stderr: "",
|
|
131
|
-
}
|
|
132
|
-
: new Error('Error from server (NotFound): deployments.apps "gone" not found'),
|
|
133
|
-
);
|
|
112
|
+
test("tri-state chain: an unreadable entity stays unobserved through describe → plan → status (#1089)", async () => {
|
|
113
|
+
clusterState.objects = { [objectKey("apps/v1", "Deployment", "web", "prod")]: observedWeb };
|
|
114
|
+
clusterState.fail = (path) =>
|
|
115
|
+
path.endsWith("/deployments/widget")
|
|
116
|
+
? { status: 403, body: statusBody(403, "Forbidden", 'deployments.apps "widget" is forbidden') }
|
|
117
|
+
: undefined;
|
|
134
118
|
|
|
135
119
|
const entities = new Map([
|
|
136
120
|
["web", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "web", namespace: "prod" } } }],
|
|
137
121
|
["gone", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "gone", namespace: "prod" } } }],
|
|
138
|
-
["widget", { entityType: "K8s::
|
|
122
|
+
["widget", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "widget", namespace: "prod" } } }],
|
|
139
123
|
]);
|
|
140
124
|
|
|
141
125
|
// 1. describe — three declared entities, three different verdicts.
|
|
@@ -148,10 +132,11 @@ describe("k8s lifecycle integration (#163)", () => {
|
|
|
148
132
|
}),
|
|
149
133
|
);
|
|
150
134
|
expect(Object.keys(observed.resources)).toEqual(["web"]);
|
|
151
|
-
expect(observed.unobserved.widget.reason).toBe("
|
|
135
|
+
expect(observed.unobserved.widget.reason).toBe("no-credentials");
|
|
152
136
|
expect(observed.unobserved.gone).toBeUndefined(); // NotFound is an absence
|
|
153
137
|
|
|
154
|
-
// 2. plan — the
|
|
138
|
+
// 2. plan — the unreadable one is `unobserved`; only the confirmed-absent
|
|
139
|
+
// one is a create.
|
|
155
140
|
const cs = buildChangeSet("prod", {
|
|
156
141
|
declared: new Set(entities.keys()),
|
|
157
142
|
observedNow: observed.resources,
|
|
@@ -163,15 +148,64 @@ describe("k8s lifecycle integration (#163)", () => {
|
|
|
163
148
|
|
|
164
149
|
// 3. status — a recorded component whose entity was never read reports
|
|
165
150
|
// `unknown`, not `stale`, and carries no `live` boolean at all.
|
|
166
|
-
const rows = reconcileStatus(
|
|
167
|
-
|
|
168
|
-
|
|
151
|
+
const rows = reconcileStatus(
|
|
152
|
+
"prod",
|
|
153
|
+
[
|
|
154
|
+
{
|
|
155
|
+
component: "widget",
|
|
156
|
+
env: "prod",
|
|
157
|
+
digest: "sha256:abc",
|
|
158
|
+
gitSha: "g",
|
|
159
|
+
runId: "r",
|
|
160
|
+
timestamp: "2026-01-01T00:00:00Z",
|
|
161
|
+
actor: "ci",
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
{ liveEvidence: liveEvidenceFromChangeSet(cs) },
|
|
165
|
+
);
|
|
169
166
|
const widgetRow = rows.find((r) => r.component === "widget")!;
|
|
170
167
|
expect(widgetRow.reconciliation).toBe("unknown");
|
|
171
168
|
expect(widgetRow.live).toBeUndefined();
|
|
172
|
-
expect(widgetRow.unobserved?.reason).toBe("
|
|
169
|
+
expect(widgetRow.unobserved?.reason).toBe("no-credentials");
|
|
173
170
|
expect(widgetRow.detail).toContain("could not be observed");
|
|
174
171
|
});
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* chant #1074's coverage claim, on the real plugin: a CRD that the old path
|
|
175
|
+
* warn-skipped as `unsupported-kind` now reads like anything else.
|
|
176
|
+
*/
|
|
177
|
+
test("a CRD is observed, not skipped (chant #1074)", async () => {
|
|
178
|
+
clusterState.objects = {
|
|
179
|
+
[objectKey("ray.io/v1", "RayCluster", "ml", "ray")]: {
|
|
180
|
+
apiVersion: "ray.io/v1",
|
|
181
|
+
kind: "RayCluster",
|
|
182
|
+
metadata: { name: "ml", namespace: "ray", uid: "uid-ray" },
|
|
183
|
+
status: { phase: "ready" },
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const observed = normalizeObservation(
|
|
188
|
+
await k8sPlugin.describeResources!({
|
|
189
|
+
environment: "prod",
|
|
190
|
+
buildOutput: "",
|
|
191
|
+
entityNames: ["ml"],
|
|
192
|
+
entities: new Map([
|
|
193
|
+
["ml", { entityType: "K8s::Ray::RayCluster", props: { metadata: { name: "ml", namespace: "ray" } } }],
|
|
194
|
+
]),
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
expect(observed.unobserved).toEqual({});
|
|
199
|
+
expect(observed.resources.ml?.physicalId).toBe("uid-ray");
|
|
200
|
+
|
|
201
|
+
const cs = buildChangeSet("prod", {
|
|
202
|
+
declared: new Set(["ml"]),
|
|
203
|
+
observedNow: observed.resources,
|
|
204
|
+
observedThen: undefined,
|
|
205
|
+
unobserved: observed.unobserved,
|
|
206
|
+
});
|
|
207
|
+
expect(cs.entries.find((e) => e.name === "ml")!.action).toBe("noop");
|
|
208
|
+
});
|
|
175
209
|
});
|
|
176
210
|
|
|
177
211
|
// The shared conformance suite (#1089) — every observing lexicon runs it.
|
|
@@ -179,18 +213,22 @@ describeObservationConformance({
|
|
|
179
213
|
lexicon: "k8s",
|
|
180
214
|
scenarios: [
|
|
181
215
|
{
|
|
182
|
-
name: "
|
|
216
|
+
name: "an RBAC-denied read alongside a confirmed absence",
|
|
183
217
|
declared: ["widget", "gone"],
|
|
184
218
|
expectUnobserved: ["widget"],
|
|
185
219
|
expectAbsent: ["gone"],
|
|
186
220
|
run: () => {
|
|
187
|
-
|
|
221
|
+
clusterState.objects = {};
|
|
222
|
+
clusterState.fail = (path) =>
|
|
223
|
+
path.endsWith("/deployments/widget")
|
|
224
|
+
? { status: 403, body: statusBody(403, "Forbidden", "forbidden") }
|
|
225
|
+
: undefined;
|
|
188
226
|
return k8sPlugin.describeResources!({
|
|
189
227
|
environment: "prod",
|
|
190
228
|
buildOutput: "",
|
|
191
229
|
entityNames: ["widget", "gone"],
|
|
192
230
|
entities: new Map([
|
|
193
|
-
["widget", { entityType: "K8s::
|
|
231
|
+
["widget", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "widget" } } }],
|
|
194
232
|
["gone", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "gone" } } }],
|
|
195
233
|
]),
|
|
196
234
|
});
|
|
@@ -201,18 +239,15 @@ describeObservationConformance({
|
|
|
201
239
|
declared: ["web"],
|
|
202
240
|
expectUnobserved: ["web"],
|
|
203
241
|
run: () => {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
);
|
|
242
|
+
clusterState.objects = {};
|
|
243
|
+
clusterState.fail = () => {
|
|
244
|
+
throw new Error("connect ECONNREFUSED 127.0.0.1:6443");
|
|
245
|
+
};
|
|
209
246
|
return k8sPlugin.describeResources!({
|
|
210
247
|
environment: "prod",
|
|
211
248
|
buildOutput: "",
|
|
212
249
|
entityNames: ["web"],
|
|
213
|
-
entities: new Map([
|
|
214
|
-
["web", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "web" } } }],
|
|
215
|
-
]),
|
|
250
|
+
entities: new Map([["web", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "web" } } }]]),
|
|
216
251
|
});
|
|
217
252
|
},
|
|
218
253
|
},
|
|
@@ -221,20 +256,25 @@ describeObservationConformance({
|
|
|
221
256
|
declared: ["web"],
|
|
222
257
|
expectPresent: ["web"],
|
|
223
258
|
run: () => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
259
|
+
clusterState.fail = undefined;
|
|
260
|
+
clusterState.objects = {
|
|
261
|
+
[objectKey("apps/v1", "Deployment", "web", "default")]: {
|
|
262
|
+
apiVersion: "apps/v1",
|
|
263
|
+
kind: "Deployment",
|
|
264
|
+
metadata: {
|
|
265
|
+
name: "web",
|
|
266
|
+
namespace: "default",
|
|
267
|
+
uid: "uid-1",
|
|
268
|
+
labels: { "app.kubernetes.io/managed-by": "chant" },
|
|
269
|
+
},
|
|
227
270
|
status: { readyReplicas: 1, replicas: 1 },
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
}));
|
|
271
|
+
},
|
|
272
|
+
};
|
|
231
273
|
return k8sPlugin.describeResources!({
|
|
232
274
|
environment: "prod",
|
|
233
275
|
buildOutput: "",
|
|
234
276
|
entityNames: ["web"],
|
|
235
|
-
entities: new Map([
|
|
236
|
-
["web", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "web" } } }],
|
|
237
|
-
]),
|
|
277
|
+
entities: new Map([["web", { entityType: "K8s::Apps::Deployment", props: { metadata: { name: "web" } } }]]),
|
|
238
278
|
});
|
|
239
279
|
},
|
|
240
280
|
},
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* k8s Op activities — resolved by the core activity registry when a project's
|
|
3
3
|
* `chant.config.ts` lists the `k8s` lexicon. Relocated from the temporal lexicon
|
|
4
4
|
* (#809) so Kubernetes-facing imperative activities live with their product:
|
|
5
|
-
* - kubectlApply —
|
|
5
|
+
* - kubectlApply — server-side apply a rendered manifest (and, since chant
|
|
6
|
+
* #1075, prune chant-owned objects it no longer declares; `applyManifest`
|
|
7
|
+
* is the same work with a report of what it did, which is what the
|
|
8
|
+
* Temporal lexicon's `nativeApply` dispatcher calls for a kubectl target)
|
|
6
9
|
* - k3dUp / k3dDown — boot/tear down a local k3d cluster
|
|
7
10
|
* - waitForArgoSync — block until an Argo CD Application is Healthy && Synced
|
|
8
11
|
*
|
|
@@ -11,8 +14,8 @@
|
|
|
11
14
|
* dependency-light — it shells out to a CLI and does not import the k8s declarable
|
|
12
15
|
* surface — so a Temporal worker loads it cheaply.
|
|
13
16
|
*/
|
|
14
|
-
export { kubectlApply } from "./kubectl";
|
|
15
|
-
export type { KubectlApplyArgs } from "./kubectl";
|
|
17
|
+
export { kubectlApply, applyManifest, readManifestDocuments } from "./kubectl";
|
|
18
|
+
export type { KubectlApplyArgs, ApplyManifestResult, AppliedRef, ApplyDeleteMode } from "./kubectl";
|
|
16
19
|
|
|
17
20
|
export { k3dUp, k3dDown, k3dUpCommand, k3dDownCommand, k3dExistsCommand } from "./k3d";
|
|
18
21
|
export type { K3dUpArgs, K3dDownArgs } from "./k3d";
|
|
@@ -23,6 +26,7 @@ export type { WaitForArgoSyncArgs, ArgoAppStatus, ArgoStatusFetcher } from "./ar
|
|
|
23
26
|
export {
|
|
24
27
|
waitForReady,
|
|
25
28
|
defaultResourceFetcher,
|
|
29
|
+
apiResourceFetcher,
|
|
26
30
|
ReadinessFailedError,
|
|
27
31
|
readinessFor,
|
|
28
32
|
isReady,
|