UNPKG

@apigeeks/fbl-k8s-plugin

Version:

fbl wrapper plugin for helm and kubectl cli utilities

226 lines 9.55 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; 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 yaml = require("js-yaml"); const typedi_1 = require("typedi"); const lodash_1 = require("lodash"); const util_1 = require("util"); const fs_1 = require("fs"); const js_yaml_1 = require("js-yaml"); const fbl_1 = require("fbl"); let K8sHelmService = class K8sHelmService { /** * Execute "helm" command * @param {string[]} args * @param {string} wd * @return {Promise<IExecOutput>} */ execHelmCommand(args, wd) { return __awaiter(this, void 0, void 0, function* () { const stdout = []; const stderr = []; const code = yield this.childProcessService.exec('helm', args, wd || '.', { stdout: (chunk) => { stdout.push(chunk.toString().trim()); }, stderr: (chunk) => { stderr.push(chunk.toString().trim()); }, }); return { code, stdout: stdout.join('\n'), stderr: stderr.join('\n'), }; }); } /** * Remove helm chart * @param {string} name * @param {IContext} context * @return {Promise<void>} */ remove(name, context) { return __awaiter(this, void 0, void 0, function* () { const result = yield this.execHelmCommand(['del', '--purge', name]); if (result.code !== 0) { throw new Error(`Unable to delete helm, command returned non-zero exit code. Code: ${result.code}\nstderr: ${result.stderr}\nstdout: ${result.stdout}`); } const contextEntity = this.createEntity({ name }); context.entities.unregistered.push(contextEntity); context.entities.deleted.push(contextEntity); }); } createEntity(helmConfig) { return { type: 'helm', payload: helmConfig, id: helmConfig.name, }; } /** * Update or install helm chart * @param {IHelmChart} config * @param {string} wd working directory * @param context * @return {Promise<void>} */ updateOrInstall(config, wd, context) { return __awaiter(this, void 0, void 0, function* () { const args = ['upgrade', '--install']; if (config.namespace) { args.push('--namespace', config.namespace); } if (config.tillerNamespace) { args.push('--tiller-namespace', config.tillerNamespace); } if (config.hasOwnProperty('timeout')) { args.push('--timeout', config.timeout.toString()); } if (config.wait) { args.push('--wait'); } if (config.variables) { if (config.variables.files) { config.variables.files.forEach(f => { args.push('-f', fbl_1.FSUtil.getAbsolutePath(f, wd)); }); } if (config.variables.inline) { const tmpFile = yield this.tempPathsRegistry.createTempFile(false, '.yml'); yield util_1.promisify(fs_1.writeFile)(tmpFile, js_yaml_1.dump(config.variables.inline), 'utf8'); args.push('-f', tmpFile); } } args.push(config.name); const localPath = fbl_1.FSUtil.getAbsolutePath(config.chart, wd); const existsLocally = yield util_1.promisify(fs_1.exists)(localPath); if (existsLocally) { args.push(localPath); } else { args.push(config.chart); } const isHelmUpdated = yield this.isDeploymentExists(config.name); const result = yield this.execHelmCommand(args); if (result.code !== 0) { throw new Error(`Unable to update or install helm chart, command returned non-zero exit code. Code: ${result.code}\nstderr: ${result.stderr}\nstdout: ${result.stdout}`); } const contextEntity = this.createEntity(config); context.entities.registered.push(contextEntity); if (!isHelmUpdated) { context.entities.created.push(contextEntity); } else { context.entities.updated.push(contextEntity); } }); } /** * List installed helms * @returns {Promise<string[]>} */ listInstalledHelms() { return __awaiter(this, void 0, void 0, function* () { const result = yield this.execHelmCommand(['list', '-q']); return result.stdout .split('\n') .map(l => l.trim()) .filter(l => l); }); } /** * Check if deployment exists * @param {string} name * @returns {Promise<boolean>} */ isDeploymentExists(name) { return __awaiter(this, void 0, void 0, function* () { const helmResult = yield this.execHelmCommand(['get', name]); return helmResult.stderr.trim() !== `Error: release: "${name}" not found`; }); } /** * Get k8s objects in helm * * @param {string} name * @return {Promise<IK8sObject[]>} */ getHelmObjects(name) { return __awaiter(this, void 0, void 0, function* () { const helmResult = yield this.execHelmCommand(['get', name]); if (helmResult.code !== 0) { throw new Error(`Unable to get helm k8s objects, command returned non-zero exit code. Code: ${helmResult.code}\nstderr: ${helmResult.stderr}\nstdout: ${helmResult.stdout}`); } const objects = helmResult.stdout.split('---\n'); objects.shift(); return objects.map((rawObject) => { return yaml.safeLoad(rawObject.replace(/^#.*Source.+?$/m, '')); }); }); } /** * Get information about helm deployment * @param {string} name * @returns {Promise<IHelmDeploymentInfo>} */ getHelmDeployment(name) { return __awaiter(this, void 0, void 0, function* () { const helmResult = yield this.execHelmCommand(['get', name]); if (helmResult.code !== 0) { throw new Error(`Unable to get helm deployment information, command returned non-zero exit code. Code: ${helmResult.code}\nstderr: ${helmResult.stderr}\nstdout: ${helmResult.stdout}`); } const matches = helmResult.stdout.split(/^([A-Z]{2,}[^:]+):/gm); matches.shift(); const chanks = lodash_1.chunk(matches, 2); const result = lodash_1.zipObject(chanks.map(e => e[0].trim()), chanks.map(e => e[1].trim())); return { revision: result['REVISION'].replace(/\n/g, ''), released: result['RELEASED'] && new Date(result['RELEASED'].replace(/\n/g, '')), chart: result['CHART'].replace(/\n/g, ''), userSuppliedValues: result['USER-SUPPLIED VALUES'] && this.parseYaml(result['USER-SUPPLIED VALUES'], {}), computedValues: result['COMPUTED VALUES'] && this.parseYaml(result['COMPUTED VALUES'], {}), }; }); } /** * @param {string} yamlValue * @param {object} defaultValue */ parseYaml(yamlValue, defaultValue) { const parseResult = yaml.safeLoad(yamlValue); if (parseResult === undefined) { return defaultValue; } return parseResult; } }; __decorate([ typedi_1.Inject(() => fbl_1.ChildProcessService), __metadata("design:type", fbl_1.ChildProcessService) ], K8sHelmService.prototype, "childProcessService", void 0); __decorate([ typedi_1.Inject(() => fbl_1.TempPathsRegistry), __metadata("design:type", fbl_1.TempPathsRegistry) ], K8sHelmService.prototype, "tempPathsRegistry", void 0); K8sHelmService = __decorate([ typedi_1.Service() ], K8sHelmService); exports.K8sHelmService = K8sHelmService; //# sourceMappingURL=K8sHelmService.js.map