UNPKG

@controlplane/cli

Version:

Control Plane Corporation CLI

169 lines 8.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HelmReleaseHistoryManager = void 0; const helm_base_1 = require("./helm-base"); const resultFetcher_1 = require("../rest/resultFetcher"); const functions_1 = require("./functions"); const constants_1 = require("./constants"); class HelmReleaseHistoryManager extends helm_base_1.HelmBase { constructor(client, session, args, ensureDeletion, latestReleaseRevision, deployedReleaseRevision, releaseRevisionSecrets) { super(client, session, args, ensureDeletion); // Required Parameters this.latestReleaseRevision = latestReleaseRevision; this.deployedReleaseRevision = deployedReleaseRevision; this.releaseRevisionSecrets = releaseRevisionSecrets; this.nextVersion = latestReleaseRevision ? (latestReleaseRevision === null || latestReleaseRevision === void 0 ? void 0 : latestReleaseRevision.release.version) + 1 : 1; this.historyLimit = this.args.historyLimit || Number(process.env[constants_1.CPLN_HELM_MAX_HISTORY_ENV_VAR]) || constants_1.CPLN_HELM_DEFAULT_HISTORY_LIMIT; } // Public Static Functions // static async initialize(client, session, args, ensureDeletion) { var _a; // Initialize the new helm base const helmBase = new helm_base_1.HelmBase(client, session, args, ensureDeletion); // This will migrate the legacy release secret to the latest version if it exists await helmBase.migrateReleaseSecretIfNecessary(args.release); // Fetch all secrets for the specified release const secretList = await client.post(`${helmBase.secretParentLink}/-query`, { kind: 'secret', spec: { match: 'all', terms: [ { op: '~', property: 'name', value: constants_1.CPLN_RELEASE_NAME_PREFIX, }, { op: '=', tag: 'name', value: args.release, }, ], }, }); // Continue fetching secrets await (0, resultFetcher_1.fetchPages)(client, session.format.max, secretList); // Treat the secret list items as an array of secrets const secrets = secretList.items; // Sort secrets by the version tag secrets.sort((a, b) => { var _a, _b; // Convert the version tag value to a number const va = Number((_a = a === null || a === void 0 ? void 0 : a.tags) === null || _a === void 0 ? void 0 : _a.version); const vb = Number((_b = b === null || b === void 0 ? void 0 : b.tags) === null || _b === void 0 ? void 0 : _b.version); // Determine if the variables are valid numbers const aIsNum = !Number.isNaN(va); const bIsNum = !Number.isNaN(vb); // If both versions numeric, order by numeric difference if (aIsNum && bIsNum) { return va - vb; } // Place A before B if only A has numeric version if (aIsNum) { return -1; } // Place B before A if only B has numeric version if (bIsNum) { return 1; } // Leave order unchanged if neither version numeric return 0; }); // Declare a variable to hold specific release revisions let lastReleaseRevision = undefined; let deployedReleaseRevision = undefined; if (secrets.length > 0) { // Load the latest release revision if there were secrets lastReleaseRevision = await helmBase.loadReleaseRevision(secrets[secrets.length - 1].name); // Iterate over the secrets and attempt to find the deployed release secret for (const secret of secrets) { if (((_a = secret.tags) === null || _a === void 0 ? void 0 : _a.status) === 'deployed') { deployedReleaseRevision = await helmBase.loadReleaseRevision(secret.name); break; } } } // Return the release revisions return new HelmReleaseHistoryManager(client, session, args, ensureDeletion, lastReleaseRevision, deployedReleaseRevision, secrets); } // Public Methods // async enforceHistoryLimit(operation) { var _a; try { // If the history limit is configured to keep all revisions, there is nothing to enforce if (this.historyLimit == constants_1.CPLN_HELM_KEEP_ALL_REVISIONS) { return; } // Count the release revision secrets plus the revision we just created as part of the current operation const totalReleaseCount = this.releaseRevisionSecrets.length + 1; // Exit early when the count is already within the limit if (totalReleaseCount <= this.historyLimit) { return; } // Determine how many secrets must be pruned to satisfy the configured limit let deletionsRequired = totalReleaseCount - this.historyLimit; // Iterate through the release history (sorted oldest → newest) until the required deletions are performed for (let i = 0; i < this.releaseRevisionSecrets.length && deletionsRequired > 0; i++) { const candidateSecret = this.releaseRevisionSecrets[i]; // Skip the currently deployed revision to mirror Helm's behavior if (((_a = candidateSecret.tags) === null || _a === void 0 ? void 0 : _a.status) === 'deployed') { continue; } // Delete the candidate revision secret const candidateRevision = await this.loadReleaseRevision(candidateSecret.name); await candidateRevision.deleteSecret(); // Remove the deleted secret from the local cache so subsequent iterations stay aligned with the backend this.releaseRevisionSecrets.splice(i, 1); i--; deletionsRequired--; } } catch (e) { this.session.err(`ERROR: Release '${this.releaseName}' ${operation} completed, but enforcing the history limit failed. Please resolve the underlying issue and rerun the command.`); this.session.abort({ error: e }); } } async revealAllReleaseRevisions() { // Declare the variable that will hold all release revision manager promises so we can await for their reveal async const promises = []; // Iterate over all sorted release secrets and accumulate for (const secret of this.releaseRevisionSecrets) { promises.push(this.loadReleaseRevision(secret.name)); } // Await for revealing all secrets return await Promise.all(promises); } async findLatestSupersededReleaseRevision() { var _a; // If there are no releases, return undefined if (this.releaseRevisionSecrets.length === 0) { return undefined; } // Iterate from the end of the array to the beginning since it is sorted for (let i = this.releaseRevisionSecrets.length - 1; i >= 0; i--) { if (((_a = this.releaseRevisionSecrets[i].tags) === null || _a === void 0 ? void 0 : _a.status) === 'superseded') { // Return the lastest 'superseded' release revision encountered return await this.loadReleaseRevision(this.releaseRevisionSecrets[i].name); } } // Return undefined if no 'superseded' release revision is found return undefined; } async getReleaseRevision(releaseName, revision) { // Find the release for the specified revision and return it if (revision !== undefined) { // Construct the secret name that holds the release revision const secretName = (0, functions_1.getReleaseSecretName)(releaseName, revision); // Return a new HelmReleaseRevisionManager instance based on the fetched secret return await this.loadReleaseRevision(secretName); } // If there is no deployed release revision, abort if (!this.deployedReleaseRevision) { this.session.abort({ message: 'ERROR: No deployed release found.' }); } // Return the deployed release revision return this.deployedReleaseRevision; } } exports.HelmReleaseHistoryManager = HelmReleaseHistoryManager; //# sourceMappingURL=helm-release-history-manager.js.map