testcontainers 7.23.2 → 8.1.1

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.
Files changed (51) hide show
  1. package/README.md +38 -12
  2. package/dist/bound-ports.d.ts +3 -0
  3. package/dist/bound-ports.js +14 -0
  4. package/dist/docker/docker-client.d.ts +9 -0
  5. package/dist/docker/docker-client.js +149 -0
  6. package/dist/docker/functions/container/create-container.d.ts +2 -2
  7. package/dist/docker/functions/container/create-container.js +11 -10
  8. package/dist/docker/functions/container/exec-container.js +16 -12
  9. package/dist/docker/functions/container/get-container.d.ts +1 -1
  10. package/dist/docker/functions/container/get-container.js +14 -2
  11. package/dist/docker/functions/container/inspect-container.d.ts +3 -4
  12. package/dist/docker/functions/container/inspect-container.js +10 -8
  13. package/dist/docker/functions/container/list-containers.js +3 -2
  14. package/dist/docker/functions/demux-stream.d.ts +1 -1
  15. package/dist/docker/functions/demux-stream.js +14 -4
  16. package/dist/docker/functions/get-info.js +3 -2
  17. package/dist/docker/functions/image/build-image.js +3 -2
  18. package/dist/docker/functions/image/list-images.js +3 -2
  19. package/dist/docker/functions/image/pull-image.js +3 -2
  20. package/dist/docker/functions/network/connect-network.js +3 -2
  21. package/dist/docker/functions/network/create-network.js +3 -2
  22. package/dist/docker/functions/network/remove-network.js +3 -2
  23. package/dist/docker/functions/run-in-container.d.ts +2 -1
  24. package/dist/docker/functions/run-in-container.js +2 -3
  25. package/dist/docker/types.d.ts +3 -0
  26. package/dist/docker-compose/default-docker-compose-options.d.ts +1 -1
  27. package/dist/docker-compose/docker-compose.d.ts +3 -0
  28. package/dist/docker-compose/docker-compose.js +10 -0
  29. package/dist/docker-compose/functions/docker-compose-down.js +1 -1
  30. package/dist/docker-compose/functions/docker-compose-stop.js +1 -1
  31. package/dist/docker-compose/functions/docker-compose-up.js +1 -1
  32. package/dist/docker-compose-environment/docker-compose-environment.d.ts +0 -1
  33. package/dist/docker-compose-environment/docker-compose-environment.js +6 -14
  34. package/dist/generic-container/generic-container.d.ts +6 -2
  35. package/dist/generic-container/generic-container.js +25 -9
  36. package/dist/log-system-diagnostics.js +2 -21
  37. package/dist/modules/kafka/kafka-container.d.ts +6 -17
  38. package/dist/modules/kafka/kafka-container.js +57 -69
  39. package/dist/port-forwarder.js +2 -2
  40. package/dist/reaper.d.ts +1 -0
  41. package/dist/reaper.js +20 -14
  42. package/dist/test-container.d.ts +2 -1
  43. package/dist/testcontainers-properties-file.d.ts +1 -0
  44. package/dist/testcontainers-properties-file.js +31 -0
  45. package/package.json +4 -2
  46. package/dist/docker/docker-host.d.ts +0 -1
  47. package/dist/docker/docker-host.js +0 -8
  48. package/dist/docker/dockerode.d.ts +0 -2
  49. package/dist/docker/dockerode.js +0 -10
  50. package/dist/docker/get-docker-host.d.ts +0 -3
  51. 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 docker_host_1 = require("./docker/docker-host");
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 = yield new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
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
- .withPrivilegedMode()
85
- .start();
86
- const host = yield docker_host_1.dockerHost;
87
- const port = container.getMappedPort(8080);
88
- logger_1.log.debug(`Connecting to Reaper ${container.getId()} on ${host}:${port}`);
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 ${container.getId()} socket timed out`))
93
- .on("error", (err) => logger_1.log.error(`Reaper ${container.getId()} socket error: ${err}`))
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 ${container.getId()} closed with error`);
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 ${container.getId()} closed`);
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 ${container.getId()}`);
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(container, socket);
112
+ const reaper = new RealReaper(startedContainer, socket);
107
113
  resolve(reaper);
108
114
  });
109
115
  });
@@ -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": "7.23.2",
4
+ "version": "8.1.1",
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 --maxWorkers=2",
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();
@@ -1,2 +0,0 @@
1
- import Dockerode from "dockerode";
2
- export declare const dockerode: Dockerode;
@@ -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,3 +0,0 @@
1
- import Dockerode from "dockerode";
2
- import { Host } from "./types";
3
- export declare const getDockerHost: (dockerode: Dockerode) => Promise<Host>;
@@ -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");