testcontainers
Version:
Testcontainers is a NodeJS library that supports tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container
134 lines • 5.78 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockerImageClient = void 0;
const dockerignore_1 = __importDefault(require("@balena/dockerignore"));
const async_lock_1 = __importDefault(require("async-lock"));
const byline_1 = __importDefault(require("byline"));
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const tar_fs_1 = __importDefault(require("tar-fs"));
const common_1 = require("../../../common");
const get_auth_config_1 = require("../../auth/get-auth-config");
class DockerImageClient {
dockerode;
indexServerAddress;
existingImages = new Set();
imageExistsLock = new async_lock_1.default();
constructor(dockerode, indexServerAddress) {
this.dockerode = dockerode;
this.indexServerAddress = indexServerAddress;
}
async build(context, opts) {
try {
common_1.log.debug(`Building image "${opts.t}" with context "${context}"...`);
const isDockerIgnored = await this.createIsDockerIgnoredFunction(context);
const tarStream = tar_fs_1.default.pack(context, {
ignore: (aPath) => {
const relativePath = path_1.default.relative(context, aPath);
if (relativePath === opts.dockerfile) {
return false;
}
else {
return isDockerIgnored(relativePath);
}
},
});
await new Promise((resolve) => {
this.dockerode
.buildImage(tarStream, opts)
.then((stream) => (0, byline_1.default)(stream))
.then((stream) => {
stream.setEncoding("utf-8");
stream.on("data", (line) => {
if (common_1.buildLog.enabled()) {
common_1.buildLog.trace(line, { imageName: opts.t });
}
});
stream.on("end", () => resolve());
});
});
common_1.log.debug(`Built image "${opts.t}" with context "${context}"`);
}
catch (err) {
common_1.log.error(`Failed to build image: ${err}`);
throw err;
}
}
async createIsDockerIgnoredFunction(context) {
const dockerIgnoreFilePath = path_1.default.join(context, ".dockerignore");
if (!(0, fs_1.existsSync)(dockerIgnoreFilePath)) {
return () => false;
}
const dockerIgnorePatterns = await fs_1.promises.readFile(dockerIgnoreFilePath, { encoding: "utf-8" });
const instance = (0, dockerignore_1.default)({ ignorecase: false });
instance.add(dockerIgnorePatterns);
const filter = instance.createFilter();
return (aPath) => !filter(aPath);
}
async inspect(imageName) {
try {
common_1.log.debug(`Inspecting image: "${imageName.string}"...`);
const imageInfo = await this.dockerode.getImage(imageName.string).inspect();
common_1.log.debug(`Inspected image: "${imageName.string}"`);
return imageInfo;
}
catch (err) {
common_1.log.debug(`Failed to inspect image "${imageName.string}"`);
throw err;
}
}
async exists(imageName) {
return this.imageExistsLock.acquire(imageName.string, async () => {
if (this.existingImages.has(imageName.string)) {
return true;
}
try {
common_1.log.debug(`Checking if image exists "${imageName.string}"...`);
await this.dockerode.getImage(imageName.string).inspect();
this.existingImages.add(imageName.string);
common_1.log.debug(`Checked if image exists "${imageName.string}"`);
return true;
}
catch (err) {
if (err instanceof Error && err.message.toLowerCase().includes("no such image")) {
common_1.log.debug(`Checked if image exists "${imageName.string}"`);
return false;
}
common_1.log.debug(`Failed to check if image exists "${imageName.string}"`);
throw err;
}
});
}
async pull(imageName, opts) {
try {
if (!opts?.force && (await this.exists(imageName))) {
common_1.log.debug(`Image "${imageName.string}" already exists`);
return;
}
common_1.log.debug(`Pulling image "${imageName.string}"...`);
const authconfig = await (0, get_auth_config_1.getAuthConfig)(imageName.registry ?? this.indexServerAddress);
const stream = await this.dockerode.pull(imageName.string, {
authconfig,
platform: opts?.platform,
});
await new Promise((resolve) => {
(0, byline_1.default)(stream).on("data", (line) => {
if (common_1.pullLog.enabled()) {
common_1.pullLog.trace(line, { imageName: imageName.string });
}
});
stream.on("end", resolve);
});
common_1.log.debug(`Pulled image "${imageName.string}"`);
}
catch (err) {
common_1.log.error(`Failed to pull image "${imageName.string}": ${err}`);
throw err;
}
}
}
exports.DockerImageClient = DockerImageClient;
//# sourceMappingURL=docker-image-client.js.map
;