@controlplane/cli
Version:
Control Plane Corporation CLI
905 lines • 40.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelmGetValues = exports.HelmGetManifest = exports.HelmGet = exports.HelmHistory = exports.HelmList = exports.HelmUninstall = exports.HelmRollback = exports.HelmUpgrade = exports.HelmInstall = exports.HelmTemplate = exports.HelmCmd = void 0;
const tmp = require("tmp");
const path = require("path");
const fs = require("fs");
const jsyaml = require("js-yaml");
const command_1 = require("../cli/command");
const functions_1 = require("../util/functions");
const resolver_1 = require("./resolver");
const objects_1 = require("../util/objects");
const io_1 = require("../util/io");
const resultFetcher_1 = require("../rest/resultFetcher");
const generic_1 = require("./generic");
const functions_2 = require("../helm/functions");
const helm_1 = require("../helm/helm");
const constants_1 = require("../helm/constants");
const helmDeploymentManager_1 = require("../helm/helmDeploymentManager");
const options_1 = require("./options");
function withSingleRelease(yargs) {
return yargs.positional('release', {
type: 'string',
describe: 'The release name',
demandOption: false,
});
}
function withSingleChart(yargs) {
return yargs.positional('chart', {
type: 'string',
describe: 'Path to chart',
demandOption: true,
});
}
function withSingleRevision(yargs) {
return yargs.positional('revision', {
type: 'string',
describe: `Revision (version) number. If this argument is omitted or set to 0, it will roll back to the previous release. To see revision numbers, run 'cpln helm history RELEASE'.`,
});
}
function withHelmTemplateOptions(yargs) {
return yargs.options({
set: {
multiple: true,
describe: 'Set values on the command line (can specify multiple or separate values: --set key1=val1 --set key2=val2)',
},
'set-string': {
multiple: true,
describe: 'Set STRING values on the command line (can specify multiple or separate values: --set-string key1=val1 --set-string key2=val2)',
},
'set-file': {
multiple: true,
describe: 'Set values from respective files specified via the command line (can specify multiple or separate values: --set-file key1=path1 --set-file key2=path2)',
},
description: {
type: 'string',
describe: 'Add a custom description',
alias: 'desc',
},
'generate-name': {
type: 'boolean',
describe: 'Generate the name (and omit the NAME parameter)',
alias: 'g',
},
'post-renderer': {
type: 'string',
describe: 'The path to an executable to be used for post rendering. If it exists in $PATH, the binary will be used, otherwise it will try to look for the executable at the given path',
},
'post-renderer-args': {
default: [],
multiple: true,
describe: 'An argument to the post-renderer (can specify multiple or separate values: --post-renderer-args arg1 --post-renderer-args arg2) (default [])',
},
repo: {
type: 'string',
describe: 'Chart repository url where to locate the requested chart',
},
values: {
type: 'string',
multiple: true,
describe: 'Specify values in a YAML file or a URL (can specify multiple or separate values: --values value1.yaml --values values2.yaml)',
alias: 'f',
},
verify: {
type: 'boolean',
describe: 'Verify the package before using it',
},
});
}
function withHelmGetOptions(yargs) {
return yargs.options({
revision: {
type: 'number',
describe: 'get the named release with revision',
},
});
}
function withHelmGetValuesOptions(yargs) {
return yargs.options({
all: {
type: 'boolean',
describe: 'dump all (computed) values',
alias: 'a',
},
});
}
function withWaitOptions(yargs) {
return yargs.options({
wait: {
type: 'boolean',
describe: `If set, will wait until all Workloads are in a ready state before marking the release as successful. It will wait for as long as --timeout`,
},
timeout: {
type: 'number',
default: 5 * 60,
describe: 'The amount of seconds to wait for workloads to be ready before timing out. Works only if the "wait" option is set to true.',
},
});
}
function withCleanupOnFail(yargs) {
return yargs.options({
'cleanup-on-fail': {
type: 'boolean',
default: false,
describe: `allow deletion of new resources created in this rollback when rollback fails`,
},
});
}
// Commands //
class HelmCmd extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'helm';
this.describe = 'Manage helm releases on cpln';
}
builder(yargs) {
return yargs
.demandCommand()
.version(false)
.help()
.command(new HelmGet().toYargs())
.command(new HelmHistory().toYargs())
.command(new HelmInstall().toYargs())
.command(new HelmList().toYargs())
.command(new HelmRollback().toYargs())
.command(new HelmTemplate().toYargs())
.command(new HelmUninstall().toYargs())
.command(new HelmUpgrade().toYargs());
}
handle() { }
}
exports.HelmCmd = HelmCmd;
class HelmTemplate extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'template [release] [chart]';
this.describe = 'Generate cpln resources from a template';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, withSingleChart, withHelmTemplateOptions, options_1.withAllOptions)(yargs);
}
handle(args) {
// Validate Arguments
(0, functions_2.validateHelmArgs)(this.session, args);
// Process arguments
(0, functions_2.processHelmArgs)(args);
// Generate a template
const template = (0, functions_2.generateHelmTemplate)(args, this.session.context.org, this.session.context.gvc, args.debug || args.verbose);
// Output the template
this.session.out(template);
}
}
exports.HelmTemplate = HelmTemplate;
class HelmInstall extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'install [release] [chart]';
this.aliases = ['apply'];
this.describe = 'Install a release';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, withSingleChart, withWaitOptions, withHelmTemplateOptions, generic_1.withTagRemovableOptions, options_1.withAllOptions)(yargs);
}
async handle(args) {
var _a, _b, _c, _d, _e;
// Validate Arguments
(0, functions_2.validateHelmArgs)(this.session, args);
// Process arguments
(0, functions_2.processHelmArgs)(args);
// Initiate a new Helm instance
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
const org = this.session.context.org;
const gvc = this.session.context.gvc || '';
const description = args.description || '';
const deployedResourceLinks = [];
const appliedWorkloadLinks = [];
const customTags = {
'cpln/release': helm.stateName,
};
// Read default values
const defaultValues = (0, functions_2.extractHelmDefaultValues)(args.chart);
// Read custom values
const valuesFiles = (0, functions_2.extractHelmCustomValues)(args.values);
// Create helm config
const helmConfig = (0, functions_2.extractHelmConfig)(args, valuesFiles);
// Print verbose
if (args.debug || args.verbose) {
this.session.out((0, functions_2.generateHelmTemplate)(args, org, this.session.context.gvc, args.debug || args.verbose));
}
// Generate a template
const template = (0, functions_2.generateHelmTemplate)(args, org, this.session.context.gvc);
// Load template output into cpln resources
const templateResources = jsyaml.safeLoadAll(template).filter((item) => item !== null);
// Sort by kind priority
(0, objects_1.sortIHasKindByPriority)(templateResources, false);
if (templateResources.length === 0) {
this.session.abort({
message: 'ERROR: There were no resources found in the generated template. Make sure you have templates in your chart.',
});
}
// Prepare the necessary variables
let state;
let release;
try {
// Attempt to fetch state
state = await helm.fetchState();
// Get release
release = await helm.getRelease(state);
// Validate release
helm.validateRelease(release);
}
catch (e) {
// Create a new state if it doesn't exist
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
try {
// Initialize an empty release
release = helm.initializeRelease();
// Create new state
state = await helm.createState(release);
}
catch (e) {
this.session.out(`ERROR: Unable to create the release '${args.release}'.`);
this.session.abort({ error: e });
}
}
else {
this.session.out(`ERROR: Unable to fetch the release '${args.release}'.`);
this.session.abort({ error: e });
}
}
// Create new deployment
let deployment;
const deploymentManager = new helmDeploymentManager_1.HelmDeploymentManager(this.session, release);
if (release.deployments.length == 0) {
deployment = deploymentManager.createFirstDeployment(helm.chart, description, helmConfig, defaultValues, valuesFiles, gvc);
release.deployments.push(deployment);
}
else if (release.deployments.length == 1 && deploymentManager.latestDeployment.status != 'deployed') {
// If there is only one deployment, and it is not deployed, return it so we can attempt to deploy it again
deployment = deploymentManager.latestDeployment;
}
else {
deployment = deploymentManager.createNextDeployment('pending-upgrade', helm.chart, description, helmConfig, defaultValues, valuesFiles, gvc);
release.deployments.push(deployment);
}
// Get the latest 'deployed' deployment to determine which resources to update or skip
const lastDeployedDeployment = deploymentManager.findLatestDeployedDeployment();
// Prepare before apply
await helm.prepareBeforeApply(templateResources, deploymentManager, deployment, state, release);
// Apply resources individually and update the state accordingly
for (const templateResource of templateResources) {
try {
const ctx = this.session.context;
// Modify context if it has been specified in the resource
if (templateResource.gvc) {
ctx.gvc = templateResource.gvc;
}
// Avoid applying GVC related resources if the GVC itself does not exist
await helm.ensureGvcExists(templateResource, ctx);
// Prepare relation links
const templateResourceSelfLink = (0, resolver_1.resolveToLink)(templateResource.kind, templateResource.name, ctx);
const templateResourceParentLink = (0, resolver_1.kindResolver)(templateResource.kind).parentLink(ctx);
// Check if this resource belongs to a different release and throw error accordingly
await helm.validateResourceReleaseTag(templateResourceSelfLink);
// Update the tags
templateResource.tags = {
...templateResource.tags,
...(0, generic_1.fromTagOptions)(args),
...(0, generic_1.fromRemoveTagOptions)(args),
...customTags,
};
// Collect workload links so we can wait for them to be ready if requested
if (templateResource.kind === 'workload') {
appliedWorkloadLinks.push(templateResourceSelfLink);
}
// A variable to determine whether we should apply template resource or not
let shouldApplyResource = await helm.shouldApplyResource(lastDeployedDeployment, templateResourceSelfLink, templateResource);
// Apply template resource if needed
if (shouldApplyResource) {
// Perform apply
const axiosResponse = await this.client.axios.put(templateResourceParentLink, templateResource);
if (axiosResponse.status == 201) {
this.session.out(`Created ${axiosResponse.headers.location}`);
}
else {
this.session.out(`Updated ${templateResourceSelfLink}'`);
}
}
else {
this.session.out(`Unchanged ${templateResourceSelfLink}'`);
}
// Confirm that the resource has been deployed
deployedResourceLinks.push(templateResourceSelfLink);
// Prepare for updating state
const fetchedResource = await this.client.get(templateResourceSelfLink);
// Attempt to find resource if the template resource already exists in the deployment
let foundResource = deployment.resources.find((resource) => resource.link === templateResourceSelfLink);
// If the template resource is already in the state, then just update the version
if (foundResource) {
foundResource.id = fetchedResource.id;
foundResource.version = fetchedResource.version;
foundResource.template = templateResource;
}
else {
// Push a new resource into the deployment
deployment.resources.push({
id: fetchedResource.id,
kind: fetchedResource.kind,
version: fetchedResource.version,
link: templateResourceSelfLink,
template: templateResource,
});
}
// Update the state
await helm.updateState(state, release);
}
catch (e) {
deploymentManager.updateDeploymentStatus(deployment, 'failed', ((_c = (_b = e.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || e.message);
await helm.updateState(state, release);
this.session.out(`ERROR: Unable to install ${templateResource.kind} '${templateResource.name}'.`);
this.session.abort({ error: e });
}
}
// Figure out the resources that are not/no longer part of the new deployment
let resourcesToDelete = [];
// Sort the deployments in descending order based on the "revision" property
const sortedDeployments = release.deployments.sort((a, b) => b.revision - a.revision);
for (const deployment of sortedDeployments) {
for (const resource of deployment.resources) {
// Skip if the resource has been applied
if (deployedResourceLinks.includes(resource.link)) {
continue;
}
// Add to the delete collection
resourcesToDelete.push(resource);
}
}
// Delete resources accumulated that are not/no longer part of the deployment
if (resourcesToDelete.length > 0) {
this.session.out('\nPerforming cleanup...\n');
try {
await helm.deleteResources(resourcesToDelete);
}
catch (e) {
deploymentManager.updateDeploymentStatus(deployment, 'failed', ((_e = (_d = e.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.message) || e.message);
await helm.updateState(state, release);
this.session.abort({ error: e });
}
}
// Supersede active deployment
if (deploymentManager.activeDeployment && release.deployments.length > 1) {
deploymentManager.updateDeploymentStatus(deploymentManager.activeDeployment, 'superseded');
}
// Mark current deployment as deployed
deploymentManager.updateDeploymentStatus(deployment, 'deployed');
await helm.updateState(state, release);
// Wait for workloads to be ready if the "wait" option is set to true
await helm.awaitWorkloadsReadiness(appliedWorkloadLinks);
// Notify user that the release is successful
this.session.out(`\nRelease '${args.release}' has been installed successfully!`);
// Print notes
this.printNotes(args, org);
}
printNotes(args, org) {
// Ignore printing if NOTES.txt does not exist
if (!fs.existsSync(path.join(args.chart, 'templates', 'NOTES.txt'))) {
return;
}
// Handle temporary directory for the chart
tmp.dir({ unsafeCleanup: true }, (err, tempDirPath, cleanupCallback) => {
if (err) {
this.session.out(`ERROR: Unable to print notes.`);
this.session.abort({ error: err });
}
// Set chart path to the temporary directory
const templateArgs = {
...args,
chart: tempDirPath,
};
try {
// Copy chart into the temporary directory path
(0, io_1.copyDirectorySync)(args.chart, tempDirPath);
// Delete all YAML templates from the temporary chart
const templatesDir = path.join(tempDirPath, 'templates');
fs.readdirSync(templatesDir).forEach((file) => {
if (path.extname(file) === '.yaml') {
fs.unlinkSync(path.join(templatesDir, file));
}
});
// Read notes content into an object
const notesPath = path.join(templatesDir, 'NOTES.txt');
const notesContent = fs.readFileSync(notesPath, 'utf8');
const notesObject = { notes: notesContent };
// Create notes.yaml and dump the notes object into it
const notesYamlPath = path.join(templatesDir, 'notes.yaml');
fs.writeFileSync(notesYamlPath, jsyaml.dump(notesObject));
const template = (0, functions_2.generateHelmTemplate)(templateArgs, org, this.session.context.gvc);
const notesObj = jsyaml.safeLoad(template);
// Finally, print notes
this.session.out(`\n${notesObj.notes}`);
// Delete tmp directory
cleanupCallback();
}
catch (error) {
// Make sure the directory is deleted on exception
cleanupCallback();
// Abort session
this.session.out(`ERROR: Unable to print notes.`);
this.session.abort({ error });
}
});
}
}
exports.HelmInstall = HelmInstall;
class HelmUpgrade extends HelmInstall {
constructor() {
super(...arguments);
this.command = 'upgrade [release] [chart]';
this.describe = 'Upgrade a release';
}
}
exports.HelmUpgrade = HelmUpgrade;
class HelmRollback extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'rollback <release> [revision]';
this.describe = 'Roll back a release to a previous revision';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, withSingleRevision, withCleanupOnFail, withWaitOptions, options_1.withAllOptions)(yargs);
}
async handle(args) {
var _a, _b, _c, _d, _e;
// Initiate a new Helm instance
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
const org = this.session.context.org;
const gvc = this.session.context.gvc || '';
const deployedResourceLinks = [];
const appliedWorkloadLinks = [];
const createdResources = [];
let state;
let release;
try {
// Attempt to fetch state
state = await helm.fetchState();
// Get release
release = await helm.getRelease(state);
// Validate release
helm.validateRelease(release);
}
catch (e) {
// Create a new state if it doesn't exist
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
this.session.abort({ message: `ERROR: Release '${args.release}' does not exit.` });
}
else {
this.session.out(`ERROR: Unable to fetch the release '${args.release}'.`);
this.session.abort({ error: e });
}
}
// Throw an error if deployments were empty
if (release.deployments.length == 0) {
this.session.abort({ message: `ERROR: Release '${release.release}' has no deployments.` });
}
// Figure out rollback target
let rollbackTarget;
const deploymentManager = new helmDeploymentManager_1.HelmDeploymentManager(this.session, release);
// Find the deployment with the specified revision
if (args.revision) {
const foundDeployment = deploymentManager.getDeployment(args.revision);
if (!foundDeployment) {
this.session.abort({ message: `ERROR: Deployment with revision '${args.revision}' does not exit.` });
}
rollbackTarget = foundDeployment;
}
else {
// Find latest superseded deployment
const foundDeployment = deploymentManager.findLatestSupersededDeployment();
if (!foundDeployment) {
this.session.abort({
message: `ERROR: There are no deployments to rollback to.`,
});
}
rollbackTarget = foundDeployment;
}
// Validate rollback target
if (rollbackTarget.status !== 'superseded') {
this.session.abort({
message: `ERROR: Deployment with revision '${rollbackTarget.revision}' is invalid, you can only rollback to superseded deployments.`,
});
}
// Prepare new deployment properties
const chart = { name: rollbackTarget.chart, appVersion: rollbackTarget.appVersion };
const description = `Rollback to ${rollbackTarget.revision}`;
// Create new deployment
const deployment = deploymentManager.createNextDeployment('pending-rollback', chart, description, rollbackTarget.config, rollbackTarget.values, rollbackTarget.valuesFiles, gvc);
release.deployments.push(deployment);
// Get the latest 'deployed' deployment to determine which resources to update or skip
const lastDeployedDeployment = deploymentManager.findLatestDeployedDeployment();
// Extract resources from rollback target
const resources = rollbackTarget.resources.map((helmResource) => helmResource.template);
// Prepare before apply
await helm.prepareBeforeApply(resources, deploymentManager, deployment, state, release);
// Initiate rollback
for (const resource of rollbackTarget.resources) {
try {
const obj = (0, resolver_1.dismantleSelfLink)(org, resource.link);
// Modify context if it has been specified in the resource
if (resource.template.gvc) {
obj.ctx.gvc = resource.template.gvc;
}
// Avoid applying GVC related resources if the GVC itself does not exist
await helm.ensureGvcExists(resource.template, obj.ctx);
// Prepare a relation link
const resourceSelfLink = (0, resolver_1.resolveToLink)(resource.kind, resource.template.name, obj.ctx);
const resourceParentLink = (0, resolver_1.kindResolver)(resource.kind).parentLink(obj.ctx);
// Check if this resource belongs to a different release and throw error accordingly
await helm.validateResourceReleaseTag(resourceSelfLink);
// Collect workload links so we can wait for them to be ready if requested
if (resource.kind === 'workload') {
appliedWorkloadLinks.push(resource.link);
}
// A variable to determine whether we should apply this resource or not
let shouldApplyResource = await helm.shouldApplyResource(lastDeployedDeployment, resourceSelfLink, resource.template);
// Apply template resource if needed
if (shouldApplyResource) {
// Perform apply
const axiosResponse = await this.client.axios.put(resourceParentLink, resource.template);
if (axiosResponse.status == 201) {
this.session.out(`Created ${axiosResponse.headers.location}`);
}
else {
this.session.out(`Updated ${resourceSelfLink}'`);
}
}
else {
this.session.out(`Unchanged ${resourceSelfLink}'`);
}
// Confirm that the resource has been deployed
deployedResourceLinks.push(resourceSelfLink);
// Prepare for updating deployment
const fetchedResource = await this.client.get(resource.link);
// Push a new resource into the deployment
deployment.resources.push({
id: fetchedResource.id,
kind: fetchedResource.kind,
version: fetchedResource.version,
link: resource.link,
template: resource.template,
});
// Update the state
await helm.updateState(state, release);
}
catch (e) {
deploymentManager.updateDeploymentStatus(deployment, 'failed', ((_c = (_b = e.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || e.message);
await helm.updateState(state, release);
// Attempt to clean up on fail
await helm.cleanupOnFail(createdResources);
this.session.out(`ERROR: Unable to rollback to deployment revision '${rollbackTarget.revision}'.`);
this.session.abort({ error: e });
}
}
// Figure out the resources that are not/no longer part of the new deployment
let resourcesToDelete = [];
// Sort the deployments in descending order based on the "revision" property
const sortedDeployments = release.deployments.sort((a, b) => b.revision - a.revision);
for (const deployment of sortedDeployments) {
for (const resource of deployment.resources) {
// Skip if the resource has been applied
if (deployedResourceLinks.includes(resource.link)) {
continue;
}
// Add to the delete collection
resourcesToDelete.push(resource);
}
}
// Delete resources accumulated that are not/no longer part of the deployment
if (resourcesToDelete.length > 0) {
this.session.out('\nPerforming cleanup...\n');
try {
await helm.deleteResources(resourcesToDelete);
}
catch (e) {
deploymentManager.updateDeploymentStatus(deployment, 'failed', ((_e = (_d = e.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.message) || e.message);
await helm.updateState(state, release);
// Attempt to clean up on fail
await helm.cleanupOnFail(createdResources);
this.session.abort({ error: e });
}
}
// Supersede active deployment
if (deploymentManager.activeDeployment) {
deploymentManager.updateDeploymentStatus(deploymentManager.activeDeployment, 'superseded');
}
try {
// Mark current deployment as deployed and update state
deploymentManager.updateDeploymentStatus(deployment, 'deployed');
await helm.updateState(state, release);
// Wait for workloads to be ready if the "wait" option is set to true
await helm.awaitWorkloadsReadiness(appliedWorkloadLinks);
}
catch (e) {
// Attempt to clean up on fail
await helm.cleanupOnFail(createdResources);
this.session.abort({ error: e });
}
// Notify user that the rollback is successful
this.session.out(`\nRollback to deployment revision '${rollbackTarget.revision}' has been successfully!`);
}
}
exports.HelmRollback = HelmRollback;
class HelmUninstall extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'uninstall <release>';
this.aliases = ['destroy', 'del', 'delete', 'un'];
this.describe = 'Uninstall a release';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, options_1.withRequestOptions, options_1.withAllOptions)(yargs);
}
async handle(args) {
var _a;
let state;
let release;
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
try {
// Attempt to fetch state
state = await helm.fetchState();
// Get release
release = await helm.getRelease(state);
// Validate release
helm.validateRelease(release);
}
catch (e) {
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
this.session.abort({ message: `ERROR: Release '${args.release}' does not exist` });
}
this.session.abort({ error: e });
}
// Delete resources of each deployment in case there are resources of failed deployments that are still running
if (release.deployments.length > 0) {
// Sort the deployments in descending order based on the "revision" property
const sortedDeployments = release.deployments.sort((a, b) => b.revision - a.revision);
// Iterate over each deployment and delete its resources
for (const deployment of sortedDeployments) {
// Delete deployment resources
await helm.deleteResources(deployment.resources);
}
}
// Delete state
await helm.deleteState(release);
this.session.out(`\nRelease '${args.release}' has been uninstalled successfully!`);
}
}
exports.HelmUninstall = HelmUninstall;
class HelmList extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'list';
this.describe = 'List releases';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
options_1.withOrgOptions, options_1.withStandardOptions)(yargs);
}
async handle(args) {
const statePromises = [];
const items = [];
// Initiate a new Helm instance
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
// Fetch helm states
const stateList = await this.client.post(`${helm.stateParentLink}/-query`, {
kind: 'secret',
spec: {
match: 'any',
terms: [
{
op: '~',
property: 'name',
value: 'cpln-release-',
},
],
},
});
// Fetch more helm states
await (0, resultFetcher_1.fetchPages)(this.client, this.session.format.max, stateList);
// Iterate over items and prepare releases
for (const state of stateList.items) {
const selfLink = (0, resolver_1.resolveToLink)('secret', state.name, this.session.context);
statePromises.push(helm.fetchState(selfLink));
}
// Fetch states in parallel
const states = await Promise.all(statePromises);
// Iterate over states and get the latest deployment
for (const state of states) {
const release = await helm.getRelease(state);
const deploymentManager = new helmDeploymentManager_1.HelmDeploymentManager(this.session, release);
let item;
// Get latest deployment
if (deploymentManager.latestDeployment) {
item = {
release: release.release,
...deploymentManager.latestDeployment,
};
}
else {
// Create a virtual deployment (this shouldn't happen, but could happen)
item = {
release: release.release,
gvc: '',
revision: 0,
updated: '',
status: 'corrupt',
chart: '',
appVersion: '',
};
}
items.push(item);
}
// Prepare accumulator
const accumulator = {
kind: 'list',
itemKind: constants_1.helmListKind,
items: items,
links: [],
};
if (this.session.format.max) {
accumulator.items = accumulator.items.slice(0, this.session.format.max);
}
// Output the deployment list with format
await this.session.outFormat(accumulator);
}
}
exports.HelmList = HelmList;
class HelmHistory extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'history <release>';
this.describe = 'Fetch release history';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, options_1.withAllOptions)(yargs);
}
async handle(args) {
var _a;
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
try {
// Attempt to fetch state
const state = await helm.fetchState();
// Get release
const release = await helm.getRelease(state);
// Throw an error if deployments were empty
if (release.deployments.length == 0) {
this.session.abort({ message: `ERROR: Release '${release.release}' has no deployments.` });
}
// Prepare accumulator
const accumulator = {
kind: 'list',
itemKind: constants_1.helmDeploymentKind,
items: release.deployments,
links: [],
};
if (this.session.format.max) {
accumulator.items = accumulator.items.slice(0, this.session.format.max);
}
// Output the state with format
await this.session.outFormat(accumulator);
}
catch (e) {
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
this.session.abort({ message: `ERROR: Release '${args.release}' does not exist` });
}
this.session.abort({ error: e });
}
}
}
exports.HelmHistory = HelmHistory;
class HelmGet extends command_1.Command {
constructor() {
super();
this.command = 'get';
this.describe = 'Download extended information of a named release';
}
builder(yargs) {
return (yargs
.demandCommand()
.version(false)
.help()
// specific
.command(new HelmGetManifest().toYargs())
.command(new HelmGetValues().toYargs()));
}
handle() { }
}
exports.HelmGet = HelmGet;
class HelmGetManifest extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'manifest <release>';
this.describe = 'Download the manifest for a named release';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, withHelmGetOptions, options_1.withOrgOptions, options_1.withStandardOptions)(yargs);
}
async handle(args) {
var _a;
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
try {
// Attempt to fetch state
const state = await helm.fetchState();
// Get release
const release = await helm.getRelease(state);
// Figure out deployment
const deploymentManager = new helmDeploymentManager_1.HelmDeploymentManager(this.session, release);
const deployment = deploymentManager.findDeployment(args.revision);
// Output the state with format
await this.session.outFormat(deployment.resources);
}
catch (e) {
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
this.session.abort({ message: `ERROR: Release '${args.release}' does not exist` });
}
this.session.abort({ error: e });
}
}
}
exports.HelmGetManifest = HelmGetManifest;
class HelmGetValues extends command_1.Command {
constructor() {
super(...arguments);
this.command = 'values <release>';
this.describe = 'Download the values file for a named release';
}
builder(yargs) {
return (0, functions_1.pipe)(
//
withSingleRelease, withHelmGetValuesOptions, withHelmGetOptions, options_1.withOrgOptions, options_1.withStandardOptions)(yargs);
}
async handle(args) {
var _a;
const helm = new helm_1.Helm(this.client, this.session, args, this.ensureDeletion);
try {
// Attempt to fetch state
const state = await helm.fetchState();
// Get release
const release = await helm.getRelease(state);
// Figure out deployment
const deploymentManager = new helmDeploymentManager_1.HelmDeploymentManager(this.session, release);
const deployment = deploymentManager.findDeployment(args.revision);
let config = {};
// Handle all
if (args.all) {
config = { ...deployment.values };
}
// Handle existing config
config = {
...config,
...deployment.config,
};
// Output the state with format
await this.session.outFormat(config);
}
catch (e) {
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
this.session.abort({ message: `ERROR: Release '${args.release}' does not exist` });
}
this.session.abort({ error: e });
}
}
}
exports.HelmGetValues = HelmGetValues;
//# sourceMappingURL=helm.js.map