@apigeeks/fbl-k8s-plugin
Version:
fbl wrapper plugin for helm and kubectl cli utilities
226 lines • 9.55 kB
JavaScript
;
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