testcontainers 9.4.0 → 9.6.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/dist/package.json +3 -3
- package/dist/src/docker/docker-client.d.ts +2 -0
- package/dist/src/docker/docker-client.js +3 -2
- package/dist/src/docker/functions/container/exec-container.d.ts +2 -1
- package/dist/src/docker/functions/container/exec-container.js +10 -5
- package/dist/src/docker/functions/container/put-container-archive.js +4 -1
- package/dist/src/docker/functions/image/image-exists.js +11 -8
- package/dist/src/docker/pull-stream-parser.d.ts +0 -1
- package/dist/src/docker/pull-stream-parser.js +1 -44
- package/dist/src/docker/resolve-host.d.ts +2 -1
- package/dist/src/docker/resolve-host.js +5 -4
- package/dist/src/docker/rootless-unix-socket-strategy.d.ts +2 -1
- package/dist/src/docker/rootless-unix-socket-strategy.js +10 -2
- package/dist/src/docker-compose/functions/docker-compose-pull.d.ts +2 -0
- package/dist/src/docker-compose/functions/docker-compose-pull.js +35 -0
- package/dist/src/docker-compose-environment/docker-compose-environment.d.ts +4 -1
- package/dist/src/docker-compose-environment/docker-compose-environment.js +18 -4
- package/dist/src/generic-container/generic-container.d.ts +2 -2
- package/dist/src/generic-container/generic-container.js +12 -10
- package/dist/src/generic-container/started-generic-container.d.ts +2 -0
- package/dist/src/generic-container/started-generic-container.js +17 -3
- package/dist/src/modules/elasticsearch/elasticsearch-container.js +1 -1
- package/dist/src/network.d.ts +1 -0
- package/dist/src/network.js +6 -3
- package/dist/src/port-check.d.ts +4 -1
- package/dist/src/port-check.js +4 -2
- package/dist/src/test-container.d.ts +1 -6
- package/dist/src/wait-for-container.d.ts +1 -1
- package/dist/src/wait-for-container.js +2 -2
- package/dist/src/wait-strategy/composite-wait-strategy.d.ts +11 -0
- package/dist/src/wait-strategy/composite-wait-strategy.js +54 -0
- package/dist/src/wait-strategy/health-check-wait-strategy.js +2 -1
- package/dist/src/wait-strategy/host-port-wait-strategy.d.ts +1 -5
- package/dist/src/wait-strategy/host-port-wait-strategy.js +18 -14
- package/dist/src/wait-strategy/http-wait-strategy.d.ts +1 -1
- package/dist/src/wait-strategy/http-wait-strategy.js +8 -4
- package/dist/src/wait-strategy/log-wait-strategy.d.ts +1 -1
- package/dist/src/wait-strategy/log-wait-strategy.js +3 -2
- package/dist/src/wait-strategy/shell-wait-strategy.js +7 -4
- package/dist/src/wait-strategy/startup-check-strategy.js +3 -1
- package/dist/src/wait-strategy/wait-strategy.d.ts +7 -4
- package/dist/src/wait-strategy/wait-strategy.js +5 -4
- package/dist/src/wait-strategy/wait.d.ts +3 -0
- package/dist/src/wait-strategy/wait.js +8 -0
- package/package.json +3 -3
- package/dist/src/docker/functions/image/list-images.d.ts +0 -3
- package/dist/src/docker/functions/image/list-images.js +0 -34
- package/dist/src/wait-strategy/default-wait-strategy.d.ts +0 -3
- package/dist/src/wait-strategy/default-wait-strategy.js +0 -7
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testcontainers",
|
|
3
3
|
"author": "Cristian Greco",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.6.0",
|
|
5
5
|
"main": "dist/src/index",
|
|
6
6
|
"types": "dist/src/index",
|
|
7
7
|
"keywords": [
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"build": "npm run clean && tsc -p tsconfig.prod.json",
|
|
28
28
|
"docs:serve": "docker-compose up",
|
|
29
29
|
"clean": "rimraf dist",
|
|
30
|
-
"test": "cross-env DEBUG=testcontainers
|
|
31
|
-
"test:ci": "
|
|
30
|
+
"test": "cross-env DEBUG=testcontainers* jest",
|
|
31
|
+
"test:ci": "npm run test -- --runInBand --coverage",
|
|
32
32
|
"format": "prettier --write package.json \"src/**/*.ts\"",
|
|
33
33
|
"lint": "eslint --fix package.json \"src/**/*.ts\"",
|
|
34
34
|
"lint:ci": "eslint package.json \"src/**/*.ts\" --max-warnings=0",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
3
|
import { HostIps } from "./lookup-host-ips";
|
|
4
|
+
export type Provider = "docker" | "podman";
|
|
4
5
|
type DockerClient = {
|
|
5
6
|
uri: string;
|
|
7
|
+
provider: Provider;
|
|
6
8
|
host: string;
|
|
7
9
|
hostIps: HostIps;
|
|
8
10
|
dockerode: Dockerode;
|
|
@@ -43,12 +43,13 @@ const getDockerClient = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
43
43
|
logger_1.log.debug(`Testing Docker client strategy URI: ${uri}`);
|
|
44
44
|
if (yield isDockerDaemonReachable(dockerode)) {
|
|
45
45
|
const indexServerAddress = (yield (0, system_info_1.getSystemInfo)(dockerode)).dockerInfo.indexServerAddress;
|
|
46
|
-
const
|
|
46
|
+
const provider = uri.includes("podman.sock") ? "podman" : "docker";
|
|
47
|
+
const host = yield (0, resolve_host_1.resolveHost)(dockerode, provider, indexServerAddress, uri);
|
|
47
48
|
const hostIps = yield (0, lookup_host_ips_1.lookupHostIps)(host);
|
|
48
49
|
logger_1.log.info(`Using Docker client strategy: ${strategy.getName()}, Docker host: ${host} (${hostIps
|
|
49
50
|
.map((hostIp) => hostIp.address)
|
|
50
51
|
.join(", ")})`);
|
|
51
|
-
return { uri, host, hostIps, dockerode, indexServerAddress, composeEnvironment };
|
|
52
|
+
return { uri, provider, host, hostIps, dockerode, indexServerAddress, composeEnvironment };
|
|
52
53
|
}
|
|
53
54
|
else {
|
|
54
55
|
logger_1.log.warn(`Docker client strategy ${strategy.getName()} is not reachable`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ExecResult } from "../../types";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
|
-
|
|
3
|
+
import { Provider } from "../../docker-client";
|
|
4
|
+
export declare const execContainer: (dockerode: Dockerode, provider: Provider, container: Dockerode.Container, command: string[], shouldLog?: boolean) => Promise<ExecResult>;
|
|
@@ -15,7 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.execContainer = void 0;
|
|
16
16
|
const logger_1 = require("../../../logger");
|
|
17
17
|
const byline_1 = __importDefault(require("byline"));
|
|
18
|
-
const
|
|
18
|
+
const demux_stream_1 = require("../demux-stream");
|
|
19
|
+
const execContainer = (dockerode, provider, container, command, shouldLog = true) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
20
|
const chunks = [];
|
|
20
21
|
try {
|
|
21
22
|
const exec = yield container.exec({
|
|
@@ -23,7 +24,7 @@ const execContainer = (container, command, shouldLog = true) => __awaiter(void 0
|
|
|
23
24
|
AttachStdout: true,
|
|
24
25
|
AttachStderr: true,
|
|
25
26
|
});
|
|
26
|
-
const stream = yield startExec(exec);
|
|
27
|
+
const stream = yield startExec(dockerode, provider, exec);
|
|
27
28
|
stream.on("data", (chunk) => chunks.push(chunk));
|
|
28
29
|
if (shouldLog && logger_1.execLog.enabled()) {
|
|
29
30
|
(0, byline_1.default)(stream).on("data", (line) => logger_1.execLog.trace(`${container.id}: ${line}`));
|
|
@@ -38,11 +39,15 @@ const execContainer = (container, command, shouldLog = true) => __awaiter(void 0
|
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
41
|
exports.execContainer = execContainer;
|
|
41
|
-
const startExec = (exec) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
|
+
const startExec = (dockerode, provider, exec) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
43
|
try {
|
|
43
44
|
const stream = yield exec.start({ stdin: true, Detach: false, Tty: true });
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (provider === "podman") {
|
|
46
|
+
return (0, demux_stream_1.demuxStream)(dockerode, stream);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return stream;
|
|
50
|
+
}
|
|
46
51
|
}
|
|
47
52
|
catch (err) {
|
|
48
53
|
logger_1.log.error(`Failed to start exec: ${err}`);
|
|
@@ -10,10 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.putContainerArchive = void 0;
|
|
13
|
+
const stream_1 = require("stream");
|
|
13
14
|
const logger_1 = require("../../../logger");
|
|
15
|
+
const stream_utils_1 = require("../../../stream-utils");
|
|
14
16
|
const putContainerArchive = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
17
|
try {
|
|
16
|
-
yield options.container.putArchive(options.stream, { path: options.containerPath });
|
|
18
|
+
const stream = yield options.container.putArchive(options.stream, { path: options.containerPath });
|
|
19
|
+
yield (0, stream_utils_1.streamToString)(stream_1.Readable.from(stream));
|
|
17
20
|
}
|
|
18
21
|
catch (err) {
|
|
19
22
|
logger_1.log.error(`Failed to put archive to container ${options.container.id}: ${err}`);
|
|
@@ -13,22 +13,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.imageExists = void 0;
|
|
16
|
-
const logger_1 = require("../../../logger");
|
|
17
16
|
const async_lock_1 = __importDefault(require("async-lock"));
|
|
18
|
-
const list_images_1 = require("./list-images");
|
|
19
17
|
const existingImages = new Set();
|
|
20
18
|
const imageCheckLock = new async_lock_1.default();
|
|
21
19
|
const imageExists = (dockerode, imageName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
-
logger_1.log.debug(`Checking if image exists: ${imageName}`);
|
|
23
20
|
return imageCheckLock.acquire(imageName.toString(), () => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
21
|
if (existingImages.has(imageName.toString())) {
|
|
25
22
|
return true;
|
|
26
23
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
existingImages.add(
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
try {
|
|
25
|
+
yield dockerode.getImage(imageName.toString()).inspect();
|
|
26
|
+
existingImages.add(imageName.toString());
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (err instanceof Error && err.message.toLowerCase().includes("no such image")) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
32
35
|
}));
|
|
33
36
|
});
|
|
34
37
|
exports.imageExists = imageExists;
|
|
@@ -11,53 +11,10 @@ class PullStreamParser {
|
|
|
11
11
|
this.logger = logger;
|
|
12
12
|
}
|
|
13
13
|
consume(stream) {
|
|
14
|
-
const messagesById = new Map();
|
|
15
|
-
const statusesById = new Map();
|
|
16
14
|
return new Promise((resolve) => {
|
|
17
|
-
(0, byline_1.default)(stream).on("data", (line) => {
|
|
18
|
-
try {
|
|
19
|
-
const json = JSON.parse(line);
|
|
20
|
-
const { id, status } = json;
|
|
21
|
-
const prefix = id
|
|
22
|
-
? `Pulling ${this.dockerImageName.toString()} - ${id}`
|
|
23
|
-
: `Pulling ${this.dockerImageName.toString()}`;
|
|
24
|
-
if (status === "Downloading") {
|
|
25
|
-
const { current, total } = json.progressDetail;
|
|
26
|
-
const percentage = Math.round(100 * (current / total));
|
|
27
|
-
const message = `${prefix} - ${json.status} ${percentage}%`;
|
|
28
|
-
const messages = this.getOrElse(messagesById, id, new Set());
|
|
29
|
-
if (!messages.has(message)) {
|
|
30
|
-
messages.add(message);
|
|
31
|
-
this.logger.trace(message);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
const statuses = this.getOrElse(statusesById, id, new Set());
|
|
36
|
-
if (!statuses.has(status)) {
|
|
37
|
-
statuses.add(status);
|
|
38
|
-
const message = `${prefix} - ${json.status}`;
|
|
39
|
-
const messages = this.getOrElse(messagesById, id, new Set());
|
|
40
|
-
if (!messages.has(message)) {
|
|
41
|
-
messages.add(message);
|
|
42
|
-
this.logger.trace(message);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch (_a) {
|
|
48
|
-
this.logger.warn(`Unexpected message format: ${line}`);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
15
|
+
(0, byline_1.default)(stream).on("data", (line) => this.logger.trace(`Pulling ${this.dockerImageName.toString()}: ${line}`));
|
|
51
16
|
stream.on("end", resolve);
|
|
52
17
|
});
|
|
53
18
|
}
|
|
54
|
-
getOrElse(map, key, orElse) {
|
|
55
|
-
const value = map.get(key);
|
|
56
|
-
if (value === undefined) {
|
|
57
|
-
map.set(key, orElse);
|
|
58
|
-
return orElse;
|
|
59
|
-
}
|
|
60
|
-
return value;
|
|
61
|
-
}
|
|
62
19
|
}
|
|
63
20
|
exports.PullStreamParser = PullStreamParser;
|
|
@@ -3,4 +3,5 @@
|
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
/// <reference types="node" />
|
|
5
5
|
import Dockerode from "dockerode";
|
|
6
|
-
|
|
6
|
+
import { Provider } from "./docker-client";
|
|
7
|
+
export declare const resolveHost: (dockerode: Dockerode, provider: Provider, indexServerAddress: string, uri: string, env?: NodeJS.ProcessEnv) => Promise<string>;
|
|
@@ -14,7 +14,7 @@ const url_1 = require("url");
|
|
|
14
14
|
const logger_1 = require("../logger");
|
|
15
15
|
const run_in_container_1 = require("./functions/run-in-container");
|
|
16
16
|
const fs_1 = require("fs");
|
|
17
|
-
const resolveHost = (dockerode, indexServerAddress, uri, env = process.env) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
const resolveHost = (dockerode, provider, indexServerAddress, uri, env = process.env) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
18
|
if (env.TESTCONTAINERS_HOST_OVERRIDE !== undefined) {
|
|
19
19
|
return env.TESTCONTAINERS_HOST_OVERRIDE;
|
|
20
20
|
}
|
|
@@ -27,7 +27,8 @@ const resolveHost = (dockerode, indexServerAddress, uri, env = process.env) => _
|
|
|
27
27
|
case "unix:":
|
|
28
28
|
case "npipe:": {
|
|
29
29
|
if (isInContainer()) {
|
|
30
|
-
const
|
|
30
|
+
const networkName = provider === "podman" ? "podman" : "bridge";
|
|
31
|
+
const gateway = yield findGateway(dockerode, networkName);
|
|
31
32
|
if (gateway !== undefined) {
|
|
32
33
|
return gateway;
|
|
33
34
|
}
|
|
@@ -43,10 +44,10 @@ const resolveHost = (dockerode, indexServerAddress, uri, env = process.env) => _
|
|
|
43
44
|
}
|
|
44
45
|
});
|
|
45
46
|
exports.resolveHost = resolveHost;
|
|
46
|
-
const findGateway = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const findGateway = (dockerode, networkName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
48
|
var _a, _b, _c;
|
|
48
49
|
logger_1.log.debug(`Checking gateway for Docker host`);
|
|
49
|
-
const inspectResult = yield dockerode.getNetwork(
|
|
50
|
+
const inspectResult = yield dockerode.getNetwork(networkName).inspect();
|
|
50
51
|
return (_c = (_b = (_a = inspectResult === null || inspectResult === void 0 ? void 0 : inspectResult.IPAM) === null || _a === void 0 ? void 0 : _a.Config) === null || _b === void 0 ? void 0 : _b.find((config) => config.Gateway !== undefined)) === null || _c === void 0 ? void 0 : _c.Gateway;
|
|
51
52
|
});
|
|
52
53
|
const findDefaultGateway = (dockerode, indexServerAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -8,7 +8,8 @@ export declare class RootlessUnixSocketStrategy implements DockerClientStrategy
|
|
|
8
8
|
constructor(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv);
|
|
9
9
|
init(): Promise<void>;
|
|
10
10
|
private getSocketPathFromEnv;
|
|
11
|
-
private
|
|
11
|
+
private getSocketPathFromHomeRunDir;
|
|
12
|
+
private getSocketPathFromHomeDesktopDir;
|
|
12
13
|
private getSocketPathFromRunDir;
|
|
13
14
|
getDockerClient(): Promise<DockerClientInit>;
|
|
14
15
|
isApplicable(): boolean;
|
|
@@ -29,7 +29,12 @@ class RootlessUnixSocketStrategy {
|
|
|
29
29
|
this.applicable = false;
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
|
-
this.socketPath = [
|
|
32
|
+
this.socketPath = [
|
|
33
|
+
this.getSocketPathFromEnv(),
|
|
34
|
+
this.getSocketPathFromHomeRunDir(),
|
|
35
|
+
this.getSocketPathFromHomeDesktopDir(),
|
|
36
|
+
this.getSocketPathFromRunDir(),
|
|
37
|
+
]
|
|
33
38
|
.filter(type_guards_1.isDefined)
|
|
34
39
|
.find((candidateSocketPath) => (0, fs_1.existsSync)(candidateSocketPath));
|
|
35
40
|
this.applicable = this.socketPath !== undefined;
|
|
@@ -44,9 +49,12 @@ class RootlessUnixSocketStrategy {
|
|
|
44
49
|
return undefined;
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
|
-
|
|
52
|
+
getSocketPathFromHomeRunDir() {
|
|
48
53
|
return path_1.default.join(os_1.default.homedir(), ".docker", "run", "docker.sock");
|
|
49
54
|
}
|
|
55
|
+
getSocketPathFromHomeDesktopDir() {
|
|
56
|
+
return path_1.default.join(os_1.default.homedir(), ".docker", "desktop", "docker.sock");
|
|
57
|
+
}
|
|
50
58
|
getSocketPathFromRunDir() {
|
|
51
59
|
return path_1.default.join("/run", "user", `${os_1.default.userInfo().uid}`, "docker.sock");
|
|
52
60
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.dockerComposePull = void 0;
|
|
13
|
+
const logger_1 = require("../../logger");
|
|
14
|
+
const docker_compose_1 = require("docker-compose");
|
|
15
|
+
const default_docker_compose_options_1 = require("../default-docker-compose-options");
|
|
16
|
+
const dockerComposePull = (options, services) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
try {
|
|
18
|
+
if (services) {
|
|
19
|
+
logger_1.log.info(`Pulling DockerCompose environment images for ${services.join(", ")}`);
|
|
20
|
+
yield (0, docker_compose_1.pullMany)(services, yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
logger_1.log.info(`Pulling DockerCompose environment images`);
|
|
24
|
+
yield (0, docker_compose_1.pullAll)(yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options));
|
|
25
|
+
}
|
|
26
|
+
logger_1.log.info(`Pulled DockerCompose environment`);
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
const errorMessage = err.err || err.message || err || "";
|
|
31
|
+
logger_1.log.error(`Failed to pull DockerCompose environment images: ${errorMessage.trim()}`);
|
|
32
|
+
throw new Error(errorMessage);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
exports.dockerComposePull = dockerComposePull;
|
|
@@ -2,6 +2,7 @@ import { WaitStrategy } from "../wait-strategy/wait-strategy";
|
|
|
2
2
|
import { Uuid } from "../uuid";
|
|
3
3
|
import { Environment } from "../docker/types";
|
|
4
4
|
import { StartedDockerComposeEnvironment } from "./started-docker-compose-environment";
|
|
5
|
+
import { PullPolicy } from "../pull-policy";
|
|
5
6
|
export declare class DockerComposeEnvironment {
|
|
6
7
|
private readonly composeFilePath;
|
|
7
8
|
private readonly composeFiles;
|
|
@@ -11,14 +12,16 @@ export declare class DockerComposeEnvironment {
|
|
|
11
12
|
private environmentFile;
|
|
12
13
|
private profiles;
|
|
13
14
|
private environment;
|
|
15
|
+
private pullPolicy;
|
|
14
16
|
private waitStrategy;
|
|
15
|
-
private startupTimeout
|
|
17
|
+
private startupTimeout?;
|
|
16
18
|
constructor(composeFilePath: string, composeFiles: string | string[], uuid?: Uuid);
|
|
17
19
|
withBuild(): this;
|
|
18
20
|
withEnvironment(environment: Environment): this;
|
|
19
21
|
withEnvironmentFile(environmentFile: string): this;
|
|
20
22
|
withProfiles(...profiles: string[]): this;
|
|
21
23
|
withNoRecreate(): this;
|
|
24
|
+
withPullPolicy(pullPolicy: PullPolicy): this;
|
|
22
25
|
withWaitStrategy(containerName: string, waitStrategy: WaitStrategy): this;
|
|
23
26
|
withStartupTimeout(startupTimeout: number): this;
|
|
24
27
|
up(services?: Array<string>): Promise<StartedDockerComposeEnvironment>;
|
|
@@ -25,7 +25,9 @@ const started_docker_compose_environment_1 = require("./started-docker-compose-e
|
|
|
25
25
|
const docker_compose_down_1 = require("../docker-compose/functions/docker-compose-down");
|
|
26
26
|
const docker_compose_up_1 = require("../docker-compose/functions/docker-compose-up");
|
|
27
27
|
const wait_for_container_1 = require("../wait-for-container");
|
|
28
|
-
const
|
|
28
|
+
const pull_policy_1 = require("../pull-policy");
|
|
29
|
+
const docker_compose_pull_1 = require("../docker-compose/functions/docker-compose-pull");
|
|
30
|
+
const wait_1 = require("../wait-strategy/wait");
|
|
29
31
|
class DockerComposeEnvironment {
|
|
30
32
|
constructor(composeFilePath, composeFiles, uuid = new uuid_1.RandomUuid()) {
|
|
31
33
|
this.build = false;
|
|
@@ -33,8 +35,8 @@ class DockerComposeEnvironment {
|
|
|
33
35
|
this.environmentFile = "";
|
|
34
36
|
this.profiles = [];
|
|
35
37
|
this.environment = {};
|
|
38
|
+
this.pullPolicy = new pull_policy_1.DefaultPullPolicy();
|
|
36
39
|
this.waitStrategy = {};
|
|
37
|
-
this.startupTimeout = 60000;
|
|
38
40
|
this.composeFilePath = composeFilePath;
|
|
39
41
|
this.composeFiles = composeFiles;
|
|
40
42
|
this.projectName = `testcontainers-${uuid.nextUuid()}`;
|
|
@@ -60,6 +62,10 @@ class DockerComposeEnvironment {
|
|
|
60
62
|
this.projectName = "testcontainers-node";
|
|
61
63
|
return this;
|
|
62
64
|
}
|
|
65
|
+
withPullPolicy(pullPolicy) {
|
|
66
|
+
this.pullPolicy = pullPolicy;
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
63
69
|
withWaitStrategy(containerName, waitStrategy) {
|
|
64
70
|
this.waitStrategy[containerName] = waitStrategy;
|
|
65
71
|
return this;
|
|
@@ -89,6 +95,9 @@ class DockerComposeEnvironment {
|
|
|
89
95
|
composeOptions.push("--env-file", this.environmentFile);
|
|
90
96
|
}
|
|
91
97
|
this.profiles.forEach((profile) => composeOptions.push("--profile", profile));
|
|
98
|
+
if (this.pullPolicy.shouldPull()) {
|
|
99
|
+
yield (0, docker_compose_pull_1.dockerComposePull)(options, services);
|
|
100
|
+
}
|
|
92
101
|
yield (0, docker_compose_up_1.dockerComposeUp)(Object.assign(Object.assign({}, options), { commandOptions, composeOptions, environment: this.environment }), services);
|
|
93
102
|
const startedContainers = (yield (0, list_containers_1.listContainers)()).filter((container) => container.Labels["com.docker.compose.project"] === this.projectName);
|
|
94
103
|
const startedContainerNames = startedContainers.reduce((containerNames, startedContainer) => [
|
|
@@ -102,7 +111,12 @@ class DockerComposeEnvironment {
|
|
|
102
111
|
const { host, hostIps } = yield (0, docker_client_1.dockerClient)();
|
|
103
112
|
const inspectResult = yield (0, inspect_container_1.inspectContainer)(container);
|
|
104
113
|
const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult);
|
|
105
|
-
const waitStrategy =
|
|
114
|
+
const waitStrategy = this.waitStrategy[containerName]
|
|
115
|
+
? this.waitStrategy[containerName]
|
|
116
|
+
: wait_1.Wait.forListeningPorts();
|
|
117
|
+
if (this.startupTimeout !== undefined) {
|
|
118
|
+
waitStrategy.withStartupTimeout(this.startupTimeout);
|
|
119
|
+
}
|
|
106
120
|
if (logger_1.containerLog.enabled()) {
|
|
107
121
|
(yield (0, container_logs_1.containerLogs)(container))
|
|
108
122
|
.on("data", (data) => logger_1.containerLog.trace(`${containerName}: ${data.trim()}`))
|
|
@@ -110,7 +124,7 @@ class DockerComposeEnvironment {
|
|
|
110
124
|
}
|
|
111
125
|
try {
|
|
112
126
|
logger_1.log.info(`Waiting for container ${containerName} to be ready`);
|
|
113
|
-
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy,
|
|
127
|
+
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, boundPorts);
|
|
114
128
|
logger_1.log.info(`Container ${containerName} is ready`);
|
|
115
129
|
}
|
|
116
130
|
catch (err) {
|
|
@@ -13,8 +13,8 @@ export declare class GenericContainer implements TestContainer {
|
|
|
13
13
|
readonly image: string;
|
|
14
14
|
static fromDockerfile(context: string, dockerfileName?: string): GenericContainerBuilder;
|
|
15
15
|
protected opts: CreateContainerOptions;
|
|
16
|
-
protected startupTimeout
|
|
17
|
-
protected waitStrategy
|
|
16
|
+
protected startupTimeout?: number;
|
|
17
|
+
protected waitStrategy: WaitStrategy;
|
|
18
18
|
protected tarToCopy?: archiver.Archiver;
|
|
19
19
|
protected networkMode?: string;
|
|
20
20
|
protected networkAliases: string[];
|
|
@@ -36,7 +36,7 @@ const get_container_1 = require("../docker/functions/container/get-container");
|
|
|
36
36
|
const labels_1 = require("../labels");
|
|
37
37
|
const wait_for_container_1 = require("../wait-for-container");
|
|
38
38
|
const create_container_options_1 = require("./create-container-options");
|
|
39
|
-
const
|
|
39
|
+
const wait_1 = require("../wait-strategy/wait");
|
|
40
40
|
const reusableContainerCreationLock = new async_lock_1.default();
|
|
41
41
|
class GenericContainer {
|
|
42
42
|
static fromDockerfile(context, dockerfileName = "Dockerfile") {
|
|
@@ -44,7 +44,7 @@ class GenericContainer {
|
|
|
44
44
|
}
|
|
45
45
|
constructor(image) {
|
|
46
46
|
this.image = image;
|
|
47
|
-
this.
|
|
47
|
+
this.waitStrategy = wait_1.Wait.forListeningPorts();
|
|
48
48
|
this.networkAliases = [];
|
|
49
49
|
this.pullPolicy = new pull_policy_1.DefaultPullPolicy();
|
|
50
50
|
const imageName = docker_image_name_1.DockerImageName.fromString(image);
|
|
@@ -101,17 +101,18 @@ class GenericContainer {
|
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
reuseContainer(container) {
|
|
104
|
-
var _a;
|
|
105
104
|
return __awaiter(this, void 0, void 0, function* () {
|
|
106
105
|
const { host, hostIps } = yield (0, docker_client_1.dockerClient)();
|
|
107
106
|
const inspectResult = yield (0, inspect_container_1.inspectContainer)(container);
|
|
108
107
|
const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
|
|
109
|
-
|
|
108
|
+
if (this.startupTimeout !== undefined) {
|
|
109
|
+
this.waitStrategy.withStartupTimeout(this.startupTimeout);
|
|
110
|
+
}
|
|
110
111
|
if (this.containerStarting) {
|
|
111
112
|
yield this.containerStarting(inspectResult, true);
|
|
112
113
|
}
|
|
113
|
-
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy,
|
|
114
|
-
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
|
|
114
|
+
yield (0, wait_for_container_1.waitForContainer)(container, this.waitStrategy, boundPorts);
|
|
115
|
+
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, this.waitStrategy);
|
|
115
116
|
if (this.containerStarted) {
|
|
116
117
|
yield this.containerStarted(startedContainer, inspectResult, true);
|
|
117
118
|
}
|
|
@@ -122,7 +123,6 @@ class GenericContainer {
|
|
|
122
123
|
});
|
|
123
124
|
}
|
|
124
125
|
startContainer(createContainerOptions) {
|
|
125
|
-
var _a;
|
|
126
126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
127
127
|
const container = yield (0, create_container_1.createContainer)(createContainerOptions);
|
|
128
128
|
if (!this.opts.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
|
|
@@ -156,7 +156,9 @@ class GenericContainer {
|
|
|
156
156
|
const { host, hostIps } = yield (0, docker_client_1.dockerClient)();
|
|
157
157
|
const inspectResult = yield (0, inspect_container_1.inspectContainer)(container);
|
|
158
158
|
const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
|
|
159
|
-
|
|
159
|
+
if (this.startupTimeout !== undefined) {
|
|
160
|
+
this.waitStrategy.withStartupTimeout(this.startupTimeout);
|
|
161
|
+
}
|
|
160
162
|
if (logger_1.containerLog.enabled()) {
|
|
161
163
|
(yield (0, container_logs_1.containerLogs)(container))
|
|
162
164
|
.on("data", (data) => logger_1.containerLog.trace(`${container.id}: ${data.trim()}`))
|
|
@@ -165,8 +167,8 @@ class GenericContainer {
|
|
|
165
167
|
if (this.containerStarting) {
|
|
166
168
|
yield this.containerStarting(inspectResult, false);
|
|
167
169
|
}
|
|
168
|
-
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy,
|
|
169
|
-
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
|
|
170
|
+
yield (0, wait_for_container_1.waitForContainer)(container, this.waitStrategy, boundPorts);
|
|
171
|
+
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, this.waitStrategy);
|
|
170
172
|
if (this.containerStarted) {
|
|
171
173
|
yield this.containerStarted(startedContainer, inspectResult, false);
|
|
172
174
|
}
|
|
@@ -13,6 +13,8 @@ export declare class StartedGenericContainer implements StartedTestContainer {
|
|
|
13
13
|
private boundPorts;
|
|
14
14
|
private readonly name;
|
|
15
15
|
private readonly waitStrategy;
|
|
16
|
+
private stoppedContainer?;
|
|
17
|
+
private stopContainerLock;
|
|
16
18
|
constructor(container: Dockerode.Container, host: string, inspectResult: InspectResult, boundPorts: BoundPorts, name: string, waitStrategy: WaitStrategy);
|
|
17
19
|
protected containerIsStopping?(): Promise<void>;
|
|
18
20
|
stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
|
|
@@ -8,6 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.StartedGenericContainer = void 0;
|
|
13
16
|
const inspect_container_1 = require("../docker/functions/container/inspect-container");
|
|
@@ -21,6 +24,7 @@ const stop_container_1 = require("../docker/functions/container/stop-container")
|
|
|
21
24
|
const restart_container_1 = require("../docker/functions/container/restart-container");
|
|
22
25
|
const wait_for_container_1 = require("../wait-for-container");
|
|
23
26
|
const docker_client_1 = require("../docker/docker-client");
|
|
27
|
+
const async_lock_1 = __importDefault(require("async-lock"));
|
|
24
28
|
class StartedGenericContainer {
|
|
25
29
|
constructor(container, host, inspectResult, boundPorts, name, waitStrategy) {
|
|
26
30
|
this.container = container;
|
|
@@ -29,10 +33,17 @@ class StartedGenericContainer {
|
|
|
29
33
|
this.boundPorts = boundPorts;
|
|
30
34
|
this.name = name;
|
|
31
35
|
this.waitStrategy = waitStrategy;
|
|
36
|
+
this.stopContainerLock = new async_lock_1.default();
|
|
32
37
|
}
|
|
33
38
|
stop(options = {}) {
|
|
34
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
return this.
|
|
40
|
+
return this.stopContainerLock.acquire("stop", () => __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (this.stoppedContainer) {
|
|
42
|
+
return this.stoppedContainer;
|
|
43
|
+
}
|
|
44
|
+
this.stoppedContainer = yield this.stopContainer(options);
|
|
45
|
+
return this.stoppedContainer;
|
|
46
|
+
}));
|
|
36
47
|
});
|
|
37
48
|
}
|
|
38
49
|
restart(options = {}) {
|
|
@@ -49,7 +60,7 @@ class StartedGenericContainer {
|
|
|
49
60
|
.on("err", (data) => logger_1.containerLog.error(`${this.container.id}: ${data.trim()}`));
|
|
50
61
|
}
|
|
51
62
|
this.boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, this.inspectResult).filter(Array.from(this.boundPorts.iterator()).map((port) => port[0]));
|
|
52
|
-
yield (0, wait_for_container_1.waitForContainer)(this.container, this.waitStrategy, this.
|
|
63
|
+
yield (0, wait_for_container_1.waitForContainer)(this.container, this.waitStrategy, this.boundPorts, startTime);
|
|
53
64
|
});
|
|
54
65
|
}
|
|
55
66
|
stopContainer(options = {}) {
|
|
@@ -95,7 +106,10 @@ class StartedGenericContainer {
|
|
|
95
106
|
return this.inspectResult.networkSettings[networkName].ipAddress;
|
|
96
107
|
}
|
|
97
108
|
exec(command) {
|
|
98
|
-
return (0,
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const { dockerode, provider } = yield (0, docker_client_1.dockerClient)();
|
|
111
|
+
return (0, exec_container_1.execContainer)(dockerode, provider, this.container, command);
|
|
112
|
+
});
|
|
99
113
|
}
|
|
100
114
|
logs() {
|
|
101
115
|
return (0, container_logs_1.containerLogs)(this.container);
|
|
@@ -26,7 +26,7 @@ class ElasticsearchContainer extends __1.GenericContainer {
|
|
|
26
26
|
.withEnvironment({ "discovery.type": "single-node" })
|
|
27
27
|
.withCopyContentToContainer([
|
|
28
28
|
{
|
|
29
|
-
content: "-
|
|
29
|
+
content: "-Xmx2G\n",
|
|
30
30
|
target: "/usr/share/elasticsearch/config/jvm.options.d/elasticsearch-default-memory-vm.options",
|
|
31
31
|
},
|
|
32
32
|
])
|
package/dist/src/network.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Uuid } from "./uuid";
|
|
|
2
2
|
import { CreateNetworkOptions } from "./docker/functions/network/create-network";
|
|
3
3
|
export declare class Network {
|
|
4
4
|
private readonly createNetworkOptions;
|
|
5
|
+
private readonly uuid;
|
|
5
6
|
constructor(createNetworkOptions?: Partial<CreateNetworkOptions>, uuid?: Uuid);
|
|
6
7
|
start(): Promise<StartedNetwork>;
|
|
7
8
|
}
|
package/dist/src/network.js
CHANGED
|
@@ -17,14 +17,17 @@ const create_network_1 = require("./docker/functions/network/create-network");
|
|
|
17
17
|
const remove_network_1 = require("./docker/functions/network/remove-network");
|
|
18
18
|
class Network {
|
|
19
19
|
constructor(createNetworkOptions = {}, uuid = new uuid_1.RandomUuid()) {
|
|
20
|
-
this.createNetworkOptions =
|
|
20
|
+
this.createNetworkOptions = createNetworkOptions;
|
|
21
|
+
this.uuid = uuid;
|
|
22
|
+
this.createNetworkOptions = createNetworkOptions;
|
|
21
23
|
}
|
|
22
24
|
start() {
|
|
23
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const options = Object.assign({ name: this.uuid.nextUuid(), driver: "bridge", checkDuplicate: true, internal: false, attachable: false, ingress: false, enableIPv6: false }, this.createNetworkOptions);
|
|
24
27
|
yield reaper_1.ReaperInstance.getInstance();
|
|
25
|
-
const id = yield (0, create_network_1.createNetwork)(
|
|
28
|
+
const id = yield (0, create_network_1.createNetwork)(options);
|
|
26
29
|
logger_1.log.info(`Started network with ID: ${id}`);
|
|
27
|
-
return new StartedNetwork(id,
|
|
30
|
+
return new StartedNetwork(id, options);
|
|
28
31
|
});
|
|
29
32
|
}
|
|
30
33
|
}
|
package/dist/src/port-check.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Dockerode from "dockerode";
|
|
2
|
+
import { Provider } from "./docker/docker-client";
|
|
2
3
|
export interface PortCheck {
|
|
3
4
|
isBound(port: number): Promise<boolean>;
|
|
4
5
|
}
|
|
@@ -8,10 +9,12 @@ export declare class HostPortCheck implements PortCheck {
|
|
|
8
9
|
isBound(port: number): Promise<boolean>;
|
|
9
10
|
}
|
|
10
11
|
export declare class InternalPortCheck implements PortCheck {
|
|
12
|
+
private readonly dockerode;
|
|
13
|
+
private readonly provider;
|
|
11
14
|
private readonly container;
|
|
12
15
|
private isDistroless;
|
|
13
16
|
private commandOutputs;
|
|
14
|
-
constructor(container: Dockerode.Container);
|
|
17
|
+
constructor(dockerode: Dockerode, provider: Provider, container: Dockerode.Container);
|
|
15
18
|
isBound(port: number): Promise<boolean>;
|
|
16
19
|
private commandOutputsKey;
|
|
17
20
|
}
|
package/dist/src/port-check.js
CHANGED
|
@@ -39,7 +39,9 @@ class HostPortCheck {
|
|
|
39
39
|
}
|
|
40
40
|
exports.HostPortCheck = HostPortCheck;
|
|
41
41
|
class InternalPortCheck {
|
|
42
|
-
constructor(container) {
|
|
42
|
+
constructor(dockerode, provider, container) {
|
|
43
|
+
this.dockerode = dockerode;
|
|
44
|
+
this.provider = provider;
|
|
43
45
|
this.container = container;
|
|
44
46
|
this.isDistroless = false;
|
|
45
47
|
this.commandOutputs = new Set();
|
|
@@ -52,7 +54,7 @@ class InternalPortCheck {
|
|
|
52
54
|
["/bin/sh", "-c", `nc -vz -w 1 localhost ${port}`],
|
|
53
55
|
["/bin/bash", "-c", `</dev/tcp/localhost/${port}`],
|
|
54
56
|
];
|
|
55
|
-
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.container, command, false)));
|
|
57
|
+
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.dockerode, this.provider, this.container, command, false)));
|
|
56
58
|
const isBound = commandResults.some((result) => result.exitCode === 0);
|
|
57
59
|
if (!isBound && logger_1.log.enabled()) {
|
|
58
60
|
const shellExists = commandResults.some((result) => result.exitCode !== 126);
|
|
@@ -42,11 +42,6 @@ export interface DockerComposeDownOptions {
|
|
|
42
42
|
timeout: number;
|
|
43
43
|
removeVolumes: boolean;
|
|
44
44
|
}
|
|
45
|
-
export interface ExecOptions {
|
|
46
|
-
tty: boolean;
|
|
47
|
-
detach: boolean;
|
|
48
|
-
stdin: boolean;
|
|
49
|
-
}
|
|
50
45
|
export interface StartedTestContainer {
|
|
51
46
|
stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
|
|
52
47
|
restart(options?: Partial<RestartOptions>): Promise<void>;
|
|
@@ -59,7 +54,7 @@ export interface StartedTestContainer {
|
|
|
59
54
|
getNetworkNames(): string[];
|
|
60
55
|
getNetworkId(networkName: string): string;
|
|
61
56
|
getIpAddress(networkName: string): string;
|
|
62
|
-
exec(command: string[]
|
|
57
|
+
exec(command: string[]): Promise<ExecResult>;
|
|
63
58
|
logs(): Promise<Readable>;
|
|
64
59
|
}
|
|
65
60
|
export interface StoppedTestContainer {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import Dockerode from "dockerode";
|
|
2
2
|
import { BoundPorts } from "./bound-ports";
|
|
3
3
|
import { WaitStrategy } from "./wait-strategy/wait-strategy";
|
|
4
|
-
export declare const waitForContainer: (container: Dockerode.Container, waitStrategy: WaitStrategy,
|
|
4
|
+
export declare const waitForContainer: (container: Dockerode.Container, waitStrategy: WaitStrategy, boundPorts: BoundPorts, startTime?: Date) => Promise<void>;
|
|
@@ -13,10 +13,10 @@ exports.waitForContainer = void 0;
|
|
|
13
13
|
const logger_1 = require("./logger");
|
|
14
14
|
const stop_container_1 = require("./docker/functions/container/stop-container");
|
|
15
15
|
const remove_container_1 = require("./docker/functions/container/remove-container");
|
|
16
|
-
const waitForContainer = (container, waitStrategy,
|
|
16
|
+
const waitForContainer = (container, waitStrategy, boundPorts, startTime) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
17
|
logger_1.log.debug(`Waiting for container to be ready: ${container.id}`);
|
|
18
18
|
try {
|
|
19
|
-
yield waitStrategy.waitUntilReady(container,
|
|
19
|
+
yield waitStrategy.waitUntilReady(container, boundPorts, startTime);
|
|
20
20
|
logger_1.log.info(`Container is ready: ${container.id}`);
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AbstractWaitStrategy, WaitStrategy } from "./wait-strategy";
|
|
2
|
+
import Dockerode from "dockerode";
|
|
3
|
+
import { BoundPorts } from "../bound-ports";
|
|
4
|
+
export declare class CompositeWaitStrategy extends AbstractWaitStrategy {
|
|
5
|
+
private readonly waitStrategies;
|
|
6
|
+
private deadline?;
|
|
7
|
+
constructor(waitStrategies: WaitStrategy[]);
|
|
8
|
+
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
|
|
9
|
+
withStartupTimeout(startupTimeout: number): this;
|
|
10
|
+
withDeadline(deadline: number): this;
|
|
11
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CompositeWaitStrategy = void 0;
|
|
13
|
+
const wait_strategy_1 = require("./wait-strategy");
|
|
14
|
+
const logger_1 = require("../logger");
|
|
15
|
+
class CompositeWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
16
|
+
constructor(waitStrategies) {
|
|
17
|
+
super();
|
|
18
|
+
this.waitStrategies = waitStrategies;
|
|
19
|
+
}
|
|
20
|
+
waitUntilReady(container, boundPorts, startTime) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
logger_1.log.debug(`Starting composite wait strategy for ${container.id}`);
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
let deadlineTimeout;
|
|
25
|
+
if (this.deadline !== undefined) {
|
|
26
|
+
deadlineTimeout = setTimeout(() => {
|
|
27
|
+
const message = `Composite wait strategy not successful after ${this.deadline}ms for ${container.id}`;
|
|
28
|
+
logger_1.log.error(message);
|
|
29
|
+
reject(new Error(message));
|
|
30
|
+
}, this.deadline);
|
|
31
|
+
}
|
|
32
|
+
Promise.all(this.waitStrategies.map((waitStrategy) => waitStrategy.waitUntilReady(container, boundPorts, startTime)))
|
|
33
|
+
.then(() => resolve())
|
|
34
|
+
.catch((err) => reject(err))
|
|
35
|
+
.finally(() => {
|
|
36
|
+
if (deadlineTimeout) {
|
|
37
|
+
clearTimeout(deadlineTimeout);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
withStartupTimeout(startupTimeout) {
|
|
44
|
+
this.waitStrategies
|
|
45
|
+
.filter((waitStrategy) => waitStrategy.getStartupTimeout() === undefined)
|
|
46
|
+
.forEach((waitStrategy) => waitStrategy.withStartupTimeout(startupTimeout));
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
withDeadline(deadline) {
|
|
50
|
+
this.deadline = deadline;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.CompositeWaitStrategy = CompositeWaitStrategy;
|
|
@@ -16,12 +16,13 @@ const inspect_container_1 = require("../docker/functions/container/inspect-conta
|
|
|
16
16
|
const wait_strategy_1 = require("./wait-strategy");
|
|
17
17
|
class HealthCheckWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
18
18
|
waitUntilReady(container) {
|
|
19
|
+
var _a;
|
|
19
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
21
|
logger_1.log.debug(`Waiting for health check for ${container.id}`);
|
|
21
22
|
const status = yield new retry_strategy_1.IntervalRetryStrategy(100).retryUntil(() => __awaiter(this, void 0, void 0, function* () { return (yield (0, inspect_container_1.inspectContainer)(container)).healthCheckStatus; }), (healthCheckStatus) => healthCheckStatus === "healthy" || healthCheckStatus === "unhealthy", () => {
|
|
22
23
|
const timeout = this.startupTimeout;
|
|
23
24
|
throw new Error(`Health check not healthy after ${timeout}ms for ${container.id}`);
|
|
24
|
-
}, this.startupTimeout);
|
|
25
|
+
}, (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT);
|
|
25
26
|
if (status !== "healthy") {
|
|
26
27
|
throw new Error(`Health check failed: ${status} for ${container.id}`);
|
|
27
28
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { PortCheck } from "../port-check";
|
|
2
1
|
import Dockerode from "dockerode";
|
|
3
2
|
import { BoundPorts } from "../bound-ports";
|
|
4
3
|
import { AbstractWaitStrategy } from "./wait-strategy";
|
|
5
4
|
export declare class HostPortWaitStrategy extends AbstractWaitStrategy {
|
|
6
|
-
|
|
7
|
-
private readonly internalPortCheck;
|
|
8
|
-
constructor(hostPortCheck: PortCheck, internalPortCheck: PortCheck);
|
|
9
|
-
waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts): Promise<void>;
|
|
5
|
+
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts): Promise<void>;
|
|
10
6
|
private waitForHostPorts;
|
|
11
7
|
private waitForInternalPorts;
|
|
12
8
|
private waitForPort;
|
|
@@ -10,44 +10,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.HostPortWaitStrategy = void 0;
|
|
13
|
+
const port_check_1 = require("../port-check");
|
|
13
14
|
const logger_1 = require("../logger");
|
|
14
15
|
const retry_strategy_1 = require("../retry-strategy");
|
|
15
16
|
const wait_strategy_1 = require("./wait-strategy");
|
|
17
|
+
const docker_client_1 = require("../docker/docker-client");
|
|
16
18
|
class HostPortWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
17
|
-
|
|
18
|
-
super();
|
|
19
|
-
this.hostPortCheck = hostPortCheck;
|
|
20
|
-
this.internalPortCheck = internalPortCheck;
|
|
21
|
-
}
|
|
22
|
-
waitUntilReady(container, host, boundPorts) {
|
|
19
|
+
waitUntilReady(container, boundPorts) {
|
|
23
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
|
|
21
|
+
const { dockerode, provider, host } = yield (0, docker_client_1.dockerClient)();
|
|
22
|
+
const hostPortCheck = new port_check_1.HostPortCheck(host);
|
|
23
|
+
const internalPortCheck = new port_check_1.InternalPortCheck(dockerode, provider, container);
|
|
24
|
+
yield Promise.all([
|
|
25
|
+
this.waitForHostPorts(hostPortCheck, container, boundPorts),
|
|
26
|
+
this.waitForInternalPorts(internalPortCheck, container, boundPorts),
|
|
27
|
+
]);
|
|
25
28
|
});
|
|
26
29
|
}
|
|
27
|
-
waitForHostPorts(container, boundPorts) {
|
|
30
|
+
waitForHostPorts(portCheck, container, boundPorts) {
|
|
28
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
32
|
for (const [, hostPort] of boundPorts.iterator()) {
|
|
30
33
|
logger_1.log.debug(`Waiting for host port ${hostPort} for ${container.id}`);
|
|
31
|
-
yield this.waitForPort(container, hostPort,
|
|
34
|
+
yield this.waitForPort(container, hostPort, portCheck);
|
|
32
35
|
logger_1.log.debug(`Host port ${hostPort} ready for ${container.id}`);
|
|
33
36
|
}
|
|
34
37
|
});
|
|
35
38
|
}
|
|
36
|
-
waitForInternalPorts(container, boundPorts) {
|
|
39
|
+
waitForInternalPorts(portCheck, container, boundPorts) {
|
|
37
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
41
|
for (const [internalPort] of boundPorts.iterator()) {
|
|
39
42
|
logger_1.log.debug(`Waiting for internal port ${internalPort} for ${container.id}`);
|
|
40
|
-
yield this.waitForPort(container, internalPort,
|
|
43
|
+
yield this.waitForPort(container, internalPort, portCheck);
|
|
41
44
|
logger_1.log.debug(`Internal port ${internalPort} ready for ${container.id}`);
|
|
42
45
|
}
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
48
|
waitForPort(container, port, portCheck) {
|
|
49
|
+
var _a;
|
|
46
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
|
|
47
52
|
yield new retry_strategy_1.IntervalRetryStrategy(100).retryUntil(() => portCheck.isBound(port), (isBound) => isBound, () => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}, this.startupTimeout);
|
|
53
|
+
throw new Error(`Port ${port} not bound after ${startupTimeout}ms for ${container.id}`);
|
|
54
|
+
}, startupTimeout);
|
|
51
55
|
});
|
|
52
56
|
}
|
|
53
57
|
}
|
|
@@ -22,6 +22,6 @@ export declare class HttpWaitStrategy extends AbstractWaitStrategy {
|
|
|
22
22
|
withReadTimeout(readTimeout: number): HttpWaitStrategy;
|
|
23
23
|
usingTls(): HttpWaitStrategy;
|
|
24
24
|
allowInsecure(): HttpWaitStrategy;
|
|
25
|
-
waitUntilReady(container: Dockerode.Container,
|
|
25
|
+
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts): Promise<void>;
|
|
26
26
|
private getAgent;
|
|
27
27
|
}
|
|
@@ -17,6 +17,7 @@ const wait_strategy_1 = require("./wait-strategy");
|
|
|
17
17
|
const retry_strategy_1 = require("../retry-strategy");
|
|
18
18
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
19
19
|
const https_1 = __importDefault(require("https"));
|
|
20
|
+
const docker_client_1 = require("../docker/docker-client");
|
|
20
21
|
class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
21
22
|
constructor(path, port) {
|
|
22
23
|
super();
|
|
@@ -66,8 +67,11 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
66
67
|
this._allowInsecure = true;
|
|
67
68
|
return this;
|
|
68
69
|
}
|
|
69
|
-
waitUntilReady(container,
|
|
70
|
+
waitUntilReady(container, boundPorts) {
|
|
71
|
+
var _a;
|
|
70
72
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const { host } = yield (0, docker_client_1.dockerClient)();
|
|
74
|
+
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
|
|
71
75
|
yield new retry_strategy_1.IntervalRetryStrategy(this.readTimeout).retryUntil(() => __awaiter(this, void 0, void 0, function* () {
|
|
72
76
|
try {
|
|
73
77
|
const url = `${this.protocol}://${host}:${boundPorts.getBinding(this.port)}${this.path}`;
|
|
@@ -78,7 +82,7 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
78
82
|
agent: this.getAgent(),
|
|
79
83
|
});
|
|
80
84
|
}
|
|
81
|
-
catch (
|
|
85
|
+
catch (_b) {
|
|
82
86
|
return undefined;
|
|
83
87
|
}
|
|
84
88
|
}), (response) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -98,8 +102,8 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
98
102
|
return true;
|
|
99
103
|
}
|
|
100
104
|
}), () => {
|
|
101
|
-
throw new Error(`URL ${this.path} not accessible after ${
|
|
102
|
-
},
|
|
105
|
+
throw new Error(`URL ${this.path} not accessible after ${startupTimeout}ms for ${container.id}`);
|
|
106
|
+
}, startupTimeout);
|
|
103
107
|
});
|
|
104
108
|
}
|
|
105
109
|
getAgent() {
|
|
@@ -6,5 +6,5 @@ export declare class LogWaitStrategy extends AbstractWaitStrategy {
|
|
|
6
6
|
private readonly message;
|
|
7
7
|
private readonly times;
|
|
8
8
|
constructor(message: Log | RegExp, times: number);
|
|
9
|
-
waitUntilReady(container: Dockerode.Container,
|
|
9
|
+
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
|
|
10
10
|
}
|
|
@@ -23,12 +23,13 @@ class LogWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
|
23
23
|
this.message = message;
|
|
24
24
|
this.times = times;
|
|
25
25
|
}
|
|
26
|
-
waitUntilReady(container,
|
|
26
|
+
waitUntilReady(container, boundPorts, startTime) {
|
|
27
|
+
var _a;
|
|
27
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28
29
|
logger_1.log.debug(`Waiting for log message "${this.message}" for ${container.id}`);
|
|
30
|
+
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
|
|
29
31
|
const stream = yield (0, container_logs_1.containerLogs)(container, { since: startTime });
|
|
30
32
|
return new Promise((resolve, reject) => {
|
|
31
|
-
const startupTimeout = this.startupTimeout;
|
|
32
33
|
const timeout = setTimeout(() => {
|
|
33
34
|
const message = `Log message "${this.message}" not received after ${startupTimeout}ms for ${container.id}`;
|
|
34
35
|
logger_1.log.error(message);
|
|
@@ -14,21 +14,24 @@ const logger_1 = require("../logger");
|
|
|
14
14
|
const wait_strategy_1 = require("./wait-strategy");
|
|
15
15
|
const retry_strategy_1 = require("../retry-strategy");
|
|
16
16
|
const exec_container_1 = require("../docker/functions/container/exec-container");
|
|
17
|
+
const docker_client_1 = require("../docker/docker-client");
|
|
17
18
|
class ShellWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
18
19
|
constructor(command) {
|
|
19
20
|
super();
|
|
20
21
|
this.command = command;
|
|
21
22
|
}
|
|
22
23
|
waitUntilReady(container) {
|
|
24
|
+
var _a;
|
|
23
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
26
|
logger_1.log.debug(`Waiting for successful shell command ${this.command} for ${container.id}`);
|
|
27
|
+
const { dockerode, provider } = yield (0, docker_client_1.dockerClient)();
|
|
28
|
+
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
|
|
25
29
|
yield new retry_strategy_1.IntervalRetryStrategy(100).retryUntil(() => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const { exitCode } = yield (0, exec_container_1.execContainer)(container, ["/bin/sh", "-c", this.command], false);
|
|
30
|
+
const { exitCode } = yield (0, exec_container_1.execContainer)(dockerode, provider, container, ["/bin/sh", "-c", this.command], false);
|
|
27
31
|
return exitCode;
|
|
28
32
|
}), (exitCode) => exitCode === 0, () => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}, this.startupTimeout);
|
|
33
|
+
throw new Error(`Shell command "${this.command}" not successful after ${startupTimeout}ms for ${container.id}`);
|
|
34
|
+
}, startupTimeout);
|
|
32
35
|
});
|
|
33
36
|
}
|
|
34
37
|
}
|
|
@@ -15,9 +15,11 @@ const retry_strategy_1 = require("../retry-strategy");
|
|
|
15
15
|
const docker_client_1 = require("../docker/docker-client");
|
|
16
16
|
class StartupCheckStrategy extends wait_strategy_1.AbstractWaitStrategy {
|
|
17
17
|
waitUntilReady(container) {
|
|
18
|
+
var _a;
|
|
18
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
20
|
const { dockerode } = yield (0, docker_client_1.dockerClient)();
|
|
20
|
-
const
|
|
21
|
+
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
|
|
22
|
+
const startupStatus = yield new retry_strategy_1.IntervalRetryStrategy(1000).retryUntil(() => __awaiter(this, void 0, void 0, function* () { return yield this.checkStartupState(dockerode, container.id); }), (startupStatus) => startupStatus === "SUCCESS" || startupStatus === "FAIL", () => new Error(`Container not accessible after ${startupTimeout}ms for ${container.id}`), startupTimeout);
|
|
21
23
|
if (startupStatus instanceof Error) {
|
|
22
24
|
throw startupStatus;
|
|
23
25
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { BoundPorts } from "../bound-ports";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
|
+
export declare const DEFAULT_STARTUP_TIMEOUT = 60000;
|
|
3
4
|
export interface WaitStrategy {
|
|
4
|
-
waitUntilReady(container: Dockerode.Container,
|
|
5
|
+
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
|
|
5
6
|
withStartupTimeout(startupTimeout: number): WaitStrategy;
|
|
7
|
+
getStartupTimeout(): number | undefined;
|
|
6
8
|
}
|
|
7
9
|
export declare abstract class AbstractWaitStrategy implements WaitStrategy {
|
|
8
|
-
protected startupTimeout
|
|
9
|
-
abstract waitUntilReady(container: Dockerode.Container,
|
|
10
|
-
withStartupTimeout(startupTimeout: number):
|
|
10
|
+
protected startupTimeout?: number;
|
|
11
|
+
abstract waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
|
|
12
|
+
withStartupTimeout(startupTimeout: number): this;
|
|
13
|
+
getStartupTimeout(): number | undefined;
|
|
11
14
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AbstractWaitStrategy = void 0;
|
|
3
|
+
exports.AbstractWaitStrategy = exports.DEFAULT_STARTUP_TIMEOUT = void 0;
|
|
4
|
+
exports.DEFAULT_STARTUP_TIMEOUT = 60000;
|
|
4
5
|
class AbstractWaitStrategy {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.startupTimeout = 60000;
|
|
7
|
-
}
|
|
8
6
|
withStartupTimeout(startupTimeout) {
|
|
9
7
|
this.startupTimeout = startupTimeout;
|
|
10
8
|
return this;
|
|
11
9
|
}
|
|
10
|
+
getStartupTimeout() {
|
|
11
|
+
return this.startupTimeout;
|
|
12
|
+
}
|
|
12
13
|
}
|
|
13
14
|
exports.AbstractWaitStrategy = AbstractWaitStrategy;
|
|
@@ -2,7 +2,10 @@ import { WaitStrategy } from "./wait-strategy";
|
|
|
2
2
|
import { HttpWaitStrategy } from "./http-wait-strategy";
|
|
3
3
|
import { Log } from "./log-wait-strategy";
|
|
4
4
|
import { ShellWaitStrategy } from "./shell-wait-strategy";
|
|
5
|
+
import { CompositeWaitStrategy } from "./composite-wait-strategy";
|
|
5
6
|
export declare class Wait {
|
|
7
|
+
static forAll(waitStrategies: WaitStrategy[]): CompositeWaitStrategy;
|
|
8
|
+
static forListeningPorts(): WaitStrategy;
|
|
6
9
|
static forLogMessage(message: Log | RegExp, times?: number): WaitStrategy;
|
|
7
10
|
static forHealthCheck(): WaitStrategy;
|
|
8
11
|
static forHttp(path: string, port: number): HttpWaitStrategy;
|
|
@@ -5,7 +5,15 @@ const http_wait_strategy_1 = require("./http-wait-strategy");
|
|
|
5
5
|
const health_check_wait_strategy_1 = require("./health-check-wait-strategy");
|
|
6
6
|
const log_wait_strategy_1 = require("./log-wait-strategy");
|
|
7
7
|
const shell_wait_strategy_1 = require("./shell-wait-strategy");
|
|
8
|
+
const host_port_wait_strategy_1 = require("./host-port-wait-strategy");
|
|
9
|
+
const composite_wait_strategy_1 = require("./composite-wait-strategy");
|
|
8
10
|
class Wait {
|
|
11
|
+
static forAll(waitStrategies) {
|
|
12
|
+
return new composite_wait_strategy_1.CompositeWaitStrategy(waitStrategies);
|
|
13
|
+
}
|
|
14
|
+
static forListeningPorts() {
|
|
15
|
+
return new host_port_wait_strategy_1.HostPortWaitStrategy();
|
|
16
|
+
}
|
|
9
17
|
static forLogMessage(message, times = 1) {
|
|
10
18
|
return new log_wait_strategy_1.LogWaitStrategy(message, times);
|
|
11
19
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testcontainers",
|
|
3
3
|
"author": "Cristian Greco",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.6.0",
|
|
5
5
|
"main": "dist/src/index",
|
|
6
6
|
"types": "dist/src/index",
|
|
7
7
|
"keywords": [
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"build": "npm run clean && tsc -p tsconfig.prod.json",
|
|
28
28
|
"docs:serve": "docker-compose up",
|
|
29
29
|
"clean": "rimraf dist",
|
|
30
|
-
"test": "cross-env DEBUG=testcontainers
|
|
31
|
-
"test:ci": "
|
|
30
|
+
"test": "cross-env DEBUG=testcontainers* jest",
|
|
31
|
+
"test:ci": "npm run test -- --runInBand --coverage",
|
|
32
32
|
"format": "prettier --write package.json \"src/**/*.ts\"",
|
|
33
33
|
"lint": "eslint --fix package.json \"src/**/*.ts\"",
|
|
34
34
|
"lint:ci": "eslint package.json \"src/**/*.ts\" --max-warnings=0",
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.listImages = void 0;
|
|
13
|
-
const docker_image_name_1 = require("../../../docker-image-name");
|
|
14
|
-
const logger_1 = require("../../../logger");
|
|
15
|
-
const listImages = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
try {
|
|
17
|
-
const images = yield dockerode.listImages();
|
|
18
|
-
return images.reduce((dockerImageNames, image) => {
|
|
19
|
-
var _a;
|
|
20
|
-
if (isDanglingImage(image)) {
|
|
21
|
-
return dockerImageNames;
|
|
22
|
-
}
|
|
23
|
-
const repoTags = (_a = image.RepoTags) !== null && _a !== void 0 ? _a : [];
|
|
24
|
-
const dockerImageNamesForImage = repoTags.map((imageRepoTag) => docker_image_name_1.DockerImageName.fromString(imageRepoTag));
|
|
25
|
-
return [...dockerImageNames, ...dockerImageNamesForImage];
|
|
26
|
-
}, []);
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
logger_1.log.error(`Failed to list images: ${err}`);
|
|
30
|
-
throw err;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
exports.listImages = listImages;
|
|
34
|
-
const isDanglingImage = (image) => image.RepoTags === null;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defaultWaitStrategy = void 0;
|
|
4
|
-
const host_port_wait_strategy_1 = require("./host-port-wait-strategy");
|
|
5
|
-
const port_check_1 = require("../port-check");
|
|
6
|
-
const defaultWaitStrategy = (host, container) => new host_port_wait_strategy_1.HostPortWaitStrategy(new port_check_1.HostPortCheck(host), new port_check_1.InternalPortCheck(container));
|
|
7
|
-
exports.defaultWaitStrategy = defaultWaitStrategy;
|