| Server IP : 34.87.99.72 / Your IP : 216.73.217.31 Web Server : Apache/2.4.46 (Unix) OpenSSL/1.1.1n System : Linux zlock-bitnami-lamp-prod-v2-vm 4.19.0-16-cloud-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 User : bitnami ( 1000) PHP Version : 7.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /opt/bitnami/nami/node_modules/provisioner/lib/ |
Upload File : |
"use strict";
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 });
const provisioner_1 = require("./provisioner");
const utils_1 = require("./utils");
const nami_wrapper_1 = require("./nami_wrapper");
const cmd_parser_1 = require("cmd-parser");
const util = require("util");
const reset_cmd_1 = require("./reset_cmd");
class CLI {
/**
* Create CLI instance
* @param argv List of arguments, usually `process.argv`
*/
constructor(argv) {
this.argv = argv;
this._initializeNami();
this._initializeParser();
}
/**
* Instance of logger
*/
get logger() {
return this.provisioner.logger;
}
/**
* Handle CLI invocation
*/
handle() {
try {
this.parser.parse(this.argv);
}
catch (e) {
// we may not have logger here, so log to stderr
process.stderr.write(`Unknown error: ${e.message}\n\n`);
throw e;
}
}
/**
* Handler for unpack CLI command
*/
unpackCommand(clean) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this._initializeOptionValues();
yield this.provisioner.unpackModules();
yield this.provisioner.unpackCustomFiles();
if (this.parser.getOption("perform-provisioning").getValue()) {
yield this.provisioner.provisionMachine();
}
if (clean) {
yield this.provisioner.unpackCleanup();
// don't need to cleanup during the unpack command
// in clouds without images
if (this.provisioner.cloud.cloudTags.indexOf("no-image") < 0) {
yield this.provisioner.cleanMachine();
}
}
this.generateUnpackSummary();
}
catch (e) {
this.logger.handleError("Unable to perform unpack operation", e);
}
});
}
generateUnpackSummary() {
const summaryModules = this.provisioner.tierDefinition.modules.map(m => ({ name: m.name, version: m.version }));
const summary = {
modules: summaryModules,
packages: this.provisioner.stackDefinition.systemPackagesDependencies
};
nami_wrapper_1.file.write(nami_wrapper_1.file.join(this.parser.getOptionValue("output-folder"), "unpack-summary.json"), JSON.stringify(summary));
}
/**
* Handler for provision CLI command
*/
provisionCommand(clean) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this._initializeOptionValues();
yield this.provisioner.provisionMachine();
if (clean) {
yield this.provisioner.cleanMachine();
}
}
catch (e) {
this.logger.handleError("Unable to perform provision operation", e);
}
});
}
/**
* Handler for initialize CLI command
* @param all whether to perform all operations - such as wait for ports
*/
initializeCommand(all) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this._initializeOptionValues();
if (all) {
yield this.provisioner.waitForRequiredPorts();
}
yield this.provisioner.initializeModules();
}
catch (e) {
this.logger.handleError("Unable to perform initialize operation", e);
}
});
}
/**
* Handler for install CLI command
* @param all whether to perform all operations - such as wait for ports
*/
installCommand(all) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this._initializeOptionValues();
yield this.provisioner.unpackModules();
yield this.provisioner.unpackCustomFiles();
if (all) {
yield this.provisioner.waitForRequiredPorts();
}
yield this.provisioner.initializeModules();
}
catch (e) {
this.logger.handleError("Unable to perform install operation", e);
}
});
}
/**
* Handler for firstboot CLI command
*/
firstbootCommand() {
return __awaiter(this, void 0, void 0, function* () {
const shouldPerformProvisioning = this.parser.getOption("perform-provisioning").getValue();
const shouldPerformReboot = this.parser.getOption("reboot").getValue();
// TODO: ensure this is only run once!
try {
yield this._initializeOptionValues();
yield this.provisioner.initializeCloudValues();
// Skip 1st Boot when customizing AMI
if (yield this.provisioner.cloud.isCustomizingMode()) {
this.logger.info("Skipping First Boot. Customizing Mode enabled!");
}
else if (shouldPerformProvisioning && shouldPerformReboot) {
yield this.provisioner.provisionMachine();
this.provisioner.platform.shutdown({ type: "reboot", delay: 30 });
}
else {
this.logger.debug("Setting random password");
yield this.provisioner.setRandomPasswordIfNotProvided();
if (shouldPerformProvisioning) {
this.logger.debug("Provisioning machine");
yield this.provisioner.provisionMachine();
}
this.logger.debug("Waiting for ports");
yield this.provisioner.waitForRequiredPorts();
this.logger.debug("First boot and wait");
yield this.provisioner.firstbootDelay();
this.logger.debug("Initializing modules");
yield this.provisioner.initializeModules();
if (shouldPerformReboot) {
yield this.provisioner.firstbootFinished(true);
this.provisioner.platform.shutdown({ type: "reboot", delay: 30 });
}
else if (!this.provisioner.provisioned) {
// to avoid issue with wrong system service state, start servicesCommand
// using the system service for provisioner
// But ONLY if we are not already provisioned: the new pipeline doesn't need this.
// And will call start explicitly after firstboot, avoiding restarting a systemd
// service within it start execution.
this.logger.info("Restarting service");
this.provisioner.platform.restartService(this.provisioner.provisionerServiceName);
yield this.provisioner.firstbootFinished(true);
}
else {
yield this.provisioner.firstbootFinished(true);
}
}
}
catch (e) {
yield this.provisioner.firstbootFinished(false);
this.logger.handleError("Unable to initialize instance", e);
}
});
}
/**
* Handler for stop, start and status CLI commands
*/
servicesCommand(cmd, reverse) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this._initializeOptionValues();
yield this.provisioner.serviceCommand(cmd);
}
catch (e) {
this.logger.handleError(`Unable to perform ${cmd} operation`, e);
throw e;
}
});
}
_initializeOptionValues() {
return __awaiter(this, void 0, void 0, function* () {
const optionMap = {
cloudName: "cloud-name",
cloudAccountId: "cloud-account-id",
storageAccountName: "storage-account-name",
storageAccountKey: "storage-account-key",
platformName: "platform-name",
instanceTier: "instance-tier",
instanceData: "instance-tier-data",
peerAddress: "peer-address",
_peerPort: "peer-port",
peerUsername: "peer-username",
peerConnectionOptions: "peer-connection-options",
publicEndpoint: "public-endpoint",
appUsername: "app-username",
appPassword: "app-password",
appDatabase: "app-database",
appRepository: "app-repository",
clusterName: "cluster-name",
clusterQuorum: "cluster-quorum",
persistentNode: "persistent-node",
booleanInput: "boolean-input",
configOverrides: "config-overrides",
snitch: "snitch",
resolveNames: "resolve-names",
recipesPath: "recipes-path",
provisioned: "provisioned"
};
this.provisioner.initializeLogger({
logLevel: this.parser.getOption("log-level").getValue()
});
for (let key of Object.keys(optionMap)) {
let optionName = optionMap[key];
if (this.parser.getOption(optionName).provided) {
this.provisioner[key] = this.parser.getOption(optionName).getValue();
}
}
if (this.parser.getOption("instance-tier-map").provided) {
this.provisioner.setInstanceTierFromQuery(this.parser.getOption("instance-tier-map").getValue());
}
// initialize peer password if provided
if (this.parser.getOption("peer-password").provided &&
(this.parser.getOption("peer-password").getValue() !== "")) {
yield this.provisioner.setPeerPassword({
value: this.parser.getOption("peer-password").getValue()
});
}
else if (this.parser.getOption("peer-password-input").provided) {
yield this.provisioner.setPeerPassword({
input: this.parser.getOption("peer-password-input").getValue()
});
}
// set unique id from either unique id input or from peer password input
if (this.parser.getOption("shared-unique-id-input").provided) {
this.provisioner.setSharedUniqueId({
input: this.parser.getOption("shared-unique-id-input").getValue()
});
}
else if (this.parser.getOption("peer-password-input").provided) {
this.provisioner.setSharedUniqueId({
input: this.parser.getOption("peer-password-input").getValue()
});
}
// Initialize extraServices if provided
if (this.parser.getOption("extra-services").provided) {
this.provisioner.setExtraServicesFromRaw(this.parser.getOption("extra-services").getValue());
}
this.provisioner.skipRecipes = this._getOptionAsArray("skip-recipes");
this.provisioner.onlyRecipes = this._getOptionAsArray("only-recipes");
if (this.parser.getOption("definition-file").provided) {
yield this.provisioner.loadDefinition(this.parser.getOption("definition-file").getValue());
}
else if (this.parser.getOption("definition-url").provided) {
yield this.provisioner.downloadDefinition(this.parser.getOption("definition-url").getValue());
}
if (this.parser.getOption("peer-nodes-prefix").provided) {
this.provisioner.peerNodes.prefix = this.parser.getOption("peer-nodes-prefix").value;
}
if (this.parser.getOption("peer-nodes-from").provided) {
this.provisioner.peerNodes.startIndex = parseInt(this.parser.getOption("peer-nodes-from").value);
}
if (this.parser.getOption("peer-nodes-count").provided) {
this.provisioner.peerNodes.count = parseInt(this.parser.getOption("peer-nodes-count").value);
}
if (this.parser.getOption("peer-nodes-index").provided) {
this.provisioner.peerNodes.index = parseInt(this.parser.getOption("peer-nodes-index").value);
}
if (this.parser.getOption("peer-nodes-addresses").provided) {
this.provisioner.peerAddresses = this._getOptionAsArray("peer-nodes-addresses");
}
if (this.parser.getOption("internal-addresses").provided) {
this.provisioner.internalAddresses = this._getOptionAsArray("internal-addresses");
}
if (this.parser.getOption("options-file").provided) {
this.provisioner.options.initializeFromFile(this.parser.getOption("options-file").getValue());
}
if (this.parser.getOption("modules-temp-dir").provided) {
this.provisioner.modulesTempDir = this.parser.getOption("modules-temp-dir").value;
}
this.provisioner.saveConfiguration();
// pass function so data is not referenced until actually logging debug info
this.logger.debug("Initialized options", () => {
return {
cloudName: this.provisioner.cloudName,
instanceTier: this.provisioner.instanceTier,
instanceData: this.provisioner.instanceData,
peerAddress: this.provisioner.peerAddress,
peerPort: this.provisioner.peerPort,
peerUsername: this.provisioner.peerUsername,
peerConnectionOptions: this.provisioner.peerConnectionOptions,
publicEndpoint: this.provisioner.publicEndpoint,
extraServices: this.provisioner.extraServices,
appUsername: this.provisioner.appUsername,
appPassword: this.provisioner.appPassword,
appDatabase: this.provisioner.appDatabase,
appRepository: this.provisioner.appRepository,
clusterName: this.provisioner.clusterName,
clusterQuorum: this.provisioner.clusterQuorum,
persistentNode: this.provisioner.persistentNode,
booleanInput: this.provisioner.booleanInput,
configOverrides: this.provisioner.configOverrides,
snitch: this.provisioner.snitch,
peerNodes: this.provisioner.peerNodes,
storageAccountName: this.provisioner.storageAccountName
};
});
yield this.provisioner.initializeProvisioner();
});
}
/**
* Handler for eval CLI command
* @param opts Options passed from `Parser` ; used to get command to run
*/
evalCommand(opts) {
return __awaiter(this, void 0, void 0, function* () {
try {
// TODO: is there any better way to extract this?
let code = opts.container._argv[opts.container._argv.length - 1];
let result;
yield this._initializeOptionValues();
result = this.provisioner.evalInContext(code);
if (result && (result instanceof Promise)) {
result = yield result;
}
if (result) {
console.log(util.inspect(result));
}
}
catch (e) {
console.log(e.message + "\n" + (e.stack || ""));
throw e;
}
});
}
/**
* Handler for callRecipes CLI command
* @param opts Options passed from `Parser` ; used to get event name to run
*/
callRecipesCommand(opts) {
return __awaiter(this, void 0, void 0, function* () {
try {
// TODO: is there any better way to extract this?
let event = opts.container._argv[opts.container._argv.length - 1];
let result;
yield this._initializeOptionValues();
yield this.provisioner.callRecipes(event, { errorOnFail: true });
}
catch (e) {
console.log(e.message + "\n" + (e.stack || ""));
throw e;
}
// context.runInContext(new vm.Script(code));
});
}
/**
*
*/
retrieveSharedPasswordCommand(opts) {
return __awaiter(this, void 0, void 0, function* () {
yield this._initializeOptionValues();
if (!(this.provisioner.peerPassword && this.provisioner.peerPassword !== "")) {
console.log("Currently there is no password stored in the system.");
console.log("Either it was set manually or has already been retrieved.");
process.exit(1);
}
try {
if (true) {
let verifyAnswer = (yield utils_1.askQuestion("WARNING! This will show the password only once and delete it from the system.\n" +
"Do you want to continue", { type: "boolean" }));
if (!verifyAnswer) {
process.exit(1);
}
}
console.log(`\nThe password is:\n\n${this.provisioner.peerPassword}\n`);
console.log("Please make sure that you have stored the password as it's removed from system");
this.provisioner.removePeerPassword();
}
catch (e) {
this.logger.handleError(`Unable to retrieve peer password`, e);
process.exit(1);
}
});
}
_initializeNami() {
this.provisioner = new provisioner_1.Provisioner();
this.provisioner.loadConfiguration();
}
_initializeParser() {
this.parser = new cmd_parser_1.Parser({
toolName: "provisioner",
throwOnExit: true,
allowProcessExit: false
});
this.parser.addOptions([
{ name: "log-level", type: "string", defaultValue: "info" },
{ name: "cloud-name", type: "string", defaultValue: this.provisioner.cloudName },
{ name: "platform-name", type: "string", defaultValue: this.provisioner.platformName },
{ name: "definition-url", type: "string", defaultValue: "" },
{ name: "definition-file", type: "string", defaultValue: "" },
{ name: "instance-tier", type: "string", defaultValue: this.provisioner.instanceTier },
{ name: "instance-tier-map", type: "string", defaultValue: "" },
{ name: "instance-tier-data", type: "string", defaultValue: "" },
{ name: "peer-nodes-prefix", type: "string", defaultValue: "" },
{ name: "peer-nodes-count", type: "integer", defaultValue: 0 },
{ name: "peer-nodes-index", type: "integer", defaultValue: 0 },
{ name: "peer-nodes-from", type: "integer", defaultValue: 0 },
{ name: "peer-nodes-addresses", type: "string", defaultValue: "" },
{ name: "internal-addresses", type: "string", defaultValue: "" },
{ name: "peer-password-input", type: "string", defaultValue: "" },
{ name: "shared-unique-id-input", type: "string", defaultValue: "" },
{ name: "peer-username", type: "string", defaultValue: "" },
{ name: "peer-password", type: "string", defaultValue: "Bitnami1" },
{ name: "peer-address", type: "string", defaultValue: "" },
{ name: "peer-port", type: "integer", defaultValue: 0 },
{ name: "peer-connection-options", type: "string", defaultValue: "" },
{
name: "extra-services",
description: "base64 encoded JSON string containing information about extra services to pass to provisioner",
type: "string",
secret: true,
defaultValue: ""
},
{ name: "public-endpoint", type: "string", defaultValue: "" },
{ name: "app-username", type: "string", defaultValue: "" },
{ name: "app-password", type: "string", defaultValue: "" },
{ name: "app-database", type: "string", defaultValue: "" },
{ name: "app-repository", type: "string", defaultValue: "" },
{ name: "cluster-name", type: "string", defaultValue: "" },
{ name: "cluster-quorum", type: "string", defaultValue: "" },
{ name: "persistent-node", type: "string", defaultValue: "" },
{ name: "boolean-input", type: "string", defaultValue: "no" },
{ name: "config-overrides", type: "string", defaultValue: "# No overrides" },
{ name: "snitch", type: "string", defaultValue: "" },
{ name: "resolve-names", type: "boolean", defaultValue: false },
{ name: "perform-provisioning", type: "boolean", defaultValue: false },
{ name: "reboot", type: "boolean", defaultValue: false },
{ name: "recipes-path", type: "string", secret: true, defaultValue: "" },
{ name: "skip-recipes", type: "string", secret: true, defaultValue: "" },
{ name: "only-recipes", type: "string", secret: true, defaultValue: "" },
{ name: "cloud-account-id", type: "string", secret: true, defaultValue: "" },
{ name: "storage-account-name", type: "string", secret: true, defaultValue: "" },
{ name: "storage-account-key", type: "string", secret: true, defaultValue: "" },
{ name: "options-file", type: "string", secret: true, defaultValue: "" },
{ name: "modules-temp-dir", type: "string", secret: true, defaultValue: "" },
{
name: "provisioned",
description: "Only setup application files, \
skipping any other provisioning action \
including 'provision' recipes",
type: "boolean",
defaultValue: false
},
{
name: "output-folder",
description: "Output path wher generated assets should be stored (summaries)",
defaultValue: "output"
}
]);
this.parser.addCommand({ name: "unpack", callback: () => {
this.unpackCommand(false);
} });
this.parser.addCommand({ name: "unpackForTarball", secret: true, callback: () => {
this.unpackCommand(true);
} });
this.parser.addCommand({ name: "initialize", callback: () => {
this.initializeCommand(false);
} });
this.parser.addCommand({ name: "initializeAll", callback: () => {
this.initializeCommand(true);
} });
this.parser.addCommand({ name: "install", callback: () => {
this.installCommand();
} });
this.parser.addCommand({ name: "provision", callback: () => {
this.provisionCommand(false);
} });
this.parser.addCommand({ name: "provisionForImage", secret: true, callback: () => {
this.provisionCommand(true);
} });
this.parser.addCommand({ name: "firstboot", callback: () => {
this.firstbootCommand();
} });
this.parser.addCommand({ name: "start", callback: () => {
this.servicesCommand("start", false);
} });
this.parser.addCommand({ name: "stop", callback: () => {
this.servicesCommand("stop", true);
} });
this.parser.addCommand({ name: "status", callback: () => {
this.servicesCommand("status", false);
} });
this.parser.addCommand({
name: "eval", secret: true, minArgs: 1, maxArgs: 1, callback: (opts) => {
this.evalCommand(opts);
}
});
this.parser.addCommand({
name: "callRecipes", secret: true, minArgs: 1, maxArgs: 1,
callback: (opts) => {
this.callRecipesCommand(opts).catch(err => { process.exit(1); });
}
});
this.parser.addCommand({
name: "retrieveSharedPassword",
callback: (opts) => {
this.retrieveSharedPasswordCommand(opts);
}
});
this.parser.addCommand({
name: "reset",
secret: true,
callback: () => new reset_cmd_1.ResetProvisioner(this).mainCommand(),
description: "Resets a provisioner deployment substituting it by a new one.\n\n" +
"Subcommands:\n" +
" clean: Stops, removes and creates a backup of the installed files.\n" +
" download: Downloads a provisioner bundle.\n" +
" extract: Extracts the latest downloaded provisioner bundle.\n" +
" bootstrap: Performs the Provisioner installation (firstboot).\n" +
" restore: Restores the last backup overriding existing files.\n" +
"\nIf no subcommand is provided, all of them are executed in sequence.",
minArgs: 0,
maxArgs: 1,
namedArgs: ["subcommand"],
}, [
{
name: "provisioner-bundle-url",
type: "string",
description: "The URL of a provisioner bundle to download and extract."
},
]);
}
_getOptionAsArray(optionName) {
const values = this.parser.getOption(optionName).getValue() || "";
if (values === "") {
return null;
}
return values.split(/[,;:\s]/).map(value => { return value.trim(); }).filter(value => {
return true;
});
}
}
exports.CLI = CLI;