@intentius/chant-lexicon-k8s 0.41.1 → 0.41.2
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/connect.d.ts +12 -15
- package/dist/api/connect.d.ts.map +1 -1
- package/dist/components/capability-plugin.d.ts +1 -1
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/api/connect.ts +17 -27
- package/src/components/capability-plugin.ts +4 -2
- package/src/components/kubectl-apply.test.ts +8 -0
- package/src/describe-resources.test.ts +13 -9
package/dist/api/connect.d.ts
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Getting from a chant environment to a live API client — chant #1074.
|
|
3
3
|
*
|
|
4
|
-
* The cluster binding (chant #1100,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* and the refusal it throws on a bound-but-mismatched context still aborts
|
|
8
|
-
* before any resource is touched. What changes is only *how the ambient
|
|
9
|
-
* context is read*: the typed client parses the kubeconfig it is about to use
|
|
10
|
-
* rather than shelling `kubectl config current-context`, so a worker image with
|
|
11
|
-
* no `kubectl` in it can still check the binding. Same question, same three
|
|
4
|
+
* The cluster binding (chant #1100/#1155, revised by #1488):
|
|
5
|
+
* `resolveClusterTarget` in core stays the single resolver, and a declared
|
|
6
|
+
* binding is now *used*, never policed against the ambient context. Two
|
|
12
7
|
* outcomes:
|
|
13
8
|
*
|
|
14
|
-
* - **Bound
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* -
|
|
9
|
+
* - **Bound** — the bound context is passed explicitly to the client,
|
|
10
|
+
* regardless of what `kubectl` is ambiently pointed at. A binding that
|
|
11
|
+
* names a context the kubeconfig does not have fails in the client with an
|
|
12
|
+
* error naming both the context and the `k8s.profiles.<env>.context`
|
|
13
|
+
* binding — never by falling back to ambient. (#1488: the old
|
|
14
|
+
* ambient-mismatch refusal meant any other project's k3d cluster stealing
|
|
15
|
+
* the current-context turned a healthy estate grey with `read-failed` as
|
|
16
|
+
* the only explanation.)
|
|
17
|
+
* - **Unbound** — the kubeconfig's own current-context, with a visible
|
|
21
18
|
* warning naming the environment and the missing binding.
|
|
22
19
|
*/
|
|
23
20
|
import { type ResolvedClusterTarget } from "@intentius/chant/kubectl-context";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/api/connect.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/api/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/E;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAEjF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAiCjC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAWA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAGzG,eAAO,MAAM,iBAAiB;;CAEpB,CAAC;AAEX,eAAO,MAAM,mBAAmB,EAAE,gBAWjC,CAAC"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "78a17d072132b7b47893de81b1df999301d1be900843975f5a60e103a3c328d8",
|
|
5
5
|
"meta.json": "c0b141b882c51483c1d1aead748a0eb171aceca7432edd2a0404b062bf6d7831",
|
|
6
6
|
"types/index.d.ts": "3be2af7494aca94adfa16269cb9c4e7a155529872207a3d70b0c4d39914f9eec",
|
|
7
7
|
"rules/argo-appset-single-project.ts": "afa9f310753aa2d475f35012b13135b2dfaebed2a35d44edbe185ebc07673674",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"skills/chant-k8s-aks.md": "e18f0e2b055f72cd7a37deaf258d7027c2d4d3e286e8fd4975b27a1f981a3ad9",
|
|
51
51
|
"skills/chant-k8s-argo.md": "b1a0b826559d8c5033a479c5781efaf650320f0aee4419d8841170bd3393cea5"
|
|
52
52
|
},
|
|
53
|
-
"composite": "
|
|
53
|
+
"composite": "e70bfcf4c83b1710e7cba2a85484ad2309622b1779279181c1cc8e91eedebe3c"
|
|
54
54
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-k8s",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.2",
|
|
4
4
|
"description": "Kubernetes lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"zod": "^4.3.6",
|
|
87
|
-
"@intentius/chant": "^0.41.
|
|
87
|
+
"@intentius/chant": "^0.41.2",
|
|
88
88
|
"typescript": "^5.9.3"
|
|
89
89
|
}
|
|
90
90
|
}
|
package/src/api/connect.ts
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Getting from a chant environment to a live API client — chant #1074.
|
|
3
3
|
*
|
|
4
|
-
* The cluster binding (chant #1100,
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* and the refusal it throws on a bound-but-mismatched context still aborts
|
|
8
|
-
* before any resource is touched. What changes is only *how the ambient
|
|
9
|
-
* context is read*: the typed client parses the kubeconfig it is about to use
|
|
10
|
-
* rather than shelling `kubectl config current-context`, so a worker image with
|
|
11
|
-
* no `kubectl` in it can still check the binding. Same question, same three
|
|
4
|
+
* The cluster binding (chant #1100/#1155, revised by #1488):
|
|
5
|
+
* `resolveClusterTarget` in core stays the single resolver, and a declared
|
|
6
|
+
* binding is now *used*, never policed against the ambient context. Two
|
|
12
7
|
* outcomes:
|
|
13
8
|
*
|
|
14
|
-
* - **Bound
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* -
|
|
9
|
+
* - **Bound** — the bound context is passed explicitly to the client,
|
|
10
|
+
* regardless of what `kubectl` is ambiently pointed at. A binding that
|
|
11
|
+
* names a context the kubeconfig does not have fails in the client with an
|
|
12
|
+
* error naming both the context and the `k8s.profiles.<env>.context`
|
|
13
|
+
* binding — never by falling back to ambient. (#1488: the old
|
|
14
|
+
* ambient-mismatch refusal meant any other project's k3d cluster stealing
|
|
15
|
+
* the current-context turned a healthy estate grey with `read-failed` as
|
|
16
|
+
* the only explanation.)
|
|
17
|
+
* - **Unbound** — the kubeconfig's own current-context, with a visible
|
|
21
18
|
* warning naming the environment and the missing binding.
|
|
22
19
|
*/
|
|
23
20
|
|
|
@@ -62,7 +59,7 @@ export interface ConnectedClient {
|
|
|
62
59
|
* build a client honoring it.
|
|
63
60
|
*/
|
|
64
61
|
export const defaultK8sConnector: K8sConnector = async (options) => {
|
|
65
|
-
const { createK8sClient
|
|
62
|
+
const { createK8sClient } = await import("@intentius/chant-k8s-client");
|
|
66
63
|
|
|
67
64
|
if (options.context !== undefined) {
|
|
68
65
|
const client = await createK8sClient({
|
|
@@ -82,17 +79,10 @@ export const defaultK8sConnector: K8sConnector = async (options) => {
|
|
|
82
79
|
const k8sConfig = (config as { k8s?: K8sChantConfig }).k8s;
|
|
83
80
|
const execAllowlist = k8sConfig?.execCredentialPlugins;
|
|
84
81
|
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
const target = await resolveClusterTarget(config as Record<string, unknown>, options.environment, "k8s", {
|
|
90
|
-
ambientContext: () =>
|
|
91
|
-
readAmbientContext({
|
|
92
|
-
kubeconfig: options.client?.kubeconfig,
|
|
93
|
-
kubeconfigPath: options.client?.kubeconfigPath,
|
|
94
|
-
}),
|
|
95
|
-
});
|
|
82
|
+
// #1488 — the resolver returns the declared binding (or ambient-with-warning
|
|
83
|
+
// when unbound); it no longer reads the ambient context at all, so no reader
|
|
84
|
+
// is supplied.
|
|
85
|
+
const target = await resolveClusterTarget(config as Record<string, unknown>, options.environment, "k8s");
|
|
96
86
|
|
|
97
87
|
const client = await createK8sClient({
|
|
98
88
|
...options.client,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* components.
|
|
10
10
|
*/
|
|
11
11
|
import type { Capability } from "@intentius/chant/components/capability";
|
|
12
|
-
import type
|
|
12
|
+
import { ownPackageVersion, type CapabilityPlugin } from "@intentius/chant/components/capability-plugin";
|
|
13
13
|
import { kubectlApplyCapability } from "./kubectl-apply";
|
|
14
14
|
|
|
15
15
|
export const K8S_VERB_FAMILIES = {
|
|
@@ -18,7 +18,9 @@ export const K8S_VERB_FAMILIES = {
|
|
|
18
18
|
|
|
19
19
|
export const k8sCapabilityPlugin: CapabilityPlugin = {
|
|
20
20
|
name: "k8s",
|
|
21
|
-
version
|
|
21
|
+
// The lexicon package's own version (#1505) — lockstep releases bump it, so
|
|
22
|
+
// a literal here was stale one release after it was written.
|
|
23
|
+
version: ownPackageVersion(import.meta.url),
|
|
22
24
|
capabilities(): Array<Capability<never, unknown>> {
|
|
23
25
|
return [kubectlApplyCapability as Capability<never, unknown>];
|
|
24
26
|
},
|
|
@@ -9,6 +9,14 @@ describe("kubectl-apply capability (#1495 piece 2)", () => {
|
|
|
9
9
|
expect(kinds).toContain("kubectl-apply");
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
+
test("the plugin's version is the lexicon package's own, not a literal (#1505)", async () => {
|
|
13
|
+
const { readFileSync } = await import("node:fs");
|
|
14
|
+
const { version } = JSON.parse(
|
|
15
|
+
readFileSync(new URL("../../package.json", import.meta.url), "utf-8"),
|
|
16
|
+
) as { version: string };
|
|
17
|
+
expect(k8sCapabilityPlugin.version).toBe(version);
|
|
18
|
+
});
|
|
19
|
+
|
|
12
20
|
test("run delegates to the server-side apply with the component's env and the step's stack", async () => {
|
|
13
21
|
let seen: unknown;
|
|
14
22
|
const cap = createKubectlApplyCapability(async (args) => {
|
|
@@ -420,8 +420,11 @@ describe("k8s describeResources", () => {
|
|
|
420
420
|
expect(result.resources.web).toMatchObject({ type: "K8s::Apps::Deployment", physicalId: "uid-1", status: "READY" });
|
|
421
421
|
});
|
|
422
422
|
|
|
423
|
-
test("bound
|
|
423
|
+
test("bound while a different context is ambient: the binding wins and the estate observes (#1488)", async () => {
|
|
424
424
|
loadChantConfigMock.mockResolvedValue({ config: { k8s: { profiles: { prod: { context: "prod-eks" } } } } });
|
|
425
|
+
// Ambient points at staging — the state any other project's k3d cluster
|
|
426
|
+
// leaves behind. Before #1488 this refused and the whole estate read
|
|
427
|
+
// grey; the declared binding must simply be used instead.
|
|
425
428
|
const ambientIsStaging = fakeKubeconfig({
|
|
426
429
|
contexts: [
|
|
427
430
|
{ name: "prod-eks", cluster: "prod", user: "prod-user" },
|
|
@@ -429,16 +432,17 @@ describe("k8s describeResources", () => {
|
|
|
429
432
|
],
|
|
430
433
|
currentContext: "staging-eks",
|
|
431
434
|
});
|
|
432
|
-
const cluster = fakeCluster({
|
|
435
|
+
const cluster = fakeCluster({
|
|
436
|
+
kubeconfig: ambientIsStaging,
|
|
437
|
+
objects: { [objectKey("apps/v1", "Deployment", "web", "prod")]: web },
|
|
438
|
+
});
|
|
433
439
|
|
|
434
|
-
await
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
).rejects.toThrow(/environment "prod".*"prod-eks".*"staging-eks"/s);
|
|
440
|
+
const result = await describeResources(
|
|
441
|
+
{ environment: "prod", buildOutput: "", entityNames: ["web"], entities: entities() },
|
|
442
|
+
(o) => defaultK8sConnector({ ...o, client: { kubeconfig: ambientIsStaging, requestLayer: cluster.layer } }),
|
|
443
|
+
);
|
|
439
444
|
|
|
440
|
-
|
|
441
|
-
expect(cluster.layer.requests).toHaveLength(0);
|
|
445
|
+
expect(result.resources.web).toMatchObject({ type: "K8s::Apps::Deployment", physicalId: "uid-1", status: "READY" });
|
|
442
446
|
});
|
|
443
447
|
|
|
444
448
|
test("unbound: the kubeconfig's own context is used, and the fallback is visible", async () => {
|