UNPKG

@apigeeks/fbl-k8s-plugin

Version:

fbl wrapper plugin for helm and kubectl cli utilities

165 lines 8.02 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 }); var K8sCleanupService_1; const minimatch = require("minimatch"); const lodash_1 = require("lodash"); const typedi_1 = require("typedi"); const K8sHelmService_1 = require("./K8sHelmService"); const K8sKubectlService_1 = require("./K8sKubectlService"); let K8sCleanupService = K8sCleanupService_1 = class K8sCleanupService { /** * Clean cluster * @param {IK8sCleanupOptions} options * @param {IContext} context * @param {ActionSnapshot} snapshot * @return {Promise<void>} */ cleanup(options, context, snapshot) { return __awaiter(this, void 0, void 0, function* () { const kinds = options.kinds || K8sCleanupService_1.defaultKinds; const registeredHelmReleases = context.entities.registered .filter(e => e.type === 'helm') .map(e => e.payload.name); const allHelmObjects = (lodash_1.flattenDeep(yield Promise.all(registeredHelmReleases.map((name) => __awaiter(this, void 0, void 0, function* () { return yield this.k8sHelmService.getHelmObjects(name); }))))); const deployedHelms = yield this.k8sHelmService.listInstalledHelms(); yield this.cleanUpHelmReleases(options, context, snapshot, registeredHelmReleases, deployedHelms); for (const kind of kinds) { const deployedK8sObjects = context.entities.registered .filter(e => e.type === kind && e.payload.metadata.namespace === options.namespace) .map(o => o.payload.metadata.name); const cluster = yield this.k8sKubectlService.listObjects(kind, options.namespace); yield this.cleanupK8sObjects(options, context, snapshot, kind, allHelmObjects, deployedK8sObjects, cluster, lodash_1.get(options, ['ignored', 'objects', kind], [])); } }); } /** * Cleanup helm releases * @param {IK8sCleanupOptions} options * @param {IContext} context * @param {ActionSnapshot} snapshot * @param {string[]} registeredHelmReleases * @param {string[]} deployedHelms * @return {Promise<void>} */ cleanUpHelmReleases(options, context, snapshot, registeredHelmReleases, deployedHelms) { return __awaiter(this, void 0, void 0, function* () { const ignoredHelms = registeredHelmReleases; const ignoredPatterns = lodash_1.get(options, 'ignored.helms', []); const diff = this.findOrphans(deployedHelms, ignoredHelms).filter(d => { for (const pattern of ignoredPatterns) { if (minimatch(d, pattern)) { return false; } } return true; }); if (!options.dryRun) { yield Promise.all(diff.map((name) => __awaiter(this, void 0, void 0, function* () { try { yield this.k8sHelmService.remove(name, context); snapshot.log(`Helm release "${name}" deleted`); } catch (e) { snapshot.log(`Helm release "${name}" failed to delete: ${e.message}`, true); } }))); } else if (diff.length) { snapshot.log(`Found following helm releases to be cleaned up: ${diff.join(', ')}`); } }); } /** * @param {IK8sCleanupOptions} options * @param {IContext} context * @param {ActionSnapshot} snapshot * @param {string} kind * @param {IK8sObject[]} allHelmObjects * @param {string[]} deployed * @param {string[]} cluster * @param {string[]} ignoredPatterns * @return {Promise<void>} */ cleanupK8sObjects(options, context, snapshot, kind, allHelmObjects, deployed, cluster, ignoredPatterns) { return __awaiter(this, void 0, void 0, function* () { const ignoredObjects = [ ...deployed, ...allHelmObjects .filter((object) => object.kind === kind) .map((object) => object.metadata.name), ]; const diff = this.findOrphans(cluster, ignoredObjects).filter(d => { for (const pattern of ignoredPatterns) { if (minimatch(d, pattern)) { return false; } } return true; }); if (!options.dryRun) { yield Promise.all(diff.map((name) => __awaiter(this, void 0, void 0, function* () { try { yield this.k8sKubectlService.deleteObject({ apiVersion: 'v1', kind: kind, metadata: { name, namespace: options.namespace, }, }, context); snapshot.log(`${kind} "${name}" deleted`); } catch (e) { snapshot.log(`${kind} "${name}" failed to delete: ${e.message}`); } }))); } else if (diff.length) { snapshot.log(`Found following ${kind}s to be cleaned up: ${diff.join(', ')}`); } }); } /** * Difference between all objects inside the cluster and ones that were deployed * * @param {string[]} inCluster * @param {string[]} deployed * @return {string[]} */ findOrphans(inCluster, deployed) { return lodash_1.difference(inCluster, deployed); } }; // All k8s Object kinds to be cleaned up // Note: order matters, PVC should go before SC, or on some environments it will just fail to delete (like AWS) K8sCleanupService.defaultKinds = ['PersistentVolumeClaim', 'StorageClass', 'Secret', 'ConfigMap']; __decorate([ typedi_1.Inject(() => K8sKubectlService_1.K8sKubectlService), __metadata("design:type", K8sKubectlService_1.K8sKubectlService) ], K8sCleanupService.prototype, "k8sKubectlService", void 0); __decorate([ typedi_1.Inject(() => K8sHelmService_1.K8sHelmService), __metadata("design:type", K8sHelmService_1.K8sHelmService) ], K8sCleanupService.prototype, "k8sHelmService", void 0); K8sCleanupService = K8sCleanupService_1 = __decorate([ typedi_1.Service() ], K8sCleanupService); exports.K8sCleanupService = K8sCleanupService; //# sourceMappingURL=K8sCleanupService.js.map