diff --git a/fullstack-network-manager/fsnetman.mjs b/fullstack-network-manager/fsnetman.mjs index 2846af3ff..98c1e061a 100755 --- a/fullstack-network-manager/fsnetman.mjs +++ b/fullstack-network-manager/fsnetman.mjs @@ -1,12 +1,4 @@ #!/usr/bin/env node import * as fnm from './src/index.mjs' -// Check the value of the DEV_MODE environment variable, ignoring case -const devMode = process.env.DEV_MODE ? process.env.DEV_MODE.toLowerCase() === 'true' : false - -// Disable stack traces if DEV_MODE is false -if (!devMode) { - Error.stackTraceLimit = 0 -} - fnm.main(process.argv) diff --git a/fullstack-network-manager/src/commands/flags.mjs b/fullstack-network-manager/src/commands/flags.mjs index ca30f1a38..a5b6aeea8 100644 --- a/fullstack-network-manager/src/commands/flags.mjs +++ b/fullstack-network-manager/src/commands/flags.mjs @@ -13,6 +13,15 @@ export function setCommandFlags (y, ...commandFlags) { }) } +export const devMode = { + name: 'dev', + definition: { + describe: 'Enable developer mode', + default: false, + type: 'boolean' + } +} + // list of common flags across commands. command specific flags are defined in the command's module. export const clusterName = { name: 'cluster-name', @@ -249,6 +258,7 @@ export const acmeClusterIssuer = { } export const allFlags = [ + devMode, clusterName, namespace, deployMirrorNode, diff --git a/fullstack-network-manager/src/commands/index.mjs b/fullstack-network-manager/src/commands/index.mjs index fa96ee0fb..d3fa43108 100644 --- a/fullstack-network-manager/src/commands/index.mjs +++ b/fullstack-network-manager/src/commands/index.mjs @@ -3,6 +3,7 @@ import { InitCommand } from './init.mjs' import { ChartCommand } from './chart.mjs' import { NodeCommand } from './node.mjs' import { RelayCommand } from './relay.mjs' +import * as flags from './flags.mjs' /* * Return a list of Yargs command builder to be exposed through CLI @@ -25,4 +26,4 @@ function Initialize (opts) { } // Expose components from the command module -export { Initialize } +export { Initialize, flags } diff --git a/fullstack-network-manager/src/commands/node.mjs b/fullstack-network-manager/src/commands/node.mjs index d32f002e6..ceb5b66c2 100644 --- a/fullstack-network-manager/src/commands/node.mjs +++ b/fullstack-network-manager/src/commands/node.mjs @@ -118,8 +118,14 @@ export class NodeCommand extends BaseCommand { { title: 'Initialize', task: async (ctx, task) => { + const cachedConfig = await self.configManager.setupConfig(argv) + const namespace = self.configManager.flagValue(cachedConfig, flags.namespace) + + // get existing choices + const namespaces = await self.kubectl.getNamespace('--no-headers', '-o name') + const config = { - namespace: await prompts.promptNamespaceArg(task, argv.namespace), + namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces), nodeIds: await prompts.promptNodeIdsArg(task, argv.nodeIds), releaseTag: await prompts.promptReleaseTag(task, argv.releaseTag), cacheDir: await prompts.promptCacheDir(task, argv.cacheDir), @@ -209,8 +215,14 @@ export class NodeCommand extends BaseCommand { { title: 'Initialize', task: async (ctx, task) => { + const cachedConfig = await self.configManager.setupConfig(argv) + const namespace = self.configManager.flagValue(cachedConfig, flags.namespace) + + // get existing choices + const namespaces = await self.kubectl.getNamespace('--no-headers', '-o name') + ctx.config = { - namespace: await prompts.promptNamespaceArg(task, argv.namespace), + namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces), nodeIds: await prompts.promptNodeIdsArg(task, argv.nodeIds) } } @@ -282,8 +294,14 @@ export class NodeCommand extends BaseCommand { { title: 'Initialize', task: async (ctx, task) => { + const cachedConfig = await self.configManager.setupConfig(argv) + const namespace = self.configManager.flagValue(cachedConfig, flags.namespace) + + // get existing choices + const namespaces = await self.kubectl.getNamespace('--no-headers', '-o name') + ctx.config = { - namespace: await prompts.promptNamespaceArg(task, argv.namespace), + namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces), nodeIds: await prompts.promptNodeIdsArg(task, argv.nodeIds) } } diff --git a/fullstack-network-manager/src/core/config_manager.mjs b/fullstack-network-manager/src/core/config_manager.mjs index e74b53872..29517a040 100644 --- a/fullstack-network-manager/src/core/config_manager.mjs +++ b/fullstack-network-manager/src/core/config_manager.mjs @@ -106,6 +106,9 @@ export class ConfigManager { config = JSON.parse(configJSON.toString()) } + this.logger.debug('Setup cached config', { cachedConfig: config }) + + this.logger.setDevMode(this.flagValue(config, flags.devMode)) return config } catch (e) { throw new FullstackTestingError(`failed to load config: ${e.message}`, e) diff --git a/fullstack-network-manager/src/core/logging.mjs b/fullstack-network-manager/src/core/logging.mjs index fbb73dfda..6869acc0e 100644 --- a/fullstack-network-manager/src/core/logging.mjs +++ b/fullstack-network-manager/src/core/logging.mjs @@ -41,20 +41,11 @@ export const Logger = class { /** * Create a new logger * @param level logging level as supported by winston library: - * { - * emerg: 0, - * alert: 1, - * crit: 2, - * error: 3, - * warning: 4, - * notice: 5, - * info: 6, - * debug: 7 - * } * @constructor */ - constructor (level) { + constructor (level = 'debug') { this.nextTraceId() + this.devMode = false this.winstonLogger = winston.createLogger({ level, @@ -76,6 +67,15 @@ export const Logger = class { }) } + setDevMode (devMode) { + this.debug(`setting dev mode: ${devMode}`) + this.devMode = devMode + } + + setLevel (level) { + this.winstonLogger.setLevel(level) + } + nextTraceId () { this.traceId = uuidv4() } @@ -94,24 +94,25 @@ export const Logger = class { } showUserError (err) { - this.error(err.message, err) - - console.log(chalk.red('ERROR: ')) - console.log(err.stack) - + const stack = [{ message: err.message, stacktrace: err.stack }] if (err.cause) { let depth = 0 let cause = err.cause while (cause !== undefined && depth < 10) { if (cause.stack) { - console.log(chalk.red('Caused by:')) - console.log(cause.stack) + stack.push({ message: cause.message, stacktrace: cause.stack }) } cause = cause.cause depth += 1 } } + + if (this.devMode) { + console.log(stack) + } + + this.error(err.message, { error: err.message, stacktrace: stack }) } error (msg, ...args) { diff --git a/fullstack-network-manager/src/core/shell_runner.mjs b/fullstack-network-manager/src/core/shell_runner.mjs index dab5276fd..a8ace9bd3 100644 --- a/fullstack-network-manager/src/core/shell_runner.mjs +++ b/fullstack-network-manager/src/core/shell_runner.mjs @@ -54,10 +54,23 @@ export class ShellRunner { errOutput.forEach(m => self.logger.showUser(chalk.red(m))) } + self.logger.error(`Error executing: '${cmd}'`, { + commandExitCode: code, + commandExitSignal: signal, + commandOutput: output, + errOutput, + error: { message: err.message, stack: err.stack } + }) + reject(err) } - self.logger.debug(`Finished executing: '${cmd}'`, { commandExitCode: code, commandExitSignal: signal, commandOutput: output }) + self.logger.debug(`Finished executing: '${cmd}'`, { + commandExitCode: code, + commandExitSignal: signal, + commandOutput: output, + errOutput + }) resolve(output) }) }) diff --git a/fullstack-network-manager/src/index.mjs b/fullstack-network-manager/src/index.mjs index f306c9e63..a66e302eb 100644 --- a/fullstack-network-manager/src/index.mjs +++ b/fullstack-network-manager/src/index.mjs @@ -1,12 +1,13 @@ import yargs from 'yargs' import { hideBin } from 'yargs/helpers' +import { flags } from './commands/index.mjs' import * as commands from './commands/index.mjs' import * as core from './core/index.mjs' import { ChartManager, ConfigManager, DependencyManager } from './core/index.mjs' import 'dotenv/config' export function main (argv) { - const logger = core.logging.NewLogger('debug') + const logger = core.logging.NewLogger() const kind = new core.Kind(logger) const helm = new core.Helm(logger) const kubectl = new core.Kubectl(logger) @@ -36,6 +37,7 @@ export function main (argv) { .alias('v', 'version') .command(commands.Initialize(opts)) .strict() + .option(flags.devMode.name, flags.devMode.definition) .wrap(120) .demand(1, 'Select a command') .parse()