@controlplane/cli
Version:
Control Plane Corporation CLI
264 lines • 9.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Spy = exports.Command = void 0;
const client_1 = require("../session/client");
const session_1 = require("../session/session");
const logger_1 = require("../util/logger");
const resolver_1 = require("../commands/resolver");
const resultFetcher_1 = require("../rest/resultFetcher");
const functions_1 = require("../util/functions");
class Command {
with(opts) {
this.formatHints = opts.formatHints;
this.prepare = opts.prepare;
return this;
}
toYargs() {
const interceptingHandler = async (args) => {
if (!args._env) {
// used only for parsing, not execution
return;
}
// set up the "this"
this.env = args._env;
// session is a lazy property of the command
let session;
Object.defineProperty(this, 'session', {
enumerable: true,
get: () => {
if (!session) {
session = (0, session_1.newDefaultSession)(args._env, args);
}
if (this.formatHints) {
session.format._hints = this.formatHints;
}
return session;
},
});
let client;
Object.defineProperty(this, 'client', {
enumerable: true,
get: () => {
if (!client) {
client = (0, client_1.makeSessionClient)(this.session);
}
return client;
},
});
// if terminal, turn off coloring no matter what
if (this.env.out === process.stdout && !process.stdout.isTTY) {
args.color = false;
}
if (this.env.err === process.stderr && !process.stderr.isTTY) {
args.color = false;
}
if (this.prepare) {
await this.prepare.call(this);
}
return this.handle(args);
};
const interceptingBuilder = (yargs) => {
if (!this.describe || !yargs['_command_stack']) {
// hidden command or yargs is not spying
// just group options under a "Command options:" group
const origMethod = yargs.options;
yargs.options = function (opts, ...more) {
if (typeof opts === 'string') {
//@ts-ignore
return origMethod(opts, ...more);
}
const overridable = [];
for (let prop in opts) {
const item = opts[prop];
if (!item.group) {
item.group = 'Command options:';
}
if (!item.multiple) {
overridable.push(prop);
}
}
if (overridable.length > 0) {
pickLast(...overridable)(yargs);
}
//@ts-ignore
return origMethod(opts, ...more);
};
return this.builder(yargs);
}
const stack = yargs['_command_stack'];
const cm = {
name: guessName(this.command),
description: this.describe,
options: [],
commands: [
{
name: 'help',
description: 'Show help',
},
],
positional: [],
};
stack.push(cm);
const spy = new Spy(yargs, cm);
spy.start();
const res = this.builder(yargs);
spy.restore();
return res;
};
return {
command: this.command,
aliases: this.aliases,
describe: this.describe,
deprecated: this.deprecated,
builder: interceptingBuilder.bind(this),
handler: interceptingHandler.bind(this),
};
}
async ensureDeletion(link, maxRetries = 10) {
logger_1.logger.debug(`Ensuring the deletion of ${link}`);
await (0, functions_1.retryFn)(async () => {
var _a;
try {
await this.client.get(link);
throw new Error('Object is found');
}
catch (e) {
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) == 404) {
logger_1.logger.debug(`Resource ${link} has been deleted and NO longer exists!`);
return;
}
throw e;
}
}, {
onFailure() {
logger_1.logger.debug(`Timed out, the resource ${link} still exists.`);
},
intervalSec: 0.5,
repeatTimes: maxRetries,
});
}
async listAndDelete(kind, context) {
const resolver = (0, resolver_1.kindResolver)(kind);
const resourceLinks = [];
// Getting all items of kind in gvc
const listLink = resolver.parentLink(context);
const listRes = await this.client.get(listLink);
// Fetch all items
await (0, resultFetcher_1.fetchPages)(this.client, -1, listRes);
// Deleting each item
for (const item of listRes.items) {
const selfLink = resolver.resourceLink(item.name, context);
await this.client.axios.delete(selfLink);
this.session.out(`Deleted ${item.kind} '${item.name}'`);
resourceLinks.push(selfLink);
}
// Ensure the deletion of these kinds of resources
if (kind == 'volumeset' || kind == 'workload') {
await Promise.all(resourceLinks.map((link) => this.ensureDeletion(link)));
}
}
requireOrg() {
if (!this.session.context.org) {
this.session.abort({ message: 'ERROR: An organization is required. Please, specify one using the --org option.' });
}
}
}
exports.Command = Command;
function guessName(s) {
var _a;
return (_a = s.split(' ')[0]) !== null && _a !== void 0 ? _a : s;
}
function toString(obj) {
if (!obj) {
return undefined;
}
return '' + obj;
}
function toArray(obj) {
if (typeof obj === 'string') {
return [obj];
}
if (Array.isArray(obj)) {
return obj;
}
return undefined;
}
class Spy {
constructor(yargs, model) {
this.yargs = yargs;
this.model = model;
this.methods = {};
}
start() {
const command = (this.methods.command = this.yargs.command);
const positional = (this.methods.positional = this.yargs.positional);
const options = (this.methods.options = this.yargs.options);
const that = this;
// collect subcommands
// @ts-ignore
this.yargs.command = function (mod) {
if (mod.describe) {
// only record described/public command
that.model.commands.push({
name: guessName(mod.command),
description: mod.describe,
});
}
return command(mod);
};
// collect positional args
// @ts-ignore
this.yargs.positional = function (name, opts) {
that.model.positional.push({
name: name,
description: opts.describe,
});
return positional(name, opts);
};
// @ts-ignore
this.yargs.options = function (opts, ...more) {
if (typeof opts === 'string') {
// the original options method calls itself multiple times if not invoked with an object
// @ts-ignore
return options(opts, ...more);
}
//console.log('xx=' ,Object.getOwnPropertyNames(opts))
for (let prop in opts) {
const item = opts[prop];
that.model.options.push({
name: prop,
alias: toArray(item.alias),
choices: item.choices,
description: item.description,
default: toString(item.default),
boolean: item.boolean,
completions: item.completions,
paths: item.paths,
});
}
return options(opts);
};
}
restore() {
this.yargs.command = this.methods.command;
this.yargs.positional = this.methods.positional;
this.yargs.options = this.methods.options;
}
}
exports.Spy = Spy;
function pickLast(...opts) {
return (yargs) => {
yargs.check((argv) => {
for (let opt of opts) {
let value = argv[opt];
if (value && Array.isArray(value)) {
value = value[value.length - 1];
argv[opt] = value;
}
}
return true;
});
return yargs;
};
}
//# sourceMappingURL=command.js.map