testcontainers 12.0.3 → 12.0.4
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.
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DockerContainerClient = void 0;
|
|
4
4
|
const stream_1 = require("stream");
|
|
5
|
+
const promises_1 = require("stream/promises");
|
|
5
6
|
const common_1 = require("../../../common");
|
|
6
7
|
class DockerContainerClient {
|
|
7
8
|
dockerode;
|
|
@@ -216,11 +217,18 @@ class DockerContainerClient {
|
|
|
216
217
|
};
|
|
217
218
|
processStream(stdoutStream, stdoutChunks);
|
|
218
219
|
processStream(stderrStream, stderrChunks);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
220
|
+
try {
|
|
221
|
+
await new Promise((res, rej) => {
|
|
222
|
+
stream.on("end", res);
|
|
223
|
+
stream.on("error", rej);
|
|
224
|
+
});
|
|
225
|
+
stdoutStream.end();
|
|
226
|
+
stderrStream.end();
|
|
227
|
+
await Promise.all([(0, promises_1.finished)(stdoutStream), (0, promises_1.finished)(stderrStream)]);
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
stream.destroy();
|
|
231
|
+
}
|
|
224
232
|
const inspectResult = await exec.inspect();
|
|
225
233
|
const exitCode = inspectResult.ExitCode ?? -1;
|
|
226
234
|
const output = outputChunks.join("");
|
package/build/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "12.0.
|
|
1
|
+
export declare const LIB_VERSION = "12.0.4";
|
package/build/version.js
CHANGED
|
@@ -23,10 +23,10 @@ export declare class HttpWaitStrategy extends AbstractWaitStrategy {
|
|
|
23
23
|
[key: string]: string;
|
|
24
24
|
}): this;
|
|
25
25
|
withBasicCredentials(username: string, password: string): this;
|
|
26
|
-
withReadTimeout(
|
|
26
|
+
withReadTimeout(readTimeoutMs: number): this;
|
|
27
27
|
usingTls(): this;
|
|
28
28
|
allowInsecure(): this;
|
|
29
29
|
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts): Promise<void>;
|
|
30
30
|
private handleContainerExit;
|
|
31
|
-
private
|
|
31
|
+
private createInsecureAgent;
|
|
32
32
|
}
|
|
@@ -47,8 +47,8 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
47
47
|
this.headers = { ...this.headers, Authorization: `Basic ${base64Encoded}` };
|
|
48
48
|
return this;
|
|
49
49
|
}
|
|
50
|
-
withReadTimeout(
|
|
51
|
-
this.readTimeoutMs =
|
|
50
|
+
withReadTimeout(readTimeoutMs) {
|
|
51
|
+
this.readTimeoutMs = readTimeoutMs;
|
|
52
52
|
return this;
|
|
53
53
|
}
|
|
54
54
|
usingTls() {
|
|
@@ -65,50 +65,60 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
65
65
|
let containerExited = false;
|
|
66
66
|
const client = await (0, container_runtime_1.getContainerRuntimeClient)();
|
|
67
67
|
const { abortOnContainerExit } = this.options;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
// Scoped per invocation: one strategy instance can drive concurrent waits, so a shared
|
|
69
|
+
// agent would let one finished wait destroy a dispatcher another is still using.
|
|
70
|
+
const agent = this.createInsecureAgent();
|
|
71
|
+
try {
|
|
72
|
+
await new common_1.IntervalRetry(this.readTimeoutMs).retryUntil(async () => {
|
|
73
|
+
try {
|
|
74
|
+
const url = `${this.protocol}://${client.info.containerRuntime.host}:${boundPorts.getBinding(this.port)}${this.path}`;
|
|
75
|
+
if (abortOnContainerExit) {
|
|
76
|
+
const containerStatus = (await client.container.inspect(container)).State.Status;
|
|
77
|
+
if (containerStatus === exitStatus) {
|
|
78
|
+
containerExited = true;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
76
81
|
}
|
|
82
|
+
return (0, undici_response_parser_1.undiciResponseToFetchResponse)(await (0, undici_1.request)(url, {
|
|
83
|
+
method: this.method,
|
|
84
|
+
signal: AbortSignal.timeout(this.readTimeoutMs),
|
|
85
|
+
headers: this.headers,
|
|
86
|
+
dispatcher: agent,
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}, async (response) => {
|
|
93
|
+
if (abortOnContainerExit && containerExited) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
if (response === undefined) {
|
|
97
|
+
return false;
|
|
77
98
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
}, async (response) => {
|
|
89
|
-
if (abortOnContainerExit && containerExited) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
if (response === undefined) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
else if (!this.predicates.length) {
|
|
96
|
-
return response.ok;
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
for (const predicate of this.predicates) {
|
|
100
|
-
const result = await predicate(response);
|
|
101
|
-
if (!result) {
|
|
102
|
-
return false;
|
|
99
|
+
else if (!this.predicates.length) {
|
|
100
|
+
return response.ok;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
for (const predicate of this.predicates) {
|
|
104
|
+
const result = await predicate(response);
|
|
105
|
+
if (!result) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
103
108
|
}
|
|
109
|
+
return true;
|
|
104
110
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
}, () => {
|
|
112
|
+
const message = `URL ${this.path} not accessible after ${this.startupTimeoutMs}ms`;
|
|
113
|
+
common_1.log.error(message, { containerId: container.id });
|
|
114
|
+
throw new Error(message);
|
|
115
|
+
}, this.startupTimeoutMs);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
// Force-close: status-only predicates never read the body, so a graceful close() could
|
|
119
|
+
// hang waiting on unreleased connections. Nothing left to drain once the wait is done.
|
|
120
|
+
await agent?.destroy();
|
|
121
|
+
}
|
|
112
122
|
if (abortOnContainerExit && containerExited) {
|
|
113
123
|
return this.handleContainerExit(container);
|
|
114
124
|
}
|
|
@@ -132,14 +142,15 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
132
142
|
common_1.log.error(message, { containerId: container.id });
|
|
133
143
|
throw new Error(message);
|
|
134
144
|
}
|
|
135
|
-
|
|
136
|
-
if (this._allowInsecure) {
|
|
137
|
-
return
|
|
138
|
-
connect: {
|
|
139
|
-
rejectUnauthorized: false,
|
|
140
|
-
},
|
|
141
|
-
});
|
|
145
|
+
createInsecureAgent() {
|
|
146
|
+
if (!this._allowInsecure) {
|
|
147
|
+
return undefined;
|
|
142
148
|
}
|
|
149
|
+
return new undici_1.Agent({
|
|
150
|
+
connect: {
|
|
151
|
+
rejectUnauthorized: false,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
143
154
|
}
|
|
144
155
|
}
|
|
145
156
|
exports.HttpWaitStrategy = HttpWaitStrategy;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testcontainers",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.4",
|
|
4
4
|
"author": "Cristian Greco",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"debug": "^4.4.3",
|
|
39
39
|
"docker-compose": "^1.4.2",
|
|
40
40
|
"dockerode": "^5.0.0",
|
|
41
|
-
"get-port": "^
|
|
41
|
+
"get-port": "^5.1.1",
|
|
42
42
|
"proper-lockfile": "^4.1.2",
|
|
43
43
|
"properties-reader": "^3.0.1",
|
|
44
44
|
"ssh-remote-port-forward": "^1.0.4",
|
|
45
45
|
"tar-fs": "^3.1.2",
|
|
46
46
|
"tmp": "^0.2.7",
|
|
47
|
-
"undici": "^8.
|
|
47
|
+
"undici": "^8.5.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/archiver": "^7.0.0",
|