UNPKG

@controlplane/cli

Version:

Control Plane Corporation CLI

185 lines 8.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HelmReleaseMigrator = void 0; const constants_1 = require("./constants"); const resolver_1 = require("../commands/resolver"); const helm_base_1 = require("./helm-base"); const functions_1 = require("./functions"); class HelmReleaseMigrator extends helm_base_1.HelmBase { constructor(client, session, args, ensureDeletion, secret) { super(client, session, args, ensureDeletion); // Required Parameters this.secret = secret; // Parameters dependant this.secretSelfLink = (0, resolver_1.resolveToLink)('secret', secret.name, this.session.context); } // Public Methods // async migrate() { // Check if the secret is already at the latest version if (this.secret.tags && this.secret.tags[constants_1.CPLN_HELM_SCHEMA_LATEST_VERSION_TAG_KEY] === constants_1.CPLN_HELM_SCHEMA_LATEST_VERSION) { // No need to migrate return; } // Handle the migration safely try { // Parse the data of the secret into a IHasSchemaVersion, no need to worry about parsing issues because // we are sure that the schema version could either be '1' or '2' for now. let releaseHasSchemaVersion; // Handle secret data differently for legacy versions >= 3 if (this.secret.tags.hasOwnProperty(constants_1.CPLN_HELM_SCHEMA_LATEST_VERSION_TAG_KEY)) { releaseHasSchemaVersion = (0, functions_1.decodeReleaseFromSecret)(this.secret); } else { releaseHasSchemaVersion = JSON.parse(this.secret.data.payload); } // Migrate based on the schema version switch (releaseHasSchemaVersion.schemaVersion) { case '1': // Migrate from version 1 to version 2 const legacyReleaseV2 = await this.migrateFromVersion1ToVersion2(releaseHasSchemaVersion); // Migrate from version 2 straight to version 4 await this.migrateFromVersion2ToVersion4(legacyReleaseV2); break; case '2': // Migrate from version 2 straight to version 4 await this.migrateFromVersion2ToVersion4(releaseHasSchemaVersion); break; case '3': // Migrate from version 3 to version 4 await this.migrateFromVersion3ToVersion4(releaseHasSchemaVersion); break; } } catch (e) { this.session.err(`ERROR: Failed to migrate release '${this.releaseName}'.`); this.session.abort({ error: e }); } } // Private Methods // async migrateFromVersion1ToVersion2(legacyReleaseV1) { var _a; const resources = []; for (const resource of legacyReleaseV1.resources) { try { resources.push({ ...resource, template: await this.fetchResource(resource.kind, resource.link), }); } catch (e) { // Ignore 404 if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) !== 404) { throw e; } } } return { schemaVersion: '2', release: legacyReleaseV1.release, deployments: [ { gvc: '', revision: 1, updated: new Date().toISOString(), status: 'deployed', chart: '', appVersion: '', description: legacyReleaseV1.description, config: {}, values: {}, valuesFiles: [], resources, }, ], }; } async migrateFromVersion2ToVersion4(legacyReleaseV2) { // A variable to hold all secret creation promises so we can await for the creation asynchronously const promises = []; // Iterate over each release deployment and create a new secret with the revision number for (const deployment of legacyReleaseV2.deployments) { // Construct the release object for schema version 3 const release = { schemaVersion: '4', name: legacyReleaseV2.release, info: { firstDeployed: new Date(this.secret.created).toISOString(), lastDeployed: deployment.updated, description: deployment.description, status: deployment.status, notes: '', resources: deployment.resources, }, chart: { metadata: { name: deployment.chart, appVersion: deployment.appVersion, }, values: deployment.values, }, config: deployment.config, manifest: '', version: deployment.revision, gvc: deployment.gvc, labels: {}, // Custom Properties valuesFiles: deployment.valuesFiles, }; // Create a new secret with the release object promises.push(this.createReleaseSecret(release, this.secret.tags)); } // Wait for all secrets to be created await Promise.all(promises); // Delete the original secret after successful migration await this.client.delete(this.secretSelfLink); } async migrateFromVersion3ToVersion4(legacyReleaseV3) { // Update the schema version tag in the secret this.secret.tags[constants_1.CPLN_HELM_SCHEMA_LATEST_VERSION_TAG_KEY] = '4'; // Initialize the release object with the latest schema version const release = { ...legacyReleaseV3, schemaVersion: constants_1.CPLN_HELM_SCHEMA_LATEST_VERSION, labels: {}, }; // Attempt to fetch the first available resource from the legacy release resources const firstResource = await this.fetchFirstAvailableResource(legacyReleaseV3.info.resources); // If a resource was found, we can extract the injected tags if (firstResource !== null) { // Extract the injected tags from the resource by finding common tags between the resource and the secret const injectedTags = Object.fromEntries(Object.entries(this.secret.tags) // 1) Drop secret core keys from the secret tags .filter(([key, _]) => !constants_1.CPLN_HELM_SECRET_CORE_KEYS.has(key)) // 2) Only keep ones that match on the resource .filter(([key, value]) => firstResource.tags[key] === value)); // Update the release labels with the injected tags (could be empty if no tags matched) release.labels = injectedTags; } // Update the secret payload with the new release object this.secret.data.payload = await (0, functions_1.encodeRelease)(release); // Update the secret and return await this.client.put(this.secretSelfLink, this.secret); } async fetchFirstAvailableResource(helmResources) { var _a; // Iterate over the resources and attempt to find at least one that exists for (const helmResource of helmResources) { try { // Fetch the resource using its link and return it return await this.client.get(helmResource.link); } catch (err) { // Ignore 404 errors and try the next resource if (((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 404) { continue; } // If the error is not a 404, rethrow it throw err; } } // If no resource was found, return null return null; } } exports.HelmReleaseMigrator = HelmReleaseMigrator; //# sourceMappingURL=helm-release-migrator.js.map