@mark1russell7/kind 0.10.1 → 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 +7 -0
- package/build/index.d.ts +33 -2
- package/build/index.js +87 -7
- package/build/index.js.map +1 -1
- package/build/{judge-BD4UVQfy.d.ts → judge-4bzoeGIb.d.ts} +18 -3
- package/build/{judge-BbLWVTYj.js → judge-DdeJ1qVd.js} +7 -4
- package/build/{judge-BbLWVTYj.js.map → judge-DdeJ1qVd.js.map} +1 -1
- package/build/judge.d.ts +1 -1
- package/build/judge.js +1 -1
- package/image/app.mjs +7 -2
- package/image/client.mjs +32 -7
- package/package.json +2 -2
package/build/judge.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as updatesOf, $t as Declaration, A as TriggerV1, At as rulesOf, B as RunCheck, Bt as ztunnelPodsOf, C as KindCellResult, Ct as outcomesOf, D as PredictionV1, Dt as requestsOf, E as LoadSample, Et as recordsOf, F as KIND_NOISE, Ft as slicesOf, G as judgeKind, Gt as PORT, H as checkRun, Ht as CLIENT, I as KindDecision, It as socketsOf, J as propagationOf, Jt as bandOf, K as observationAfter, Kt as REDIS, L as KindVerdict, Lt as stoppingOf, M as upgrade, Mt as signalsOf, N as upgradeCell, Nt as sliceDropOf, O as RunCheckV1, Ot as restartOf, P as Deleted, Pt as sliceEmptyOf, Q as unitOf, Qt as Band, R as LAST_SLACK, Rt as transitionOf, S as KindCellRecordV1, St as kernelCounts, T as KindVerdictV1, Tt as podsOf, U as deletionsOf, Ut as HEALTH_PORT, V as RunFacts, Vt as ztunnelReplaced, W as factsOf, Wt as LOG_LABEL, X as referenceOf, Xt as secondsOf, Y as propagationSource, Yt as seconds, Z as reusesReset, Zt as showBand, _ as ClusterManifest, _n as Workload, _t as dropOf, a as STAGES, an as MeshMode, at as RecordLine, b as FORMAT_V1, bt as intakeOf, c as readRecord, cn as RedisDeclaration, ct as SliceLine, d as calibrationOf, dn as ResetReuse, dt as TunnelLine, en as KindCell, et as Endpoint, f as cellsTable, fn as Stack, ft as ZtunnelPodLine, g as BandV1, gn as WindowPrediction, gt as deletionOf, h as timeSpread, hn as TriggerKind, ht as byNode, i as quantileOf, in as MeshFlavor, it as PropagationSource, j as judge, jt as signalOf, k as RunFactsV1, kt as restartsAt, l as Judged, ln as Reference, lt as SocketLine, m as predictionText, mn as Trigger, mt as byClients, n as medianInterval, nn as KubeletProbe, nt as Line, o as kindCellRecordSchema, on as PodSettings, ot as Request, p as medianText, pn as Template, pt as backendsAt, q as observationEnd, qt as SERVER, r as middle, rn as Mesh, rt as PodLine, s as kindCellRecordV1Schema, sn as Prediction, st as RulesLine, t as RELATIVE, tn as KindRun, tt as HBONE_PORT, u as TimeSpread, un as Replica, ut as TCP_STATE, v as EnvironmentManifest, vt as emptyOf, w as KindCellV1, wt as podsAt, x as KindCellRecord, xn as KubeProxyMode, xt as isTunnelState, y as FORMAT, yt as failuresOf, z as Propagated, zt as tunnelsOf } from "./judge-
|
|
1
|
+
import { $ as updatesOf, $t as Declaration, A as TriggerV1, At as rulesOf, B as RunCheck, Bt as ztunnelPodsOf, C as KindCellResult, Ct as outcomesOf, D as PredictionV1, Dt as requestsOf, E as LoadSample, Et as recordsOf, F as KIND_NOISE, Ft as slicesOf, G as judgeKind, Gt as PORT, H as checkRun, Ht as CLIENT, I as KindDecision, It as socketsOf, J as propagationOf, Jt as bandOf, K as observationAfter, Kt as REDIS, L as KindVerdict, Lt as stoppingOf, M as upgrade, Mt as signalsOf, N as upgradeCell, Nt as sliceDropOf, O as RunCheckV1, Ot as restartOf, P as Deleted, Pt as sliceEmptyOf, Q as unitOf, Qt as Band, R as LAST_SLACK, Rt as transitionOf, S as KindCellRecordV1, St as kernelCounts, T as KindVerdictV1, Tt as podsOf, U as deletionsOf, Ut as HEALTH_PORT, V as RunFacts, Vt as ztunnelReplaced, W as factsOf, Wt as LOG_LABEL, X as referenceOf, Xt as secondsOf, Y as propagationSource, Yt as seconds, Z as reusesReset, Zt as showBand, _ as ClusterManifest, _n as Workload, _t as dropOf, a as STAGES, an as MeshMode, at as RecordLine, b as FORMAT_V1, bt as intakeOf, c as readRecord, cn as RedisDeclaration, ct as SliceLine, d as calibrationOf, dn as ResetReuse, dt as TunnelLine, en as KindCell, et as Endpoint, f as cellsTable, fn as Stack, ft as ZtunnelPodLine, g as BandV1, gn as WindowPrediction, gt as deletionOf, h as timeSpread, hn as TriggerKind, ht as byNode, i as quantileOf, in as MeshFlavor, it as PropagationSource, j as judge, jt as signalOf, k as RunFactsV1, kt as restartsAt, l as Judged, ln as Reference, lt as SocketLine, m as predictionText, mn as Trigger, mt as byClients, n as medianInterval, nn as KubeletProbe, nt as Line, o as kindCellRecordSchema, on as PodSettings, ot as Request, p as medianText, pn as Template, pt as backendsAt, q as observationEnd, qt as SERVER, r as middle, rn as Mesh, rt as PodLine, s as kindCellRecordV1Schema, sn as Prediction, st as RulesLine, t as RELATIVE, tn as KindRun, tt as HBONE_PORT, u as TimeSpread, un as Replica, ut as TCP_STATE, v as EnvironmentManifest, vt as emptyOf, w as KindCellV1, wt as podsAt, x as KindCellRecord, xn as KubeProxyMode, xt as isTunnelState, y as FORMAT, yt as failuresOf, z as Propagated, zt as tunnelsOf } from "./judge-4bzoeGIb.js";
|
|
2
2
|
export { type Band, type BandV1, CLIENT, type ClusterManifest, type Declaration, type Deleted, Endpoint, type EnvironmentManifest, FORMAT, FORMAT_V1, HBONE_PORT, HEALTH_PORT, type Judged, KIND_NOISE, type KindCell, type KindCellRecord, type KindCellRecordV1, type KindCellResult, type KindCellV1, type KindDecision, type KindRun, type KindVerdict, type KindVerdictV1, type KubeProxyMode, type KubeletProbe, LAST_SLACK, LOG_LABEL, Line, type LoadSample, type Mesh, type MeshFlavor, type MeshMode, PORT, PodLine, type PodSettings, type Prediction, type PredictionV1, type Propagated, PropagationSource, REDIS, RELATIVE, RecordLine, type RedisDeclaration, type Reference, type Replica, Request, type ResetReuse, RulesLine, type RunCheck, type RunCheckV1, type RunFacts, type RunFactsV1, SERVER, STAGES, SliceLine, SocketLine, type Stack, TCP_STATE, type Template, type TimeSpread, type Trigger, type TriggerKind, type TriggerV1, TunnelLine, type WindowPrediction, type Workload, ZtunnelPodLine, backendsAt, bandOf, byClients, byNode, calibrationOf, cellsTable, checkRun, deletionOf, deletionsOf, dropOf, emptyOf, factsOf, failuresOf, intakeOf, isTunnelState, judge, judgeKind, kernelCounts, kindCellRecordSchema, kindCellRecordV1Schema, medianInterval, medianText, middle, observationAfter, observationEnd, outcomesOf, podsAt, podsOf, predictionText, propagationOf, propagationSource, quantileOf, readRecord, recordsOf, referenceOf, requestsOf, restartOf, restartsAt, reusesReset, rulesOf, seconds, secondsOf, showBand, signalOf, signalsOf, sliceDropOf, sliceEmptyOf, slicesOf, socketsOf, stoppingOf, timeSpread, transitionOf, tunnelsOf, unitOf, updatesOf, upgrade, upgradeCell, ztunnelPodsOf, ztunnelReplaced };
|
package/build/judge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ut as CLIENT, u as FORMAT, d as FORMAT_V1, N as HBONE_PORT, dt as HEALTH_PORT, h as KIND_NOISE, g as LAST_SLACK, ft as LOG_LABEL, pt as PORT, mt as REDIS, k as RELATIVE, ht as SERVER, t as STAGES, P as TCP_STATE, F as backendsAt, gt as bandOf, I as byClients, L as byNode, a as calibrationOf, o as cellsTable, _ as checkRun, R as deletionOf, v as deletionsOf, z as dropOf, B as emptyOf, y as factsOf, V as failuresOf, H as intakeOf, U as isTunnelState, f as judge, b as judgeKind, W as kernelCounts, n as kindCellRecordSchema, r as kindCellRecordV1Schema, A as medianInterval, s as medianText, j as middle, x as observationAfter, S as observationEnd, G as outcomesOf, K as podsAt, q as podsOf, c as predictionText, C as propagationOf, w as propagationSource, M as quantileOf, i as readRecord, J as recordsOf, T as referenceOf, Y as requestsOf, X as restartOf, Z as restartsAt, E as reusesReset, Q as rulesOf, _t as seconds, vt as secondsOf, yt as showBand, $ as signalOf, et as signalsOf, tt as sliceDropOf, nt as sliceEmptyOf, rt as slicesOf, it as socketsOf, at as stoppingOf, l as timeSpread, ot as transitionOf, st as tunnelsOf, D as unitOf, O as updatesOf, p as upgrade, m as upgradeCell, ct as ztunnelPodsOf, lt as ztunnelReplaced } from "./judge-
|
|
1
|
+
export { ut as CLIENT, u as FORMAT, d as FORMAT_V1, N as HBONE_PORT, dt as HEALTH_PORT, h as KIND_NOISE, g as LAST_SLACK, ft as LOG_LABEL, pt as PORT, mt as REDIS, k as RELATIVE, ht as SERVER, t as STAGES, P as TCP_STATE, F as backendsAt, gt as bandOf, I as byClients, L as byNode, a as calibrationOf, o as cellsTable, _ as checkRun, R as deletionOf, v as deletionsOf, z as dropOf, B as emptyOf, y as factsOf, V as failuresOf, H as intakeOf, U as isTunnelState, f as judge, b as judgeKind, W as kernelCounts, n as kindCellRecordSchema, r as kindCellRecordV1Schema, A as medianInterval, s as medianText, j as middle, x as observationAfter, S as observationEnd, G as outcomesOf, K as podsAt, q as podsOf, c as predictionText, C as propagationOf, w as propagationSource, M as quantileOf, i as readRecord, J as recordsOf, T as referenceOf, Y as requestsOf, X as restartOf, Z as restartsAt, E as reusesReset, Q as rulesOf, _t as seconds, vt as secondsOf, yt as showBand, $ as signalOf, et as signalsOf, tt as sliceDropOf, nt as sliceEmptyOf, rt as slicesOf, it as socketsOf, at as stoppingOf, l as timeSpread, ot as transitionOf, st as tunnelsOf, D as unitOf, O as updatesOf, p as upgrade, m as upgradeCell, ct as ztunnelPodsOf, lt as ztunnelReplaced } from "./judge-DdeJ1qVd.js";
|
package/image/app.mjs
CHANGED
|
@@ -53,7 +53,8 @@ const redis =
|
|
|
53
53
|
{ clock, record },
|
|
54
54
|
);
|
|
55
55
|
|
|
56
|
-
// the flag file fails the check of the liveness restart: the agent writes it in the root of the container
|
|
56
|
+
// the flag file fails the check of the liveness restart: the agent writes it in the root of the container.
|
|
57
|
+
// With failsRoute of the config (cannot-serve), the flag also fails the route
|
|
57
58
|
const FLAG = process.env.LAB_FLAG ?? "/tmp/lab-fail";
|
|
58
59
|
const flag = () => (existsSync(FLAG) ? "error" : "ok");
|
|
59
60
|
|
|
@@ -68,7 +69,10 @@ const KNOBS = { server_idle_close: s(6), server_idle_sweep_interval: s(1), serve
|
|
|
68
69
|
// service is not ready
|
|
69
70
|
const server = http.createServer();
|
|
70
71
|
server.on("listening", () => say({ ev: "app", what: "listening", port: config.port }));
|
|
71
|
-
|
|
72
|
+
// lameDuck false of the declaration keeps each connection open while the service is not ready: then a
|
|
73
|
+
// caller learns only from the endpoints (the candidate A of S2). The default is the lame duck
|
|
74
|
+
const edge = declaration.lameDuck === false ? { keepAlive: () => true } : {};
|
|
75
|
+
const transport = httpTransport(server, KNOBS, { listen: { port: config.port }, clock, ...edge });
|
|
72
76
|
// each request of the port is the one route. A failure of the route answers 503, as the lab always
|
|
73
77
|
// did: the T07 and T18 cells count the 503s, and T18 predicts them while Redis is down. Each 503 gets
|
|
74
78
|
// Retry-After from the rule of the transport
|
|
@@ -77,6 +81,7 @@ transport.mount(
|
|
|
77
81
|
CONTROLLER,
|
|
78
82
|
() => ROUTE,
|
|
79
83
|
async (_req, signal) => {
|
|
84
|
+
if (config.failsRoute === true && existsSync(FLAG)) throw new Error("the replica cannot serve");
|
|
80
85
|
if (redis !== undefined) {
|
|
81
86
|
const sent = await redis.send("GET", ["lab"], { signal });
|
|
82
87
|
if (sent.outcome !== "ok") throw new Error(`redis ${sent.outcome}: ${sent.error}`);
|
package/image/client.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// A client of a kind cell: an open loop of requests to the ClusterIP of the service, each on a new
|
|
2
|
-
// connection, thus kube-proxy picks a backend for each one.
|
|
3
|
-
//
|
|
2
|
+
// connection, thus kube-proxy picks a backend for each one. With CONNECTIONS, the client keeps that
|
|
3
|
+
// count of keep-alive connections, and each request goes on the next one in turn. kube-proxy picks a
|
|
4
|
+
// backend only for a new connection. SIGHUP opens new connections. Each request is one JSON line with
|
|
5
|
+
// its start on CLOCK_MONOTONIC, its duration, its outcome (ok, 503, refused, reset, timeout,
|
|
4
6
|
// unreachable, or another error) and its local port (`lp`).
|
|
5
7
|
import http from "node:http";
|
|
6
8
|
|
|
@@ -10,6 +12,23 @@ const timeout = Number(process.env.TIMEOUT_MS ?? 1000);
|
|
|
10
12
|
const pod = process.env.POD_NAME ?? "client";
|
|
11
13
|
const node = process.env.NODE_NAME ?? "";
|
|
12
14
|
const now = () => Number(process.hrtime.bigint()) / 1e6;
|
|
15
|
+
const connections = process.env.CONNECTIONS === undefined ? 0 : Number(process.env.CONNECTIONS);
|
|
16
|
+
|
|
17
|
+
// each agent holds one keep-alive connection. A `Connection: close` of the server ends it after its
|
|
18
|
+
// answer, and the next request on the agent opens a new connection
|
|
19
|
+
const agentsOf = () => Array.from({ length: connections }, () => new http.Agent({ keepAlive: true, maxSockets: 1 }));
|
|
20
|
+
let agents = agentsOf();
|
|
21
|
+
let turn = 0;
|
|
22
|
+
// SIGHUP: new agents for the next requests. The old agents go after the timeout, thus each request
|
|
23
|
+
// on them ends first
|
|
24
|
+
process.on("SIGHUP", () => {
|
|
25
|
+
const old = agents;
|
|
26
|
+
agents = agentsOf();
|
|
27
|
+
say({ ev: "client", what: "reconnect", t: now() });
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
for (const agent of old) agent.destroy();
|
|
30
|
+
}, timeout + 100);
|
|
31
|
+
});
|
|
13
32
|
|
|
14
33
|
let pending = [];
|
|
15
34
|
const flush = () => {
|
|
@@ -51,7 +70,11 @@ const fire = () => {
|
|
|
51
70
|
lp ??= portOf(socket);
|
|
52
71
|
say({ ev: "req", t, d: Math.round((now() - t) * 1000) / 1000, o, ...extra, lp });
|
|
53
72
|
};
|
|
54
|
-
const
|
|
73
|
+
const options =
|
|
74
|
+
connections === 0
|
|
75
|
+
? { agent: false, headers: { connection: "close" } }
|
|
76
|
+
: { agent: agents[turn++ % connections] };
|
|
77
|
+
const req = http.request({ host, port: Number(port), path: "/work", ...options }, (res) => {
|
|
55
78
|
let body = "";
|
|
56
79
|
res.setEncoding("utf8");
|
|
57
80
|
res.on("data", (chunk) => {
|
|
@@ -73,12 +96,14 @@ const fire = () => {
|
|
|
73
96
|
// connect() comes in the tick before this event, thus the handle has the port here, a refused
|
|
74
97
|
// connection's too: in 200 refusals, each port was here and none at setImmediate
|
|
75
98
|
lp = portOf(opened);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
// a kept connection is already connected: a listener on it does not fire, and stays
|
|
100
|
+
if (opened.connecting)
|
|
101
|
+
opened.once("connect", () => {
|
|
102
|
+
lp ??= portOf(opened);
|
|
103
|
+
});
|
|
79
104
|
});
|
|
80
105
|
req.end();
|
|
81
106
|
};
|
|
82
107
|
|
|
83
|
-
say({ ev: "client", what: "start", t: now(), target: `${host}:${port}`, every, timeout });
|
|
108
|
+
say({ ev: "client", what: "start", t: now(), target: `${host}:${port}`, every, timeout, connections });
|
|
84
109
|
setInterval(fire, every);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/kind",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"description": "Kubernetes in Docker as a lab for connection timers: a kind cluster from a scenario, faults in the namespaces of its pods, observations on the one monotonic clock of the VM, and predictions from the ordering law. Its judge entry reads and judges a raw record without Docker.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"kubernetes",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@mark1russell7/harness": "^0.12.4",
|
|
69
69
|
"@mark1russell7/quantity": "^0.2.0",
|
|
70
|
-
"@mark1russell7/service": "^0.5.
|
|
70
|
+
"@mark1russell7/service": "^0.5.18",
|
|
71
71
|
"testcontainers": "12.2.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|