testcontainers 7.23.2 → 8.1.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -12
- package/dist/bound-ports.d.ts +3 -0
- package/dist/bound-ports.js +14 -0
- package/dist/docker/docker-client.d.ts +9 -0
- package/dist/docker/docker-client.js +158 -0
- package/dist/docker/functions/container/create-container.d.ts +2 -2
- package/dist/docker/functions/container/create-container.js +11 -10
- package/dist/docker/functions/container/exec-container.js +16 -12
- package/dist/docker/functions/container/get-container.d.ts +1 -1
- package/dist/docker/functions/container/get-container.js +14 -2
- package/dist/docker/functions/container/inspect-container.d.ts +3 -4
- package/dist/docker/functions/container/inspect-container.js +10 -8
- package/dist/docker/functions/container/list-containers.js +3 -2
- package/dist/docker/functions/demux-stream.d.ts +1 -1
- package/dist/docker/functions/demux-stream.js +14 -4
- package/dist/docker/functions/get-info.js +3 -2
- package/dist/docker/functions/image/build-image.js +3 -2
- package/dist/docker/functions/image/list-images.js +3 -2
- package/dist/docker/functions/image/pull-image.js +3 -2
- package/dist/docker/functions/network/connect-network.js +3 -2
- package/dist/docker/functions/network/create-network.js +3 -2
- package/dist/docker/functions/network/remove-network.js +3 -2
- package/dist/docker/functions/run-in-container.d.ts +2 -1
- package/dist/docker/functions/run-in-container.js +2 -3
- package/dist/docker/types.d.ts +3 -0
- package/dist/docker-compose/default-docker-compose-options.d.ts +1 -1
- package/dist/docker-compose/docker-compose.d.ts +3 -0
- package/dist/docker-compose/docker-compose.js +10 -0
- package/dist/docker-compose/functions/docker-compose-down.js +1 -1
- package/dist/docker-compose/functions/docker-compose-stop.js +1 -1
- package/dist/docker-compose/functions/docker-compose-up.js +1 -1
- package/dist/docker-compose-environment/docker-compose-environment.d.ts +0 -1
- package/dist/docker-compose-environment/docker-compose-environment.js +6 -14
- package/dist/generic-container/generic-container.d.ts +6 -2
- package/dist/generic-container/generic-container.js +25 -9
- package/dist/log-system-diagnostics.js +2 -21
- package/dist/modules/kafka/kafka-container.d.ts +6 -17
- package/dist/modules/kafka/kafka-container.js +57 -69
- package/dist/port-forwarder.js +2 -2
- package/dist/reaper.d.ts +1 -0
- package/dist/reaper.js +20 -14
- package/dist/test-container.d.ts +2 -1
- package/dist/testcontainers-properties-file.d.ts +1 -0
- package/dist/testcontainers-properties-file.js +31 -0
- package/package.json +4 -2
- package/dist/docker/docker-host.d.ts +0 -1
- package/dist/docker/docker-host.js +0 -8
- package/dist/docker/dockerode.d.ts +0 -2
- package/dist/docker/dockerode.js +0 -10
- package/dist/docker/get-docker-host.d.ts +0 -3
- package/dist/docker/get-docker-host.js +0 -60
package/dist/reaper.js
CHANGED
|
@@ -14,7 +14,7 @@ const net_1 = require("net");
|
|
|
14
14
|
const logger_1 = require("./logger");
|
|
15
15
|
const generic_container_1 = require("./generic-container/generic-container");
|
|
16
16
|
const session_id_1 = require("./docker/session-id");
|
|
17
|
-
const
|
|
17
|
+
const docker_client_1 = require("./docker/docker-client");
|
|
18
18
|
const images_1 = require("./images");
|
|
19
19
|
class RealReaper {
|
|
20
20
|
constructor(container, socket) {
|
|
@@ -68,6 +68,9 @@ class ReaperInstance {
|
|
|
68
68
|
static isEnabled() {
|
|
69
69
|
return process.env.TESTCONTAINERS_RYUK_DISABLED !== "true";
|
|
70
70
|
}
|
|
71
|
+
static isPrivileged() {
|
|
72
|
+
return process.env.TESTCONTAINERS_RYUK_PRIVILEGED === "true";
|
|
73
|
+
}
|
|
71
74
|
static createDisabledInstance() {
|
|
72
75
|
logger_1.log.debug(`Not creating new Reaper for session: ${session_id_1.sessionId}`);
|
|
73
76
|
return Promise.resolve(new DisabledReaper());
|
|
@@ -77,33 +80,36 @@ class ReaperInstance {
|
|
|
77
80
|
return __awaiter(this, void 0, void 0, function* () {
|
|
78
81
|
const dockerSocket = (_a = process.env["TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"]) !== null && _a !== void 0 ? _a : "/var/run/docker.sock";
|
|
79
82
|
logger_1.log.debug(`Creating new Reaper for session: ${session_id_1.sessionId}`);
|
|
80
|
-
const container =
|
|
83
|
+
const container = new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
|
|
81
84
|
.withName(`testcontainers-ryuk-${session_id_1.sessionId}`)
|
|
82
85
|
.withExposedPorts(8080)
|
|
83
|
-
.withBindMount(dockerSocket, "/var/run/docker.sock")
|
|
84
|
-
|
|
85
|
-
.
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
86
|
+
.withBindMount(dockerSocket, "/var/run/docker.sock");
|
|
87
|
+
if (this.isPrivileged()) {
|
|
88
|
+
container.withPrivilegedMode();
|
|
89
|
+
}
|
|
90
|
+
const startedContainer = yield container.start();
|
|
91
|
+
const containerId = startedContainer.getId();
|
|
92
|
+
const host = (yield docker_client_1.dockerClient).host;
|
|
93
|
+
const port = startedContainer.getMappedPort(8080);
|
|
94
|
+
logger_1.log.debug(`Connecting to Reaper ${containerId} on ${host}:${port}`);
|
|
89
95
|
const socket = new net_1.Socket();
|
|
90
96
|
socket.unref();
|
|
91
97
|
socket
|
|
92
|
-
.on("timeout", () => logger_1.log.error(`Reaper ${
|
|
93
|
-
.on("error", (err) => logger_1.log.error(`Reaper ${
|
|
98
|
+
.on("timeout", () => logger_1.log.error(`Reaper ${containerId} socket timed out`))
|
|
99
|
+
.on("error", (err) => logger_1.log.error(`Reaper ${containerId} socket error: ${err}`))
|
|
94
100
|
.on("close", (hadError) => {
|
|
95
101
|
if (hadError) {
|
|
96
|
-
logger_1.log.error(`Connection to Reaper ${
|
|
102
|
+
logger_1.log.error(`Connection to Reaper ${containerId} closed with error`);
|
|
97
103
|
}
|
|
98
104
|
else {
|
|
99
|
-
logger_1.log.warn(`Connection to Reaper ${
|
|
105
|
+
logger_1.log.warn(`Connection to Reaper ${containerId} closed`);
|
|
100
106
|
}
|
|
101
107
|
});
|
|
102
108
|
return new Promise((resolve) => {
|
|
103
109
|
socket.connect(port, host, () => {
|
|
104
|
-
logger_1.log.debug(`Connected to Reaper ${
|
|
110
|
+
logger_1.log.debug(`Connected to Reaper ${containerId}`);
|
|
105
111
|
socket.write(`label=org.testcontainers.session-id=${session_id_1.sessionId}\r\n`);
|
|
106
|
-
const reaper = new RealReaper(
|
|
112
|
+
const reaper = new RealReaper(startedContainer, socket);
|
|
107
113
|
resolve(reaper);
|
|
108
114
|
});
|
|
109
115
|
});
|
package/dist/test-container.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Port } from "./port";
|
|
|
3
3
|
import { PullPolicy } from "./pull-policy";
|
|
4
4
|
import { WaitStrategy } from "./wait-strategy";
|
|
5
5
|
import { Readable } from "stream";
|
|
6
|
-
import { BindMode, Command, ContainerName, Dir, EnvKey, EnvValue, ExecResult, Host, Id, NetworkMode, TmpFs } from "./docker/types";
|
|
6
|
+
import { BindMode, Command, ContainerName, Dir, EnvKey, EnvValue, ExecResult, ExtraHost, Host, Id, NetworkMode, TmpFs } from "./docker/types";
|
|
7
7
|
export interface TestContainer {
|
|
8
8
|
start(): Promise<StartedTestContainer>;
|
|
9
9
|
withEnv(key: EnvKey, value: EnvValue): this;
|
|
@@ -14,6 +14,7 @@ export interface TestContainer {
|
|
|
14
14
|
withWaitStrategy(waitStrategy: WaitStrategy): this;
|
|
15
15
|
withStartupTimeout(startupTimeout: number): this;
|
|
16
16
|
withNetworkMode(networkMode: NetworkMode): this;
|
|
17
|
+
withExtraHosts(...extraHosts: ExtraHost[]): this;
|
|
17
18
|
withDefaultLogDriver(): this;
|
|
18
19
|
withPrivilegedMode(): this;
|
|
19
20
|
withUser(user: string): this;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
const os_1 = require("os");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const properties_reader_1 = __importDefault(require("properties-reader"));
|
|
11
|
+
const file = path_1.default.resolve(os_1.homedir(), ".testcontainers.properties");
|
|
12
|
+
if (fs_1.existsSync(file)) {
|
|
13
|
+
logger_1.log.debug("Found .testcontainers.properties file");
|
|
14
|
+
const string = fs_1.readFileSync(file, { encoding: "utf-8" });
|
|
15
|
+
const properties = properties_reader_1.default("").read(string);
|
|
16
|
+
const host = properties.get("docker.host");
|
|
17
|
+
if (host !== null) {
|
|
18
|
+
logger_1.log.debug(`Setting DOCKER_HOST to ${host}`);
|
|
19
|
+
process.env.DOCKER_HOST = host;
|
|
20
|
+
}
|
|
21
|
+
const tlsVerify = properties.get("docker.tls.verify");
|
|
22
|
+
if (tlsVerify !== null) {
|
|
23
|
+
logger_1.log.debug(`Setting DOCKER_TLS_VERIFY to ${tlsVerify}`);
|
|
24
|
+
process.env.DOCKER_TLS_VERIFY = `${tlsVerify}`;
|
|
25
|
+
}
|
|
26
|
+
const certPath = properties.get("docker.cert.path");
|
|
27
|
+
if (certPath !== null) {
|
|
28
|
+
logger_1.log.debug(`Setting DOCKER_CERT_PATH to ${certPath}`);
|
|
29
|
+
process.env.DOCKER_CERT_PATH = certPath;
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testcontainers",
|
|
3
3
|
"author": "Cristian Greco",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "8.1.1-beta.0",
|
|
5
5
|
"main": "dist/index",
|
|
6
6
|
"types": "dist/index",
|
|
7
7
|
"keywords": [
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"pre-commit": "lint-staged",
|
|
27
27
|
"build": "npm run clean && tsc",
|
|
28
28
|
"clean": "rimraf dist",
|
|
29
|
-
"test": "cross-env DEBUG=testcontainers jest --
|
|
29
|
+
"test": "cross-env DEBUG=testcontainers jest --runInBand",
|
|
30
30
|
"format": "prettier --write package.json \"src/**/*.ts\"",
|
|
31
31
|
"lint": "eslint --fix package.json \"src/**/*.ts\"",
|
|
32
32
|
"updateDeps": "npx npm-check-updates -u"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"dockerode": "^3.3.1",
|
|
42
42
|
"get-port": "^5.1.1",
|
|
43
43
|
"glob": "^7.2.0",
|
|
44
|
+
"properties-reader": "^2.2.0",
|
|
44
45
|
"slash": "^3.0.0",
|
|
45
46
|
"ssh-remote-port-forward": "^1.0.4",
|
|
46
47
|
"tar-fs": "^2.1.1"
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"@types/node": "^16.9.6",
|
|
55
56
|
"@types/node-fetch": "^2.5.11",
|
|
56
57
|
"@types/pg": "^8.6.1",
|
|
58
|
+
"@types/properties-reader": "^2.1.1",
|
|
57
59
|
"@types/tar-fs": "^2.0.1",
|
|
58
60
|
"@typescript-eslint/eslint-plugin": "^4.31.2",
|
|
59
61
|
"@typescript-eslint/parser": "^4.31.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const dockerHost: Promise<string>;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dockerHost = void 0;
|
|
4
|
-
const log_system_diagnostics_1 = require("../log-system-diagnostics");
|
|
5
|
-
const get_docker_host_1 = require("./get-docker-host");
|
|
6
|
-
const dockerode_1 = require("./dockerode");
|
|
7
|
-
exports.dockerHost = get_docker_host_1.getDockerHost(dockerode_1.dockerode);
|
|
8
|
-
log_system_diagnostics_1.logSystemDiagnostics();
|
package/dist/docker/dockerode.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.dockerode = void 0;
|
|
7
|
-
const dockerode_1 = __importDefault(require("dockerode"));
|
|
8
|
-
const logger_1 = require("../logger");
|
|
9
|
-
logger_1.log.debug("Creating new Docker instance");
|
|
10
|
-
exports.dockerode = new dockerode_1.default();
|
|
@@ -1,60 +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
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.getDockerHost = void 0;
|
|
16
|
-
const logger_1 = require("../logger");
|
|
17
|
-
const run_in_container_1 = require("./functions/run-in-container");
|
|
18
|
-
const fs_1 = __importDefault(require("fs"));
|
|
19
|
-
const DEFAULT_HOST = "localhost";
|
|
20
|
-
const getDockerHost = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
-
if (process.env.DOCKER_HOST) {
|
|
22
|
-
logger_1.log.info(`Detected DOCKER_HOST environment variable: ${process.env.DOCKER_HOST}`);
|
|
23
|
-
}
|
|
24
|
-
for (const [hostStrategyName, hostStrategy] of Object.entries(hostStrategies(dockerode))) {
|
|
25
|
-
const result = yield hostStrategy();
|
|
26
|
-
if (result) {
|
|
27
|
-
logger_1.log.info(`Docker host strategy ${hostStrategyName}: ${result}`);
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
logger_1.log.info(`Docker host strategy FALLBACK: ${DEFAULT_HOST}`);
|
|
32
|
-
return DEFAULT_HOST;
|
|
33
|
-
});
|
|
34
|
-
exports.getDockerHost = getDockerHost;
|
|
35
|
-
const hostStrategies = (dockerode) => ({
|
|
36
|
-
MODEM: () => __awaiter(void 0, void 0, void 0, function* () { return dockerode.modem.host; }),
|
|
37
|
-
TESTCONTAINERS_HOST_OVERRIDE: () => __awaiter(void 0, void 0, void 0, function* () { return process.env["TESTCONTAINERS_HOST_OVERRIDE"]; }),
|
|
38
|
-
OUTSIDE_CONTAINER: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
-
if (!isInContainer()) {
|
|
40
|
-
return DEFAULT_HOST;
|
|
41
|
-
}
|
|
42
|
-
}),
|
|
43
|
-
INSIDE_CONTAINER_NO_IPAM: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
-
const network = yield dockerode.getNetwork("bridge").inspect();
|
|
45
|
-
if (!network.IPAM || !network.IPAM.Config) {
|
|
46
|
-
return DEFAULT_HOST;
|
|
47
|
-
}
|
|
48
|
-
}),
|
|
49
|
-
INSIDE_CONTAINER_IPAM: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
-
const network = yield dockerode.getNetwork("bridge").inspect();
|
|
51
|
-
if (network.IPAM && network.IPAM.Config) {
|
|
52
|
-
const gateways = network.IPAM.Config.filter((config) => !!config.Gateway);
|
|
53
|
-
if (gateways.length > 0) {
|
|
54
|
-
return gateways[0].Gateway;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}),
|
|
58
|
-
CONTAINER_GATEWAY: () => __awaiter(void 0, void 0, void 0, function* () { return run_in_container_1.runInContainer("alpine:3.5", ["sh", "-c", "ip route|awk '/default/ { print $3 }'"]); }),
|
|
59
|
-
});
|
|
60
|
-
const isInContainer = () => fs_1.default.existsSync("/.dockerenv");
|