@microtica/mocks
Version:
Mock services for automated tests
117 lines • 4.1 kB
JavaScript
;
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