UNPKG

@microtica/mocks

Version:

Mock services for automated tests

117 lines 4.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // tslint:disable:no-console const Dockerode = require("dockerode"); /** * Executes docker commands on your behalf to run containers for you. Mostly for testing purposes * * @export * @class DockerRunner */ class DockerRunner { /** * Creates an instance of DockerRunner. * @param {string} imageName image scope/name which will be pulled from Docker Hub * @param {string} containerName unique name of the container * @memberof DockerRunner */ constructor(imageName, containerName) { this.imageName = imageName; this.containerName = containerName; this.docker = new Dockerode({ socketPath: "/var/run/docker.sock" }); this.docker.ping().catch(err => { console.error("[ERROR] Docker is not running"); console.error(err); throw err; }); } /** * Checks whether there is at least one running container with the name * * @returns {Promise<boolean>} * @memberof DockerRunner */ async isRunning() { const containers = await this.getContainers(); return !!containers.find(container => container.State === "running"); } /** * Tries to find the container in the list of all containers * * @returns container info * @memberof DockerRunner */ async getContainers() { const containers = await this.docker.listContainers({ all: true }); return containers.filter(container => container.Names.includes(`/${this.containerName}`)); } /** * Forcefully removes all containers with the name * * @returns {Promise<void>} * @memberof DockerRunner */ async remove() { const containers = await this.getContainers(); containers.forEach(async (container) => { await this.docker.getContainer(container.Id).remove({ force: true }); }); } /** * Downloads the image from Docker Hub * * @private * @returns {Promise<void>} * @memberof DockerRunner */ downloadImage() { return new Promise(async (resolve, reject) => { console.log(`Pulling image ${this.imageName}`); const stream = await this.docker.createImage({ fromImage: this.imageName }); stream.on("data", () => process.stdout.write(".")); stream.on("end", () => console.log("\nimage downloaded")); stream.on("end", resolve); stream.on("error", reject); }); } /** * Runs a container from the specified image in the constructor after the image was pulled. * It does nothing if the container is already running * * @param {RunOptions} opt options object * @param {string[]} opt.env array of environment variables in unix format (key=value) * @param {numbner[]} opt.portsToOpen opens the specified TCP ports for you * @returns {Promise<Dockerode.Container>} Container instance * @memberof DockerRunner */ async run(opt) { if (await this.isRunning()) { console.log("There is at least one running container, reusing"); return; } await Promise.all([ this.downloadImage(), this.remove() ]); const portBindings = opt.portsToOpen.reduce((bindings, port) => { bindings[`${port}/tcp`] = [{ HostPort: port.toString() }]; return bindings; }, {}); const container = await this.docker.createContainer({ name: this.containerName, Image: this.imageName, Env: opt.env || [], HostConfig: { PortBindings: portBindings } }); console.log(`[INFO] Container ${container.id} created`); await container.start(); console.log(`[INFO] Container ${container.id} started`); return container; } } exports.DockerRunner = DockerRunner; //# sourceMappingURL=runner.js.map