@mark1russell7/harness 0.11.2 → 0.11.3
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 +38 -7
- package/build/cell-BmSnJJtn.d.ts +993 -0
- package/build/image-Q_fs3rCC.js +410 -0
- package/build/image-Q_fs3rCC.js.map +1 -0
- package/build/index.d.ts +117 -945
- package/build/index.js +21 -192
- package/build/index.js.map +1 -1
- package/build/schema.d.ts +19 -0
- package/build/schema.js +56 -0
- package/build/schema.js.map +1 -0
- package/image/pg/client-pg.mjs +4 -0
- package/package.json +5 -1
package/build/index.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
+
import { C as targetSourceOf, S as targetImageOf, T as unpinnedBases, _ as proceduresImage, a as SHIPPED_NAMES, b as subjectClient, c as harnessImage, d as inContext, f as mongoClientImage, g as planOf, h as pgClientImage, i as SHIPPED_CLIENTS, l as imageOf, m as nodeHttpImage, n as PINNED, o as SUBJECTS, p as nodeClientImage, r as REPOSITORY, s as goHttpImage, t as CLIENT_NAMES, u as imageProblems, v as programOf, w as unlockedManifests, x as subjectProblems, y as routerImage } from "./image-Q_fs3rCC.js";
|
|
1
2
|
import { quantity, valueIn } from "@mark1russell7/quantity";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
4
|
-
import { createRequire } from "node:module";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
import { dirname, join, relative } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
4
|
//#region src/cell.ts
|
|
9
5
|
/** This function tells if a fault place is a hop of a topology. */
|
|
10
6
|
const isHopPlace = (place) => typeof place === "object" && "hop" in place;
|
|
@@ -1898,151 +1894,8 @@ const measureSocket = (cell, run) => {
|
|
|
1898
1894
|
};
|
|
1899
1895
|
//#endregion
|
|
1900
1896
|
//#region src/lab.ts
|
|
1901
|
-
/**
|
|
1902
|
-
* These are the roots of the two packages that the images read: this package, and the prober
|
|
1903
|
-
* that Node resolves for it. In a workspace, they are two folders side by side. From npm, the
|
|
1904
|
-
* prober is a link, and a Docker build context does not follow a link. Thus each image builds
|
|
1905
|
-
* from a context that the harness copies from the two roots.
|
|
1906
|
-
*/
|
|
1907
|
-
const ROOTS = {
|
|
1908
|
-
harness: fileURLToPath(new URL("..", import.meta.url)),
|
|
1909
|
-
prober: dirname(realpathSync(createRequire(import.meta.url).resolve("@mark1russell7/prober/package.json")))
|
|
1910
|
-
};
|
|
1911
|
-
/** This function gives the path of a part of an image, which is `<package>/<path>` in the context. */
|
|
1912
|
-
const pathOf = (part) => {
|
|
1913
|
-
const [root, ...rest] = part.split("/");
|
|
1914
|
-
const base = ROOTS[root];
|
|
1915
|
-
if (base === void 0) throw new Error(`${part} is in no package that the images read`);
|
|
1916
|
-
return join(base, ...rest);
|
|
1917
|
-
};
|
|
1918
1897
|
/** This function loads Testcontainers when a lab first opens. Code that only measures and judges does not load it. */
|
|
1919
1898
|
const containers = () => import("testcontainers");
|
|
1920
|
-
/** This image holds the prober, the TCP client, the injector and the namespace admin. */
|
|
1921
|
-
const HARNESS = {
|
|
1922
|
-
name: "loom-harness",
|
|
1923
|
-
dockerfile: "harness/image/Dockerfile",
|
|
1924
|
-
from: [
|
|
1925
|
-
"harness/image/Dockerfile",
|
|
1926
|
-
"harness/image/native",
|
|
1927
|
-
"prober/bpf",
|
|
1928
|
-
"prober/native",
|
|
1929
|
-
"prober/fixtures"
|
|
1930
|
-
]
|
|
1931
|
-
};
|
|
1932
|
-
/** This image holds the Node client: ioredis 6.0.0 on Node 24.21.0. */
|
|
1933
|
-
const NODE = {
|
|
1934
|
-
name: "loom-harness-node",
|
|
1935
|
-
dockerfile: "harness/image/node/Dockerfile",
|
|
1936
|
-
from: ["harness/image/node"]
|
|
1937
|
-
};
|
|
1938
|
-
/** This image holds the Go HTTP client: the http.Transport of Go 1.27.2. */
|
|
1939
|
-
const GO_HTTP = {
|
|
1940
|
-
name: "loom-harness-go-http",
|
|
1941
|
-
dockerfile: "harness/image/go-http/Dockerfile",
|
|
1942
|
-
from: ["harness/image/go-http"]
|
|
1943
|
-
};
|
|
1944
|
-
/** This image holds the Node HTTP clients: the http.Agent of Node 24.21.0, and undici 8.12.2. */
|
|
1945
|
-
const NODE_HTTP = {
|
|
1946
|
-
name: "loom-harness-node-http",
|
|
1947
|
-
dockerfile: "harness/image/node-http/Dockerfile",
|
|
1948
|
-
from: ["harness/image/node-http"]
|
|
1949
|
-
};
|
|
1950
|
-
/** This image holds the MongoDB client: the driver mongodb 7.7.0 on Node 24.21.0, and its step-down script. */
|
|
1951
|
-
const MONGO = {
|
|
1952
|
-
name: "loom-harness-mongo",
|
|
1953
|
-
dockerfile: "harness/image/mongo/Dockerfile",
|
|
1954
|
-
from: ["harness/image/mongo"]
|
|
1955
|
-
};
|
|
1956
|
-
/** This image holds the PostgreSQL client: node-postgres (pg 8.23.1 with pg-pool 3.14.0) on Node 24.21.0. */
|
|
1957
|
-
const PG = {
|
|
1958
|
-
name: "loom-harness-pg",
|
|
1959
|
-
dockerfile: "harness/image/pg/Dockerfile",
|
|
1960
|
-
from: ["harness/image/pg"]
|
|
1961
|
-
};
|
|
1962
|
-
/** This image holds `@procedures/client` 0.7.0 on Node 24.21.0: its WebSocket client as a client of the harness, and the script of its server. */
|
|
1963
|
-
const PROCEDURES = {
|
|
1964
|
-
name: "loom-harness-procedures",
|
|
1965
|
-
dockerfile: "harness/image/procedures/Dockerfile",
|
|
1966
|
-
from: ["harness/image/procedures"]
|
|
1967
|
-
};
|
|
1968
|
-
/** This image is the router of a middlebox chain: NAT and conntrack, with a form for a forgotten flow. */
|
|
1969
|
-
const ROUTER = {
|
|
1970
|
-
name: "loom-harness-router",
|
|
1971
|
-
dockerfile: "harness/image/router/Dockerfile",
|
|
1972
|
-
from: ["harness/image/router"]
|
|
1973
|
-
};
|
|
1974
|
-
/** This function gives each file under a path, in a stable sequence, but not the output of a local build. */
|
|
1975
|
-
const sources = (path) => {
|
|
1976
|
-
if (statSync(path).isFile()) return [path];
|
|
1977
|
-
return readdirSync(path, { withFileTypes: true }).filter((entry) => entry.name !== "target" && entry.name !== "node_modules").flatMap((entry) => sources(join(path, entry.name))).sort();
|
|
1978
|
-
};
|
|
1979
|
-
/** This function gives each file of an image, with its path in the build context. */
|
|
1980
|
-
const filesOf = (image) => image.from.flatMap((part) => {
|
|
1981
|
-
const base = pathOf(part);
|
|
1982
|
-
return sources(base).map((file) => ({
|
|
1983
|
-
file,
|
|
1984
|
-
at: join(part, relative(base, file)).replaceAll("\\", "/")
|
|
1985
|
-
}));
|
|
1986
|
-
});
|
|
1987
|
-
/** This function gives the tag of an image from its content. Thus a changed probe or client cannot operate as an old one. */
|
|
1988
|
-
const imageTag = (image) => {
|
|
1989
|
-
const hash = createHash("sha256");
|
|
1990
|
-
for (const { file, at } of filesOf(image)) {
|
|
1991
|
-
hash.update(at);
|
|
1992
|
-
hash.update(readFileSync(file));
|
|
1993
|
-
}
|
|
1994
|
-
return `${image.name}:${hash.digest("hex").slice(0, 12)}`;
|
|
1995
|
-
};
|
|
1996
|
-
/** This function copies the files of an image into a new build context, and gives its path. */
|
|
1997
|
-
const stage = (image) => {
|
|
1998
|
-
const context = mkdtempSync(join(tmpdir(), `${image.name}-`));
|
|
1999
|
-
for (const { file, at } of filesOf(image)) {
|
|
2000
|
-
mkdirSync(dirname(join(context, at)), { recursive: true });
|
|
2001
|
-
copyFileSync(file, join(context, at));
|
|
2002
|
-
}
|
|
2003
|
-
return context;
|
|
2004
|
-
};
|
|
2005
|
-
const built = /* @__PURE__ */ new Map();
|
|
2006
|
-
/** This function builds an image one time for each process. Docker keeps its layers between runs. */
|
|
2007
|
-
const build = (image) => {
|
|
2008
|
-
let tag = built.get(image.name);
|
|
2009
|
-
if (tag === void 0) {
|
|
2010
|
-
tag = (async () => {
|
|
2011
|
-
const name = imageTag(image);
|
|
2012
|
-
const { GenericContainer } = await containers();
|
|
2013
|
-
const context = stage(image);
|
|
2014
|
-
try {
|
|
2015
|
-
await GenericContainer.fromDockerfile(context, image.dockerfile).build(name, { deleteOnExit: false });
|
|
2016
|
-
} finally {
|
|
2017
|
-
rmSync(context, {
|
|
2018
|
-
recursive: true,
|
|
2019
|
-
force: true
|
|
2020
|
-
});
|
|
2021
|
-
}
|
|
2022
|
-
return name;
|
|
2023
|
-
})();
|
|
2024
|
-
built.set(image.name, tag);
|
|
2025
|
-
}
|
|
2026
|
-
return tag;
|
|
2027
|
-
};
|
|
2028
|
-
/** This function gives the image of the harness. */
|
|
2029
|
-
const harnessImage = () => build(HARNESS);
|
|
2030
|
-
/** This function gives the image of the Node client. */
|
|
2031
|
-
const nodeClientImage = () => build(NODE);
|
|
2032
|
-
/** This function gives the image of the router. */
|
|
2033
|
-
const routerImage = () => build(ROUTER);
|
|
2034
|
-
/** This function gives the image of the Go HTTP client. */
|
|
2035
|
-
const goHttpImage = () => build(GO_HTTP);
|
|
2036
|
-
/** This function gives the image of the Node HTTP clients. */
|
|
2037
|
-
const nodeHttpImage = () => build(NODE_HTTP);
|
|
2038
|
-
/** This function gives the image of the MongoDB client. */
|
|
2039
|
-
const mongoClientImage = () => build(MONGO);
|
|
2040
|
-
/** This function gives the image of the PostgreSQL client. */
|
|
2041
|
-
const pgClientImage = () => build(PG);
|
|
2042
|
-
/** This function gives the image of `@procedures/client`: its WebSocket client and its server. */
|
|
2043
|
-
const proceduresImage = () => build(PROCEDURES);
|
|
2044
|
-
/** This function gives the image that a target operates: its stock image, or an image of the harness (`Target.harness`). */
|
|
2045
|
-
const targetImageOf = (target) => target.harness === "procedures" ? proceduresImage() : Promise.resolve(target.image);
|
|
2046
1899
|
/**
|
|
2047
1900
|
* This time is the interval of the listing of a router, when its hop does not set one. A listing
|
|
2048
1901
|
* evicts each expired flow that it walks past, and the DESTROY event of that flow follows.
|
|
@@ -2209,47 +2062,19 @@ const netnsOf = async (container) => {
|
|
|
2209
2062
|
if (inode === void 0) throw new Error(`not a network namespace: ${link}`);
|
|
2210
2063
|
return Number(inode);
|
|
2211
2064
|
};
|
|
2212
|
-
/**
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
if (
|
|
2220
|
-
clientImage: await nodeClientImage(),
|
|
2221
|
-
command: ["node", "/opt/harness/node/client-ioredis.mjs"],
|
|
2222
|
-
clientKind: kind
|
|
2223
|
-
};
|
|
2224
|
-
if (kind === "go-http") return {
|
|
2225
|
-
clientImage: await goHttpImage(),
|
|
2226
|
-
command: ["/opt/harness/client-go"],
|
|
2227
|
-
clientKind: kind
|
|
2228
|
-
};
|
|
2229
|
-
if (kind === "http-agent" || kind === "undici") return {
|
|
2230
|
-
clientImage: await nodeHttpImage(),
|
|
2231
|
-
command: ["node", `/opt/harness/node-http/client-${kind === "undici" ? "undici" : "agent"}.mjs`],
|
|
2232
|
-
clientKind: kind
|
|
2233
|
-
};
|
|
2234
|
-
if (kind === "mongodb") return {
|
|
2235
|
-
clientImage: await mongoClientImage(),
|
|
2236
|
-
command: ["node", "/opt/harness/mongo/client-mongo.mjs"],
|
|
2237
|
-
clientKind: kind
|
|
2238
|
-
};
|
|
2239
|
-
if (kind === "pg") return {
|
|
2240
|
-
clientImage: await pgClientImage(),
|
|
2241
|
-
command: ["node", "/opt/harness/pg/client-pg.mjs"],
|
|
2242
|
-
clientKind: kind
|
|
2243
|
-
};
|
|
2244
|
-
if (kind === "procedures-ws") return {
|
|
2245
|
-
clientImage: await proceduresImage(),
|
|
2246
|
-
command: ["node", "/opt/harness/procedures/client-ws.mjs"],
|
|
2247
|
-
clientKind: kind
|
|
2248
|
-
};
|
|
2065
|
+
/**
|
|
2066
|
+
* This function gives the image and the command of the client of each run, its kind for the
|
|
2067
|
+
* manifest, and the source of its image. A client by its name is a client that the harness ships
|
|
2068
|
+
* (`SHIPPED_CLIENTS`). A client image gives its own image and command.
|
|
2069
|
+
*/
|
|
2070
|
+
const clientOf = async (kind) => {
|
|
2071
|
+
const client = typeof kind === "string" ? Object.hasOwn(SHIPPED_CLIENTS, kind) ? SHIPPED_CLIENTS[kind] : void 0 : kind;
|
|
2072
|
+
if (client === void 0) throw new Error(`the harness ships no client ${String(kind)}`);
|
|
2249
2073
|
return {
|
|
2250
|
-
clientImage: image,
|
|
2251
|
-
command:
|
|
2252
|
-
clientKind: kind
|
|
2074
|
+
clientImage: await imageOf(client.image),
|
|
2075
|
+
command: client.command,
|
|
2076
|
+
clientKind: typeof kind === "string" ? kind : "image",
|
|
2077
|
+
...typeof client.image === "string" ? {} : { source: client.image }
|
|
2253
2078
|
};
|
|
2254
2079
|
};
|
|
2255
2080
|
/** This function gives the device of a route from its line in `ip -o route get`: "10.0.0.2 dev eth0 src …". */
|
|
@@ -2280,7 +2105,7 @@ const deviceOf = (route) => {
|
|
|
2280
2105
|
*/
|
|
2281
2106
|
const openLab = async (target, kind = "tcp", topology) => {
|
|
2282
2107
|
const image = await harnessImage();
|
|
2283
|
-
const { clientImage, command, clientKind } = await clientOf(kind
|
|
2108
|
+
const { clientImage, command, clientKind, source } = await clientOf(kind);
|
|
2284
2109
|
const hops = topology?.hops ?? [];
|
|
2285
2110
|
const { GenericContainer, Network, Wait, getContainerRuntimeClient } = await containers();
|
|
2286
2111
|
const runtime = await getContainerRuntimeClient();
|
|
@@ -2853,7 +2678,10 @@ const openLab = async (target, kind = "tcp", topology) => {
|
|
|
2853
2678
|
docker: `${runtime.info.containerRuntime.serverVersion} on ${runtime.info.containerRuntime.operatingSystem}`,
|
|
2854
2679
|
target: {
|
|
2855
2680
|
image: targetImage,
|
|
2856
|
-
...target.
|
|
2681
|
+
...target.subject !== void 0 ? {
|
|
2682
|
+
subject: target.subject,
|
|
2683
|
+
base: target.image
|
|
2684
|
+
} : target.harness === void 0 ? {} : {
|
|
2857
2685
|
harness: target.harness,
|
|
2858
2686
|
base: target.image
|
|
2859
2687
|
},
|
|
@@ -2874,7 +2702,8 @@ const openLab = async (target, kind = "tcp", topology) => {
|
|
|
2874
2702
|
},
|
|
2875
2703
|
client: {
|
|
2876
2704
|
kind: clientKind,
|
|
2877
|
-
image: clientImage
|
|
2705
|
+
image: clientImage,
|
|
2706
|
+
...source === void 0 ? {} : { source }
|
|
2878
2707
|
},
|
|
2879
2708
|
netns,
|
|
2880
2709
|
sysctls,
|
|
@@ -4783,6 +4612,6 @@ const runCell = async (cell, say = () => {}) => {
|
|
|
4783
4612
|
}
|
|
4784
4613
|
};
|
|
4785
4614
|
//#endregion
|
|
4786
|
-
export { CONVERGE_MS, INJECT, KEPT, LINGER_MS, LISTING, MEMBER_MARKS, NOISE, PUMP, QUIET_MS, RELATIVE, REPLICA_SET_STAGES, STAGES, STATUS_SCRIPT, STEPS, STEP_DOWN, callOf, clockOffsetOf, closeOrExit, crossingsOf, cutOf, deadlineOf, delayVoids, deviceOf, dropFinding, dropOf, endpointAfter, errorsOf, exitOf, fieldOf, fieldsOf, firstUnanswered, goHttpImage, groupOnce, groupVerdictOf, harnessImage, hzOf, infoOf, initiateScript, isHopPlace, judge, lagsOf, latestEndOf, leftAfter, matches, measure, measureDriver, measureGroup, medianInterval, memberCommand, memberConfig, memberLineOf, mongoClientImage, nodeClientImage, nodeHttpImage, noiseOf, onMonotonic, openGroupLab, openLab, openReplicaSetLab, peersOf, pgClientImage, pingsOf, proceduresImage, programLines, quantileOf, reconnectFinding, reconnectOf, referenceOf, reorderingOf, replicaSetArgs, replicaSetOnce, replicaSetStagesOf, requestOf, requestWords, routerImage, routesOf, runCell, sentinelConfig, socketAt, socketOf, socketsOf, spread, spreadOf, stagesOf, statusViewOf, subscriptionsOf, targetImageOf, templated, toxicBody, verdictOf, viewOf, writesOf };
|
|
4615
|
+
export { CLIENT_NAMES, CONVERGE_MS, INJECT, KEPT, LINGER_MS, LISTING, MEMBER_MARKS, NOISE, PINNED, PUMP, QUIET_MS, RELATIVE, REPLICA_SET_STAGES, REPOSITORY, SHIPPED_CLIENTS, SHIPPED_NAMES, STAGES, STATUS_SCRIPT, STEPS, STEP_DOWN, SUBJECTS, callOf, clockOffsetOf, closeOrExit, crossingsOf, cutOf, deadlineOf, delayVoids, deviceOf, dropFinding, dropOf, endpointAfter, errorsOf, exitOf, fieldOf, fieldsOf, firstUnanswered, goHttpImage, groupOnce, groupVerdictOf, harnessImage, hzOf, imageOf, imageProblems, inContext, infoOf, initiateScript, isHopPlace, judge, lagsOf, latestEndOf, leftAfter, matches, measure, measureDriver, measureGroup, medianInterval, memberCommand, memberConfig, memberLineOf, mongoClientImage, nodeClientImage, nodeHttpImage, noiseOf, onMonotonic, openGroupLab, openLab, openReplicaSetLab, peersOf, pgClientImage, pingsOf, planOf, proceduresImage, programLines, programOf, quantileOf, reconnectFinding, reconnectOf, referenceOf, reorderingOf, replicaSetArgs, replicaSetOnce, replicaSetStagesOf, requestOf, requestWords, routerImage, routesOf, runCell, sentinelConfig, socketAt, socketOf, socketsOf, spread, spreadOf, stagesOf, statusViewOf, subjectClient, subjectProblems, subscriptionsOf, targetImageOf, targetSourceOf, templated, toxicBody, unlockedManifests, unpinnedBases, verdictOf, viewOf, writesOf };
|
|
4787
4616
|
|
|
4788
4617
|
//# sourceMappingURL=index.js.map
|