@intentius/chant-lexicon-k8s 0.31.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 +10 -0
- package/dist/api/classify.d.ts.map +1 -1
- 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/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 +15 -0
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/export-resources.d.ts +6 -2
- 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 +6 -3
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/kubectl.d.ts +91 -9
- package/dist/op/activities/kubectl.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/api/classify.ts +13 -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/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 +224 -1
- package/src/describe-resources.ts +86 -1
- package/src/export-resources.ts +6 -22
- 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/op/activities/index.ts +6 -3
- package/src/op/activities/kubectl.test.ts +298 -26
- package/src/op/activities/kubectl.ts +313 -20
- package/src/plugin.test.ts +58 -1
- package/src/plugin.ts +29 -0
package/dist/api/classify.d.ts
CHANGED
|
@@ -37,6 +37,16 @@ export type K8sReadOutcome =
|
|
|
37
37
|
};
|
|
38
38
|
/** Classify a failure from the typed client into the observation tri-state. */
|
|
39
39
|
export declare function classifyApiFailure(err: unknown): K8sReadOutcome;
|
|
40
|
+
/**
|
|
41
|
+
* The cluster's own discovery reports no such kind at all — distinct from a
|
|
42
|
+
* kind that exists but currently has zero live instances. `classifyApiFailure`
|
|
43
|
+
* folds both into `absent` for the declared-entity read path, where "no
|
|
44
|
+
* instance can exist" is exactly the signal a `create` needs. `chant kube get`
|
|
45
|
+
* (chant #1079) needs the finer distinction: an ad hoc `chant kube get
|
|
46
|
+
* widgets` against a kind the cluster has never heard of should say so, not
|
|
47
|
+
* print "No resources found." as if `widgets` were a real, empty kind.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isUnknownResource(err: unknown): boolean;
|
|
40
50
|
/**
|
|
41
51
|
* Whether a failure kills the whole observation rather than one entity. A
|
|
42
52
|
* refused binding, a missing client package and a rejected credential plugin
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/api/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,MAAM,cAAc;AACxB,kFAAkF;AAChF;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,4DAA4D;GAC1D;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAuBrE,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAwC/D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK5D;AAED,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,QAEuE,CAAC"}
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/api/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,MAAM,cAAc;AACxB,kFAAkF;AAChF;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,4DAA4D;GAC1D;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAuBrE,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAwC/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK5D;AAED,2DAA2D;AAC3D,eAAO,MAAM,qBAAqB,QAEuE,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolving a live Kubernetes object's `ownerReferences` chain up to a
|
|
3
|
+
* declared, chant-observed entity (chant #1077).
|
|
4
|
+
*
|
|
5
|
+
* There is no server-side "who ultimately owns this object" query — Kubernetes'
|
|
6
|
+
* own garbage collector does not have one either; it walks the same chain one
|
|
7
|
+
* hop at a time, reading each intermediate owner. A Pod's `ownerReferences`
|
|
8
|
+
* names its ReplicaSet, which chant never declared; the ReplicaSet's own
|
|
9
|
+
* `ownerReferences` names the Deployment, which is declared. Reaching that
|
|
10
|
+
* declared entity takes reading the ReplicaSet in between.
|
|
11
|
+
*
|
|
12
|
+
* This module's only job is assembling that chain — fetching each hop through
|
|
13
|
+
* the typed client, bounded and cycle-guarded so a corrupt or adversarial
|
|
14
|
+
* chain cannot hang an observation. The bounded/cycle-safe *interpretation* of
|
|
15
|
+
* the assembled chain (declared / unowned / foreign / unknown) is core's
|
|
16
|
+
* `classifyOwnerChain` (`@intentius/chant/owner-chain`) — the issue's own
|
|
17
|
+
* division of labor: core owns the category, the lexicon supplies the chain.
|
|
18
|
+
*/
|
|
19
|
+
import type { K8sClient, K8sObject } from "@intentius/chant-k8s-client";
|
|
20
|
+
import { type OwnerChainVerdict } from "@intentius/chant/owner-chain";
|
|
21
|
+
/** The client surface this module needs — a single object read, addressed by
|
|
22
|
+
* an owner reference's own coordinates. */
|
|
23
|
+
export type OwnerChainReader = Pick<K8sClient, "readIfPresent">;
|
|
24
|
+
export interface ResolveOwnerChainOptions {
|
|
25
|
+
/** uid → declared chant entity name, from this observation's own resolved entities. */
|
|
26
|
+
declaredByUid: ReadonlyMap<string, string>;
|
|
27
|
+
/** Reads each intermediate owner. */
|
|
28
|
+
reader: OwnerChainReader;
|
|
29
|
+
/**
|
|
30
|
+
* Namespace the starting object lives in. Owner references are same-namespace
|
|
31
|
+
* only — a namespaced object cannot be owned by an object in another
|
|
32
|
+
* namespace, the same rule Kubernetes' own garbage collector enforces —so
|
|
33
|
+
* every hop is read in this namespace.
|
|
34
|
+
*/
|
|
35
|
+
namespace: string | undefined;
|
|
36
|
+
maxDepth?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Walk `obj`'s owner-reference chain up to a declared entity, a foreign root,
|
|
40
|
+
* or a bound (#1077). Fetches at most `maxDepth + 1` objects (the starting
|
|
41
|
+
* object plus up to `maxDepth` ancestors) — the same bound `classifyOwnerChain`
|
|
42
|
+
* enforces when interpreting the result, so nothing is fetched that the
|
|
43
|
+
* interpretation would not have used anyway.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveK8sOwnerChain(obj: K8sObject, options: ResolveOwnerChainOptions): Promise<OwnerChainVerdict>;
|
|
46
|
+
//# sourceMappingURL=owner-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-chain.d.ts","sourceRoot":"","sources":["../../src/api/owner-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AA2BtC;2CAC2C;AAC3C,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACvC,uFAAuF;IACvF,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,qCAAqC;IACrC,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA8D5B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kinds chant sweeps when nothing narrows the question.
|
|
3
|
+
*
|
|
4
|
+
* A *product* decision — what a bare `chant import` should pull back, and
|
|
5
|
+
* (chant #1075) which kinds an ownership-scoped prune has to look at to notice
|
|
6
|
+
* that a whole kind was removed from source. Not an addressing limit: since
|
|
7
|
+
* chant #1074 removed `KUBECTL_RESOURCE`, a `--selector type=<entity type>`
|
|
8
|
+
* import can name any of the ~180 types the generated operation surface
|
|
9
|
+
* carries, CRDs included.
|
|
10
|
+
*
|
|
11
|
+
* It lives in its own module, with no imports of its own, because both
|
|
12
|
+
* consumers reach it from different directions — `../export-resources.ts`
|
|
13
|
+
* pulls in the whole import parser, and a Temporal worker loading the apply
|
|
14
|
+
* activity should not.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_IMPORT_TYPES: readonly string[];
|
|
17
|
+
//# sourceMappingURL=sweep-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweep-types.d.ts","sourceRoot":"","sources":["../../src/api/sweep-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAoBjD,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The k8s lexicon's *static* deep-observation noise rules (#1076, epic #1073).
|
|
3
|
+
*
|
|
4
|
+
* Split out from `./deep-observe.ts` for one reason: this file must be safe
|
|
5
|
+
* to import from `plugin.ts` at module load time, because
|
|
6
|
+
* `LexiconPlugin.deepNormalizationHooks` is plain data core reads to
|
|
7
|
+
* normalize the *declared* tree — the half of the contract that runs whether
|
|
8
|
+
* or not a cluster is ever touched (`lifecycle diff` without `--live`,
|
|
9
|
+
* `chant build`, tests that only exercise normalization). `./deep-observe.ts`
|
|
10
|
+
* itself imports `@intentius/chant-k8s-client` for the live read, and chant
|
|
11
|
+
* #1074 made that package's reachability from the build path a structural
|
|
12
|
+
* property (`examples/k8s-client-boundary.test.ts`) rather than a lint rule —
|
|
13
|
+
* so nothing this file exports may pull that package in, directly or
|
|
14
|
+
* transitively. It imports nothing but the core contract's own types.
|
|
15
|
+
*
|
|
16
|
+
* What lives here is deliberately the *entityType-keyed, resource-agnostic*
|
|
17
|
+
* half of the rules: which fields the API server always populates regardless
|
|
18
|
+
* of what a manager wrote (`status`, `metadata.uid`, …), which fields
|
|
19
|
+
* Kubernetes defaults when a manifest is silent about them, and which arrays
|
|
20
|
+
* are sets addressed by a well-known identity (containers by name, ports by
|
|
21
|
+
* containerPort+protocol). None of that needs a live object in hand.
|
|
22
|
+
*
|
|
23
|
+
* What does *not* live here is the managed-fields prune — whether one
|
|
24
|
+
* specific field on one specific live object is chant-owned, foreign-owned,
|
|
25
|
+
* or contested. That is inherently per-object (it depends on *that* object's
|
|
26
|
+
* `metadata.managedFields`, which the declared tree never carries and which
|
|
27
|
+
* differs between two Deployments of the same type), so it cannot be
|
|
28
|
+
* expressed as a fixed rule keyed only by entity type and path — the shape
|
|
29
|
+
* every other hook in this file takes. `./deep-observe.ts` computes it once
|
|
30
|
+
* per resource and layers it on top of the rules below.
|
|
31
|
+
*
|
|
32
|
+
* The *entity-type-agnostic* half of these rules — which fields every
|
|
33
|
+
* Kubernetes API object carries regardless of kind, and the well-known
|
|
34
|
+
* list-map-key ordering conventions (containers/env/volumes/ports) — lives in
|
|
35
|
+
* `@intentius/chant/managed-fields` (chant #1087), because a GCP Config
|
|
36
|
+
* Connector custom resource is a Kubernetes object too and needs the exact
|
|
37
|
+
* same rules without depending on this lexicon's package. What stays here is
|
|
38
|
+
* only what's genuinely k8s-*lexicon*-specific: {@link K8S_SERVICE_DEFAULTS},
|
|
39
|
+
* keyed by chant's own k8s entityType catalog.
|
|
40
|
+
*/
|
|
41
|
+
import type { DeepNormalizationHooks } from "@intentius/chant/lexicon";
|
|
42
|
+
/**
|
|
43
|
+
* Kubernetes-defaulted fields, per entity type, as index-erased property
|
|
44
|
+
* paths. Subtracted only where source never declared the property
|
|
45
|
+
* (`side === "live" && counterpart === "absent"`) — cdk-real-drift's default
|
|
46
|
+
* subtraction, same convention as AWS/Azure/Temporal's tables.
|
|
47
|
+
*
|
|
48
|
+
* Sparse and evidence-based rather than derived from the generated schema:
|
|
49
|
+
* the k8s OpenAPI spec this lexicon's codegen consumes
|
|
50
|
+
* (`lexicons/k8s/src/spec/parse.ts`) does not carry a `default` value for
|
|
51
|
+
* these fields the way ARM's schema sometimes does, so "per discovery" is not
|
|
52
|
+
* actually expressible today. Widening this table is additive and needs no
|
|
53
|
+
* contract change.
|
|
54
|
+
*
|
|
55
|
+
* `spec.strategy` is listed whole, not as `spec.strategy.type`, for the same
|
|
56
|
+
* reason Temporal's `TEMPORAL_SCHEDULE_DEFAULTS` lists `state` whole: pruning
|
|
57
|
+
* only the leaf would still recurse into the object, and a nested default the
|
|
58
|
+
* table does not separately name (`rollingUpdate.maxSurge`/`maxUnavailable`,
|
|
59
|
+
* both `"25%"` when `spec.strategy` is omitted entirely) would leave behind an
|
|
60
|
+
* empty `strategy: {}` — a value distinct from no `strategy` key at all, and
|
|
61
|
+
* itself a spurious "undeclared" finding. Matching the whole node first, before
|
|
62
|
+
* its children are ever visited, drops the wrapper outright when every field
|
|
63
|
+
* under it is exactly at its default.
|
|
64
|
+
*/
|
|
65
|
+
export declare const K8S_SERVICE_DEFAULTS: Record<string, Record<string, unknown>>;
|
|
66
|
+
/**
|
|
67
|
+
* The k8s lexicon's static noise rules: the generic Kubernetes object
|
|
68
|
+
* envelope (unconditional, by pattern, `@intentius/chant/managed-fields`) and
|
|
69
|
+
* Kubernetes-defaulted fields (gated on `counterpart === "absent"`), plus the
|
|
70
|
+
* array orderings the acceptance criteria name — `x-kubernetes-patch-merge-
|
|
71
|
+
* key`/`list-map-keys` conventions the generated surface does not currently
|
|
72
|
+
* carry (see the module doc), so these are the "else named-by-name
|
|
73
|
+
* conventions" the issue calls for: containers by `name`, `env` by `name`,
|
|
74
|
+
* `volumes` by `name`, container/service `ports` by `containerPort`/`port` +
|
|
75
|
+
* `protocol` — the same conventions `@intentius/chant/managed-fields`'s
|
|
76
|
+
* `k8sListMapOrderKey` implements, reused verbatim.
|
|
77
|
+
*
|
|
78
|
+
* This is the object `k8sPlugin.deepNormalizationHooks` is. It is also what
|
|
79
|
+
* `./deep-observe.ts` layers its per-resource managed-fields prune on top of,
|
|
80
|
+
* so the two normalization passes (the reader's own, and core's later
|
|
81
|
+
* re-normalization of both the declared and the already-normalized live tree
|
|
82
|
+
* — see `packages/core/src/lifecycle/deep-observe.ts`) apply the identical
|
|
83
|
+
* entityType-keyed rules either way.
|
|
84
|
+
*/
|
|
85
|
+
export declare const k8sDeepNormalizationHooks: DeepNormalizationHooks;
|
|
86
|
+
//# sourceMappingURL=deep-observe-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-observe-hooks.d.ts","sourceRoot":"","sources":["../src/deep-observe-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAY,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGjF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAcxE,CAAC;AAaF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,yBAAyB,EAAE,sBAWvC,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubernetes deep observation (#1076) — the k8s row of the deep-observe
|
|
3
|
+
* contract (#1014), and the epic's (#1073) thesis made real: chant compiled
|
|
4
|
+
* the manifest, so it knows which fields it authored; the API server records,
|
|
5
|
+
* per field, which manager last wrote it (`metadata.managedFields`, chant
|
|
6
|
+
* #1075/#1178). Intersecting those two makes Kubernetes drift *derived*
|
|
7
|
+
* rather than the hand-maintained `ignoreDifferences` list every Argo user
|
|
8
|
+
* keeps.
|
|
9
|
+
*
|
|
10
|
+
* ## Why this is not "the AWS reader, with `kubectl get` instead of Cloud
|
|
11
|
+
* Control"
|
|
12
|
+
*
|
|
13
|
+
* AWS, Azure and Temporal's rows all prune by a **static, entityType-keyed**
|
|
14
|
+
* table: an ARN always looks like an ARN, `provisioningState` is always
|
|
15
|
+
* server-populated, a namespace's retention default is always the same
|
|
16
|
+
* value. None of that needs the specific live object in hand — it is exactly
|
|
17
|
+
* what `./deep-observe-hooks.ts`'s `k8sDeepNormalizationHooks` is, and it
|
|
18
|
+
* covers Kubernetes' *equivalent* static noise (`status`,
|
|
19
|
+
* `metadata.{uid,resourceVersion,generation,creationTimestamp}`, a handful of
|
|
20
|
+
* server-defaulted pod-spec fields).
|
|
21
|
+
*
|
|
22
|
+
* managedFields is not that kind of rule. Whether `spec.replicas` is noise on
|
|
23
|
+
* *this* Deployment depends on whether *this* Deployment's
|
|
24
|
+
* `metadata.managedFields` says a controller owns it — a fact that differs
|
|
25
|
+
* between two Deployments of the same type, and that the declared tree never
|
|
26
|
+
* carries at all (chant's source has no `managedFields` key to normalize).
|
|
27
|
+
* `DeepNormalizationHooks.prune` cannot see the object it is walking, only a
|
|
28
|
+
* path and a value, so this cannot be expressed as a fixed hook the way the
|
|
29
|
+
* other three rows' entire contribution is. It has to be computed once per
|
|
30
|
+
* resource, here, and layered on top of the static rules before the tree is
|
|
31
|
+
* normalized.
|
|
32
|
+
*
|
|
33
|
+
* ## The contested-field rule, precisely
|
|
34
|
+
*
|
|
35
|
+
* For every path on the live tree, three questions, each independent:
|
|
36
|
+
*
|
|
37
|
+
* 1. **Does any chant field manager (`chant`, `chant:<stack>` — chant #1075,
|
|
38
|
+
* matched on the family so a stack rename does not stop recognizing its
|
|
39
|
+
* own history) own this path?** If so it is chant's business regardless of
|
|
40
|
+
* what else is true — always diffable, never pruned by this rule.
|
|
41
|
+
* 2. **Does some *other* manager own this path, and chant does not?** That is
|
|
42
|
+
* controller-managed noise — HPA rewriting `spec.replicas`, a mutating
|
|
43
|
+
* webhook defaulting a field, `kubectl-client-side-apply` from a human
|
|
44
|
+
* operator — *provided* nobody declared it (next question). Prune it.
|
|
45
|
+
* 3. **Does chant's own manifest *also* set this path?** — independent of
|
|
46
|
+
* who currently owns it live. This is the case the issue calls out by
|
|
47
|
+
* name: **a contested field chant declared is drift-relevant.** The
|
|
48
|
+
* reasoning: chant's source is a statement of intent regardless of
|
|
49
|
+
* whether a previous apply is what currently holds the field, and a
|
|
50
|
+
* foreign write that overrides a value chant's manifest asks for is
|
|
51
|
+
* exactly the thing `lifecycle diff --live` exists to surface — silencing
|
|
52
|
+
* it because *something else* currently owns the field would hide the one
|
|
53
|
+
* case where chant and the cluster disagree about a property chant is
|
|
54
|
+
* actively declaring. So: foreign-owned *and* declared is never pruned by
|
|
55
|
+
* this rule, whatever #2 would otherwise do.
|
|
56
|
+
*
|
|
57
|
+
* `counterpart: "unknown"` and why it does not help here: core's own
|
|
58
|
+
* counterpart tri-state (`side === "live" && counterpart === "absent"`, what
|
|
59
|
+
* {@link K8S_SERVICE_DEFAULTS} is gated on) answers "did the *declared tree*
|
|
60
|
+
* carry this path at all" — which is exactly question 3, but it is computed
|
|
61
|
+
* by *core*, from the raw declared and raw live trees, only on the **second**
|
|
62
|
+
* normalization pass (`packages/core/src/lifecycle/deep-observe.ts`'s
|
|
63
|
+
* `diffDeepObservation`). This reader's own call to
|
|
64
|
+
* {@link normalizeDeepProperties} runs first, with no `counterpartPaths`
|
|
65
|
+
* supplied — same as the other three rows — so `counterpart` is `"unknown"`
|
|
66
|
+
* for every node here, and a rule gated on `"absent"` would never fire during
|
|
67
|
+
* this read at all. That is fine for a table keyed only by entityType (AWS's
|
|
68
|
+
* service defaults are subtracted on core's later pass, not this one), but it
|
|
69
|
+
* is *not* fine for the managed-fields rule: if this reader left
|
|
70
|
+
* `spec.replicas` in the tree waiting for core's second pass to prune it,
|
|
71
|
+
* core would be normalizing with the *static* `k8sDeepNormalizationHooks`,
|
|
72
|
+
* which has no managedFields for this object in hand either (this reader
|
|
73
|
+
* already computed its ownership sets from data it read once and does not
|
|
74
|
+
* return). So question 3 is answered **here**, directly against the declared
|
|
75
|
+
* `props` this reader was handed — not via `counterpart` — and the result is
|
|
76
|
+
* baked into what this reader returns: a foreign-owned, undeclared field is
|
|
77
|
+
* gone from the tree before it ever reaches core, and a contested one is
|
|
78
|
+
* still there for the ordinary declared-vs-live comparison to catch.
|
|
79
|
+
*
|
|
80
|
+
* ## Resolving a managedFields entry against a live array
|
|
81
|
+
*
|
|
82
|
+
* `metadata.managedFields[].fieldsV1` encodes a list item three ways —
|
|
83
|
+
* `k:{"name":"web"}` (by key), `v:"blue"` (by value), `i:3` (by index) — and
|
|
84
|
+
* chant #1178's `managed-fields.ts` renders all three to a path *string*
|
|
85
|
+
* (`.spec.containers[name="web"]`) for display. Parsing that string back
|
|
86
|
+
* would be ambiguous in general (a label key may itself contain `.`, e.g.
|
|
87
|
+
* `app.kubernetes.io/name`, indistinguishable in the rendered form from
|
|
88
|
+
* nested fields), so this reader does not parse strings at all: it walks the
|
|
89
|
+
* *structured* `fieldsV1` tree directly (`walkOwnership`, below), matching
|
|
90
|
+
* each `k:`/`v:` entry against the actual live array to find the concrete
|
|
91
|
+
* index, and against the actual declared array (by the same key or value) to
|
|
92
|
+
* answer question 3 for that element specifically — a declared container
|
|
93
|
+
* named `app` at index 0 is still "declared" if a sidecar gets injected in
|
|
94
|
+
* front of it and shifts it to live index 1.
|
|
95
|
+
*
|
|
96
|
+
* ## What is deliberately not modeled
|
|
97
|
+
*
|
|
98
|
+
* A manager's `.` entry (SSA's "I own this element's presence") on a
|
|
99
|
+
* container that also sets no scalar sub-fields (unusual — a real apply
|
|
100
|
+
* setting a container almost always sets `image`/`name` too) would not confer
|
|
101
|
+
* ownership onto a sibling field nobody's `fieldsV1` entry lists explicitly.
|
|
102
|
+
* That is the conservative direction: a path absent from every manager's
|
|
103
|
+
* fields is treated as "no ownership information", which leaves it diffable
|
|
104
|
+
* rather than silently pruned. Reported drift that turns out to be more
|
|
105
|
+
* noise than expected is a tuning problem; drift silently dropped is not.
|
|
106
|
+
*
|
|
107
|
+
* ## `buildOwnershipSets` lives in core now
|
|
108
|
+
*
|
|
109
|
+
* The ownership walk itself (`walkOwnership`, resolving a `fieldsV1` tree
|
|
110
|
+
* against the live and declared trees) has nothing k8s-*lexicon*-specific
|
|
111
|
+
* about it — it is generic Kubernetes SSA machinery. Chant #1087 (GCP's row,
|
|
112
|
+
* reusing this one, since a Config Connector CR is a Kubernetes object too)
|
|
113
|
+
* moved it to `@intentius/chant/managed-fields` rather than have gcp depend
|
|
114
|
+
* on this lexicon's package, the same reason chant #1100's
|
|
115
|
+
* `resolveClusterTarget` lives in core. This module re-exports
|
|
116
|
+
* `buildOwnershipSets`/`OwnershipSets` from there so nothing here changes for
|
|
117
|
+
* an existing importer of this file.
|
|
118
|
+
*/
|
|
119
|
+
import type { DeepObservationResult } from "@intentius/chant/lexicon";
|
|
120
|
+
import { buildOwnershipSets, type OwnershipSets } from "@intentius/chant/managed-fields";
|
|
121
|
+
import { type K8sConnector } from "./api/connect.js";
|
|
122
|
+
import { k8sDeepNormalizationHooks } from "./deep-observe-hooks.js";
|
|
123
|
+
export { k8sDeepNormalizationHooks, buildOwnershipSets, type OwnershipSets };
|
|
124
|
+
export interface K8sDeepObserveOptions {
|
|
125
|
+
environment: string;
|
|
126
|
+
buildOutput?: string;
|
|
127
|
+
entityNames: string[];
|
|
128
|
+
entities: Map<string, {
|
|
129
|
+
entityType: string;
|
|
130
|
+
props: Record<string, unknown>;
|
|
131
|
+
}>;
|
|
132
|
+
stack?: string;
|
|
133
|
+
owned?: boolean;
|
|
134
|
+
/** Directory whose `chant.config.ts` carries the cluster binding. Defaults to cwd. */
|
|
135
|
+
cwd?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Read the live property tree for each declared entity, pruning by
|
|
139
|
+
* `metadata.managedFields` (see the module doc). Reuses the same connector,
|
|
140
|
+
* discovery/caching client and tri-state failure classification as the thin
|
|
141
|
+
* read (`./describe-resources.ts`) — the binding check (chant #1100/#1155)
|
|
142
|
+
* still refuses before any resource is touched, and a connect failure still
|
|
143
|
+
* becomes NOT-OBSERVED for every declared entity rather than an empty result.
|
|
144
|
+
*/
|
|
145
|
+
export declare function observeResourcesDeepK8s(options: K8sDeepObserveOptions, connect?: K8sConnector): Promise<DeepObservationResult>;
|
|
146
|
+
//# sourceMappingURL=deep-observe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-observe.d.ts","sourceRoot":"","sources":["../src/deep-observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqHG;AAGH,OAAO,KAAK,EAEV,qBAAqB,EAGtB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAAE,kBAAkB,EAAoB,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC3G,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAQvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AASjE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,KAAK,aAAa,EAAE,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAuBD;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,qBAAqB,EAC9B,OAAO,GAAE,YAAkC,GAC1C,OAAO,CAAC,qBAAqB,CAAC,CA0GhC"}
|
|
@@ -35,6 +35,21 @@
|
|
|
35
35
|
* NOT-OBSERVED with a reason. A declared `k8s.profiles.<env>.context` that
|
|
36
36
|
* disagrees with the ambient one still refuses before a single resource is
|
|
37
37
|
* touched, via the same `resolveClusterTarget` the GCP lexicon shares.
|
|
38
|
+
*
|
|
39
|
+
* ## Runtime children (chant #1077)
|
|
40
|
+
*
|
|
41
|
+
* A Pod a declared Deployment's controller created is live and undeclared —
|
|
42
|
+
* exactly the shape `lifecycle diff --live` has always classified `orphan`.
|
|
43
|
+
* On Kubernetes that is wrong: it is expected runtime, not drift, and will be
|
|
44
|
+
* recreated the moment it is deleted. After the declared-entity reads above
|
|
45
|
+
* resolve, this scans Pods in the namespaces they actually live in and walks
|
|
46
|
+
* each one's `ownerReferences` chain (`./api/owner-chain.ts`) against the
|
|
47
|
+
* entities this very call resolved. A chain reaching one of them is reported
|
|
48
|
+
* with `ownerChain: { root: "declared", ... }`; core's diff/change-set engine
|
|
49
|
+
* reads that as `runtime` instead of `orphan`. Deliberately scoped to Pods —
|
|
50
|
+
* the concrete case the issue and its acceptance criteria name — and to the
|
|
51
|
+
* namespaces this observation already touched, not a cluster-wide sweep;
|
|
52
|
+
* widening to other controller-spawned kinds is the same walk repeated.
|
|
38
53
|
*/
|
|
39
54
|
import type { ObservationResult } from "@intentius/chant/lexicon";
|
|
40
55
|
import type { K8sObject } from "@intentius/chant-k8s-client";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-resources.d.ts","sourceRoot":"","sources":["../src/describe-resources.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"describe-resources.d.ts","sourceRoot":"","sources":["../src/describe-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAsC,MAAM,0BAA0B,CAAC;AAGtG,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAkBvE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAUvD;AAQD,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,EACjC,OAAO,GAAE,YAAkC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,CAqH5B"}
|
|
@@ -18,12 +18,16 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { ExportedTemplate, ResourceSelector } from "@intentius/chant/lexicon";
|
|
20
20
|
import { type K8sConnector } from "./api/connect.js";
|
|
21
|
+
import { DEFAULT_IMPORT_TYPES } from "./api/sweep-types.js";
|
|
21
22
|
/**
|
|
22
23
|
* Entity types a bare `chant import --from <cluster>` sweeps: the workload,
|
|
23
24
|
* config, networking and RBAC kinds people actually author. Everything else is
|
|
24
|
-
* reachable by naming it with `--selector type=...`.
|
|
25
|
+
* reachable by naming it with `--selector type=...`. Defined in
|
|
26
|
+
* `./api/sweep-types.ts` and re-exported here, its original home — chant
|
|
27
|
+
* #1075's ownership-scoped prune needs the same list without pulling the
|
|
28
|
+
* import parser into a Temporal worker.
|
|
25
29
|
*/
|
|
26
|
-
export
|
|
30
|
+
export { DEFAULT_IMPORT_TYPES };
|
|
27
31
|
export declare function exportResources(options: {
|
|
28
32
|
environment: string;
|
|
29
33
|
selector?: ResourceSelector;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export-resources.d.ts","sourceRoot":"","sources":["../src/export-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"export-resources.d.ts","sourceRoot":"","sources":["../src/export-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAGvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;;;;GAOG;AACH,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,wBAAsB,eAAe,CACnC,OAAO,EAAE;IACP,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,EACD,OAAO,GAAE,YAAkC,GAC1C,OAAO,CAAC,gBAAgB,CAAC,CA4B3B"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "115699ca99d75d4b540b73fc2bbae4ca9b2c10a58e2229d24f72571b9daee693",
|
|
5
5
|
"meta.json": "6d112006daa7196eb28619ac5a3893b709dc2b845edbd537db7d7b471e8dc104",
|
|
6
6
|
"types/index.d.ts": "7b873148146a5512c22baabfde6cfcc3248c24c2c7578f68a19544af5dc675f6",
|
|
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": "57c3eed6bb041d08264adcedaa5e166e624257e15c6d8121053cc945e7d212f3"
|
|
54
54
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant kube apply` (chant #1079) — "writes are not cloned": this calls
|
|
3
|
+
* `applyManifest` (`../op/activities/kubectl.ts`) directly, the exact
|
|
4
|
+
* function the k8s Op activity registers under `kubectlApply` — server-side
|
|
5
|
+
* apply, chant's field-manager identity, the same `FieldManagerConflictError`
|
|
6
|
+
* surface (chant #1075/#1178) — never a second implementation of `kubectl
|
|
7
|
+
* apply`. An explicit manifest path is mandatory; there is no bare-sweep form.
|
|
8
|
+
*
|
|
9
|
+
* The one thing this verb adds on top of the activity is a confirmation
|
|
10
|
+
* gate, matching the issue's "route through plan, gate, and ownership": a
|
|
11
|
+
* bare `chant kube apply -f x.yaml` performs a server-side dry run — every
|
|
12
|
+
* document validated and previewed, nothing persisted — and says so; only
|
|
13
|
+
* `--yes` performs the real, persisting apply. That is a deliberate
|
|
14
|
+
* divergence from `kubectl apply`, which persists by default; a terminal
|
|
15
|
+
* command that can rewrite a live Deployment is worth one extra keystroke of
|
|
16
|
+
* intent.
|
|
17
|
+
*/
|
|
18
|
+
import { type K8sConnector } from "../api/connect.js";
|
|
19
|
+
import { type KubectlApplyArgs, type ApplyManifestResult } from "../op/activities/kubectl.js";
|
|
20
|
+
export type ApplyFn = (args: KubectlApplyArgs, signal?: AbortSignal, connect?: K8sConnector) => Promise<ApplyManifestResult>;
|
|
21
|
+
export interface ApplyDeps {
|
|
22
|
+
connect?: K8sConnector;
|
|
23
|
+
apply?: ApplyFn;
|
|
24
|
+
}
|
|
25
|
+
export declare function runApply(rawArgs: string[], deps?: ApplyDeps): Promise<number>;
|
|
26
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/kube/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG1G,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAE7H,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,SAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoEvF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connecting to a cluster on `chant kube`'s behalf (chant #1079), honoring
|
|
3
|
+
* the exact same environment→cluster binding every other observing path
|
|
4
|
+
* does (chant #1100/#1155): `--env` resolves `k8s.profiles.<env>.context`
|
|
5
|
+
* and refuses loudly on a mismatch, `--context` is an explicit override that
|
|
6
|
+
* skips the binding entirely, and neither given falls back to the ambient
|
|
7
|
+
* kubeconfig context — the same three modes `describeResources` and the Op
|
|
8
|
+
* activities already use, via the same `defaultK8sConnector`. Nothing here
|
|
9
|
+
* reimplements that resolution; this only turns a connect failure into the
|
|
10
|
+
* observation tri-state so a verb can render NOT-OBSERVED-with-reason
|
|
11
|
+
* instead of a stack trace.
|
|
12
|
+
*/
|
|
13
|
+
import type { UnobservedReason } from "@intentius/chant/observation";
|
|
14
|
+
import { type ConnectOptions, type ConnectedClient, type K8sConnector } from "../api/connect.js";
|
|
15
|
+
export type KubeConnectResult = ({
|
|
16
|
+
kind: "connected";
|
|
17
|
+
} & ConnectedClient) | {
|
|
18
|
+
kind: "unobserved";
|
|
19
|
+
reason: UnobservedReason;
|
|
20
|
+
detail: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Connect, or classify the failure into the tri-state. A bound-but-mismatched
|
|
24
|
+
* `--env` (`ClusterBindingMismatchError`), a missing `@intentius/chant-k8s-client`
|
|
25
|
+
* install, and a refused exec-credential plugin are the "nothing left the
|
|
26
|
+
* process" failures every verb must treat identically: NOT-OBSERVED, never
|
|
27
|
+
* an empty/absent result.
|
|
28
|
+
*/
|
|
29
|
+
export declare function kubeConnect(options: ConnectOptions, connect?: K8sConnector): Promise<KubeConnectResult>;
|
|
30
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/kube/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAuB,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnH,MAAM,MAAM,iBAAiB,GACzB,CAAC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GAAG,eAAe,CAAC,GACzC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,YAAkC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,CAqB5B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant kube delete` (chant #1079) — routes through the typed client's own
|
|
3
|
+
* `delete()` (`packages/k8s-client/src/client.ts`), the identical typed
|
|
4
|
+
* delete `applyManifest`'s prune step already uses (chant #1075) — never a
|
|
5
|
+
* second implementation. A kind and a name are both mandatory: there is no
|
|
6
|
+
* bare `chant kube delete deployments` form, so nothing here can become a
|
|
7
|
+
* sweep by omission (the issue's "nothing destructive happens without an
|
|
8
|
+
* explicit resource argument").
|
|
9
|
+
*
|
|
10
|
+
* Two guardrails on top of the typed delete itself:
|
|
11
|
+
*
|
|
12
|
+
* - **Gate.** A bare invocation reads the object, reports what it found (and
|
|
13
|
+
* whether chant owns it), and stops — only `--yes` performs the delete.
|
|
14
|
+
* - **Ownership, surfaced not enforced.** kubectl itself deletes anything
|
|
15
|
+
* RBAC allows, chant-applied or not, and this keeps that: an explicit name
|
|
16
|
+
* is already an informed decision. What's added is visibility — a
|
|
17
|
+
* warning when the object carries no chant ownership marker, so the
|
|
18
|
+
* operator knows they are about to delete something chant did not apply.
|
|
19
|
+
*/
|
|
20
|
+
import { type K8sConnector } from "../api/connect.js";
|
|
21
|
+
import { type KubeProjectContext } from "./project.js";
|
|
22
|
+
export interface DeleteDeps {
|
|
23
|
+
connect?: K8sConnector;
|
|
24
|
+
loadProject?: (cwd?: string) => Promise<KubeProjectContext | undefined>;
|
|
25
|
+
}
|
|
26
|
+
export declare function runDelete(rawArgs: string[], deps?: DeleteDeps): Promise<number>;
|
|
27
|
+
//# sourceMappingURL=delete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/kube/delete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIxE,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG5E,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;CACzE;AAQD,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0GzF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant kube describe` (chant #1079) — a generic, multi-section human view:
|
|
3
|
+
* identity, chant's own verdict + provenance (when inside a project), a
|
|
4
|
+
* pretty-printed spec/status, and the object's Events (reusing `./events.ts`'s
|
|
5
|
+
* `listEvents`/`filterInvolved`, the same machinery `chant kube events`
|
|
6
|
+
* itself uses — one implementation, not two). This is not kubectl's
|
|
7
|
+
* per-kind template set (`OldReplicaSets`/`NewReplicaSet` for a Deployment,
|
|
8
|
+
* per-container detail for a Pod, and so on for every built-in kind) — a
|
|
9
|
+
* generic describe covering the fields every object carries, plus the
|
|
10
|
+
* context only chant can add.
|
|
11
|
+
*/
|
|
12
|
+
import { type K8sConnector } from "../api/connect.js";
|
|
13
|
+
import { type KubeProjectContext } from "./project.js";
|
|
14
|
+
export interface DescribeDeps {
|
|
15
|
+
connect?: K8sConnector;
|
|
16
|
+
loadProject?: (cwd?: string) => Promise<KubeProjectContext | undefined>;
|
|
17
|
+
}
|
|
18
|
+
export declare function runDescribe(rawArgs: string[], deps?: DescribeDeps): Promise<number>;
|
|
19
|
+
//# sourceMappingURL=describe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/kube/describe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKxE,OAAO,EAA8C,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAMhG,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;CACzE;AA0ED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4F7F"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant kube events` (chant #1079) — the core `v1 Event` kind is addressed
|
|
3
|
+
* exactly like any other read (`client.list`), no client extension needed.
|
|
4
|
+
* The one thing the typed client's `ListOptions` does not carry is a field
|
|
5
|
+
* selector, so `--for <kind>/<name>` (kubectl's own `kubectl events
|
|
6
|
+
* --for=kind/name` shape) filters client-side against `involvedObject` after
|
|
7
|
+
* the list comes back, rather than asking the server to. Event volume in a
|
|
8
|
+
* single namespace is small enough that this is a fine trade for not
|
|
9
|
+
* widening the client's surface for one caller.
|
|
10
|
+
*/
|
|
11
|
+
import type { K8sClient, K8sObject } from "@intentius/chant-k8s-client";
|
|
12
|
+
import { type K8sConnector } from "../api/connect.js";
|
|
13
|
+
export interface EventsDeps {
|
|
14
|
+
connect?: K8sConnector;
|
|
15
|
+
}
|
|
16
|
+
/** Events whose `involvedObject` names `ref`, oldest first — kubectl's own default order. */
|
|
17
|
+
export declare function filterInvolved(events: readonly K8sObject[], ref: {
|
|
18
|
+
kind: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}): K8sObject[];
|
|
21
|
+
/**
|
|
22
|
+
* List Events for `namespace` (or every namespace, when `namespace` is
|
|
23
|
+
* undefined), sorted oldest first. Shared by `runEvents` and `describe`'s own
|
|
24
|
+
* Events section, so the two verbs agree on what "the events for this object"
|
|
25
|
+
* means.
|
|
26
|
+
*/
|
|
27
|
+
export declare function listEvents(client: K8sClient, options?: {
|
|
28
|
+
namespace?: string;
|
|
29
|
+
labelSelector?: string;
|
|
30
|
+
}): Promise<K8sObject[]>;
|
|
31
|
+
/** Render an events table — reused by `describe`'s Events section. */
|
|
32
|
+
export declare function renderEvents(events: readonly K8sObject[]): string;
|
|
33
|
+
export declare function runEvents(rawArgs: string[], deps?: EventsDeps): Promise<number>;
|
|
34
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/kube/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMxE,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAoBD,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,EAAE,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAAE,CAK7G;AAaD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3D,OAAO,CAAC,SAAS,EAAE,CAAC,CAMtB;AAcD,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAGjE;AASD,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDzF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flag parsing shared by every `chant kube <verb>` (chant #1079).
|
|
3
|
+
*
|
|
4
|
+
* `CommandGroupContext.rawArgs` is unparsed argv — core has no vocabulary for
|
|
5
|
+
* a lexicon's own verbs (chant #1078) — so every verb here does its own
|
|
6
|
+
* parsing, reusing `splitJoinedFlags`/`unknownFlagError` for the same
|
|
7
|
+
* `--flag=value` splitting and rejection discipline core's own parser
|
|
8
|
+
* applies (chant #1127). This module adds the flag vocabulary every verb
|
|
9
|
+
* shares (namespace, selector, output, cluster targeting) so each verb file
|
|
10
|
+
* only has to declare what is actually its own (`--tail`, `--for`, ...).
|
|
11
|
+
*/
|
|
12
|
+
import type { ConnectOptions } from "../api/connect.js";
|
|
13
|
+
/** A verb's own flag vocabulary, merged with the common set below. */
|
|
14
|
+
export interface FlagSpec {
|
|
15
|
+
/** Value flags this verb accepts, alias → canonical key (e.g. `{ "--tail": "tail" }`). */
|
|
16
|
+
value?: Record<string, string>;
|
|
17
|
+
/** Boolean flags this verb accepts, alias → canonical key. */
|
|
18
|
+
boolean?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
export interface ParsedFlags {
|
|
21
|
+
/** Non-flag tokens, in order — the verb's own positional arguments (kind, name, ...). */
|
|
22
|
+
positional: string[];
|
|
23
|
+
/** Resolved value-flag key → the value given. */
|
|
24
|
+
values: Record<string, string>;
|
|
25
|
+
/** Resolved boolean-flag key → true (absent keys are false). */
|
|
26
|
+
flags: Record<string, boolean>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse `rawArgs` against the common flag set plus `spec`. Throws
|
|
30
|
+
* {@link unknownFlagError}'s shape on anything starting with `-` that
|
|
31
|
+
* neither set recognizes, and on a value flag given with nothing after it.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseKubeFlags(rawArgs: string[], spec?: FlagSpec): ParsedFlags;
|
|
34
|
+
/** Build the typed client's `ConnectOptions` from a parsed common flag set. */
|
|
35
|
+
export declare function connectOptionsFrom(values: Record<string, string>): ConnectOptions;
|
|
36
|
+
/** kubectl duration shorthand: "3600" (bare seconds), "1h", "90m", "45s". Shared by `logs --since` and `wait --timeout`. */
|
|
37
|
+
export declare function parseDurationSeconds(value: string): number;
|
|
38
|
+
/** {@link parseDurationSeconds} in milliseconds. */
|
|
39
|
+
export declare function parseDurationMs(value: string): number;
|
|
40
|
+
//# sourceMappingURL=flags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../../src/kube/flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,sEAAsE;AACtE,MAAM,WAAW,QAAQ;IACvB,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAoBD,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,QAAa,GAAG,WAAW,CA6BlF;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,CAMjF;AAED,4HAA4H;AAC5H,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAY1D;AAED,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
|