UNPKG

@atomist/sdm-pack-docker

Version:

Extension Pack for an Atomist SDM to integrate Docker

121 lines 5.7 kB
"use strict"; /* * Copyright © 2019 Atomist, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const automation_client_1 = require("@atomist/automation-client"); const sdm_1 = require("@atomist/sdm"); const child_process_1 = require("child_process"); const portfinder = require("portfinder"); /** * Deployer that uses `docker run` in order to deploy images produces by the `DockerBuild` goal. */ class DockerPerBranchDeployer { constructor(options) { this.options = options; // Already allocated ports this.repoBranchToPort = {}; // Keys are ports: values are containerIds this.portToContainer = {}; } // tslint:disable-next-line:deprecation deployProject(goalInvocation) { return __awaiter(this, void 0, void 0, function* () { const branch = goalInvocation.goalEvent.branch; let port = this.repoBranchToPort[goalInvocation.id.repo + ":" + branch]; if (!port) { port = yield portfinder.getPortPromise({ /*host: this.options.baseUrl,*/ port: this.options.lowerPort }); this.repoBranchToPort[goalInvocation.id.repo + ":" + branch] = port; } const existingContainer = this.portToContainer[port]; if (!!existingContainer) { yield stopAndRemoveContainer(existingContainer); } else { // Check we won't end with a crazy number of child processes const presentCount = Object.keys(this.portToContainer) .filter(n => typeof n === "number") .length; if (presentCount >= 5) { throw new Error(`Unable to deploy project at ${goalInvocation.id} as limit of 5 has been reached`); } } const name = `${goalInvocation.id.repo}_${branch}`; const childProcess = child_process_1.spawn("docker", [ "run", `-p${port}:${this.options.sourcePort}`, `--name=${name}`, goalInvocation.goalEvent.push.after.image.imageName, ], {}); if (!childProcess.pid) { throw new Error("Fatal error deploying using Docker"); } const deployment = { childProcess, endpoint: `${this.options.baseUrl}:${port}`, }; this.portToContainer[port] = name; const newLineDelimitedLog = new sdm_1.DelimitedWriteProgressLogDecorator(goalInvocation.progressLog, "\n"); childProcess.stdout.on("data", what => newLineDelimitedLog.write(what.toString())); childProcess.stderr.on("data", what => newLineDelimitedLog.write(what.toString())); let stdout = ""; let stderr = ""; // tslint:disable-next-line:deprecation return new Promise((resolve, reject) => { childProcess.stdout.addListener("data", what => { if (!!what) { stdout += what.toString(); } if (this.options.successPatterns.some(successPattern => successPattern.test(stdout))) { resolve(deployment); } }); childProcess.stderr.addListener("data", what => { if (!!what) { stderr += what.toString(); } }); childProcess.addListener("exit", () => __awaiter(this, void 0, void 0, function* () { if (this.options.successPatterns.some(successPattern => successPattern.test(stdout))) { resolve(deployment); } else { automation_client_1.logger.error("Docker deployment failure vvvvvvvvvvvvvvvvvvvvvv"); automation_client_1.logger.error("stdout:\n%s\nstderr:\n%s\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", stdout, stderr); reject(new Error("Docker deployment failure")); } })); childProcess.addListener("error", reject); }); }); } } exports.DockerPerBranchDeployer = DockerPerBranchDeployer; function stopAndRemoveContainer(existingContainer) { return sdm_1.execPromise("docker", [ "rm", "-f", existingContainer, ]); } //# sourceMappingURL=DockerPerBranchDeployer.js.map