UNPKG

navy

Version:

Quick and powerful development environments using Docker and Docker Compose

230 lines (221 loc) 15.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _commander = require("commander"); var _chalk = _interopRequireDefault(require("chalk")); var _errors = require("../errors"); var _config = require("../config"); var _driverLogging = require("../driver-logging"); var _configProvider = require("../config-provider"); var _mergeActionOptions = require("./util/merge-action-options"); const loadingLabelMap = { destroy: 'Destroying services...', start: 'Starting services...', stop: 'Stopping services...', restart: 'Restarting services...', kill: 'Killing services...', rm: 'Removing services...', update: 'Updating service images...', delete: 'Deleting navy configuration...', useTag: 'Pulling custom tag...', resetTag: 'Resetting to default tag...', usePort: 'Setting up port mapping...', resetPort: 'Resetting port mapping...' }; function removeFirstLineFromStackTrace(stack) { return stack?.split('\n')?.slice(1)?.join('\n'); } function normaliseLazyRequireArgs(args) { if (args.length === 0) return args; const last = args[args.length - 1]; if (!last || typeof last.optsWithGlobals !== 'function') { return args; } const command = last; const rest = args.slice(0, -1); if (rest.length === 0) { return rest; } const lastOpt = rest[rest.length - 1]; if (lastOpt && typeof lastOpt === 'object' && !Array.isArray(lastOpt)) { return [...rest.slice(0, -1), (0, _mergeActionOptions.mergeActionOptions)(lastOpt, command)]; } return rest; } function wrapper(res) { if (res.catch) { res.catch(ex => { (0, _driverLogging.stopDriverLogging)({ success: false }); if (ex instanceof _errors.NavyError) { ex.prettyPrint(); } else if (ex.name === 'Invariant Violation') { console.log(); console.log(_chalk.default.bgRed(_chalk.default.bold(' ' + ex.name + ' '))); console.log(); console.log(' ' + ex.message.substring(ex.message.indexOf(': ') + 2)); console.log(); console.log(' ' + _chalk.default.blue('Run') + ' ' + _chalk.default.bold('navy doctor') + ' ' + _chalk.default.blue('to attempt troubleshooting')); console.log(); console.log(_chalk.default.dim(removeFirstLineFromStackTrace(ex.stack))); console.log(); } else { console.error(ex.stack); } process.exit(1); }); } return res; } function basicCliWrapper(fnName, wrapperOpts = {}) { const driverLogging = wrapperOpts.driverLogging == null ? true : wrapperOpts.driverLogging; return async function (maybeServices, ...args) { const { getNavy } = require('../navy'); // commander v12 invokes action handlers with a trailing Command instance // appended after the parsed options. Strip it and merge global options // (e.g. `navy -e dev start`) into the opts object. let command = null; if (args.length > 0) { const last = args[args.length - 1]; if (last && typeof last.optsWithGlobals === 'function') { command = last; args = args.slice(0, -1); } } let opts = args.length === 0 ? maybeServices : args[args.length - 1]; const otherArgs = args.slice(0, args.length - 1); if (command && opts && typeof opts === 'object' && !Array.isArray(opts)) { opts = (0, _mergeActionOptions.mergeActionOptions)(opts, command); } const envName = opts.navy; if (wrapperOpts.serviceBasedAlias && maybeServices.length) { console.log(`This command should not be called with a list of services. calling '${wrapperOpts.serviceBasedAlias}' instead`); fnName = wrapperOpts.serviceBasedAlias; maybeServices = maybeServices.split(' '); } process.on('unhandledRejection', ex => { (0, _driverLogging.stopDriverLogging)({ success: false }); if (ex instanceof _errors.NavyError) { ex.prettyPrint(); } else { console.error(ex.stack); } process.exit(); }); if (driverLogging) (0, _driverLogging.startDriverLogging)(loadingLabelMap[fnName]); const navy = getNavy(envName); await navy.ensurePluginsLoaded(); await navy.emitAsync(`cli.before.${fnName}`, fnName); const returnVal = await navy[fnName](Array.isArray(maybeServices) && maybeServices.length === 0 ? undefined : maybeServices, ...otherArgs); await navy.emitAsync(`cli.after.${fnName}`, fnName); if (driverLogging) (0, _driverLogging.stopDriverLogging)(); if (Array.isArray(returnVal)) { return console.log(returnVal.join('\n')); } if (returnVal != null) { console.log(returnVal); } }; } function lazyRequire(path) { return function (...args) { const mod = require(path); const normalised = normaliseLazyRequireArgs(args); return wrapper((mod.default || mod)(...normalised)); }; } const defaultNavy = process.env.NAVY_NAME || (0, _config.getConfig)().defaultNavy; // Strictly separate parent and subcommand options so an option that isn't // declared on a subcommand (e.g. `navy status -e foo`) is reported as // unknown rather than silently absorbed by the parent program. _commander.program.enablePositionalOptions(); _commander.program.option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy); const importCommand = _commander.program.command('import').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Imports docker compose configuration from the current working directory and initialises a new navy').action(lazyRequire('./import')); (0, _configProvider.getImportCommandLineOptions)().forEach(opt => importCommand.option(...opt)); _commander.program.command('launch [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Launches the given services in a navy').action(lazyRequire('./launch')).on('--help', () => console.log(` This will prompt you for the services that you want to bring up. You can optionally provide the names of services to bring up which will disable the interactive prompt. `)); _commander.program.command('destroy').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Destroys a navy and all related data and services').action(basicCliWrapper('destroy', { serviceBasedAlias: 'kill' })).on('--help', () => console.log(` This will destroy an entire navy and all of its data and services. Examples: $ navy destroy # destroy "${defaultNavy}" navy $ navy destroy -e dev # destroy "dev" navy $ navy destroy -e test # destroy "test" navy `)); _commander.program.command('delete').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Removes a navy configuration without removing any docker containers or services').action(basicCliWrapper('delete')); _commander.program.command('ps').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).option('--json', 'output JSON instead of a table').description('Lists the running services for a navy').action(lazyRequire('./ps')); _commander.program.command('start [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Starts the given services').action(basicCliWrapper('start')); _commander.program.command('stop [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Stops the given services').action(basicCliWrapper('stop')); _commander.program.command('restart [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Restarts the given services').action(basicCliWrapper('restart')); _commander.program.command('kill [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Kills the given services').action(basicCliWrapper('kill')); _commander.program.command('rm [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Removes the given services').action(basicCliWrapper('rm')); _commander.program.command('update [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Pulls the given services\' images from their respective registries and relaunches the services').action(basicCliWrapper('update')); _commander.program.command('updates').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Checks for updates for all the launched services').action(lazyRequire('./updates')); _commander.program.command('logs [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Streams logs for the given services').action(lazyRequire('./logs')); _commander.program.command('health').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Shows the health status for all of the launched services').action(lazyRequire('./health')); _commander.program.command('wait-for-healthy [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Waits for the given services to be healthy').action(lazyRequire('./wait-for-healthy')); _commander.program.command('use-tag <service> <tag>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Uses a specific tag for the given service').action(basicCliWrapper('useTag')); _commander.program.command('reset-tag <service>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Resets any tag override on the given service').action(basicCliWrapper('resetTag')); _commander.program.command('https [services...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).option('-d, --disable <service>', 'disable https (deletes cert) for a given service', null).option('-s, --setup', 'generate the Navy root CA (if needed) and install it in the system trust store').option('-a, --all', 'enable HTTPS for every service in this navy').option('-i, --issue <url>', 'issue a TLS certificate and key for a URL (non-Navy service), signed with the Navy root CA').option('-o, --issue-out <dir>', 'output directory for --issue (default: current working directory)').description('Prints or enables HTTPS services').action(lazyRequire('./https')).on('--help', () => console.log(` Examples: List urls of services that listen on https: $ navy https Enable https for mywebservice and anotherwebservice services $ navy https mywebservice anotherwebservice Enable https for all services $ navy https --all Disable https for mywebservice $ navy https -d mywebservice Generate the Navy root CA and install it for this user (no service names) $ navy https --setup Issue a cert for an external host (writes leaf key/cert + navy-root-ca.crt) $ navy https --issue https://api.example.test $ navy https --issue https://api.example.test -o ./tls `)); _commander.program.command('use-port <service> <internal> <external>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Uses a specific external port for the given service and internal port').action(basicCliWrapper('usePort')); _commander.program.command('reset-port <service> <internal>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Resets a specific external port mapping set by use-port').action(basicCliWrapper('resetPort')); _commander.program.command('url <service>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Prints the external URL for the given service if it is a web service').action(basicCliWrapper('url', { driverLogging: false })).on('--help', () => console.log(` Examples: $ navy url mywebserver http://mywebserver.dev.127.0.0.1.nip.io `)); _commander.program.command('open <service>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Opens the given service in the default web browser, if the service is configured with a URL').action(lazyRequire('./open')).on('--help', () => console.log(` Examples: $ navy open mywebserver Opening mywebserver... `)); _commander.program.command('port <service> <port>').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Prints the external port for the given internal port of the given service').action(basicCliWrapper('port', { driverLogging: false })).on('--help', () => console.log(` Examples: $ navy port mywebserver 80 35821 `)); _commander.program.command('available-services').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Prints the names of the services that are launched or can be launched').action(basicCliWrapper('getAvailableServiceNames', { driverLogging: false })); _commander.program.command('develop [service]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Puts the given service into development using the current working directory').action(lazyRequire('./develop')); _commander.program.command('live [service]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Takes the given service out of development').action(lazyRequire('./live')); _commander.program.command('run <name> [args...]').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Runs a named command specific to the given Navy').action(lazyRequire('./run')); _commander.program.command('refresh-config').option('-e, --navy [env]', `set the navy name to be used [${defaultNavy}]`, defaultNavy).description('Refreshes the configuration for the given Navy').action(lazyRequire('./refresh-config')); _commander.program.command('status').option('--json', 'output JSON instead of a table').description('List all of the imported navies').action(lazyRequire('./status')); _commander.program.command('doctor').description('Identifies and tries to fix some common issues which might cause Navy to stop working').action(lazyRequire('./doctor')); _commander.program.command('config').description('Modify and get Navy global config - run `navy config` for help').action(lazyRequire('./config/wrapper')); _commander.program.command('external-ip').description('Prints the external IP which services are accessible on').action(lazyRequire('./external-ip')); _commander.program.command('use-lan-ip').description('Use your LAN ip address for connecting to Navy services').action(lazyRequire('./lan-ip')); _commander.program.command('use-local-ip').description('Use your local ip address (127.0.0.1) for connecting to Navy services').action(lazyRequire('./local-ip')); var _default = exports.default = _commander.program; module.exports = exports.default;