@cat-factory/cli 0.10.4 → 0.11.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/README.md +8 -0
- package/dist/args.d.ts +16 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +44 -14
- package/dist/args.js.map +1 -1
- package/dist/bin.js +7 -1
- package/dist/bin.js.map +1 -1
- package/dist/errorText.d.ts +6 -0
- package/dist/errorText.d.ts.map +1 -0
- package/dist/errorText.js +175 -0
- package/dist/errorText.js.map +1 -0
- package/dist/host-shell.d.ts +26 -0
- package/dist/host-shell.d.ts.map +1 -1
- package/dist/host-shell.js +19 -0
- package/dist/host-shell.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/k3s-handler.d.ts +35 -20
- package/dist/k3s-handler.d.ts.map +1 -1
- package/dist/k3s-handler.js +54 -26
- package/dist/k3s-handler.js.map +1 -1
- package/dist/k3s-ingress.d.ts +259 -0
- package/dist/k3s-ingress.d.ts.map +1 -0
- package/dist/k3s-ingress.js +372 -0
- package/dist/k3s-ingress.js.map +1 -0
- package/dist/k3s-probe.d.ts +38 -3
- package/dist/k3s-probe.d.ts.map +1 -1
- package/dist/k3s-probe.js +93 -5
- package/dist/k3s-probe.js.map +1 -1
- package/dist/k3s-provision.d.ts +92 -18
- package/dist/k3s-provision.d.ts.map +1 -1
- package/dist/k3s-provision.js +280 -28
- package/dist/k3s-provision.js.map +1 -1
- package/dist/k3s.d.ts +3 -0
- package/dist/k3s.d.ts.map +1 -1
- package/dist/k3s.js +149 -24
- package/dist/k3s.js.map +1 -1
- package/package.json +3 -3
package/dist/k3s-provision.d.ts
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import { type CliOptions } from './args.js';
|
|
2
|
-
import { type HostShell } from './host-shell.js';
|
|
2
|
+
import { type Command, type HostShell } from './host-shell.js';
|
|
3
|
+
import { type IngressReadiness, type TcpProbe } from './k3s-ingress.js';
|
|
3
4
|
import { type Io } from './io.js';
|
|
4
5
|
import { type HostState, type OfferId } from './k3s-probe.js';
|
|
5
6
|
/** The namespace + ServiceAccount + long-lived token Secret the guided setup creates. */
|
|
6
7
|
export declare const CAT_FACTORY_NAMESPACE = "cat-factory";
|
|
7
8
|
export declare const SERVICE_ACCOUNT_NAME = "cat-factory";
|
|
9
|
+
/** The apiserver port k3d/kind is asked to publish (the kube default). */
|
|
10
|
+
export declare const DEFAULT_API_PORT = 6443;
|
|
8
11
|
/**
|
|
9
12
|
* Watchdog budget (ms) for `k3d cluster create` / `kind create cluster`. These pull node images on
|
|
10
13
|
* the first run and routinely take 30–90s, so they need far more than the {@link HostShell} default
|
|
11
14
|
* (10s) — otherwise the watchdog SIGKILLs the create mid-flight and the whole create path fails.
|
|
12
15
|
*/
|
|
13
16
|
export declare const CLUSTER_CREATE_TIMEOUT_MS = 300000;
|
|
14
|
-
/**
|
|
15
|
-
export
|
|
16
|
-
cmd: string;
|
|
17
|
-
args: string[];
|
|
18
|
-
input?: string;
|
|
19
|
-
/** Per-command watchdog override (ms). Absent ⇒ the {@link HostShell} default applies. */
|
|
20
|
-
timeoutMs?: number;
|
|
21
|
-
}
|
|
17
|
+
/** Watchdog budget (ms) for `k3d/kind cluster delete`, which tears down containers + volumes. */
|
|
18
|
+
export declare const CLUSTER_DELETE_TIMEOUT_MS = 120000;
|
|
22
19
|
/**
|
|
23
20
|
* The resolved local-k3s connection produced by provisioning: the apiserver URL read from the
|
|
24
21
|
* kubeconfig plus the minted ServiceAccount token. Consumed by the hand-off (slice 3 builds the
|
|
@@ -29,9 +26,27 @@ export interface ResolvedConnection {
|
|
|
29
26
|
engine: 'local-k3s';
|
|
30
27
|
/** The provisioned/created cluster name (create paths only; absent for reuse). */
|
|
31
28
|
clusterName?: string;
|
|
29
|
+
/** The distribution the cluster was created/recreated with; absent when reusing a context. */
|
|
30
|
+
runtime?: 'k3d' | 'kind';
|
|
32
31
|
apiServerUrl: string;
|
|
33
32
|
apiToken: string;
|
|
34
33
|
insecureSkipTlsVerify: true;
|
|
34
|
+
/**
|
|
35
|
+
* What the ingress probe ESTABLISHED, never what the distribution is assumed to do. Everything
|
|
36
|
+
* downstream that would otherwise promise an ingress-derived environment URL (the printed
|
|
37
|
+
* summary, the connect-form deep link) keys off this.
|
|
38
|
+
*/
|
|
39
|
+
ingress: IngressReadiness;
|
|
40
|
+
/**
|
|
41
|
+
* The cluster a `--recreate` could name, when there is one: the cluster this run built, or (on
|
|
42
|
+
* the reuse path) the k3d/kind cluster the kubeconfig context resolves to. Absent when no such
|
|
43
|
+
* target exists, and a remedy that would print a recreate has to WITHHOLD it then, because
|
|
44
|
+
* `--recreate` refuses anything it cannot name.
|
|
45
|
+
*/
|
|
46
|
+
recreateTarget?: {
|
|
47
|
+
runtime: 'k3d' | 'kind';
|
|
48
|
+
clusterName: string;
|
|
49
|
+
};
|
|
35
50
|
}
|
|
36
51
|
/** Raised when a provisioning command fails; carries an actionable message (never the token). */
|
|
37
52
|
export declare class ProvisionError extends Error {
|
|
@@ -57,10 +72,48 @@ export declare class ProvisionError extends Error {
|
|
|
57
72
|
* token must be kept private.)
|
|
58
73
|
*/
|
|
59
74
|
export declare const RBAC_MANIFEST = "apiVersion: v1\nkind: Namespace\nmetadata:\n name: cat-factory\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: cat-factory\n namespace: cat-factory\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: cat-factory-env\nrules:\n - apiGroups: ['']\n resources: ['namespaces']\n verbs: ['create', 'get', 'list', 'watch', 'delete']\n - apiGroups: ['']\n resources: ['services', 'configmaps', 'persistentvolumeclaims', 'pods']\n verbs: ['create', 'get', 'list', 'watch', 'patch', 'update', 'delete']\n - apiGroups: ['']\n resources: ['secrets', 'serviceaccounts']\n verbs: ['create', 'get', 'patch', 'update', 'delete']\n - apiGroups: ['']\n resources: ['pods/proxy']\n verbs: ['create', 'get']\n - apiGroups: ['apps']\n resources: ['deployments', 'statefulsets', 'replicasets']\n verbs: ['create', 'get', 'list', 'watch', 'patch', 'update', 'delete']\n - apiGroups: ['batch']\n resources: ['jobs']\n verbs: ['create', 'get', 'list', 'watch', 'patch', 'update', 'delete']\n - apiGroups: ['networking.k8s.io']\n resources: ['ingresses']\n verbs: ['create', 'get', 'list', 'watch', 'patch', 'update', 'delete']\n - apiGroups: ['gateway.networking.k8s.io']\n resources: ['gateways', 'httproutes']\n verbs: ['create', 'get', 'list', 'watch', 'patch', 'update', 'delete']\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: cat-factory-env\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: cat-factory-env\nsubjects:\n - kind: ServiceAccount\n name: cat-factory\n namespace: cat-factory\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: cat-factory-token\n namespace: cat-factory\n annotations:\n kubernetes.io/service-account.name: cat-factory\ntype: kubernetes.io/service-account-token\n";
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
/**
|
|
76
|
+
* `k3d cluster create <name> --api-port <p> -p <ingress>:80@loadbalancer`.
|
|
77
|
+
*
|
|
78
|
+
* The `-p` is the half that used to be missing, and it can only be supplied HERE: k3d forwards
|
|
79
|
+
* exactly the host ports it was asked for when the load-balancer container was created, and
|
|
80
|
+
* Docker cannot publish a new one onto a running container. A cluster created without it can
|
|
81
|
+
* never serve an ingress-derived URL, however correct the rest of the configuration is.
|
|
82
|
+
*
|
|
83
|
+
* A default k3d cluster DOES bundle an ingress controller (k3s installs Traefik through a
|
|
84
|
+
* HelmChart manifest, verified against k3d 5.7.5 / k3s v1.30.6), so the create path publishes a
|
|
85
|
+
* port and installs nothing.
|
|
86
|
+
*/
|
|
87
|
+
export declare function k3dCreateCommand(name: string, apiPort?: number, ingressPort?: number): Command;
|
|
88
|
+
/**
|
|
89
|
+
* The kind cluster config fed to `kind create cluster --config -`.
|
|
90
|
+
*
|
|
91
|
+
* Both settings are create-time-only and both are needed before any ingress controller can work:
|
|
92
|
+
* `extraPortMappings` is kind's equivalent of k3d's `-p`, and `ingress-ready=true` is the node
|
|
93
|
+
* label every published kind ingress recipe selects on.
|
|
94
|
+
*
|
|
95
|
+
* What this deliberately does NOT do is install a controller. kind, unlike k3d, ships none, and
|
|
96
|
+
* the ways to get one (a third-party manifest fetched from the internet, or the separate
|
|
97
|
+
* `cloud-provider-kind` host process) are both choices about what runs on the operator's machine
|
|
98
|
+
* that a guided setup should not make silently. So the create path lays the irreversible half and
|
|
99
|
+
* the probe then reports the controller as verified-missing with the exact command, which a
|
|
100
|
+
* re-run turns into a verified-ready.
|
|
101
|
+
*/
|
|
102
|
+
export declare function kindClusterConfig(ingressPort?: number): string;
|
|
103
|
+
/** `kind create cluster --name <name> --config -`, with the ingress config on stdin. */
|
|
104
|
+
export declare function kindCreateCommand(name: string, ingressPort?: number): Command;
|
|
105
|
+
/**
|
|
106
|
+
* The create command for either distribution, so every caller (the create path, the recreate leg,
|
|
107
|
+
* and the printed guidance) issues the SAME line. The printed one used to be hand-written and had
|
|
108
|
+
* therefore lost the `-p` publish flag, telling an operator to build exactly the cluster whose
|
|
109
|
+
* missing host port the next run then asked them to recreate.
|
|
110
|
+
*/
|
|
111
|
+
export declare function clusterCreateCommand(runtime: 'k3d' | 'kind', name: string, ingressPort?: number): Command;
|
|
112
|
+
/** `k3d cluster delete <name>` / `kind delete cluster --name <name>`. Destroys the cluster. */
|
|
113
|
+
export declare function clusterDeleteCommand(runtime: 'k3d' | 'kind', name: string): Command;
|
|
114
|
+
/** Namespaces on the target context, read so a destructive prompt can name what is on it. */
|
|
115
|
+
export declare function listNamespacesCommand(context?: string): Command;
|
|
116
|
+
export declare function parseUserNamespaces(stdout: string): string[];
|
|
64
117
|
/** The kubeconfig context name k3d/kind assigns to a cluster it creates. */
|
|
65
118
|
export declare function contextName(runtime: 'k3d' | 'kind', name: string): string;
|
|
66
119
|
/** `kubectl apply -f -` with the RBAC manifest on stdin (idempotent), targeting `context`. */
|
|
@@ -84,8 +137,12 @@ export declare function looksLocalCluster(context: string | undefined, apiServer
|
|
|
84
137
|
export interface ProvisionDeps {
|
|
85
138
|
shell: HostShell;
|
|
86
139
|
io: Io;
|
|
140
|
+
/** TCP reachability seam, used to establish that a host ingress port is actually served. */
|
|
141
|
+
tcp: TcpProbe;
|
|
87
142
|
/** Delay between token-Secret read attempts (real setTimeout; a no-op in tests). */
|
|
88
143
|
sleep?: (ms: number) => Promise<void>;
|
|
144
|
+
/** Clock the ingress settle wait is measured against (default `Date.now`); see `probeIngress`. */
|
|
145
|
+
now?: () => number;
|
|
89
146
|
/**
|
|
90
147
|
* How many times to poll the freshly-applied token Secret for a populated `.data.token` before
|
|
91
148
|
* giving up (500ms between attempts). Absent ⇒ {@link DEFAULT_TOKEN_READ_ATTEMPTS} (a snappy
|
|
@@ -94,12 +151,29 @@ export interface ProvisionDeps {
|
|
|
94
151
|
*/
|
|
95
152
|
tokenReadAttempts?: number;
|
|
96
153
|
}
|
|
154
|
+
/** The host port a Docker failure names as already bound, when it names one. */
|
|
155
|
+
export declare function boundPortFromDetail(detail: string): number | undefined;
|
|
156
|
+
/**
|
|
157
|
+
* An extra hint appended to a create failure that looks like a host-port collision.
|
|
158
|
+
*
|
|
159
|
+
* A create asks for TWO host ports, so the hint READS which one Docker refused out of its own
|
|
160
|
+
* message instead of naming the apiserver port, which it used to do unconditionally and would
|
|
161
|
+
* misattribute an ingress-port collision. Port 80 is taken often enough on Windows and macOS that
|
|
162
|
+
* an opaque `k3d cluster create` failure here is the likely first experience, so the hint names
|
|
163
|
+
* the flag that moves it.
|
|
164
|
+
*/
|
|
165
|
+
export declare function portCollisionHint(ingressPort: number): (detail: string) => string;
|
|
166
|
+
/** The distribution behind a create/recreate offer; `null` for the reuse path. */
|
|
167
|
+
export declare function offerRuntime(chosen: OfferId): 'k3d' | 'kind' | null;
|
|
168
|
+
/** The ingress host port a run targets: `--ingress-port`, else {@link DEFAULT_INGRESS_PORT}. */
|
|
169
|
+
export declare function resolveIngressPort(options: CliOptions): number;
|
|
97
170
|
/**
|
|
98
|
-
* Provision (or reuse) a local cluster for the chosen offer, create the
|
|
99
|
-
* ServiceAccount + RBAC, mint a long-lived token,
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
171
|
+
* Provision (create, recreate or reuse) a local cluster for the chosen offer, create the
|
|
172
|
+
* least-privilege ServiceAccount + RBAC, mint a long-lived token, read the apiserver URL, and
|
|
173
|
+
* PROBE whether an ingress-derived environment URL can actually be served, returning the resolved
|
|
174
|
+
* `local-k3s` connection. Every MUTATING step (cluster create/delete, RBAC apply) is behind an
|
|
175
|
+
* explicit confirm unless `--yes`. Idempotent apart from `recreate-*`: an existing cluster/SA is
|
|
176
|
+
* reused, not duplicated. `install-k3s` is NOT handled here (guidance-only).
|
|
103
177
|
*/
|
|
104
178
|
export declare function provisionCluster(chosen: Exclude<OfferId, 'install-k3s'>, state: HostState, options: CliOptions, deps: ProvisionDeps): Promise<ResolvedConnection>;
|
|
105
179
|
//# sourceMappingURL=k3s-provision.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k3s-provision.d.ts","sourceRoot":"","sources":["../src/k3s-provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAmB,MAAM,WAAW,CAAA;AAC5D,OAAO,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"k3s-provision.d.ts","sourceRoot":"","sources":["../src/k3s-provision.ts"],"names":[],"mappings":"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"}
|
package/dist/k3s-provision.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { OPTION_DEFAULTS } from './args.js';
|
|
2
|
-
import {} from './host-shell.js';
|
|
2
|
+
import { runCommand } from './host-shell.js';
|
|
3
|
+
import { DEFAULT_INGRESS_PORT, INGRESS_CONTAINER_HTTP_PORT, INGRESS_SETTLE_WAIT_MS, probeIngress, } from './k3s-ingress.js';
|
|
3
4
|
import {} from './io.js';
|
|
4
|
-
import {} from './k3s-probe.js';
|
|
5
|
+
import { isRecreateOffer, RECREATE_OFFERS, recreateTargetForContext, } from './k3s-probe.js';
|
|
5
6
|
/** The namespace + ServiceAccount + long-lived token Secret the guided setup creates. */
|
|
6
7
|
export const CAT_FACTORY_NAMESPACE = 'cat-factory';
|
|
7
8
|
export const SERVICE_ACCOUNT_NAME = 'cat-factory';
|
|
8
9
|
const TOKEN_SECRET_NAME = 'cat-factory-token';
|
|
9
10
|
/** The apiserver port k3d/kind is asked to publish (the kube default). */
|
|
10
|
-
const DEFAULT_API_PORT = 6443;
|
|
11
|
+
export const DEFAULT_API_PORT = 6443;
|
|
11
12
|
/**
|
|
12
13
|
* Watchdog budget (ms) for `k3d cluster create` / `kind create cluster`. These pull node images on
|
|
13
14
|
* the first run and routinely take 30–90s, so they need far more than the {@link HostShell} default
|
|
14
15
|
* (10s) — otherwise the watchdog SIGKILLs the create mid-flight and the whole create path fails.
|
|
15
16
|
*/
|
|
16
17
|
export const CLUSTER_CREATE_TIMEOUT_MS = 300_000;
|
|
18
|
+
/** Watchdog budget (ms) for `k3d/kind cluster delete`, which tears down containers + volumes. */
|
|
19
|
+
export const CLUSTER_DELETE_TIMEOUT_MS = 120_000;
|
|
17
20
|
/** Raised when a provisioning command fails; carries an actionable message (never the token). */
|
|
18
21
|
export class ProvisionError extends Error {
|
|
19
22
|
}
|
|
@@ -103,22 +106,122 @@ type: kubernetes.io/service-account-token
|
|
|
103
106
|
// ---------------------------------------------------------------------------
|
|
104
107
|
// Pure command planners — no shell-out, so they are unit-testable in isolation.
|
|
105
108
|
// ---------------------------------------------------------------------------
|
|
106
|
-
/**
|
|
107
|
-
|
|
109
|
+
/**
|
|
110
|
+
* `k3d cluster create <name> --api-port <p> -p <ingress>:80@loadbalancer`.
|
|
111
|
+
*
|
|
112
|
+
* The `-p` is the half that used to be missing, and it can only be supplied HERE: k3d forwards
|
|
113
|
+
* exactly the host ports it was asked for when the load-balancer container was created, and
|
|
114
|
+
* Docker cannot publish a new one onto a running container. A cluster created without it can
|
|
115
|
+
* never serve an ingress-derived URL, however correct the rest of the configuration is.
|
|
116
|
+
*
|
|
117
|
+
* A default k3d cluster DOES bundle an ingress controller (k3s installs Traefik through a
|
|
118
|
+
* HelmChart manifest, verified against k3d 5.7.5 / k3s v1.30.6), so the create path publishes a
|
|
119
|
+
* port and installs nothing.
|
|
120
|
+
*/
|
|
121
|
+
export function k3dCreateCommand(name, apiPort = DEFAULT_API_PORT, ingressPort = DEFAULT_INGRESS_PORT) {
|
|
108
122
|
return {
|
|
109
123
|
cmd: 'k3d',
|
|
110
|
-
args: [
|
|
124
|
+
args: [
|
|
125
|
+
'cluster',
|
|
126
|
+
'create',
|
|
127
|
+
name,
|
|
128
|
+
'--api-port',
|
|
129
|
+
String(apiPort),
|
|
130
|
+
'-p',
|
|
131
|
+
`${ingressPort}:${INGRESS_CONTAINER_HTTP_PORT}@loadbalancer`,
|
|
132
|
+
],
|
|
111
133
|
timeoutMs: CLUSTER_CREATE_TIMEOUT_MS,
|
|
112
134
|
};
|
|
113
135
|
}
|
|
114
|
-
/**
|
|
115
|
-
|
|
136
|
+
/**
|
|
137
|
+
* The kind cluster config fed to `kind create cluster --config -`.
|
|
138
|
+
*
|
|
139
|
+
* Both settings are create-time-only and both are needed before any ingress controller can work:
|
|
140
|
+
* `extraPortMappings` is kind's equivalent of k3d's `-p`, and `ingress-ready=true` is the node
|
|
141
|
+
* label every published kind ingress recipe selects on.
|
|
142
|
+
*
|
|
143
|
+
* What this deliberately does NOT do is install a controller. kind, unlike k3d, ships none, and
|
|
144
|
+
* the ways to get one (a third-party manifest fetched from the internet, or the separate
|
|
145
|
+
* `cloud-provider-kind` host process) are both choices about what runs on the operator's machine
|
|
146
|
+
* that a guided setup should not make silently. So the create path lays the irreversible half and
|
|
147
|
+
* the probe then reports the controller as verified-missing with the exact command, which a
|
|
148
|
+
* re-run turns into a verified-ready.
|
|
149
|
+
*/
|
|
150
|
+
export function kindClusterConfig(ingressPort = DEFAULT_INGRESS_PORT) {
|
|
151
|
+
return `kind: Cluster
|
|
152
|
+
apiVersion: kind.x-k8s.io/v1alpha4
|
|
153
|
+
nodes:
|
|
154
|
+
- role: control-plane
|
|
155
|
+
kubeadmConfigPatches:
|
|
156
|
+
- |
|
|
157
|
+
kind: InitConfiguration
|
|
158
|
+
nodeRegistration:
|
|
159
|
+
kubeletExtraArgs:
|
|
160
|
+
node-labels: "ingress-ready=true"
|
|
161
|
+
extraPortMappings:
|
|
162
|
+
- containerPort: ${INGRESS_CONTAINER_HTTP_PORT}
|
|
163
|
+
hostPort: ${ingressPort}
|
|
164
|
+
protocol: TCP
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
/** `kind create cluster --name <name> --config -`, with the ingress config on stdin. */
|
|
168
|
+
export function kindCreateCommand(name, ingressPort = DEFAULT_INGRESS_PORT) {
|
|
116
169
|
return {
|
|
117
170
|
cmd: 'kind',
|
|
118
|
-
args: ['create', 'cluster', '--name', name],
|
|
171
|
+
args: ['create', 'cluster', '--name', name, '--config', '-'],
|
|
172
|
+
input: kindClusterConfig(ingressPort),
|
|
119
173
|
timeoutMs: CLUSTER_CREATE_TIMEOUT_MS,
|
|
120
174
|
};
|
|
121
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* The create command for either distribution, so every caller (the create path, the recreate leg,
|
|
178
|
+
* and the printed guidance) issues the SAME line. The printed one used to be hand-written and had
|
|
179
|
+
* therefore lost the `-p` publish flag, telling an operator to build exactly the cluster whose
|
|
180
|
+
* missing host port the next run then asked them to recreate.
|
|
181
|
+
*/
|
|
182
|
+
export function clusterCreateCommand(runtime, name, ingressPort = DEFAULT_INGRESS_PORT) {
|
|
183
|
+
return runtime === 'kind'
|
|
184
|
+
? kindCreateCommand(name, ingressPort)
|
|
185
|
+
: k3dCreateCommand(name, DEFAULT_API_PORT, ingressPort);
|
|
186
|
+
}
|
|
187
|
+
/** `k3d cluster delete <name>` / `kind delete cluster --name <name>`. Destroys the cluster. */
|
|
188
|
+
export function clusterDeleteCommand(runtime, name) {
|
|
189
|
+
return {
|
|
190
|
+
cmd: runtime,
|
|
191
|
+
args: runtime === 'k3d' ? ['cluster', 'delete', name] : ['delete', 'cluster', '--name', name],
|
|
192
|
+
timeoutMs: CLUSTER_DELETE_TIMEOUT_MS,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/** Namespaces on the target context, read so a destructive prompt can name what is on it. */
|
|
196
|
+
export function listNamespacesCommand(context) {
|
|
197
|
+
const args = [
|
|
198
|
+
'get',
|
|
199
|
+
'namespaces',
|
|
200
|
+
'-o',
|
|
201
|
+
'jsonpath={range .items[*]}{.metadata.name}{"\\n"}{end}',
|
|
202
|
+
'--request-timeout=5s',
|
|
203
|
+
];
|
|
204
|
+
return { cmd: 'kubectl', args: context ? [...args, '--context', context] : args };
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Namespaces a cluster did not come with, so "what is about to be lost" names the operator's own
|
|
208
|
+
* workloads rather than the four every cluster has. `cat-factory` is EXCLUDED as system-ish on
|
|
209
|
+
* purpose: it holds only the ServiceAccount this command mints, which a recreate mints again.
|
|
210
|
+
*/
|
|
211
|
+
const SYSTEM_NAMESPACES = new Set([
|
|
212
|
+
'default',
|
|
213
|
+
'kube-system',
|
|
214
|
+
'kube-public',
|
|
215
|
+
'kube-node-lease',
|
|
216
|
+
'local-path-storage',
|
|
217
|
+
CAT_FACTORY_NAMESPACE,
|
|
218
|
+
]);
|
|
219
|
+
export function parseUserNamespaces(stdout) {
|
|
220
|
+
return stdout
|
|
221
|
+
.split('\n')
|
|
222
|
+
.map((line) => line.trim())
|
|
223
|
+
.filter((line) => line.length > 0 && !SYSTEM_NAMESPACES.has(line));
|
|
224
|
+
}
|
|
122
225
|
/** The kubeconfig context name k3d/kind assigns to a cluster it creates. */
|
|
123
226
|
export function contextName(runtime, name) {
|
|
124
227
|
return `${runtime}-${name}`;
|
|
@@ -217,11 +320,50 @@ async function runOrThrow(shell, command, what, hint) {
|
|
|
217
320
|
}
|
|
218
321
|
return result;
|
|
219
322
|
}
|
|
220
|
-
/**
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
323
|
+
/**
|
|
324
|
+
* The two shapes Docker names a refused host port in, and both are common:
|
|
325
|
+
*
|
|
326
|
+
* `Bind for 0.0.0.0:80 failed: port is already allocated`
|
|
327
|
+
* `... Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use`
|
|
328
|
+
*
|
|
329
|
+
* Matching only the first left every collision reported through the second reading as "one of the
|
|
330
|
+
* two ports", which is the misattribution the hint exists to remove.
|
|
331
|
+
*/
|
|
332
|
+
const BOUND_PORT_PATTERNS = [
|
|
333
|
+
/bind for\s+\S*?:(\d+)/i,
|
|
334
|
+
/listen tcp\d?\s+\S*?:(\d+):\s*bind:/i,
|
|
335
|
+
];
|
|
336
|
+
/** The host port a Docker failure names as already bound, when it names one. */
|
|
337
|
+
export function boundPortFromDetail(detail) {
|
|
338
|
+
for (const pattern of BOUND_PORT_PATTERNS) {
|
|
339
|
+
const port = Number(pattern.exec(detail)?.[1]);
|
|
340
|
+
if (Number.isInteger(port) && port > 0)
|
|
341
|
+
return port;
|
|
342
|
+
}
|
|
343
|
+
return undefined;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* An extra hint appended to a create failure that looks like a host-port collision.
|
|
347
|
+
*
|
|
348
|
+
* A create asks for TWO host ports, so the hint READS which one Docker refused out of its own
|
|
349
|
+
* message instead of naming the apiserver port, which it used to do unconditionally and would
|
|
350
|
+
* misattribute an ingress-port collision. Port 80 is taken often enough on Windows and macOS that
|
|
351
|
+
* an opaque `k3d cluster create` failure here is the likely first experience, so the hint names
|
|
352
|
+
* the flag that moves it.
|
|
353
|
+
*/
|
|
354
|
+
export function portCollisionHint(ingressPort) {
|
|
355
|
+
return (detail) => {
|
|
356
|
+
if (!/already (allocated|in use)|address already in use|port is already/i.test(detail))
|
|
357
|
+
return '';
|
|
358
|
+
const bound = boundPortFromDetail(detail);
|
|
359
|
+
if (bound === ingressPort) {
|
|
360
|
+
return ` (host port ${ingressPort} is already in use: free it, or re-run with \`--ingress-port <free port>\`)`;
|
|
361
|
+
}
|
|
362
|
+
if (bound !== undefined) {
|
|
363
|
+
return ` (host port ${bound} is already in use: free it, or remove the conflicting cluster, then re-run)`;
|
|
364
|
+
}
|
|
365
|
+
return ` (a requested host port is already in use, either the apiserver's ${DEFAULT_API_PORT} or the ingress' ${ingressPort}: free it, or re-run with \`--ingress-port <free port>\`)`;
|
|
366
|
+
};
|
|
225
367
|
}
|
|
226
368
|
/** Ask to run a mutating step; `--yes` proceeds without prompting. Declining throws. */
|
|
227
369
|
async function confirmStep(io, options, prompt) {
|
|
@@ -249,32 +391,114 @@ async function readSaToken(deps, context) {
|
|
|
249
391
|
}
|
|
250
392
|
throw new ProvisionError(`The ServiceAccount token Secret "${TOKEN_SECRET_NAME}" never populated. Re-run \`cat-factory k3s\` once the cluster is settled.`);
|
|
251
393
|
}
|
|
394
|
+
/** The distribution behind a create/recreate offer; `null` for the reuse path. */
|
|
395
|
+
export function offerRuntime(chosen) {
|
|
396
|
+
if (chosen === 'create-k3d' || chosen === RECREATE_OFFERS.k3d)
|
|
397
|
+
return 'k3d';
|
|
398
|
+
if (chosen === 'create-kind' || chosen === RECREATE_OFFERS.kind)
|
|
399
|
+
return 'kind';
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
/** The ingress host port a run targets: `--ingress-port`, else {@link DEFAULT_INGRESS_PORT}. */
|
|
403
|
+
export function resolveIngressPort(options) {
|
|
404
|
+
return options.ingressPort ?? DEFAULT_INGRESS_PORT;
|
|
405
|
+
}
|
|
252
406
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
407
|
+
* Destroy a local cluster and build it again from the CURRENT flags, so a recreate is how you
|
|
408
|
+
* change anything that is fixed at create time (the published ingress port above all, but the
|
|
409
|
+
* apiserver port and the name too).
|
|
410
|
+
*
|
|
411
|
+
* Why this is offered at all rather than documented: these clusters are transient and dropping
|
|
412
|
+
* one is routine. The reasons are open-ended (a wedged cluster, one created by hand with the
|
|
413
|
+
* wrong flags, a k3s version bump, namespaces left behind by failed runs), so it is a general
|
|
414
|
+
* operation, not the remedy attached to any one detected condition.
|
|
415
|
+
*
|
|
416
|
+
* Safety, in the order it is enforced:
|
|
417
|
+
*
|
|
418
|
+
* - The TARGET is only ever a k3d/kind cluster the CLI can see BY NAME, which is why the
|
|
419
|
+
* caller resolves `recreate-*` and never `use-existing`. There is no recreate recipe for
|
|
420
|
+
* "whatever the current context points at", and that context can be a shared cluster.
|
|
421
|
+
* - What is about to be lost is READ and named (its non-system namespaces) before the prompt,
|
|
422
|
+
* rather than a generic warning, because a routine operation stays safe only if the prompt
|
|
423
|
+
* shows the thing being destroyed.
|
|
424
|
+
* - `--yes` skips the confirmation ONLY because reaching here at all required `--recreate`,
|
|
425
|
+
* a flag whose entire meaning is "destroy and rebuild". `--yes` on its own can never select
|
|
426
|
+
* this path: the recreate offers are deliberately absent from the recommendation priority,
|
|
427
|
+
* so the destructive intent is always stated and never inferred from "don't prompt me".
|
|
428
|
+
*/
|
|
429
|
+
async function recreateCluster(runtime, clusterName, options, deps) {
|
|
430
|
+
const { io, shell } = deps;
|
|
431
|
+
const context = contextName(runtime, clusterName);
|
|
432
|
+
// Best-effort: a cluster too wedged to answer kubectl is exactly one a recreate fixes, so an
|
|
433
|
+
// unreadable namespace list must not block the operation. It is reported as unread rather than
|
|
434
|
+
// rendered as "nothing on it", which would read like an empty cluster.
|
|
435
|
+
const namespaces = await runCommand(shell, listNamespacesCommand(context));
|
|
436
|
+
const lost = namespaces.code === 0 ? parseUserNamespaces(namespaces.stdout) : null;
|
|
437
|
+
io.warn([
|
|
438
|
+
`About to DESTROY the ${runtime} cluster "${clusterName}" and everything running on it.`,
|
|
439
|
+
lost === null
|
|
440
|
+
? ' Its namespaces could not be read, so this cannot list what is on it.'
|
|
441
|
+
: lost.length === 0
|
|
442
|
+
? ' It holds no namespaces of its own.'
|
|
443
|
+
: ` It holds ${lost.length} namespace(s) of its own: ${lost.join(', ')}`,
|
|
444
|
+
' This cannot be undone.',
|
|
445
|
+
].join('\n'));
|
|
446
|
+
await confirmStep(io, options, `Delete and re-create the ${runtime} cluster "${clusterName}"?`);
|
|
447
|
+
io.info(`Deleting the ${runtime} cluster "${clusterName}"…`);
|
|
448
|
+
await runOrThrow(shell, clusterDeleteCommand(runtime, clusterName), `Deleting the ${runtime} cluster`);
|
|
449
|
+
io.info(`Re-creating the ${runtime} cluster "${clusterName}" (this can take a minute)…`);
|
|
450
|
+
const ingressPort = resolveIngressPort(options);
|
|
451
|
+
const create = clusterCreateCommand(runtime, clusterName, ingressPort);
|
|
452
|
+
const result = await runCommand(shell, create);
|
|
453
|
+
if (result.code !== 0) {
|
|
454
|
+
// Deleted-but-not-recreated is worse than either end, so the failure says WHICH state the
|
|
455
|
+
// host is in and how to leave it, rather than reporting only the create's own error.
|
|
456
|
+
const detail = (result.stderr || result.stdout).trim() || `${create.cmd} exited ${result.code}`;
|
|
457
|
+
throw new ProvisionError(`The ${runtime} cluster "${clusterName}" was DELETED, but re-creating it failed: ${detail}` +
|
|
458
|
+
`${portCollisionHint(ingressPort)(detail)}. Your host now has no cluster by that name. ` +
|
|
459
|
+
`Fix the cause, then run \`cat-factory k3s --runtime ${runtime} --cluster-name ${clusterName} --ingress-port ${ingressPort}\` to create it.`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Provision (create, recreate or reuse) a local cluster for the chosen offer, create the
|
|
464
|
+
* least-privilege ServiceAccount + RBAC, mint a long-lived token, read the apiserver URL, and
|
|
465
|
+
* PROBE whether an ingress-derived environment URL can actually be served, returning the resolved
|
|
466
|
+
* `local-k3s` connection. Every MUTATING step (cluster create/delete, RBAC apply) is behind an
|
|
467
|
+
* explicit confirm unless `--yes`. Idempotent apart from `recreate-*`: an existing cluster/SA is
|
|
468
|
+
* reused, not duplicated. `install-k3s` is NOT handled here (guidance-only).
|
|
258
469
|
*/
|
|
259
470
|
export async function provisionCluster(chosen, state, options, deps) {
|
|
260
471
|
const { io, shell } = deps;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
//
|
|
472
|
+
const ingressPort = resolveIngressPort(options);
|
|
473
|
+
const runtime = offerRuntime(chosen);
|
|
474
|
+
// The kubeconfig context every subsequent command targets. Create/recreate paths get an
|
|
475
|
+
// explicit `--context` (so we never mutate the user's global current-context); reuse operates
|
|
476
|
+
// on the already-current context (`undefined`).
|
|
264
477
|
let targetContext;
|
|
265
478
|
let createdName;
|
|
266
|
-
|
|
479
|
+
// A cluster this run BUILT is given time for its BUNDLED controller to install; anything else is
|
|
480
|
+
// probed once, because that answer is already final. `settleWaitFor` is what decides, and the
|
|
481
|
+
// distinction it draws (kind installs no controller, so waiting cannot change kind's verdict) is
|
|
482
|
+
// the difference between a one-read create and one that burns the whole budget by design.
|
|
483
|
+
let ingressWaitMs = 0;
|
|
484
|
+
if (runtime !== null) {
|
|
267
485
|
const clusterName = options.clusterName ?? OPTION_DEFAULTS.k3sClusterName;
|
|
268
|
-
const runtime = chosen === 'create-kind' ? 'kind' : 'k3d';
|
|
269
486
|
const existing = runtime === 'kind' ? state.detections.kindClusters : state.detections.k3dClusters;
|
|
270
|
-
if (
|
|
487
|
+
if (isRecreateOffer(chosen)) {
|
|
488
|
+
if (!existing.includes(clusterName)) {
|
|
489
|
+
throw new ProvisionError(`There is no ${runtime} cluster named "${clusterName}" to recreate (${runtime} reports: ${existing.join(', ') || 'none'}). Drop --recreate to create it, or name an existing one with --cluster-name.`);
|
|
490
|
+
}
|
|
491
|
+
await recreateCluster(runtime, clusterName, options, deps);
|
|
492
|
+
ingressWaitMs = settleWaitFor(runtime);
|
|
493
|
+
}
|
|
494
|
+
else if (existing.includes(clusterName)) {
|
|
271
495
|
io.info(`Reusing the existing ${runtime} cluster "${clusterName}".`);
|
|
272
496
|
}
|
|
273
497
|
else {
|
|
274
498
|
await confirmStep(io, options, `Create a local ${runtime} cluster "${clusterName}"?`);
|
|
275
499
|
io.info(`Creating the ${runtime} cluster "${clusterName}" (this can take a minute)…`);
|
|
276
|
-
|
|
277
|
-
|
|
500
|
+
await runOrThrow(shell, clusterCreateCommand(runtime, clusterName, ingressPort), `Creating the ${runtime} cluster`, portCollisionHint(ingressPort));
|
|
501
|
+
ingressWaitMs = settleWaitFor(runtime);
|
|
278
502
|
}
|
|
279
503
|
targetContext = contextName(runtime, clusterName);
|
|
280
504
|
createdName = clusterName;
|
|
@@ -283,6 +507,12 @@ export async function provisionCluster(chosen, state, options, deps) {
|
|
|
283
507
|
// use-existing: operate on the current context (its name is what the probe detected).
|
|
284
508
|
targetContext = undefined;
|
|
285
509
|
}
|
|
510
|
+
// The cluster whose published host ports can be read, and the one `--recreate` could name: the
|
|
511
|
+
// cluster this run built, or on the reuse path whichever k3d/kind cluster the current context
|
|
512
|
+
// resolves to (`null` for anything else, e.g. a bare k3s service).
|
|
513
|
+
const clusterTarget = runtime !== null && createdName !== undefined
|
|
514
|
+
? { runtime, clusterName: createdName }
|
|
515
|
+
: recreateTargetForContext(state.detections);
|
|
286
516
|
// Read the apiserver URL first (a read-only op): it names the target in the confirm below and
|
|
287
517
|
// gates the reuse path against accidentally mutating a non-local cluster.
|
|
288
518
|
const apiServer = await runOrThrow(shell, readApiServerCommand(targetContext), 'Reading the apiserver URL');
|
|
@@ -292,7 +522,7 @@ export async function provisionCluster(chosen, state, options, deps) {
|
|
|
292
522
|
}
|
|
293
523
|
const contextLabel = state.detections.clusterContext;
|
|
294
524
|
const targetDescription = createdName
|
|
295
|
-
? `the ${
|
|
525
|
+
? `the ${runtime} cluster "${createdName}" (${apiServerUrl})`
|
|
296
526
|
: contextLabel
|
|
297
527
|
? `context "${contextLabel}" (${apiServerUrl})`
|
|
298
528
|
: `the current cluster (${apiServerUrl})`;
|
|
@@ -306,12 +536,34 @@ export async function provisionCluster(chosen, state, options, deps) {
|
|
|
306
536
|
await runOrThrow(shell, applyRbacCommand(targetContext), 'Applying the RBAC manifest');
|
|
307
537
|
io.info('Minting the ServiceAccount token…');
|
|
308
538
|
const apiToken = await readSaToken(deps, targetContext);
|
|
539
|
+
io.info('Checking whether this cluster can serve an ingress-derived environment URL…');
|
|
540
|
+
const ingress = await probeIngress({ shell, tcp: deps.tcp, sleep: deps.sleep, now: deps.now }, {
|
|
541
|
+
context: targetContext,
|
|
542
|
+
port: ingressPort,
|
|
543
|
+
waitMs: ingressWaitMs,
|
|
544
|
+
...(clusterTarget ? { cluster: clusterTarget } : {}),
|
|
545
|
+
});
|
|
309
546
|
return {
|
|
310
547
|
engine: 'local-k3s',
|
|
311
548
|
clusterName: createdName,
|
|
549
|
+
...(runtime !== null ? { runtime } : {}),
|
|
312
550
|
apiServerUrl,
|
|
313
551
|
apiToken,
|
|
314
552
|
insecureSkipTlsVerify: true,
|
|
553
|
+
ingress,
|
|
554
|
+
...(clusterTarget ? { recreateTarget: clusterTarget } : {}),
|
|
315
555
|
};
|
|
316
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* How long a freshly built cluster is given before its ingress verdict is final.
|
|
559
|
+
*
|
|
560
|
+
* k3d/k3s install Traefik through a HelmChart Job that completes ~20-30s AFTER the create returns,
|
|
561
|
+
* so judging immediately would report a definitive `missing` for a cluster that is merely still
|
|
562
|
+
* starting. kind installs NO controller (by design, see {@link kindClusterConfig}), so its verdict
|
|
563
|
+
* is final the moment the create returns, and waiting would spend the whole budget re-reading a
|
|
564
|
+
* fact that cannot change.
|
|
565
|
+
*/
|
|
566
|
+
function settleWaitFor(runtime) {
|
|
567
|
+
return runtime === 'kind' ? 0 : INGRESS_SETTLE_WAIT_MS;
|
|
568
|
+
}
|
|
317
569
|
//# sourceMappingURL=k3s-provision.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k3s-provision.js","sourceRoot":"","sources":["../src/k3s-provision.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"k3s-provision.js","sourceRoot":"","sources":["../src/k3s-provision.ts"],"names":[],"mappings":"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"}
|