@zukhruf/testing 0.3.37 → 0.3.38
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 +40 -36
- package/dist/databases/clickhouse.d.ts +3 -3
- package/dist/databases/clickhouse.d.ts.map +1 -1
- package/dist/databases/clickhouse.js +2 -3
- package/dist/databases/clickhouse.js.map +1 -1
- package/dist/databases/database.d.ts +2 -2
- package/dist/databases/database.d.ts.map +1 -1
- package/dist/databases/mysql-family-server.d.ts.map +1 -1
- package/dist/databases/mysql-family-server.js +5 -4
- package/dist/databases/mysql-family-server.js.map +1 -1
- package/dist/databases/postgres.d.ts.map +1 -1
- package/dist/databases/postgres.js +11 -4
- package/dist/databases/postgres.js.map +1 -1
- package/dist/databases/sqlserver.d.ts.map +1 -1
- package/dist/databases/sqlserver.js +3 -5
- package/dist/databases/sqlserver.js.map +1 -1
- package/dist/databases/succeeded.d.ts +7 -0
- package/dist/databases/succeeded.d.ts.map +1 -0
- package/dist/databases/succeeded.js +11 -0
- package/dist/databases/succeeded.js.map +1 -0
- package/dist/docker/{docker.d.ts → fixtures.d.ts} +31 -25
- package/dist/docker/fixtures.d.ts.map +1 -0
- package/dist/docker/fixtures.js +265 -0
- package/dist/docker/fixtures.js.map +1 -0
- package/dist/docker/host.d.ts +3 -10
- package/dist/docker/host.d.ts.map +1 -1
- package/dist/docker/host.js +21 -41
- package/dist/docker/host.js.map +1 -1
- package/dist/docker/index.d.ts +2 -3
- package/dist/docker/index.d.ts.map +1 -1
- package/dist/docker/index.js +2 -3
- package/dist/docker/index.js.map +1 -1
- package/dist/docker/service-container.d.ts +20 -0
- package/dist/docker/service-container.d.ts.map +1 -0
- package/dist/docker/service-container.js +30 -0
- package/dist/docker/service-container.js.map +1 -0
- package/dist/scripts/run-cleanup.js +1 -1
- package/dist/scripts/run-cleanup.js.map +1 -1
- package/package.json +2 -2
- package/dist/docker/container.d.ts +0 -30
- package/dist/docker/container.d.ts.map +0 -1
- package/dist/docker/container.js +0 -53
- package/dist/docker/container.js.map +0 -1
- package/dist/docker/docker.d.ts.map +0 -1
- package/dist/docker/docker.js +0 -263
- package/dist/docker/docker.js.map +0 -1
- package/dist/docker/volume.d.ts +0 -9
- package/dist/docker/volume.d.ts.map +0 -1
- package/dist/docker/volume.js +0 -13
- package/dist/docker/volume.js.map +0 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import pMemoize from 'p-memoize';
|
|
3
|
+
import { ConnectionFailedError, Docker, ImageNotFoundError, } from '@zukhruf/docker';
|
|
4
|
+
import { DockerDirectory } from "./directory.js";
|
|
5
|
+
import { DockerHost } from "./host.js";
|
|
6
|
+
import { ServiceContainer } from "./service-container.js";
|
|
7
|
+
import { TestRun } from "./test-run.js";
|
|
8
|
+
/** Marks a server that `reuse()` shares across processes and runs. */
|
|
9
|
+
export const SHARED_SERVER_LABEL = 'dev.zukhruf.testing.shared';
|
|
10
|
+
/** The fingerprint of a shared server's configuration. */
|
|
11
|
+
export const CONFIG_LABEL = 'dev.zukhruf.testing.config';
|
|
12
|
+
const units = {
|
|
13
|
+
b: 1,
|
|
14
|
+
k: 1024,
|
|
15
|
+
m: 1024 ** 2,
|
|
16
|
+
g: 1024 ** 3,
|
|
17
|
+
t: 1024 ** 4,
|
|
18
|
+
p: 1024 ** 5,
|
|
19
|
+
};
|
|
20
|
+
/** Bytes of a size such as `1g`, in the binary units of the Docker CLI's `--memory`. */
|
|
21
|
+
function bytes(size) {
|
|
22
|
+
const match = /^(\d+(?:\.\d+)?)\s?([bkmgtp])?i?b?$/i.exec(size);
|
|
23
|
+
if (!match?.[1])
|
|
24
|
+
throw new Error(`Invalid memory size: ${size}`);
|
|
25
|
+
return Math.trunc(Number(match[1]) * (units[match[2]?.toLowerCase() ?? 'b'] ?? 1));
|
|
26
|
+
}
|
|
27
|
+
const byKey = ([a], [b]) => {
|
|
28
|
+
if (a < b)
|
|
29
|
+
return -1;
|
|
30
|
+
if (a > b)
|
|
31
|
+
return 1;
|
|
32
|
+
return 0;
|
|
33
|
+
};
|
|
34
|
+
const generatedName = (image) => `test-${image.replace(/[^a-zA-Z0-9_.-]/g, '-')}-${randomUUID()}`;
|
|
35
|
+
/**
|
|
36
|
+
* Container fixtures on the engine that `environment` selects. The engine is
|
|
37
|
+
* connected on the first acquisition and kept: handles keep the engine they
|
|
38
|
+
* were made on. Docker owns cross-process coordination; this instance holds
|
|
39
|
+
* no server cache.
|
|
40
|
+
*/
|
|
41
|
+
export class DockerFixtures {
|
|
42
|
+
#environment;
|
|
43
|
+
#run;
|
|
44
|
+
#engine = pMemoize(async () => {
|
|
45
|
+
this.#run?.recordThisProcess();
|
|
46
|
+
const client = await Docker.connect({
|
|
47
|
+
environment: this.#environment,
|
|
48
|
+
}).catch((error) => {
|
|
49
|
+
if (error instanceof ConnectionFailedError)
|
|
50
|
+
throw new Error('Docker is required for container-backed tests', {
|
|
51
|
+
cause: error,
|
|
52
|
+
});
|
|
53
|
+
throw error;
|
|
54
|
+
});
|
|
55
|
+
try {
|
|
56
|
+
return { client, host: new DockerHost(client.host, this.#run) };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
await client[Symbol.asyncDispose]();
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
constructor({ environment }) {
|
|
64
|
+
this.#environment = environment;
|
|
65
|
+
this.#run = TestRun.fromEnvironment(environment);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Defaults for disposable test containers, including external launchers.
|
|
69
|
+
* A launcher creates with these labels and no acquisition of this class:
|
|
70
|
+
* the read records this process, so the global teardown sweeps the run.
|
|
71
|
+
*/
|
|
72
|
+
get defaults() {
|
|
73
|
+
this.#run?.recordThisProcess();
|
|
74
|
+
return {
|
|
75
|
+
resources: { memory: '1g', cpus: 1 },
|
|
76
|
+
labels: this.#run?.labels ?? {},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** The client of the engine that this instance's handles are on. */
|
|
80
|
+
async client() {
|
|
81
|
+
return (await this.#engine()).client;
|
|
82
|
+
}
|
|
83
|
+
/** A fixture directory on the engine's host. */
|
|
84
|
+
async directory() {
|
|
85
|
+
return DockerDirectory.create((await this.#engine()).host, this.#run);
|
|
86
|
+
}
|
|
87
|
+
/** Creates a named volume. Its run's cleanup removes it if this process dies first. */
|
|
88
|
+
async volume() {
|
|
89
|
+
const { client } = await this.#engine();
|
|
90
|
+
return client.volumes.create({
|
|
91
|
+
Name: `zukhruf-testing-${randomUUID()}`,
|
|
92
|
+
Labels: this.defaults.labels,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Starts a container this process owns. It stays after it stops, until disposal removes it. */
|
|
96
|
+
async start(options) {
|
|
97
|
+
const engine = await this.#engine();
|
|
98
|
+
const container = await this.#create(engine, this.#owned(options), {
|
|
99
|
+
name: options.name ?? generatedName(options.image),
|
|
100
|
+
});
|
|
101
|
+
await this.#startOrRemove(container);
|
|
102
|
+
return container;
|
|
103
|
+
}
|
|
104
|
+
/** Starts a dedicated server. Failure or disposal removes it. */
|
|
105
|
+
async serve(options) {
|
|
106
|
+
const engine = await this.#engine();
|
|
107
|
+
const owned = this.#owned(options);
|
|
108
|
+
const container = await this.#create(engine, this.#published(owned, options.internalPort), { name: options.name ?? generatedName(options.image) });
|
|
109
|
+
const remove = () => container.remove({ force: true, v: true });
|
|
110
|
+
await this.#startOrRemove(container);
|
|
111
|
+
try {
|
|
112
|
+
return await this.#ready(engine, container, options, remove);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
await remove().catch(() => { });
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reuse one server per configuration on this engine, across processes and
|
|
121
|
+
* runs. Docker reserves the name atomically. Readiness failure leaves it
|
|
122
|
+
* running. Disposal closes only the forward; the server keeps running for
|
|
123
|
+
* its other users.
|
|
124
|
+
*/
|
|
125
|
+
async reuse(options) {
|
|
126
|
+
const engine = await this.#engine();
|
|
127
|
+
const fingerprint = this.#fingerprint(options);
|
|
128
|
+
const name = options.name ?? `zukhruf-testing-${fingerprint}`;
|
|
129
|
+
const body = this.#published(this.#body({
|
|
130
|
+
...options,
|
|
131
|
+
labels: {
|
|
132
|
+
...options.labels,
|
|
133
|
+
[SHARED_SERVER_LABEL]: '1',
|
|
134
|
+
[CONFIG_LABEL]: fingerprint,
|
|
135
|
+
},
|
|
136
|
+
}), options.internalPort);
|
|
137
|
+
const { container } = await this.#creating(engine, () => engine.client.containers.createOrGet(body, { name }));
|
|
138
|
+
const inspected = await container.inspect();
|
|
139
|
+
const labels = inspected.Config?.Labels;
|
|
140
|
+
if (labels?.[SHARED_SERVER_LABEL] !== '1' ||
|
|
141
|
+
labels[CONFIG_LABEL] !== fingerprint)
|
|
142
|
+
throw new Error(`Container ${name} does not match the shared test configuration`);
|
|
143
|
+
if (inspected.State?.Status !== 'running')
|
|
144
|
+
await container.start();
|
|
145
|
+
return this.#ready(engine, container, options, undefined);
|
|
146
|
+
}
|
|
147
|
+
/** Runs a container to completion and gives its output and exit code. The container is removed afterwards. */
|
|
148
|
+
async run(options) {
|
|
149
|
+
const engine = await this.#engine();
|
|
150
|
+
const body = this.#owned(options);
|
|
151
|
+
return this.#creating(engine, () => engine.client.containers.run(body, {
|
|
152
|
+
name: options.name ?? generatedName(options.image),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
async #create(engine, body, { name }) {
|
|
156
|
+
return this.#creating(engine, () => engine.client.containers.create(body, { name }));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Runs `create` under a creating record, and pulls a missing image before
|
|
160
|
+
* a second try, as `docker run` does.
|
|
161
|
+
*/
|
|
162
|
+
async #creating(engine, create) {
|
|
163
|
+
await using _creating = await this.#run?.recordCreating();
|
|
164
|
+
try {
|
|
165
|
+
return await create();
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (!(error instanceof ImageNotFoundError))
|
|
169
|
+
throw error;
|
|
170
|
+
await engine.client.images.pull(error.image);
|
|
171
|
+
return await create();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async #startOrRemove(container) {
|
|
175
|
+
try {
|
|
176
|
+
await container.start();
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
await container.remove({ force: true, v: true }).catch(() => { });
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async #ready(engine, container, { internalPort, healthy }, remove) {
|
|
184
|
+
const published = await container.port(internalPort);
|
|
185
|
+
if (!published)
|
|
186
|
+
throw new Error(`Container ${container.id} publishes no port for ${internalPort}`);
|
|
187
|
+
const connection = await engine.host.forward(published.port);
|
|
188
|
+
const service = new ServiceContainer(container, connection.port, connection.close, remove);
|
|
189
|
+
try {
|
|
190
|
+
await healthy?.(service);
|
|
191
|
+
return service;
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
await service.disconnect();
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/** The body of a container this process owns: it carries the run's labels. */
|
|
199
|
+
#owned(options) {
|
|
200
|
+
return this.#body({
|
|
201
|
+
...options,
|
|
202
|
+
labels: { ...options.labels, ...this.defaults.labels },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/** Publishes `internalPort` on 127.0.0.1 of the engine's host; the engine removes the container when it stops. */
|
|
206
|
+
#published(body, internalPort) {
|
|
207
|
+
const port = `${internalPort}/tcp`;
|
|
208
|
+
return {
|
|
209
|
+
...body,
|
|
210
|
+
ExposedPorts: { [port]: {} },
|
|
211
|
+
HostConfig: {
|
|
212
|
+
...body.HostConfig,
|
|
213
|
+
AutoRemove: true,
|
|
214
|
+
PortBindings: { [port]: [{ HostIp: '127.0.0.1', HostPort: '' }] },
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
#body(options) {
|
|
219
|
+
const { resources } = this.defaults;
|
|
220
|
+
const hostConfig = {
|
|
221
|
+
Binds: (options.mounts ?? []).map(({ source, target, readOnly }) => `${source}:${target}${readOnly ? ':ro' : ''}`),
|
|
222
|
+
Tmpfs: Object.fromEntries((options.tmpfs ?? []).map((spec) => {
|
|
223
|
+
const separator = spec.indexOf(':');
|
|
224
|
+
return separator === -1
|
|
225
|
+
? [spec, '']
|
|
226
|
+
: [spec.slice(0, separator), spec.slice(separator + 1)];
|
|
227
|
+
})),
|
|
228
|
+
Memory: bytes(options.memory ?? resources.memory),
|
|
229
|
+
NanoCpus: Math.round((options.cpus ?? resources.cpus) * 1e9),
|
|
230
|
+
...(options.ipcHost ? { IpcMode: 'host' } : {}),
|
|
231
|
+
...(options.memorySwappiness === undefined
|
|
232
|
+
? {}
|
|
233
|
+
: { MemorySwappiness: options.memorySwappiness }),
|
|
234
|
+
};
|
|
235
|
+
return {
|
|
236
|
+
Image: options.image,
|
|
237
|
+
...(options.command ? { Cmd: options.command } : {}),
|
|
238
|
+
...(options.hostname ? { Hostname: options.hostname } : {}),
|
|
239
|
+
Labels: options.labels ?? {},
|
|
240
|
+
Env: Object.entries(options.env ?? {}).map(([key, value]) => `${key}=${value}`),
|
|
241
|
+
HostConfig: hostConfig,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
#fingerprint(options) {
|
|
245
|
+
const { resources } = this.defaults;
|
|
246
|
+
return createHash('sha256')
|
|
247
|
+
.update(JSON.stringify({
|
|
248
|
+
transportVersion: 3,
|
|
249
|
+
memory: options.memory ?? resources.memory,
|
|
250
|
+
cpus: options.cpus ?? resources.cpus,
|
|
251
|
+
image: options.image,
|
|
252
|
+
command: options.command ?? [],
|
|
253
|
+
hostname: options.hostname,
|
|
254
|
+
internalPort: options.internalPort,
|
|
255
|
+
env: Object.entries(options.env ?? {}).sort(byKey),
|
|
256
|
+
labels: Object.entries(options.labels ?? {}).sort(byKey),
|
|
257
|
+
mounts: options.mounts ?? [],
|
|
258
|
+
tmpfs: options.tmpfs ?? [],
|
|
259
|
+
ipcHost: Boolean(options.ipcHost),
|
|
260
|
+
memorySwappiness: options.memorySwappiness,
|
|
261
|
+
}))
|
|
262
|
+
.digest('hex');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/docker/fixtures.ts"],"names":[],"mappings":"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"}
|
package/dist/docker/host.d.ts
CHANGED
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
import { type Result } from 'nano-spawn';
|
|
2
2
|
import { type TestRun } from './test-run.ts';
|
|
3
3
|
export declare const quote: (value: string) => string;
|
|
4
|
-
/** How long one Docker CLI call may take before this process stops it. */
|
|
5
|
-
export declare const DOCKER_COMMAND_TIMEOUT = 240000;
|
|
6
4
|
/** How long one command in the SSH engine's remote shell may take. */
|
|
7
5
|
export declare const SHELL_TIMEOUT = 30000;
|
|
8
|
-
/** The environment that points the Docker CLI at `endpoint`, whatever context is selected. */
|
|
9
|
-
export declare const dockerEnvironment: (endpoint: string) => Record<string, string | undefined>;
|
|
10
6
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* has a process record while it runs.
|
|
7
|
+
* The endpoint of an engine, for what the Engine API does not do: a shell
|
|
8
|
+
* on the host of an SSH engine and port forwards from it. With a run, each
|
|
9
|
+
* command it starts has a process record while it runs.
|
|
14
10
|
*/
|
|
15
11
|
export declare class DockerHost {
|
|
16
12
|
#private;
|
|
17
13
|
readonly endpoint: string;
|
|
18
14
|
constructor(endpoint: string, run: TestRun | undefined);
|
|
19
|
-
/** The engine the Docker CLI selects. A run gets this process's process record. */
|
|
20
|
-
static resolve(run: TestRun | undefined): Promise<DockerHost>;
|
|
21
15
|
get remote(): boolean;
|
|
22
|
-
readonly command: (args: string[]) => Promise<Result>;
|
|
23
16
|
sshArgs(options?: string[]): string[];
|
|
24
17
|
shell(script: string, input?: string): Promise<Result>;
|
|
25
18
|
forward(port: number): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/docker/host.ts"],"names":[],"mappings":"AAKA,OAAgB,EACd,KAAK,MAAM,EAGZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,KAAK,OAAO,EAAiB,MAAM,eAAe,CAAC;AAE5D,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,MACC,CAAC;AAExC,
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/docker/host.ts"],"names":[],"mappings":"AAKA,OAAgB,EACd,KAAK,MAAM,EAGZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,KAAK,OAAO,EAAiB,MAAM,eAAe,CAAC;AAE5D,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,MACC,CAAC;AAExC,sEAAsE;AACtE,eAAO,MAAM,aAAa,QAAS,CAAC;AAwBpC;;;;GAIG;AACH,qBAAa,UAAU;;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGd,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,SAAS;IAUtD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,OAAO,CAAC,OAAO,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE;IAqBzC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUhD,OAAO,CACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;CAkJzD"}
|
package/dist/docker/host.js
CHANGED
|
@@ -6,21 +6,31 @@ import command, { SubprocessError, } from 'nano-spawn';
|
|
|
6
6
|
import { timebox } from "../async/timebox.js";
|
|
7
7
|
import { forwardPrefix } from "./test-run.js";
|
|
8
8
|
export const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
9
|
-
/** How long one Docker CLI call may take before this process stops it. */
|
|
10
|
-
export const DOCKER_COMMAND_TIMEOUT = 240_000;
|
|
11
9
|
/** How long one command in the SSH engine's remote shell may take. */
|
|
12
10
|
export const SHELL_TIMEOUT = 30_000;
|
|
13
|
-
/** The environment that points the Docker CLI at `endpoint`, whatever context is selected. */
|
|
14
|
-
export const dockerEnvironment = (endpoint) => ({
|
|
15
|
-
DOCKER_CONTEXT: undefined,
|
|
16
|
-
DOCKER_HOST: endpoint,
|
|
17
|
-
});
|
|
18
11
|
/** Local Unix sockets, Docker Desktop's named pipe on Windows, and SSH engines. A `tcp://` engine may be on another machine. */
|
|
19
12
|
const supportedEndpoints = ['unix://', 'npipe://', 'ssh://'];
|
|
20
13
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
14
|
+
* A command this process started. A killed process leaves its commands
|
|
15
|
+
* running; their process records keep its run until they end.
|
|
16
|
+
*/
|
|
17
|
+
async function recorded(run, subprocess) {
|
|
18
|
+
if (!run)
|
|
19
|
+
return subprocess;
|
|
20
|
+
// Awaited below; a command that fails while its record is written must
|
|
21
|
+
// not count as an unhandled rejection.
|
|
22
|
+
subprocess.catch(() => { });
|
|
23
|
+
const { pid } = await subprocess.nodeChildProcess;
|
|
24
|
+
// Node leaves pid undefined when the spawn failed: no process to record.
|
|
25
|
+
if (pid === undefined)
|
|
26
|
+
return subprocess;
|
|
27
|
+
await using _record = await run.recordProcess(pid);
|
|
28
|
+
return await subprocess;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The endpoint of an engine, for what the Engine API does not do: a shell
|
|
32
|
+
* on the host of an SSH engine and port forwards from it. With a run, each
|
|
33
|
+
* command it starts has a process record while it runs.
|
|
24
34
|
*/
|
|
25
35
|
export class DockerHost {
|
|
26
36
|
endpoint;
|
|
@@ -32,39 +42,9 @@ export class DockerHost {
|
|
|
32
42
|
this.endpoint = endpoint;
|
|
33
43
|
this.#run = run;
|
|
34
44
|
}
|
|
35
|
-
/** The engine the Docker CLI selects. A run gets this process's process record. */
|
|
36
|
-
static async resolve(run) {
|
|
37
|
-
const { stdout } = await command('docker', [
|
|
38
|
-
'context',
|
|
39
|
-
'inspect',
|
|
40
|
-
'--format',
|
|
41
|
-
'{{.Endpoints.docker.Host}}',
|
|
42
|
-
]);
|
|
43
|
-
const host = new DockerHost(stdout.trim(), run);
|
|
44
|
-
await run?.recordProcess(process.pid);
|
|
45
|
-
return host;
|
|
46
|
-
}
|
|
47
45
|
get remote() {
|
|
48
46
|
return this.endpoint.startsWith('ssh://');
|
|
49
47
|
}
|
|
50
|
-
command = (args) => this.#recorded(command('docker', args, {
|
|
51
|
-
env: dockerEnvironment(this.endpoint),
|
|
52
|
-
timeout: DOCKER_COMMAND_TIMEOUT,
|
|
53
|
-
}));
|
|
54
|
-
/** A killed process leaves its commands running; their records keep its run until they end. */
|
|
55
|
-
async #recorded(subprocess) {
|
|
56
|
-
if (!this.#run)
|
|
57
|
-
return subprocess;
|
|
58
|
-
// Awaited below; a command that fails while its record is written must
|
|
59
|
-
// not count as an unhandled rejection.
|
|
60
|
-
subprocess.catch(() => { });
|
|
61
|
-
const { pid } = await subprocess.nodeChildProcess;
|
|
62
|
-
// Node leaves pid undefined when the spawn failed: no process to record.
|
|
63
|
-
if (pid === undefined)
|
|
64
|
-
return subprocess;
|
|
65
|
-
await using _record = await this.#run.recordProcess(pid);
|
|
66
|
-
return await subprocess;
|
|
67
|
-
}
|
|
68
48
|
sshArgs(options = []) {
|
|
69
49
|
const url = new URL(this.endpoint);
|
|
70
50
|
// Pass the original hostname to OpenSSH: ~/.ssh/config, jump hosts, keys,
|
|
@@ -86,7 +66,7 @@ export class DockerHost {
|
|
|
86
66
|
];
|
|
87
67
|
}
|
|
88
68
|
shell(script, input) {
|
|
89
|
-
return this.#
|
|
69
|
+
return recorded(this.#run, command('ssh', [...this.sshArgs(), script], {
|
|
90
70
|
stdin: input === undefined ? 'ignore' : { string: input },
|
|
91
71
|
timeout: SHELL_TIMEOUT,
|
|
92
72
|
}));
|
package/dist/docker/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/docker/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAe,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,OAAO,EAAE,EAGd,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAgB,aAAa,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE,CAC7C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;AAExC,
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/docker/host.ts"],"names":[],"mappings":"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"}
|
package/dist/docker/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export { Container, type DockerCommand, ServiceContainer, } from './container.ts';
|
|
2
1
|
export { DockerDirectory } from './directory.ts';
|
|
3
|
-
export { type ContainerOptions,
|
|
2
|
+
export { type ContainerOptions, DockerFixtures, type DockerFixturesOptions, type Mount, type ServiceOptions, } from './fixtures.ts';
|
|
3
|
+
export { ServiceContainer } from './service-container.ts';
|
|
4
4
|
export { TestRun } from './test-run.ts';
|
|
5
|
-
export { DockerVolume } from './volume.ts';
|
|
6
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/docker/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/docker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,KAAK,gBAAgB,EACrB,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,KAAK,EACV,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/docker/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export { Container, ServiceContainer, } from "./container.js";
|
|
2
1
|
export { DockerDirectory } from "./directory.js";
|
|
3
|
-
export {
|
|
2
|
+
export { DockerFixtures, } from "./fixtures.js";
|
|
3
|
+
export { ServiceContainer } from "./service-container.js";
|
|
4
4
|
export { TestRun } from "./test-run.js";
|
|
5
|
-
export { DockerVolume } from "./volume.js";
|
|
6
5
|
//# sourceMappingURL=index.js.map
|
package/dist/docker/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/docker/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/docker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAEL,cAAc,GAIf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Container } from '@zukhruf/docker';
|
|
2
|
+
/**
|
|
3
|
+
* A container whose port answers on 127.0.0.1 of this machine, through an SSH
|
|
4
|
+
* forward when the engine is remote. Disposal closes the forward. A dedicated
|
|
5
|
+
* server's disposal also removes its container; a shared server's leaves it
|
|
6
|
+
* running for its other users.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ServiceContainer implements AsyncDisposable {
|
|
9
|
+
#private;
|
|
10
|
+
readonly container: Container;
|
|
11
|
+
readonly host = "127.0.0.1";
|
|
12
|
+
readonly port: number;
|
|
13
|
+
/** Closes the forward and leaves the container running for its other users. */
|
|
14
|
+
readonly disconnect: () => Promise<void>;
|
|
15
|
+
constructor(container: Container, port: number, disconnect: () => Promise<void>, remove: (() => Promise<void>) | undefined);
|
|
16
|
+
/** Removes a dedicated server's container, then closes the forward; when both fail, a SuppressedError holds both. */
|
|
17
|
+
cleanup(): Promise<void>;
|
|
18
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=service-container.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-container.d.ts","sourceRoot":"","sources":["../../src/docker/service-container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,eAAe;;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;gBAIvC,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC/B,MAAM,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS;IAQ3C,qHAAqH;IAC/G,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A container whose port answers on 127.0.0.1 of this machine, through an SSH
|
|
3
|
+
* forward when the engine is remote. Disposal closes the forward. A dedicated
|
|
4
|
+
* server's disposal also removes its container; a shared server's leaves it
|
|
5
|
+
* running for its other users.
|
|
6
|
+
*/
|
|
7
|
+
export class ServiceContainer {
|
|
8
|
+
container;
|
|
9
|
+
host = '127.0.0.1';
|
|
10
|
+
port;
|
|
11
|
+
/** Closes the forward and leaves the container running for its other users. */
|
|
12
|
+
disconnect;
|
|
13
|
+
#remove;
|
|
14
|
+
constructor(container, port, disconnect, remove) {
|
|
15
|
+
this.container = container;
|
|
16
|
+
this.port = port;
|
|
17
|
+
this.disconnect = disconnect;
|
|
18
|
+
this.#remove = remove;
|
|
19
|
+
}
|
|
20
|
+
/** Removes a dedicated server's container, then closes the forward; when both fail, a SuppressedError holds both. */
|
|
21
|
+
async cleanup() {
|
|
22
|
+
await using forward = new AsyncDisposableStack();
|
|
23
|
+
forward.defer(this.disconnect);
|
|
24
|
+
await this.#remove?.();
|
|
25
|
+
}
|
|
26
|
+
[Symbol.asyncDispose]() {
|
|
27
|
+
return this.cleanup();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=service-container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-container.js","sourceRoot":"","sources":["../../src/docker/service-container.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IAClB,SAAS,CAAY;IACrB,IAAI,GAAG,WAAW,CAAC;IACnB,IAAI,CAAS;IACtB,+EAA+E;IACtE,UAAU,CAAsB;IAChC,OAAO,CAAoC;IAEpD,YACE,SAAoB,EACpB,IAAY,EACZ,UAA+B,EAC/B,MAAyC;QAEzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,qHAAqH;IACrH,KAAK,CAAC,OAAO;QACX,YAAY,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IACzB,CAAC;IAED,CAAC,MAAM,CAAC,YAAY,CAAC;QACnB,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -3,7 +3,7 @@ import { readFile, readdir, rm } from 'node:fs/promises';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import { Docker } from '@zukhruf/docker';
|
|
6
|
-
import { SHARED_SERVER_LABEL } from "../docker/
|
|
6
|
+
import { SHARED_SERVER_LABEL } from "../docker/fixtures.js";
|
|
7
7
|
import { DockerHost, SHELL_TIMEOUT, quote } from "../docker/host.js";
|
|
8
8
|
import { TEST_RUN_LABEL, TestRun, directoryPrefix, forwardPrefix, } from "../docker/test-run.js";
|
|
9
9
|
/** How long one Engine API call of the cleanup may take. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cleanup.js","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"run-cleanup.js","sourceRoot":"","sources":["../../src/scripts/run-cleanup.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/testing",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.38",
|
|
4
4
|
"description": "Disposable fixtures for integration tests: Docker containers and database servers, SQLite and DuckDB databases, HTTP servers and streams. Node's global setup and global teardown remove what a killed test run left behind.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"pg": "^8.23.1"
|
|
132
132
|
},
|
|
133
133
|
"dependencies": {
|
|
134
|
-
"@zukhruf/docker": "^0.3.
|
|
134
|
+
"@zukhruf/docker": "^0.3.38",
|
|
135
135
|
"nano-spawn": "^2.1.0",
|
|
136
136
|
"p-memoize": "^8.0.0",
|
|
137
137
|
"p-retry": "^8.0.1"
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type Result } from 'nano-spawn';
|
|
2
|
-
/** The Docker CLI, bound to the engine that a handle was created on. */
|
|
3
|
-
export type DockerCommand = (args: string[]) => Promise<Result>;
|
|
4
|
-
/** A container this process started. Disposal removes it with its anonymous volumes. */
|
|
5
|
-
export declare class Container implements AsyncDisposable {
|
|
6
|
-
readonly containerId: string;
|
|
7
|
-
readonly command: DockerCommand;
|
|
8
|
-
constructor(containerId: string, command: DockerCommand);
|
|
9
|
-
readonly exec: (command: string[]) => Promise<Result>;
|
|
10
|
-
/** What the container printed so far, standard output and error interleaved. */
|
|
11
|
-
logs(): Promise<string>;
|
|
12
|
-
/** Sends `signal` to the container's main process, as `docker kill` does. */
|
|
13
|
-
kill(signal?: string): Promise<void>;
|
|
14
|
-
cleanup(): Promise<void>;
|
|
15
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* A container whose port answers on 127.0.0.1 of this machine, through an SSH
|
|
19
|
-
* forward when the engine is remote. Disposal also closes the forward.
|
|
20
|
-
*/
|
|
21
|
-
export declare class ServiceContainer extends Container {
|
|
22
|
-
readonly host = "127.0.0.1";
|
|
23
|
-
readonly port: number;
|
|
24
|
-
/** Closes the forward and leaves the container running for its other users. */
|
|
25
|
-
readonly disconnect: () => Promise<void>;
|
|
26
|
-
constructor(containerId: string, port: number, command: DockerCommand, disconnect: () => Promise<void>);
|
|
27
|
-
/** Removes the container, then closes the forward; when both fail, a SuppressedError holds both. */
|
|
28
|
-
cleanup(): Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=container.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/docker/container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,YAAY,CAAC;AAE1D,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEhE,wFAAwF;AACxF,qBAAa,SAAU,YAAW,eAAe;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;gBAEpB,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa;IAMvD,QAAQ,CAAC,IAAI,GAAI,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAAC,CACG;IAEvD,gFAAgF;IAC1E,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAK7B,6EAA6E;IACvE,IAAI,CAAC,MAAM,SAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;gBAGvC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAOjC,oGAAoG;IACrF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAKxC"}
|