@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
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { connect } from 'node:net';
|
|
2
|
+
import { COMMAND_NOT_FOUND, COMMAND_TIMED_OUT, runCommand, } from './host-shell.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whether an environment URL derived from an ingress HOST TEMPLATE can actually be served, which
|
|
5
|
+
* takes two independent things and not one:
|
|
6
|
+
*
|
|
7
|
+
* 1. an ingress CONTROLLER inside the cluster (an `IngressClass` is its observable trace), and
|
|
8
|
+
* 2. a HOST PORT published into it, because every local distribution runs the cluster inside
|
|
9
|
+
* Docker and forwards only the ports it was asked for at create time.
|
|
10
|
+
*
|
|
11
|
+
* Both were previously assumed. `cat-factory k3s` printed `{{branch}}.127.0.0.1.nip.io` as wired
|
|
12
|
+
* on every path, including a reused cluster it had never looked at, and the failure landed at the
|
|
13
|
+
* `tester` step against a URL that answered nothing: environment readiness is WORKLOAD readiness,
|
|
14
|
+
* so provisioning still reported success.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Default host port published into the ingress controller's plain-HTTP entrypoint.
|
|
18
|
+
*
|
|
19
|
+
* ONE port is published and it maps to the controller's plain-HTTP entrypoint, so `http` is the
|
|
20
|
+
* scheme that port serves and the only one the CLI can claim. Publishing the TLS entrypoint
|
|
21
|
+
* instead would trade a connection error for a CERTIFICATE error, because a local ingress
|
|
22
|
+
* controller serves a self-signed default cert: a worse version of the failure this module exists
|
|
23
|
+
* to remove, since it surfaces at the tester rather than here.
|
|
24
|
+
*/
|
|
25
|
+
export const DEFAULT_INGRESS_PORT = 80;
|
|
26
|
+
/**
|
|
27
|
+
* The host the rendered template resolves to. `nip.io` is wildcard DNS that maps
|
|
28
|
+
* `<anything>.127.0.0.1.nip.io` to loopback with no local DNS setup, so the port probe below
|
|
29
|
+
* targets loopback directly rather than resolving a sample hostname.
|
|
30
|
+
*/
|
|
31
|
+
export const INGRESS_PROBE_HOST = '127.0.0.1';
|
|
32
|
+
/**
|
|
33
|
+
* The ingress HOST template, with no port in it. It is deliberately portless: the rendered value
|
|
34
|
+
* is also the Ingress `spec.rules[].host` a service's manifests declare, and Kubernetes rejects a
|
|
35
|
+
* `host` carrying a port. A non-default host port travels as the URL source's own `port` field
|
|
36
|
+
* instead (see {@link ingressUrlPort}).
|
|
37
|
+
*/
|
|
38
|
+
export const INGRESS_HOST_TEMPLATE = '{{branch}}.127.0.0.1.nip.io';
|
|
39
|
+
/** The container port an ingress controller serves plain HTTP on (Traefik `web`, nginx `http`). */
|
|
40
|
+
export const INGRESS_CONTAINER_HTTP_PORT = 80;
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Pure planners + reduction: no shell-out, no sockets, so unit-testable alone.
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
/** `kubectl get ingressclass -o json`, targeting `context` when one is supplied. */
|
|
45
|
+
export function listIngressClassesCommand(context) {
|
|
46
|
+
const args = ['get', 'ingressclass', '-o', 'json', '--request-timeout=5s'];
|
|
47
|
+
return { cmd: 'kubectl', args: context ? [...args, '--context', context] : args };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* `docker port <cluster container>`: every host port the cluster's own container forwards. This is
|
|
51
|
+
* the ONLY check that attributes an answering host port to the cluster rather than to whatever
|
|
52
|
+
* else may be bound there, and it is the same one used by hand to establish that a default k3d
|
|
53
|
+
* create publishes nothing but the apiserver.
|
|
54
|
+
*
|
|
55
|
+
* The container is the one each distribution puts the forward on: k3d's load balancer, kind's
|
|
56
|
+
* control-plane node. The whole table is asked for rather than one port, because a container that
|
|
57
|
+
* forwards NOTHING answers that with an empty success, where naming the port makes the same
|
|
58
|
+
* cluster fail exactly as an unknown container does.
|
|
59
|
+
*/
|
|
60
|
+
export function publishedPortsCommand(runtime, clusterName) {
|
|
61
|
+
const container = runtime === 'k3d' ? `k3d-${clusterName}-serverlb` : `${clusterName}-control-plane`;
|
|
62
|
+
return { cmd: 'docker', args: ['port', container] };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Host ports mapped to the ingress container port, out of `docker port` output
|
|
66
|
+
* (`80/tcp -> 0.0.0.0:18080`, one mapping per line). Reads the text after the LAST colon so an
|
|
67
|
+
* IPv6 bind address (`[::]:18080`) does not parse as the port.
|
|
68
|
+
*/
|
|
69
|
+
export function parsePublishedHostPorts(stdout) {
|
|
70
|
+
const ports = new Set();
|
|
71
|
+
for (const line of stdout.split('\n')) {
|
|
72
|
+
const [containerPort, hostAddress] = line.split('->').map((part) => part.trim());
|
|
73
|
+
if (containerPort !== `${INGRESS_CONTAINER_HTTP_PORT}/tcp` || !hostAddress)
|
|
74
|
+
continue;
|
|
75
|
+
const port = Number(hostAddress.slice(hostAddress.lastIndexOf(':') + 1));
|
|
76
|
+
if (Number.isInteger(port) && port > 0)
|
|
77
|
+
ports.add(port);
|
|
78
|
+
}
|
|
79
|
+
return [...ports];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Controller names out of a `kubectl get ingressclass -o json` payload (an `items` list).
|
|
83
|
+
* Returns `null` for anything unparseable, which the reduction reports as `unknown` rather than
|
|
84
|
+
* as an absent controller.
|
|
85
|
+
*/
|
|
86
|
+
export function parseIngressClasses(stdout) {
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(stdout);
|
|
89
|
+
if (!Array.isArray(parsed.items))
|
|
90
|
+
return null;
|
|
91
|
+
return parsed.items
|
|
92
|
+
.map((item) => {
|
|
93
|
+
const spec = item?.spec;
|
|
94
|
+
const name = item?.metadata?.name;
|
|
95
|
+
if (typeof spec?.controller === 'string' && spec.controller.length > 0)
|
|
96
|
+
return spec.controller;
|
|
97
|
+
return typeof name === 'string' && name.length > 0 ? name : undefined;
|
|
98
|
+
})
|
|
99
|
+
.filter((c) => c !== undefined);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** How much of a command's own error output a message carries before it stops being readable. */
|
|
106
|
+
const DETAIL_CAP = 300;
|
|
107
|
+
/** The first line of a failure's output, capped, so a message names the cause it was given. */
|
|
108
|
+
function firstDetailLine(result) {
|
|
109
|
+
const raw = (result.stderr || result.stdout).trim().split('\n')[0]?.trim() ?? '';
|
|
110
|
+
return raw.length > DETAIL_CAP ? `${raw.slice(0, DETAIL_CAP)}…` : raw;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Turn the `kubectl get ingressclass` result into a read outcome that NAMES its cause.
|
|
114
|
+
*
|
|
115
|
+
* The shell already distinguishes a missing binary from a watchdog kill from a real non-zero
|
|
116
|
+
* exit, and the exit carries the apiserver's own words (an RBAC refusal, a bad context). Throwing
|
|
117
|
+
* that away and reporting "could not read the cluster's IngressClasses" is the degrade-quietly
|
|
118
|
+
* failure: four fixes, one message, and a remedy that fits none of them.
|
|
119
|
+
*/
|
|
120
|
+
export function readIngressClasses(result) {
|
|
121
|
+
if (result.code === COMMAND_NOT_FOUND) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
cause: 'kubectl-missing',
|
|
125
|
+
detail: 'kubectl is not installed, or not on PATH',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (result.code === COMMAND_TIMED_OUT) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
cause: 'cluster-unreachable',
|
|
132
|
+
detail: 'the apiserver did not answer before the probe timed out',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (result.code !== 0) {
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
cause: 'cluster-refused',
|
|
139
|
+
detail: firstDetailLine(result) || `kubectl exited ${result.code}`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const controllers = parseIngressClasses(result.stdout);
|
|
143
|
+
if (controllers === null) {
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
cause: 'unparseable',
|
|
147
|
+
detail: 'kubectl answered with something this could not read as an IngressClass list',
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return { ok: true, controllers };
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Reduce the probed facts to one verdict.
|
|
154
|
+
*
|
|
155
|
+
* An UNREADABLE cluster is `unknown` outright: with no controller list, neither half is settled.
|
|
156
|
+
* An EMPTY list is a definitive `missing`, even when the port probe could not tell, because a
|
|
157
|
+
* cluster with no ingress controller cannot serve the URL whatever the host port does.
|
|
158
|
+
*
|
|
159
|
+
* The PUBLICATION check outranks the socket on the port half, in both directions: a runtime that
|
|
160
|
+
* reports the cluster forwarding no such host port makes an answering socket somebody ELSE'S
|
|
161
|
+
* listener (the case that used to read as ready), and one that reports the forward makes an
|
|
162
|
+
* answering socket attributable to the cluster rather than merely coincident with it.
|
|
163
|
+
*/
|
|
164
|
+
export function classifyIngress(facts) {
|
|
165
|
+
const { port, classes, hostPort, publication } = facts;
|
|
166
|
+
if (!classes.ok) {
|
|
167
|
+
return {
|
|
168
|
+
status: 'unknown',
|
|
169
|
+
port,
|
|
170
|
+
cause: classes.cause,
|
|
171
|
+
probeFailure: classes.detail,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const published = publication.checked ? publication.hostPorts.includes(port) : undefined;
|
|
175
|
+
const gaps = [];
|
|
176
|
+
if (classes.controllers.length === 0)
|
|
177
|
+
gaps.push('controller');
|
|
178
|
+
if (hostPort === 'closed' || published === false)
|
|
179
|
+
gaps.push('hostPort');
|
|
180
|
+
if (gaps.length > 0) {
|
|
181
|
+
const elsewhere = publication.checked
|
|
182
|
+
? publication.hostPorts.find((p) => p !== port)
|
|
183
|
+
: undefined;
|
|
184
|
+
return {
|
|
185
|
+
status: 'missing',
|
|
186
|
+
port,
|
|
187
|
+
gaps,
|
|
188
|
+
...(published === false && elsewhere !== undefined ? { publishedOn: elsewhere } : {}),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
if (hostPort === 'unknown') {
|
|
192
|
+
return {
|
|
193
|
+
status: 'unknown',
|
|
194
|
+
port,
|
|
195
|
+
cause: 'host-port-filtered',
|
|
196
|
+
probeFailure: `nothing answered on host port ${port} and the probe could not tell whether it is closed or filtered`,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
status: 'ready',
|
|
201
|
+
port,
|
|
202
|
+
controller: classes.controllers[0] ?? 'unknown',
|
|
203
|
+
attribution: published === true ? 'cluster' : 'unattributed',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The remedy for each gap, rendered from what the probe just read.
|
|
208
|
+
*
|
|
209
|
+
* A missing HOST PORT has exactly one fix on every local distribution: neither k3d's `-p` nor
|
|
210
|
+
* kind's `extraPortMappings` can be added to a cluster that already exists, so the cluster has to
|
|
211
|
+
* be built again. That is why a recreate is named here rather than a `docker` incantation that
|
|
212
|
+
* does not work.
|
|
213
|
+
*/
|
|
214
|
+
export function ingressRemedies(readiness, context = {}) {
|
|
215
|
+
const { runtime, recreateCommand } = context;
|
|
216
|
+
if (readiness.status === 'ready')
|
|
217
|
+
return [];
|
|
218
|
+
if (readiness.status === 'unknown')
|
|
219
|
+
return [...unknownRemedies(readiness), URL_SOURCE_ALTERNATIVE];
|
|
220
|
+
const lines = [];
|
|
221
|
+
if (readiness.gaps.includes('controller')) {
|
|
222
|
+
lines.push(runtime === 'kind'
|
|
223
|
+
? 'kind ships no ingress controller. Install one, e.g. `kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml`, then wait for it to be Ready.'
|
|
224
|
+
: 'The cluster has no ingress controller. A default k3d/k3s cluster installs Traefik unless it was created with `--disable=traefik`; install an ingress controller, or build the cluster again without that flag.');
|
|
225
|
+
}
|
|
226
|
+
if (readiness.gaps.includes('hostPort')) {
|
|
227
|
+
lines.push(readiness.publishedOn !== undefined
|
|
228
|
+
? `The cluster publishes its ingress controller on host port ${readiness.publishedOn}, not ${readiness.port}. Re-run with \`--ingress-port ${readiness.publishedOn}\` to use it as it is.`
|
|
229
|
+
: `Nothing on the host serves port ${readiness.port} for this cluster. A published host port cannot be added to an existing k3d/kind cluster, so the cluster has to be created again:`);
|
|
230
|
+
if (readiness.publishedOn === undefined) {
|
|
231
|
+
lines.push(recreateCommand
|
|
232
|
+
? ` ${recreateCommand}`
|
|
233
|
+
: 'This command can only rebuild a k3d/kind cluster it can name, which this is not, so re-create it with the tool that made it, publishing the host port into the ingress controller.');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
lines.push(URL_SOURCE_ALTERNATIVE);
|
|
237
|
+
return lines;
|
|
238
|
+
}
|
|
239
|
+
/** The fix that needs no cluster change at all, and therefore applies to every negative verdict. */
|
|
240
|
+
const URL_SOURCE_ALTERNATIVE = 'Or leave ingress alone and switch the connect form\'s "Environment URL source" to "Service status", naming the Service your manifests expose.';
|
|
241
|
+
/** One remedy per {@link IngressProbeCause}, because each cause needs a different thing done. */
|
|
242
|
+
function unknownRemedies(readiness) {
|
|
243
|
+
const byHand = `Check it by hand: \`kubectl get ingressclass\` and \`curl -sv http://cat-factory-probe.127.0.0.1.nip.io:${readiness.port}/\`.`;
|
|
244
|
+
switch (readiness.cause) {
|
|
245
|
+
case 'kubectl-missing':
|
|
246
|
+
return [
|
|
247
|
+
'Install `kubectl` (or put it on PATH) and re-run `cat-factory k3s`: without it nothing can read what the cluster runs.',
|
|
248
|
+
];
|
|
249
|
+
case 'cluster-unreachable':
|
|
250
|
+
return [
|
|
251
|
+
'The apiserver did not answer. Check the cluster is up and the context points at it (`kubectl cluster-info`), then re-run `cat-factory k3s`.',
|
|
252
|
+
byHand,
|
|
253
|
+
];
|
|
254
|
+
case 'cluster-refused':
|
|
255
|
+
return [
|
|
256
|
+
`The cluster refused the read: ${readiness.probeFailure}. If that is an RBAC refusal, use a context allowed to list ingressclasses; then re-run \`cat-factory k3s\`.`,
|
|
257
|
+
byHand,
|
|
258
|
+
];
|
|
259
|
+
case 'unparseable':
|
|
260
|
+
return [`Read it by hand: \`kubectl get ingressclass -o json\`.`];
|
|
261
|
+
case 'host-port-filtered':
|
|
262
|
+
return [
|
|
263
|
+
`Nothing answered on host port ${readiness.port}, and a dropped packet is not a closed port, so this is undecided rather than missing. Check what is bound there (a firewall silently dropping the connection looks the same), then re-run \`cat-factory k3s\`.`,
|
|
264
|
+
byHand,
|
|
265
|
+
];
|
|
266
|
+
default:
|
|
267
|
+
return refuseUnknownCause(readiness.cause);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* A cause outside {@link IngressProbeCause}. The `never` parameter keeps the switch above total at
|
|
272
|
+
* COMPILE time (a new cause with no remedy stops building) while still refusing a value the union
|
|
273
|
+
* never had, rather than falling off the end and rendering an empty remedy list.
|
|
274
|
+
*/
|
|
275
|
+
function refuseUnknownCause(cause) {
|
|
276
|
+
throw new Error(`Unhandled ingress probe cause '${String(cause)}'`);
|
|
277
|
+
}
|
|
278
|
+
export function ingressHostTemplate(readiness) {
|
|
279
|
+
return readiness.status === 'ready' ? INGRESS_HOST_TEMPLATE : null;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* The `port` an `ingressTemplate` URL source should carry: the verified host port when it is not
|
|
283
|
+
* the scheme's default, else `null` (the derivation composes `scheme://host` with no port).
|
|
284
|
+
*/
|
|
285
|
+
export function ingressUrlPort(readiness) {
|
|
286
|
+
if (readiness.status !== 'ready')
|
|
287
|
+
return null;
|
|
288
|
+
return readiness.port === DEFAULT_INGRESS_PORT ? null : readiness.port;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The real, socket-backed probe.
|
|
292
|
+
*
|
|
293
|
+
* `ECONNREFUSED` is the one error that settles the negative: something answered the SYN with a
|
|
294
|
+
* reset, so nothing is listening. A timeout or any other error leaves it undecided (a firewall
|
|
295
|
+
* drops packets silently), and the reduction above keeps that distinct.
|
|
296
|
+
*/
|
|
297
|
+
export function createNodeTcpProbe() {
|
|
298
|
+
return {
|
|
299
|
+
probe(host, port, timeoutMs) {
|
|
300
|
+
return new Promise((resolve) => {
|
|
301
|
+
let settled = false;
|
|
302
|
+
const finish = (state) => {
|
|
303
|
+
if (settled)
|
|
304
|
+
return;
|
|
305
|
+
settled = true;
|
|
306
|
+
socket.destroy();
|
|
307
|
+
resolve(state);
|
|
308
|
+
};
|
|
309
|
+
const socket = connect({ host, port });
|
|
310
|
+
socket.setTimeout(timeoutMs);
|
|
311
|
+
socket.on('connect', () => finish('open'));
|
|
312
|
+
socket.on('timeout', () => finish('unknown'));
|
|
313
|
+
socket.on('error', (err) => finish(err.code === 'ECONNREFUSED' ? 'closed' : 'unknown'));
|
|
314
|
+
});
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/** How long a freshly created cluster is given to bring its bundled controller up. */
|
|
319
|
+
export const INGRESS_SETTLE_WAIT_MS = 90_000;
|
|
320
|
+
const ATTEMPT_INTERVAL_MS = 2_000;
|
|
321
|
+
const PORT_PROBE_TIMEOUT_MS = 2_000;
|
|
322
|
+
const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
323
|
+
/**
|
|
324
|
+
* Probe every half and reduce, retrying while `waitMs` of WALL CLOCK remains.
|
|
325
|
+
*
|
|
326
|
+
* The wait exists because a k3d cluster's bundled Traefik is installed by a Job that completes
|
|
327
|
+
* ~20-30s AFTER `k3d cluster create` returns: probing once, immediately, would report a
|
|
328
|
+
* definitive `missing` for a cluster that is merely still starting, which is the same class of
|
|
329
|
+
* lie as the promise this replaces. A settled cluster answers on the first attempt, so the wait
|
|
330
|
+
* costs nothing on the reuse path, where callers pass 0.
|
|
331
|
+
*
|
|
332
|
+
* The budget covers the attempts as well as the gaps between them, so a run whose every probe is
|
|
333
|
+
* slow gives up on time rather than multiplying the deadline by the cost of an attempt.
|
|
334
|
+
*/
|
|
335
|
+
export async function probeIngress(deps, options) {
|
|
336
|
+
const sleep = deps.sleep ?? realSleep;
|
|
337
|
+
const now = deps.now ?? Date.now;
|
|
338
|
+
const deadline = now() + (options.waitMs ?? 0);
|
|
339
|
+
for (;;) {
|
|
340
|
+
const [classes, hostPort, publication] = await Promise.all([
|
|
341
|
+
runCommand(deps.shell, listIngressClassesCommand(options.context)),
|
|
342
|
+
deps.tcp.probe(INGRESS_PROBE_HOST, options.port, PORT_PROBE_TIMEOUT_MS),
|
|
343
|
+
readPortPublication(deps.shell, options.cluster),
|
|
344
|
+
]);
|
|
345
|
+
const last = classifyIngress({
|
|
346
|
+
port: options.port,
|
|
347
|
+
classes: readIngressClasses(classes),
|
|
348
|
+
hostPort,
|
|
349
|
+
publication,
|
|
350
|
+
});
|
|
351
|
+
if (last.status === 'ready' || now() + ATTEMPT_INTERVAL_MS > deadline)
|
|
352
|
+
return last;
|
|
353
|
+
await sleep(ATTEMPT_INTERVAL_MS);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Ask the container runtime which host ports the cluster forwards its controller entrypoint to.
|
|
358
|
+
*
|
|
359
|
+
* Any failure is `checked: false`, never "publishes nothing": the container may be named
|
|
360
|
+
* differently (a `--no-lb` k3d cluster has no load balancer at all), Docker may not be the
|
|
361
|
+
* runtime, or there may be no Docker. Reading a failure as a definitive negative would send an
|
|
362
|
+
* operator to rebuild a cluster whose port was fine.
|
|
363
|
+
*/
|
|
364
|
+
async function readPortPublication(shell, cluster) {
|
|
365
|
+
if (!cluster)
|
|
366
|
+
return { checked: false };
|
|
367
|
+
const result = await runCommand(shell, publishedPortsCommand(cluster.runtime, cluster.clusterName));
|
|
368
|
+
if (result.code !== 0)
|
|
369
|
+
return { checked: false };
|
|
370
|
+
return { checked: true, hostPorts: parsePublishedHostPorts(result.stdout) };
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=k3s-ingress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k3s-ingress.js","sourceRoot":"","sources":["../src/k3s-ingress.ts"],"names":[],"mappings":"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"}
|
package/dist/k3s-probe.d.ts
CHANGED
|
@@ -28,7 +28,42 @@ export interface HostDetections {
|
|
|
28
28
|
kindClusters: string[];
|
|
29
29
|
}
|
|
30
30
|
/** The setup paths the probe can offer. */
|
|
31
|
-
export type OfferId = 'use-existing' | 'create-k3d' | 'create-kind' | 'install-k3s';
|
|
31
|
+
export type OfferId = 'use-existing' | 'create-k3d' | 'create-kind' | 'recreate-k3d' | 'recreate-kind' | 'install-k3s';
|
|
32
|
+
/**
|
|
33
|
+
* The DESTRUCTIVE offers, keyed by the runtime each one rebuilds. This is the ONE definition of
|
|
34
|
+
* the recreate set: {@link recreateOfferFor} resolves `--recreate`'s target from it and
|
|
35
|
+
* {@link isRecreateOffer} recognises one, so a `K3sRuntime` with no entry cannot be folded into a
|
|
36
|
+
* neighbour's branch by a two-way ternary.
|
|
37
|
+
*
|
|
38
|
+
* `k3s` has no entry deliberately: it is a HOST SERVICE (a systemd unit installed by `curl | sh`,
|
|
39
|
+
* which this CLI only ever prints), so there is no cluster for the CLI to delete and build again.
|
|
40
|
+
*/
|
|
41
|
+
export declare const RECREATE_OFFERS: {
|
|
42
|
+
readonly k3d: 'recreate-k3d';
|
|
43
|
+
readonly kind: 'recreate-kind';
|
|
44
|
+
};
|
|
45
|
+
/** A runtime `--recreate` can target: one with an entry in {@link RECREATE_OFFERS}. */
|
|
46
|
+
export type RecreatableRuntime = keyof typeof RECREATE_OFFERS;
|
|
47
|
+
export type RecreateOfferId = (typeof RECREATE_OFFERS)[RecreatableRuntime];
|
|
48
|
+
/** The recreate offer for a runtime, or `null` when that runtime has no recreate at all. */
|
|
49
|
+
export declare function recreateOfferFor(runtime: K3sRuntime): RecreateOfferId | null;
|
|
50
|
+
/** Whether an offer is one of the destructive ones. */
|
|
51
|
+
export declare function isRecreateOffer(id: OfferId): id is RecreateOfferId;
|
|
52
|
+
/**
|
|
53
|
+
* The k3d/kind cluster a REUSED kubeconfig context names, when the CLI can both name it and build
|
|
54
|
+
* it again. `null` for anything else (a bare k3s host service, a shared cluster, a context whose
|
|
55
|
+
* cluster the runtime no longer reports).
|
|
56
|
+
*
|
|
57
|
+
* This exists because a remedy has to be a command that WORKS. `--recreate`'s target rule is
|
|
58
|
+
* exactly "a k3d/kind cluster this command can name", and on the reuse path nothing else knows
|
|
59
|
+
* which cluster that is: the offer was `use-existing`, so no name was passed. Without this, the
|
|
60
|
+
* missing-host-port remedy printed `cat-factory k3s --recreate` against the DEFAULT name, which
|
|
61
|
+
* `chooseOffer` then refused for any cluster not called `cat-factory`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function recreateTargetForContext(d: HostDetections): {
|
|
64
|
+
runtime: RecreatableRuntime;
|
|
65
|
+
clusterName: string;
|
|
66
|
+
} | null;
|
|
32
67
|
/** One offered setup path, with whether it's currently possible + why not. */
|
|
33
68
|
export interface Offer {
|
|
34
69
|
id: OfferId;
|
|
@@ -51,7 +86,7 @@ export interface HostState {
|
|
|
51
86
|
* `install-k3s` offer's copy — k3s is Linux-only, so on Windows/macOS that path points at
|
|
52
87
|
* k3s-in-Docker via k3d instead of a `curl | sh` install that can't run there.
|
|
53
88
|
*/
|
|
54
|
-
export declare function classifyHost(d: HostDetections, preferred?: K3sRuntime, platform?: NodeJS.Platform): HostState;
|
|
89
|
+
export declare function classifyHost(d: HostDetections, preferred?: K3sRuntime, platform?: NodeJS.Platform, clusterName?: string): HostState;
|
|
55
90
|
/** Parse `k3d cluster list --output json` (an array of `{ name }`) into cluster names. */
|
|
56
91
|
export declare function parseK3dClusters(stdout: string): string[];
|
|
57
92
|
/** Parse `kind get clusters` (newline-separated names; a "No kind clusters" note ⇒ empty). */
|
|
@@ -74,5 +109,5 @@ export declare function hasServerVersion(stdout: string): boolean;
|
|
|
74
109
|
* `--request-timeout` — a kubeconfig pointing at a down cluster then fails fast instead of hanging
|
|
75
110
|
* the probe (the {@link HostShell} watchdog is the outer backstop).
|
|
76
111
|
*/
|
|
77
|
-
export declare function probeHost(shell: HostShell, preferred?: K3sRuntime, platform?: NodeJS.Platform): Promise<HostState>;
|
|
112
|
+
export declare function probeHost(shell: HostShell, preferred?: K3sRuntime, platform?: NodeJS.Platform, clusterName?: string): Promise<HostState>;
|
|
78
113
|
//# sourceMappingURL=k3s-probe.d.ts.map
|
package/dist/k3s-probe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k3s-probe.d.ts","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"k3s-probe.d.ts","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"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"}
|
package/dist/k3s-probe.js
CHANGED
|
@@ -1,9 +1,66 @@
|
|
|
1
|
-
import {} from './args.js';
|
|
1
|
+
import { OPTION_DEFAULTS } from './args.js';
|
|
2
2
|
import { COMMAND_NOT_FOUND } from './host-shell.js';
|
|
3
|
+
/** The cluster name the recreate offers key off when `--cluster-name` was not supplied. */
|
|
4
|
+
const DEFAULT_CLUSTER_NAME = OPTION_DEFAULTS.k3sClusterName;
|
|
5
|
+
/**
|
|
6
|
+
* The DESTRUCTIVE offers, keyed by the runtime each one rebuilds. This is the ONE definition of
|
|
7
|
+
* the recreate set: {@link recreateOfferFor} resolves `--recreate`'s target from it and
|
|
8
|
+
* {@link isRecreateOffer} recognises one, so a `K3sRuntime` with no entry cannot be folded into a
|
|
9
|
+
* neighbour's branch by a two-way ternary.
|
|
10
|
+
*
|
|
11
|
+
* `k3s` has no entry deliberately: it is a HOST SERVICE (a systemd unit installed by `curl | sh`,
|
|
12
|
+
* which this CLI only ever prints), so there is no cluster for the CLI to delete and build again.
|
|
13
|
+
*/
|
|
14
|
+
export const RECREATE_OFFERS = {
|
|
15
|
+
k3d: 'recreate-k3d',
|
|
16
|
+
kind: 'recreate-kind',
|
|
17
|
+
};
|
|
18
|
+
/** The recreate offer for a runtime, or `null` when that runtime has no recreate at all. */
|
|
19
|
+
export function recreateOfferFor(runtime) {
|
|
20
|
+
return runtime in RECREATE_OFFERS ? RECREATE_OFFERS[runtime] : null;
|
|
21
|
+
}
|
|
22
|
+
/** Whether an offer is one of the destructive ones. */
|
|
23
|
+
export function isRecreateOffer(id) {
|
|
24
|
+
return Object.values(RECREATE_OFFERS).includes(id);
|
|
25
|
+
}
|
|
26
|
+
/** kubeconfig context prefixes k3d/kind assign, paired with the runtime that owns them. */
|
|
27
|
+
const CONTEXT_RUNTIMES = [
|
|
28
|
+
['k3d-', 'k3d'],
|
|
29
|
+
['kind-', 'kind'],
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* The k3d/kind cluster a REUSED kubeconfig context names, when the CLI can both name it and build
|
|
33
|
+
* it again. `null` for anything else (a bare k3s host service, a shared cluster, a context whose
|
|
34
|
+
* cluster the runtime no longer reports).
|
|
35
|
+
*
|
|
36
|
+
* This exists because a remedy has to be a command that WORKS. `--recreate`'s target rule is
|
|
37
|
+
* exactly "a k3d/kind cluster this command can name", and on the reuse path nothing else knows
|
|
38
|
+
* which cluster that is: the offer was `use-existing`, so no name was passed. Without this, the
|
|
39
|
+
* missing-host-port remedy printed `cat-factory k3s --recreate` against the DEFAULT name, which
|
|
40
|
+
* `chooseOffer` then refused for any cluster not called `cat-factory`.
|
|
41
|
+
*/
|
|
42
|
+
export function recreateTargetForContext(d) {
|
|
43
|
+
const context = d.clusterContext;
|
|
44
|
+
if (!context)
|
|
45
|
+
return null;
|
|
46
|
+
for (const [prefix, runtime] of CONTEXT_RUNTIMES) {
|
|
47
|
+
if (!context.startsWith(prefix))
|
|
48
|
+
continue;
|
|
49
|
+
const clusterName = context.slice(prefix.length);
|
|
50
|
+
const known = runtime === 'kind' ? d.kindClusters : d.k3dClusters;
|
|
51
|
+
if (clusterName.length > 0 && known.includes(clusterName))
|
|
52
|
+
return { runtime, clusterName };
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
3
56
|
/**
|
|
4
57
|
* Priority order for picking the recommendation, given the user's preferred runtime. A live cluster
|
|
5
58
|
* always wins; otherwise the preferred distribution's create/install path is tried first, then the
|
|
6
59
|
* others as fallbacks. Every list ends with `install-k3s`, which is always available.
|
|
60
|
+
*
|
|
61
|
+
* The `recreate-*` offers appear in NO list, deliberately: they destroy a cluster, and a
|
|
62
|
+
* recommendation is what `--yes` follows when nobody is watching. They are reachable only by an
|
|
63
|
+
* explicit `--recreate` or an interactive pick, so the destructive intent is always stated.
|
|
7
64
|
*/
|
|
8
65
|
function offerPriority(preferred) {
|
|
9
66
|
switch (preferred) {
|
|
@@ -23,7 +80,7 @@ function offerPriority(preferred) {
|
|
|
23
80
|
* `install-k3s` offer's copy — k3s is Linux-only, so on Windows/macOS that path points at
|
|
24
81
|
* k3s-in-Docker via k3d instead of a `curl | sh` install that can't run there.
|
|
25
82
|
*/
|
|
26
|
-
export function classifyHost(d, preferred = 'k3d', platform = 'linux') {
|
|
83
|
+
export function classifyHost(d, preferred = 'k3d', platform = 'linux', clusterName = DEFAULT_CLUSTER_NAME) {
|
|
27
84
|
const useExisting = {
|
|
28
85
|
id: 'use-existing',
|
|
29
86
|
label: d.clusterContext
|
|
@@ -67,7 +124,38 @@ export function classifyHost(d, preferred = 'k3d', platform = 'linux') {
|
|
|
67
124
|
available: true,
|
|
68
125
|
recommended: false,
|
|
69
126
|
};
|
|
70
|
-
|
|
127
|
+
// Recreating is a first-class operation rather than the remedy for any one condition: these
|
|
128
|
+
// clusters are transient and the reasons to want a fresh one are open-ended (wedged, created by
|
|
129
|
+
// hand with the wrong flags, a version bump, a pile of leftover namespaces, or no stated reason
|
|
130
|
+
// at all). What does NOT open up is the TARGET, and that is a safety boundary: it is offered
|
|
131
|
+
// only for a cluster this CLI can both NAME and build again, which is why there is no recreate
|
|
132
|
+
// for `use-existing` (that fires for any reachable kubeconfig, including a shared cluster, and
|
|
133
|
+
// there is no recipe for re-creating "whatever this context points at").
|
|
134
|
+
const recreate = (runtime) => {
|
|
135
|
+
const id = RECREATE_OFFERS[runtime];
|
|
136
|
+
const tooling = runtime === 'kind' ? d.kind : d.k3d;
|
|
137
|
+
const clusters = runtime === 'kind' ? d.kindClusters : d.k3dClusters;
|
|
138
|
+
const known = clusters.includes(clusterName);
|
|
139
|
+
return {
|
|
140
|
+
id,
|
|
141
|
+
label: `Recreate the ${runtime} cluster "${clusterName}" (DESTROYS it and everything on it)`,
|
|
142
|
+
available: d.docker.running && tooling.installed && known,
|
|
143
|
+
recommended: false,
|
|
144
|
+
reason: dockerReason ??
|
|
145
|
+
(!tooling.installed
|
|
146
|
+
? `${runtime} is not installed`
|
|
147
|
+
: !known
|
|
148
|
+
? `no ${runtime} cluster named "${clusterName}" exists`
|
|
149
|
+
: undefined),
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
const offers = [
|
|
153
|
+
useExisting,
|
|
154
|
+
createK3d,
|
|
155
|
+
createKind,
|
|
156
|
+
...Object.keys(RECREATE_OFFERS).map(recreate),
|
|
157
|
+
installK3s,
|
|
158
|
+
];
|
|
71
159
|
const recommended = offerPriority(preferred).find((id) => offers.find((o) => o.id === id)?.available) ??
|
|
72
160
|
'install-k3s';
|
|
73
161
|
for (const o of offers)
|
|
@@ -142,7 +230,7 @@ export function hasServerVersion(stdout) {
|
|
|
142
230
|
* `--request-timeout` — a kubeconfig pointing at a down cluster then fails fast instead of hanging
|
|
143
231
|
* the probe (the {@link HostShell} watchdog is the outer backstop).
|
|
144
232
|
*/
|
|
145
|
-
export async function probeHost(shell, preferred = 'k3d', platform = process.platform) {
|
|
233
|
+
export async function probeHost(shell, preferred = 'k3d', platform = process.platform, clusterName = DEFAULT_CLUSTER_NAME) {
|
|
146
234
|
const [kubectlVersion, kubectlContext, k3dVersion, k3dList, kindVersion, kindList, k3sVersion, dockerVersion,] = await Promise.all([
|
|
147
235
|
shell.run('kubectl', ['version', '--output=json', '--request-timeout=3s']),
|
|
148
236
|
shell.run('kubectl', ['config', 'current-context']),
|
|
@@ -171,6 +259,6 @@ export async function probeHost(shell, preferred = 'k3d', platform = process.pla
|
|
|
171
259
|
k3dClusters: k3dList.code === 0 ? parseK3dClusters(k3dList.stdout) : [],
|
|
172
260
|
kindClusters: kindList.code === 0 ? parseKindClusters(kindList.stdout) : [],
|
|
173
261
|
};
|
|
174
|
-
return classifyHost(detections, preferred, platform);
|
|
262
|
+
return classifyHost(detections, preferred, platform, clusterName);
|
|
175
263
|
}
|
|
176
264
|
//# sourceMappingURL=k3s-probe.js.map
|
package/dist/k3s-probe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k3s-probe.js","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"k3s-probe.js","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"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"}
|