From c8bf023bcb7fa1d4a10b5bd60b5cc757471144ba Mon Sep 17 00:00:00 2001 From: zodern Date: Wed, 12 Apr 2017 21:11:17 -0500 Subject: [PATCH 1/2] Experimental docker build --- src/modules/meteor/assets/templates/start.sh | 28 +++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/modules/meteor/assets/templates/start.sh b/src/modules/meteor/assets/templates/start.sh index c7835a00..e2c72bb6 100644 --- a/src/modules/meteor/assets/templates/start.sh +++ b/src/modules/meteor/assets/templates/start.sh @@ -36,11 +36,37 @@ docker network disconnect bridge -f $APPNAME-nginx-proxy echo "Removed $APPNAME-nginx-proxy" # We don't need to fail the deployment because of a docker hub downtime +<% if (docker.image === 'cache-build') { %> +rm -rf $APP_PATH/tmp/build +mkdir $APP_PATH/tmp/build +tar xzf $BUNDLE_PATH/bundle.tar.gz -C $APP_PATH/tmp/build +cd $APP_PATH/tmp/build + +cat < ./Dockerfile + FROM abernix/meteord:base +# RUN mkdir -p /bundle/programs/server +# WORKDIR /bundle/programs/server + #ADD bundle/programs/server/package.json ./package.json + #ADD bundle/programs/server/npm-shrinkwrap.json ./npm-shrinkwrap.json + #ADD bundle/programs/server/npm-rebuild.js ./npm-rebuild.js + #ADD bundle/programs/server/npm-rebuild-args.js ./npm-rebuild-args.js +# ADD bundle/programs/server ./ + WORKDIR /bundle + COPY . /bundle + WORKDIR /bundle/bundle/programs/server + RUN npm install --unsafe-perm + WORKDIR /bundle/bundle + ENTRYPOINT node main.js +EOF +docker build -t $APPNAME . +<% } else { %> set +e docker pull <%= docker.image %> set -e echo "Pulled <%= docker.image %>" +<% } %> + docker run \ -d \ --restart=always \ @@ -63,7 +89,7 @@ docker run \ -e "LETSENCRYPT_EMAIL=<%= sslConfig.autogenerate.email %>" \ <% } %> \ --name=$APPNAME \ - <%= docker.image %> + <%= docker.image === 'cache-build' ? '$APPNAME' : docker.image %> echo "Ran <%= docker.image %>" sleep 15s From 3bc5738f54378c04af5f88eb97f89cc064978b75 Mon Sep 17 00:00:00 2001 From: zodern Date: Wed, 12 Apr 2017 21:13:12 -0500 Subject: [PATCH 2/2] Revert "Merge branch 'plugins'" This reverts commit 2adf63d02a3d90f6d9f7cd98b06ef87cd0636eea. # Conflicts: # CHANGELOG.md --- .eslintrc.yml | 1 - CHANGELOG.md | 8 - package.json | 5 +- src/index.js | 246 +++++++++++++----------- src/modules/command-wrapper.js | 16 -- src/modules/default/commands.js | 60 ------ src/modules/default/index.js | 112 ++++++++++- src/modules/default/tasks.js | 109 ----------- src/modules/docker/commands.js | 16 -- src/modules/docker/index.js | 64 ++++++- src/modules/docker/tasks.js | 58 ------ src/modules/index.js | 12 +- src/modules/meteor/commands.js | 32 ---- src/modules/meteor/index.js | 321 +++++++++++++++++++++++++++++++- src/modules/meteor/tasks.js | 320 ------------------------------- src/modules/mongo/commands.js | 21 --- src/modules/mongo/index.js | 109 ++++++++++- src/modules/mongo/tasks.js | 106 ----------- src/mup-api.js | 27 +-- src/tasks.js | 21 --- 20 files changed, 750 insertions(+), 914 deletions(-) delete mode 100644 src/modules/command-wrapper.js delete mode 100644 src/modules/default/commands.js delete mode 100644 src/modules/default/tasks.js delete mode 100644 src/modules/docker/commands.js delete mode 100644 src/modules/docker/tasks.js delete mode 100644 src/modules/meteor/commands.js delete mode 100644 src/modules/meteor/tasks.js delete mode 100644 src/modules/mongo/commands.js delete mode 100644 src/modules/mongo/tasks.js delete mode 100644 src/tasks.js diff --git a/.eslintrc.yml b/.eslintrc.yml index 8ad0a5fd..9a3a63d3 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -239,7 +239,6 @@ rules: quotes: - 2 - single - - avoidEscape: true radix: 2 require-yield: 2 semi: diff --git a/CHANGELOG.md b/CHANGELOG.md index acd9b02b..74aebe26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,6 @@ -## Next -- All commands have a description and are listed in help -- All options are shown in help -- Remove `mup proxy` and `mup docker dump` commands which were placeholders. -- Remove `mup meteor push`. `mup meteor deploy` should be used instead. -- Remove `mup meteor envconfig`. `mup reconfig` should be used instead - ## 1.2.6 - Match 29, 20 - Fix `force-ssl` warning appearing when ssl is setup correctly - ## 1.2.5 - March 22, 2017 - Support changing docker exposed port @abernix - New `mup docker restart` command diff --git a/package.json b/package.json index 6a3a035f..f3d38fcf 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "prepublish": "npm run build -s", - "build": "babel src --out-dir lib --sourceRoot=./ --copy-files --source-maps --presets=es2015,es2016,es2017,stage-3", + "build": "babel src --out-dir lib --sourceRoot=./ --copy-files --presets=es2015,es2016,es2017,stage-3", "build:watch": "npm run build -s -- -w", "test": "bash ./tests/run.sh", "test:custom-server": "nofat test", @@ -61,7 +61,6 @@ "silent-npm-registry-client": "2.x.x", "ssh2": "0.4.x", "underscore": "1.x.x", - "uuid": "2.x.x", - "yargs": "^7.0.2" + "uuid": "2.x.x" } } diff --git a/src/index.js b/src/index.js index 91129f7d..1c2aedac 100644 --- a/src/index.js +++ b/src/index.js @@ -1,119 +1,157 @@ +import MupAPI from './mup-api'; import checkUpdates from './updates'; -import modules, { loadPlugins } from './modules/'; +import modules from './modules/'; import pkg from '../package.json'; -// import program from 'commander'; -import yargs from 'yargs'; -import chalk from 'chalk'; -import MupAPI from './mup-api'; +import program from 'commander'; -function addModuleCommands(builder, module) { - Object.keys(module.commands).forEach((commandName) => { - let command = module.commands[commandName]; - command.builder = command.builder || {}; - builder.command( - commandName, - command.description, - command.builder, - commandWrapper(command.handler) - ); - }); -} +let settingsPath; +let configPath; +const args = process.argv.slice(2); + +program + .arguments(' [subcommand]') + .version(pkg.version) + .action(argAction) + .option('--settings ', 'Meteor settings file', setSettingsPath) + .option('--config ', 'mup.js config file', setConfigPath) + .option( + '--verbose', + 'Print more output while building and running tasks on server' + ) + .on('--help', function() { + console.log(' Commands:'); -function filterArgv() { - const unwanted = [ - '_', - '$0', - 'settings', - 'config' - ]; - let result = [...yargs.argv._]; - - Object.keys(yargs.argv).forEach((key) => { - if (unwanted.indexOf(key) === -1 && yargs.argv[key] !== false && yargs.argv[key] !== undefined) { - result.push(`--${key}`); - - if (typeof yargs.argv[key] !== 'boolean') { - result.push(yargs.argv[key]); - } + function listModuleCommands(commands) { + Object.keys(commands).forEach(command => { + if (command === 'default') { + listModuleCommands(commands['default']); + return; + } + console.log(` ${command}`); + }); } - }); - return result; -} + listModuleCommands(modules); -function commandWrapper(handler) { - return function() { - checkUpdates().then(() => { - const api = new MupAPI( - process.cwd(), - filterArgv(), - yargs.argv - ); - - let potentialPromise = handler(api); - - if (potentialPromise && typeof potentialPromise.then === 'function') { - potentialPromise.catch(e => { - if (e.nodemiralHistory instanceof Array) { - // Error is form nodemiral when running a task list. - // Nodemiral already displayed the error - return; - } - console.log(e); - }); - } - }).catch(e => { - console.error(e); - }); - }; -} + console.log(''); + console.log(' For list of subcommands, run '); + console.log(' mup help'); + }) + .parse(process.argv); -// Load plugins -let config = new MupAPI(process.cwd(), process.argv, yargs.argv).getConfig(); -if (config.plugins) { - loadPlugins(config.plugins); +if (program.args.length === 0) { + program.help(); + process.exit(0); } -let program = yargs - .usage(`\nUsage: ${chalk.yellow('mup')} [args]`) - .version(pkg.version) - .alias('version', 'V') - .global('version', false) - .option('settings', { - description: 'Path to Meteor settings file', - requiresArg: true, - string: true - }) - .option('config', { - description: 'Path to mup.js config file', - requiresArg: true, - string: true - }) - .option('verbose', { - description: 'Print output from build and server scripts', - boolean: true - }) - .strict(true) - .alias('help', 'h') - .epilogue('For more information, read the docs at https://github.com/zodern/meteor-up') - .help('help'); - -Object.keys(modules).forEach(moduleName => { - if (moduleName !== 'default' && modules[moduleName].commands) { - yargs.command( - moduleName, - modules[moduleName].description, - (subYargs) => { - addModuleCommands(subYargs, modules[moduleName], moduleName); +function argAction(arg, subarg) { + let moduleArg = arg; + let command = subarg; + + if (!command && !modules[moduleArg]) { + command = moduleArg; + moduleArg = 'default'; + } + + if (moduleArg === 'default' && command === 'help') { + program.help(); + process.exit(); + } + + let module; + + if (modules[moduleArg]) { + module = modules[moduleArg]; + } else { + console.error(`No such module ${moduleArg}`); + program.help(); + process.exit(1); + } + + if (!command) { + if (moduleArg === 'default') { + program.help(); + } else { + module.help(args); + } + process.exit(0); + } + + if (!module[command]) { + console.error('error: unknown command %s', command); + if (moduleArg === 'default') { + program.help(); + process.exit(1); + } + + module.help(args); + process.exit(1); + } + + if (program.settings) { + let settingsIndex = argIndex(args, '--settings'); + + if (args[settingsIndex].indexOf('--settings=') === 0) { + args.splice(settingsIndex, 1); + } else { + args.splice(settingsIndex, 2); + } + } + + if (program.config) { + let configIndex = argIndex(args, '--config'); + + if (args[configIndex].indexOf('--config=') === 0) { + args.splice(configIndex, 1); + } else { + args.splice(configIndex, 2); + } + } + + checkUpdates().then(() => { + const base = process.cwd(); + const api = new MupAPI( + base, + args, + configPath, + settingsPath, + program.verbose + ); + let potentialPromise = module[command](api); + if (potentialPromise && typeof potentialPromise.then === 'function') { + potentialPromise.catch(e => { + if (e.nodemiralHistory instanceof Array) { + // Error is from nodemiral when running a task list + // Nodemiral already displayed the error to the user + return; } - ); - } else if (moduleName === 'default') { - addModuleCommands(yargs, modules[moduleName], moduleName); + + console.log(e); + }); + } + }); +} + +function argIndex(list, string) { + for (let i = 0; i < list.length; i++) { + if (list[i].indexOf(string) === 0) { + return i; + } } -}); + return -1; +} + +function handleErrors(e) { + console.log(e.name, e.message); + process.exit(1); +} -program = program.argv; +function setSettingsPath(settingsPathArg) { + settingsPath = settingsPathArg; +} -if (program._.length === 0) { - yargs.showHelp(); +function setConfigPath(configPathArg) { + configPath = configPathArg; } + +process.on('uncaughtException', handleErrors); diff --git a/src/modules/command-wrapper.js b/src/modules/command-wrapper.js deleted file mode 100644 index dd9fd34b..00000000 --- a/src/modules/command-wrapper.js +++ /dev/null @@ -1,16 +0,0 @@ -import {argv} from 'yargs'; -import MupAPI from '../mup-api'; - -export default function(handler) { - return function() { - const api = new MupAPI( - process.cwd(), - process.argv.slice(2), - argv.config, - argv['settings '], - argv['config '], - argv.verbose - ); - handler(api); - }; -} diff --git a/src/modules/default/commands.js b/src/modules/default/commands.js deleted file mode 100644 index f3b2147d..00000000 --- a/src/modules/default/commands.js +++ /dev/null @@ -1,60 +0,0 @@ -import * as commandFunctions from './tasks'; - -export let init = { - description: 'Setup files for new mup project', - handler: commandFunctions.init -}; - -export let deploy = { - description: 'Deploy app to server', - builder(yargs) { - return yargs.option('cached-build', { - description: 'Use build from previous deploy', - boolean: true - }); - }, - handler: commandFunctions.deploy -}; - -export let logs = { - description: "Show app\'s logs. Supports options from docker logs", - builder(yargs) { - return yargs - .strict(false) - .option('tail', { - description: 'Number of lines to show form the end of the logs', - number: true - }) - .option('follow', { - description: 'Follow log output', - alias: 'f', - boolean: true - }); - }, - handler: commandFunctions.logs -}; - -export let reconfig = { - description: 'Updates server env and start script to match config', - handler: commandFunctions.reconfig -}; - -export let restart = { - description: 'Restart app', - handler: commandFunctions.restart -}; - -export let setup = { - description: 'Install dependencies, custom certificates, and MongoDB on server', - handler: commandFunctions.setup -}; - -export let start = { - description: 'Start app', - handler: commandFunctions.start -}; - -export let stop = { - description: 'Stop app', - handler: commandFunctions.stop -}; diff --git a/src/modules/default/index.js b/src/modules/default/index.js index c3951363..28a97d98 100644 --- a/src/modules/default/index.js +++ b/src/modules/default/index.js @@ -1,5 +1,109 @@ -import * as _commands from './commands'; -import * as tasks from './tasks'; +import * as docker from '../docker/'; +import * as meteor from '../meteor/'; +import * as mongo from '../mongo/'; -export let commands = _commands; -export default tasks; +import debug from 'debug'; +import { resolvePath } from '../utils'; +import sh from 'shelljs'; +import fs from 'fs'; + +const log = debug('mup:module:default'); + +sh.config.silent = true; + +export function deploy(api) { + log('exec => mup deploy'); + return meteor.deploy(api); +} + +export function help() { + log('exec => mup help'); +} +export function init() { + log('exec => mup init'); + + const mupJs = resolvePath(__dirname, 'template/mup.js.sample'); + const settinsJson = resolvePath(__dirname, 'template/settings.json'); + const mupJsDst = resolvePath(process.cwd(), 'mup.js'); + const settingsJsonDst = resolvePath(process.cwd(), 'settings.json'); + const mupJsExists = fs.existsSync(mupJsDst); + const settingsJsonExist = fs.existsSync(settingsJsonDst); + + if (!settingsJsonExist) { + sh.cp(settinsJson, settingsJsonDst); + console.log('Created settings.json'); + } else { + console.log('Skipping creation of settings.json.'); + console.log(`settings.json already exist at ${settingsJsonDst}.`); + } + + if (!mupJsExists) { + sh.cp(mupJs, mupJsDst); + + console.log('Created mup.js'); + console.log(''); + console.log('Next Steps:'); + console.log(''); + console.log(' Open mup.js and edit the config to meet your needs.'); + console.log(' Required changes have been marked with a TODO comment.'); + console.log(''); + console.log(' Available options can be found in the docs at'); + console.log(' https://github.com/zodern/meteor-up'); + console.log(''); + console.log(' Then run the command:'); + console.log(' mup setup'); + } else { + console.log('Skipping creation of mup.js'); + console.log(`mup.js already exists at ${mupJsDst}`); + } +} + +export function logs(api) { + log('exec => mup logs'); + return meteor.logs(api); +} + +export function reconfig(api) { + log('exec => mup reconfig'); + return meteor.envconfig(api).then(() => meteor.start(api)); +} + +export function restart(api) { + log('exec => mup restart'); + return meteor.stop(api).then(() => meteor.start(api)); +} + +export function setup(api) { + function displayNextSteps() { + console.log(''); + console.log('Next, you should run:'); + console.log(' mup deploy'); + } + + log('exec => mup setup'); + const config = api.getConfig(); + return docker + .setup(api) + .then(meteor.setup.bind(null, api)) + .then(() => { + if (config.mongo) { + return mongo.setup(api); + } + }) + .then(() => { + if (config.mongo) { + return mongo.start(api); + } + }) + .then(displayNextSteps); +} + +export function start(api) { + log('exec => mup start'); + return meteor.start(api); +} + +export function stop(api) { + log('exec => mup stop'); + return meteor.stop(api); +} diff --git a/src/modules/default/tasks.js b/src/modules/default/tasks.js deleted file mode 100644 index 9f627453..00000000 --- a/src/modules/default/tasks.js +++ /dev/null @@ -1,109 +0,0 @@ -import * as docker from '../docker/tasks'; -import * as meteor from '../meteor/tasks'; -import * as mongo from '../mongo/tasks'; - -import debug from 'debug'; -import { resolvePath } from '../utils'; -import sh from 'shelljs'; -import fs from 'fs'; - -const log = debug('mup:module:default'); - -sh.config.silent = true; - -export function deploy(api) { - log('exec => mup deploy'); - return meteor.deploy(api); -} - -export function help() { - log('exec => mup help'); -} -export function init() { - log('exec => mup init'); - - const mupJs = resolvePath(__dirname, 'template/mup.js.sample'); - const settinsJson = resolvePath(__dirname, 'template/settings.json'); - const mupJsDst = resolvePath(process.cwd(), 'mup.js'); - const settingsJsonDst = resolvePath(process.cwd(), 'settings.json'); - const mupJsExists = fs.existsSync(mupJsDst); - const settingsJsonExist = fs.existsSync(settingsJsonDst); - - if (!settingsJsonExist) { - sh.cp(settinsJson, settingsJsonDst); - console.log('Created settings.json'); - } else { - console.log('Skipping creation of settings.json.'); - console.log(`settings.json already exist at ${settingsJsonDst}.`); - } - - if (!mupJsExists) { - sh.cp(mupJs, mupJsDst); - - console.log('Created mup.js'); - console.log(''); - console.log('Next Steps:'); - console.log(''); - console.log(' Open mup.js and edit the config to meet your needs.'); - console.log(' Required changes have been marked with a TODO comment.'); - console.log(''); - console.log(' Available options can be found in the docs at'); - console.log(' https://github.com/zodern/meteor-up'); - console.log(''); - console.log(' Then run the command:'); - console.log(' mup setup'); - } else { - console.log('Skipping creation of mup.js'); - console.log(`mup.js already exists at ${mupJsDst}`); - } -} - -export function logs(api) { - log('exec => mup logs'); - return meteor.logs(api); -} - -export function reconfig(api) { - log('exec => mup reconfig'); - return meteor.envconfig(api).then(() => meteor.start(api)); -} - -export function restart(api) { - log('exec => mup restart'); - return meteor.stop(api).then(() => meteor.start(api)); -} - -export function setup(api) { - function displayNextSteps() { - console.log(''); - console.log('Next, you should run:'); - console.log(' mup deploy'); - } - - log('exec => mup setup'); - const config = api.getConfig(); - return docker - .setup(api) - .then(() => meteor.setup(api)) - .then(() => { - if (config.mongo) { - return mongo.setup(api); - } - }) - .then(() => { - if (config.mongo) { - return mongo.start(api); - } - }) - .then(displayNextSteps); -} - -export function start(api) { - log('exec => mup start'); - return meteor.start(api); -} - -export function stop(api) { - log('exec => mup stop'); - return meteor.stop(api); -} diff --git a/src/modules/docker/commands.js b/src/modules/docker/commands.js deleted file mode 100644 index 51729389..00000000 --- a/src/modules/docker/commands.js +++ /dev/null @@ -1,16 +0,0 @@ -import * as commandFunctions from './tasks'; - -export let setup = { - description: 'Install and start docker', - handler: commandFunctions.setup -}; - -export let restart = { - description: 'Restart docker daemon', - handler: commandFunctions.restart -}; - -export let ps = { - description: 'View running containers. Accepts same options as docker ps', - handler: commandFunctions.ps -}; diff --git a/src/modules/docker/index.js b/src/modules/docker/index.js index 0a330d9e..ee864b8c 100644 --- a/src/modules/docker/index.js +++ b/src/modules/docker/index.js @@ -1,6 +1,60 @@ -import * as tasks from './tasks'; -import * as _commands from './commands'; +import debug from 'debug'; +import nodemiral from 'nodemiral'; +import { resolvePath } from '../utils'; +import { runTaskList } from '../utils'; +import { each } from 'async'; +import chalk from 'chalk'; +const log = debug('mup:module:docker'); -export const description = 'Setup and manage docker'; -export const commands = _commands; -export default tasks; +function uniqueSessions(api) { + const sessions = api.getSessions(['meteor', 'mongo', 'proxy']); + return sessions.reduce( + (prev, curr) => { + if (prev.map(session => session._host).indexOf(curr._host) === -1) { + prev.push(curr); + } + return prev; + }, + [] + ); +} + +export function help() { + log('exec => mup docker help'); +} + +export function setup(api) { + log('exec => mup docker setup'); + const list = nodemiral.taskList('Setup Docker'); + + list.executeScript('Setup Docker', { + script: resolvePath(__dirname, 'assets/docker-setup.sh') + }); + + const sessions = uniqueSessions(api); + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} + +export function restart(api) { + const list = nodemiral.taskList('Restart Docker Daemon'); + + list.executeScript('Restart Docker', { + script: resolvePath(__dirname, 'assets/docker-restart.sh') + }); + + const sessions = uniqueSessions(api); + + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} + +export function ps(api) { + let args = api.getArgs(); + args.shift(); + each(uniqueSessions(api), (session, cb) => { + session.execute(`sudo docker ${args.join(' ')} 2>&1`, (err, code, logs) => { + console.log(chalk.magenta(`[${session._host}]`) + chalk.blue(` docker ${args.join(' ')}`)); + console.log(logs.stdout); + cb(); + }); + }); +} diff --git a/src/modules/docker/tasks.js b/src/modules/docker/tasks.js deleted file mode 100644 index 0f8323f1..00000000 --- a/src/modules/docker/tasks.js +++ /dev/null @@ -1,58 +0,0 @@ -import debug from 'debug'; -import nodemiral from 'nodemiral'; -import { resolvePath } from '../utils'; -import { runTaskList } from '../utils'; -import { each } from 'async'; -import chalk from 'chalk'; -import { argv } from 'yargs'; - -const log = debug('mup:module:docker'); - -function uniqueSessions(api) { - const sessions = api.getSessions(['meteor', 'mongo', 'proxy']); - return sessions.reduce( - (prev, curr) => { - if (prev.map(session => session._host).indexOf(curr._host) === -1) { - prev.push(curr); - } - return prev; - }, - [] - ); -} - -export function setup(api) { - log('exec => mup docker setup'); - const list = nodemiral.taskList('Setup Docker'); - - list.executeScript('Setup Docker', { - script: resolvePath(__dirname, 'assets/docker-setup.sh') - }); - - const sessions = uniqueSessions(api); - return runTaskList(list, sessions, { verbose: argv.verbose }); -} - -export function restart(api) { - const list = nodemiral.taskList('Restart Docker Daemon'); - - list.executeScript('Restart Docker', { - script: resolvePath(__dirname, 'assets/docker-restart.sh') - }); - - const sessions = uniqueSessions(api); - - return runTaskList(list, sessions, { verbose: argv.verbose }); -} - -export function ps(api) { - let args = api.getArgs(); - args.shift(); - each(uniqueSessions(api), (session, cb) => { - session.execute(`sudo docker ${args.join(' ')} 2>&1`, (err, code, logs) => { - console.log(chalk.magenta(`[${session._host}]`) + chalk.blue(` docker ${args.join(' ')}`)); - console.log(logs.stdout); - cb(); - }); - }); -} diff --git a/src/modules/index.js b/src/modules/index.js index 400616c5..488fa004 100644 --- a/src/modules/index.js +++ b/src/modules/index.js @@ -1,18 +1,16 @@ import fs from 'fs'; import path from 'path'; -import commandWrapper from './command-wrapper'; + const modules = {}; export default modules; // Load all subdirectories as MUP modules. // The directory name is the module name. -fs.readdirSync(__dirname).filter(isDirectoryMupModule).forEach(loadModule); - -export function loadPlugins(plugins) { - console.dir(plugins); -} +fs.readdirSync(__dirname) + .filter(isMupModule) + .forEach(loadModule); -function isDirectoryMupModule(name) { +function isMupModule(name) { if (name === '__tests__') { return false; } diff --git a/src/modules/meteor/commands.js b/src/modules/meteor/commands.js deleted file mode 100644 index 752a493e..00000000 --- a/src/modules/meteor/commands.js +++ /dev/null @@ -1,32 +0,0 @@ -import * as commandFunctions from './tasks'; - -export let setup = { - description: 'Prepare server to deploy meteor apps', - handler: commandFunctions.setup -}; - -export let deploy = { - description: 'Deploy meteor apps', - builder(subYargs) { - return subYargs.option('cached-build', { - description: 'Use build from previous deploy', - boolean: true - }); - }, - handler: commandFunctions.deploy -}; - -export let logs = { - description: 'View meteor app\'s logs', - handler: commandFunctions.logs -}; - -export let start = { - description: 'Start meteor app', - handler: commandFunctions.start -}; - -export let stop = { - description: 'Stop meteor app', - handler: commandFunctions.stop -}; diff --git a/src/modules/meteor/index.js b/src/modules/meteor/index.js index ac296fde..22112370 100644 --- a/src/modules/meteor/index.js +++ b/src/modules/meteor/index.js @@ -1,7 +1,318 @@ -import * as _commands from './commands'; -import * as tasks from './tasks'; +import * as _ from 'underscore'; -export const description = 'Deploy and manage meteor apps'; +import { getDockerLogs, resolvePath, runTaskList } from '../utils'; -export let commands = _commands; -export default tasks; +import buildApp from './build.js'; +import debug from 'debug'; +import fs from 'fs'; +import nodemiral from 'nodemiral'; +import random from 'random-seed'; +import uuid from 'uuid'; +import os from 'os'; + +const log = debug('mup:module:meteor'); + +function tmpBuildPath(appPath) { + let rand = random.create(appPath); + let uuidNumbers = []; + for (let i = 0; i < 16; i++) { + uuidNumbers.push(rand(255)); + } + return resolvePath( + os.tmpdir(), + `mup-meteor-${uuid.v4({ random: uuidNumbers })}` + ); +} + +export function help() { + log('exec => mup meteor help'); + console.log('mup meteor', Object.keys(this)); +} + +export function logs(api) { + log('exec => mup meteor logs'); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + const args = api.getArgs(); + const sessions = api.getSessions(['meteor']); + return getDockerLogs(config.name, sessions, args); +} + +export function setup(api) { + log('exec => mup meteor setup'); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + const list = nodemiral.taskList('Setup Meteor'); + + list.executeScript('Setup Environment', { + script: resolvePath(__dirname, 'assets/meteor-setup.sh'), + vars: { + name: config.name + } + }); + + if (config.ssl && typeof config.ssl.autogenerate !== 'object') { + const basePath = api.getBasePath(); + + if (config.ssl.upload !== false) { + list.executeScript('Cleaning up SSL Certificates', { + script: resolvePath(__dirname, 'assets/ssl-cleanup.sh'), + vars: { + name: config.name + } + }); + list.copy('Copying SSL Certificate Bundle', { + src: resolvePath(basePath, config.ssl.crt), + dest: '/opt/' + config.name + '/config/bundle.crt' + }); + + list.copy('Copying SSL Private Key', { + src: resolvePath(basePath, config.ssl.key), + dest: '/opt/' + config.name + '/config/private.key' + }); + } + + list.executeScript('Verifying SSL Configurations', { + script: resolvePath(__dirname, 'assets/verify-ssl-config.sh'), + vars: { + name: config.name + } + }); + } + + const sessions = api.getSessions(['meteor']); + + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} + +export async function push(api) { + log('exec => mup meteor push'); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + const appPath = resolvePath(api.getBasePath(), config.path); + + let buildOptions = config.buildOptions || {}; + buildOptions.buildLocation = buildOptions.buildLocation || + tmpBuildPath(appPath); + + var bundlePath = resolvePath(buildOptions.buildLocation, 'bundle.tar.gz'); + + if (!api.optionEnabled('cached-build')) { + // Check if using force-ssl package and ssl is not setup. + // This is a common problem people encounter when deploying + try { + var contents = fs + .readFileSync(resolvePath(appPath, '.meteor/versions')) + .toString(); + // Looks for "force-ssl@" in the begining of a + // line or at the start of the file + var match = /(^|\s)force-ssl@/m; + if (match.test(contents) && !config.ssl) { + console.log( + 'Your app is using the "force-ssl" package, but ssl is not setup in your mup config.' + ); + console.log('This can cause unexpected redirects.'); + } + } catch (e) { + // This is optional functionality and if it fails + // it shouldn't prevent building. + } + + console.log('Building App Bundle Locally'); + await buildApp(appPath, buildOptions, api.getVerbose()); + } else { + const buildCached = fs.existsSync(bundlePath); + if (!buildCached) { + console.log('Unable to use previous build. It doesn\'t exist.'); + console.log('Remove the "--cached-build" option and try again.'); + process.exit(1); + } + console.log('Skipping build. Using previous build at'); + console.log(`${buildOptions.buildLocation}`); + } + + const list = nodemiral.taskList('Pushing Meteor App'); + + list.copy('Pushing Meteor App Bundle to The Server', { + src: bundlePath, + dest: '/opt/' + config.name + '/tmp/bundle.tar.gz', + progressBar: config.enableUploadProgressBar + }); + + const sessions = api.getSessions(['meteor']); + return runTaskList(list, sessions, { + series: true, + verbose: api.getVerbose() + }); +} + +export function envconfig(api) { + log('exec => mup meteor envconfig'); + + const config = api.getConfig().meteor; + let bindAddress = '0.0.0.0'; + + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + config.log = config.log || { + opts: { + 'max-size': '100m', + 'max-file': 10 + } + }; + + config.nginx = config.nginx || {}; + + if (config.docker && config.docker.bind) { + bindAddress = config.docker.bind; + } + + if (!config.docker) { + if (config.dockerImage) { + config.docker = { + image: config.dockerImage + }; + delete config.dockerImage; + } else { + config.docker = { + image: 'kadirahq/meteord' + }; + } + } + if (config.dockerImageFrontendServer) { + config.docker.imageFrontendServer = config.dockerImageFrontendServer; + } + if (!config.docker.imageFrontendServer) { + config.docker.imageFrontendServer = 'meteorhacks/mup-frontend-server'; + } + + // If imagePort is not set, go with port 80 which was the traditional + // port used by kadirahq/meteord and meteorhacks/meteord + config.docker.imagePort = config.docker.imagePort || 80; + + if (config.ssl) { + config.ssl.port = config.ssl.port || 443; + } + + const list = nodemiral.taskList('Configuring App'); + list.copy('Pushing the Startup Script', { + src: resolvePath(__dirname, 'assets/templates/start.sh'), + dest: '/opt/' + config.name + '/config/start.sh', + vars: { + appName: config.name, + useLocalMongo: api.getConfig().mongo ? 1 : 0, + port: config.env.PORT || 80, + bind: bindAddress, + sslConfig: config.ssl, + logConfig: config.log, + volumes: config.volumes, + docker: config.docker, + nginxClientUploadLimit: config.nginx.clientUploadLimit || '10M' + } + }); + + var env = _.clone(config.env); + env.METEOR_SETTINGS = JSON.stringify(api.getSettings()); + // sending PORT to the docker container is useless. + // It'll run on PORT 80 and we can't override it + // Changing the port is done via the start.sh script + delete env.PORT; + + list.copy('Sending Environment Variables', { + src: resolvePath(__dirname, 'assets/templates/env.list'), + dest: '/opt/' + config.name + '/config/env.list', + vars: { + env: env || {}, + appName: config.name + } + }); + + const sessions = api.getSessions(['meteor']); + return runTaskList(list, sessions, { + series: true, + verbose: api.getVerbose() + }); +} + +export function start(api) { + log('exec => mup meteor start'); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + const list = nodemiral.taskList('Start Meteor'); + + list.executeScript('Start Meteor', { + script: resolvePath(__dirname, 'assets/meteor-start.sh'), + vars: { + appName: config.name + } + }); + + list.executeScript('Verifying Deployment', { + script: resolvePath(__dirname, 'assets/meteor-deploy-check.sh'), + vars: { + deployCheckWaitTime: config.deployCheckWaitTime || 60, + appName: config.name, + deployCheckPort: config.deployCheckPort || config.env.PORT || 80 + } + }); + + const sessions = api.getSessions(['meteor']); + return runTaskList(list, sessions, { + series: true, + verbose: api.getVerbose() + }); +} + +export function deploy(api) { + log('exec => mup meteor deploy'); + + // validate settings and config before starting + api.getSettings(); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + return push(api).then(() => envconfig(api)).then(() => start(api)); +} + +export function stop(api) { + log('exec => mup meteor stop'); + const config = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + + const list = nodemiral.taskList('Stop Meteor'); + + list.executeScript('Stop Meteor', { + script: resolvePath(__dirname, 'assets/meteor-stop.sh'), + vars: { + appName: config.name + } + }); + + const sessions = api.getSessions(['meteor']); + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} diff --git a/src/modules/meteor/tasks.js b/src/modules/meteor/tasks.js deleted file mode 100644 index a5c94d16..00000000 --- a/src/modules/meteor/tasks.js +++ /dev/null @@ -1,320 +0,0 @@ -import * as _ from 'underscore'; - -import { getDockerLogs, resolvePath, runTaskList } from '../utils'; - -import buildApp from './build.js'; -import debug from 'debug'; -import fs from 'fs'; -import nodemiral from 'nodemiral'; -import random from 'random-seed'; -import uuid from 'uuid'; -import os from 'os'; - -const log = debug('mup:module:meteor'); - -function tmpBuildPath(appPath) { - let rand = random.create(appPath); - let uuidNumbers = []; - for (let i = 0; i < 16; i++) { - uuidNumbers.push(rand(255)); - } - return resolvePath( - os.tmpdir(), - `mup-meteor-${uuid.v4({ random: uuidNumbers })}` - ); -} - -export function help() { - log('exec => mup meteor help'); - console.log('mup meteor', Object.keys(this)); -} - -export function logs(api) { - log('exec => mup meteor logs'); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - const args = api.getArgs(); - if (args[0] === 'meteor') { - args.shift(); - } - const sessions = api.getSessions(['meteor']); - return getDockerLogs(config.name, sessions, args); -} - -export function setup(api) { - log('exec => mup meteor setup'); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - const list = nodemiral.taskList('Setup Meteor'); - - list.executeScript('Setup Environment', { - script: resolvePath(__dirname, 'assets/meteor-setup.sh'), - vars: { - name: config.name - } - }); - - if (config.ssl && typeof config.ssl.autogenerate !== 'object') { - const basePath = api.getBasePath(); - - if (config.ssl.upload !== false) { - list.executeScript('Cleaning up SSL Certificates', { - script: resolvePath(__dirname, 'assets/ssl-cleanup.sh'), - vars: { - name: config.name - } - }); - list.copy('Copying SSL Certificate Bundle', { - src: resolvePath(basePath, config.ssl.crt), - dest: '/opt/' + config.name + '/config/bundle.crt' - }); - - list.copy('Copying SSL Private Key', { - src: resolvePath(basePath, config.ssl.key), - dest: '/opt/' + config.name + '/config/private.key' - }); - } - - list.executeScript('Verifying SSL Configurations', { - script: resolvePath(__dirname, 'assets/verify-ssl-config.sh'), - vars: { - name: config.name - } - }); - } - - const sessions = api.getSessions(['meteor']); - - return runTaskList(list, sessions, { verbose: api.verbose }); -} - -export async function push(api) { - log('exec => mup meteor push'); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - const appPath = resolvePath(api.getBasePath(), config.path); - - let buildOptions = config.buildOptions || {}; - buildOptions.buildLocation = buildOptions.buildLocation || - tmpBuildPath(appPath); - - var bundlePath = resolvePath(buildOptions.buildLocation, 'bundle.tar.gz'); - if (!api.program['cached-build']) { - // Check if using force-ssl package and ssl is not setup. - // This is a common problem people encounter when deploying - try { - var contents = fs - .readFileSync(resolvePath(appPath, '.meteor/versions')) - .toString(); - // Looks for "force-ssl@" in the begining of a - // line or at the start of the file - var match = /(^|\s)force-ssl@/m; - if (match.test(contents)) { - console.log( - 'Your app is using the "force-ssl" package, but ssl is not setup in your mup config.' - ); - console.log('This can cause unexpected redirects.'); - } - } catch (e) { - // This is optional functionality and if it fails - // it shouldn't prevent building. - } - - console.log('Building App Bundle Locally'); - await buildApp(appPath, buildOptions, api.verbose); - } else { - const buildCached = fs.existsSync(bundlePath); - if (!buildCached) { - console.log('Unable to use previous build. It doesn\'t exist.'); - console.log('Remove the "--cached-build" option and try again.'); - process.exit(1); - } - console.log('Skipping build. Using previous build at'); - console.log(`${buildOptions.buildLocation}`); - } - - const list = nodemiral.taskList('Pushing Meteor App'); - - list.copy('Pushing Meteor App Bundle to The Server', { - src: bundlePath, - dest: '/opt/' + config.name + '/tmp/bundle.tar.gz', - progressBar: config.enableUploadProgressBar - }); - - const sessions = api.getSessions(['meteor']); - return runTaskList(list, sessions, { - series: true, - verbose: api.verbose - }); -} - -export function envconfig(api) { - log('exec => mup meteor envconfig'); - - const config = api.getConfig().meteor; - let bindAddress = '0.0.0.0'; - - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - config.log = config.log || { - opts: { - 'max-size': '100m', - 'max-file': 10 - } - }; - - config.nginx = config.nginx || {}; - - if (config.docker && config.docker.bind) { - bindAddress = config.docker.bind; - } - - if (!config.docker) { - if (config.dockerImage) { - config.docker = { - image: config.dockerImage - }; - delete config.dockerImage; - } else { - config.docker = { - image: 'kadirahq/meteord' - }; - } - } - if (config.dockerImageFrontendServer) { - config.docker.imageFrontendServer = config.dockerImageFrontendServer; - } - if (!config.docker.imageFrontendServer) { - config.docker.imageFrontendServer = 'meteorhacks/mup-frontend-server'; - } - - // If imagePort is not set, go with port 80 which was the traditional - // port used by kadirahq/meteord and meteorhacks/meteord - config.docker.imagePort = config.docker.imagePort || 80; - - if (config.ssl) { - config.ssl.port = config.ssl.port || 443; - } - - const list = nodemiral.taskList('Configuring App'); - list.copy('Pushing the Startup Script', { - src: resolvePath(__dirname, 'assets/templates/start.sh'), - dest: '/opt/' + config.name + '/config/start.sh', - vars: { - appName: config.name, - useLocalMongo: api.getConfig().mongo ? 1 : 0, - port: config.env.PORT || 80, - bind: bindAddress, - sslConfig: config.ssl, - logConfig: config.log, - volumes: config.volumes, - docker: config.docker, - nginxClientUploadLimit: config.nginx.clientUploadLimit || '10M' - } - }); - - var env = _.clone(config.env); - env.METEOR_SETTINGS = JSON.stringify(api.getSettings()); - // sending PORT to the docker container is useless. - // It'll run on PORT 80 and we can't override it - // Changing the port is done via the start.sh script - delete env.PORT; - - list.copy('Sending Environment Variables', { - src: resolvePath(__dirname, 'assets/templates/env.list'), - dest: '/opt/' + config.name + '/config/env.list', - vars: { - env: env || {}, - appName: config.name - } - }); - - const sessions = api.getSessions(['meteor']); - return runTaskList(list, sessions, { - series: true, - verbose: api.verbose - }); -} - -export function start(api) { - log('exec => mup meteor start'); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - const list = nodemiral.taskList('Start Meteor'); - - list.executeScript('Start Meteor', { - script: resolvePath(__dirname, 'assets/meteor-start.sh'), - vars: { - appName: config.name - } - }); - - list.executeScript('Verifying Deployment', { - script: resolvePath(__dirname, 'assets/meteor-deploy-check.sh'), - vars: { - deployCheckWaitTime: config.deployCheckWaitTime || 60, - appName: config.name, - deployCheckPort: config.deployCheckPort || config.env.PORT || 80 - } - }); - - const sessions = api.getSessions(['meteor']); - return runTaskList(list, sessions, { - series: true, - verbose: api.verbose - }); -} - -export function deploy(api) { - log('exec => mup meteor deploy'); - - // validate settings and config before starting - api.getSettings(); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - return push(api).then(() => envconfig(api)).then(() => start(api)); -} - -export function stop(api) { - log('exec => mup meteor stop'); - const config = api.getConfig().meteor; - if (!config) { - console.error('error: no configs found for meteor'); - process.exit(1); - } - - const list = nodemiral.taskList('Stop Meteor'); - - list.executeScript('Stop Meteor', { - script: resolvePath(__dirname, 'assets/meteor-stop.sh'), - vars: { - appName: config.name - } - }); - - const sessions = api.getSessions(['meteor']); - return runTaskList(list, sessions, { verbose: api.verbose }); -} diff --git a/src/modules/mongo/commands.js b/src/modules/mongo/commands.js deleted file mode 100644 index df9541db..00000000 --- a/src/modules/mongo/commands.js +++ /dev/null @@ -1,21 +0,0 @@ -import * as commandFunctions from './tasks'; - -export let setup = { - description: 'Installs and starts MongoDB', - handler: commandFunctions.setup -}; - -export let logs = { - description: 'View MongoDB logs', - handler: commandFunctions.logs -}; - -export let start = { - description: 'Start MongoDB', - handler: commandFunctions.start -}; - -export let stop = { - description: 'Stop MongoDB', - handler: commandFunctions.stop -}; diff --git a/src/modules/mongo/index.js b/src/modules/mongo/index.js index 976f5f23..f80cead5 100644 --- a/src/modules/mongo/index.js +++ b/src/modules/mongo/index.js @@ -1,6 +1,105 @@ -import * as _commands from './commands'; -import * as tasks from './tasks'; +import { getDockerLogs, resolvePath, runTaskList } from '../utils'; -export const description = 'Commands to manage MongoDB'; -export let commands = _commands; -export default tasks; +import debug from 'debug'; +import nodemiral from 'nodemiral'; + +const log = debug('mup:module:mongo'); + +export function dump() { + log('exec => mup mongo dump'); +} + +export function help() { + log('exec => mup mongo help'); +} + +export function logs(api) { + log('exec => mup mongo logs'); + + const args = api.getArgs(); + const sessions = api.getSessions(['mongo']); + args.shift(); // remove mongo from args sent to docker + return getDockerLogs('mongodb', sessions, args); +} + +export function setup(api) { + log('exec => mup mongo setup'); + + if (!api.getConfig().mongo) { + // could happen when running "mup mongo setup" + console.log( + 'Not setting up built-in mongodb since there is no mongo config' + ); + return; + } + + const mongoSessions = api.getSessions(['mongo']); + const meteorSessions = api.getSessions(['meteor']); + + if (meteorSessions.length !== 1) { + console.log( + 'To use mup built-in mongodb setup, you should have only one meteor app server. To have more app servers, use an external mongodb setup' + ); + return; + } else if (mongoSessions[0]._host !== meteorSessions[0]._host) { + console.log( + 'To use mup built-in mongodb setup, you should have both meteor app and mongodb on the same server' + ); + return; + } + + const list = nodemiral.taskList('Setup Mongo'); + + list.executeScript('Setup Environment', { + script: resolvePath(__dirname, 'assets/mongo-setup.sh') + }); + + list.copy('Copying mongodb.conf', { + src: resolvePath(__dirname, 'assets/mongodb.conf'), + dest: '/opt/mongodb/mongodb.conf' + }); + + const sessions = api.getSessions(['mongo']); + + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} + +export function start(api) { + log('exec => mup mongo start'); + + const mongoSessions = api.getSessions(['mongo']); + const meteorSessions = api.getSessions(['meteor']); + const config = api.getConfig().mongo; + + if ( + meteorSessions.length !== 1 || + mongoSessions[0]._host !== meteorSessions[0]._host + ) { + log('Skipping mongodb start. Incompatible config'); + return; + } + + const list = nodemiral.taskList('Start Mongo'); + + list.executeScript('Start Mongo', { + script: resolvePath(__dirname, 'assets/mongo-start.sh'), + vars: { + mongoVersion: config.version || '3.4.1' + } + }); + + const sessions = api.getSessions(['mongo']); + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} + +export function stop(api) { + log('exec => mup mongo stop'); + const list = nodemiral.taskList('Stop Mongo'); + + list.executeScript('stop mongo', { + script: resolvePath(__dirname, 'assets/mongo-stop.sh') + }); + + const sessions = api.getSessions(['mongo']); + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} diff --git a/src/modules/mongo/tasks.js b/src/modules/mongo/tasks.js deleted file mode 100644 index bad51d81..00000000 --- a/src/modules/mongo/tasks.js +++ /dev/null @@ -1,106 +0,0 @@ -import { getDockerLogs, resolvePath, runTaskList } from '../utils'; -import { argv } from 'yargs'; - -import debug from 'debug'; -import nodemiral from 'nodemiral'; - -const log = debug('mup:module:mongo'); - -export function dump() { - log('exec => mup mongo dump'); -} - -export function help() { - log('exec => mup mongo help'); -} - -export function logs(api) { - log('exec => mup mongo logs'); - - const args = api.getArgs(); - const sessions = api.getSessions(['mongo']); - args.shift(); // remove mongo from args sent to docker - return getDockerLogs('mongodb', sessions, args); -} - -export function setup(api) { - log('exec => mup mongo setup'); - - if (!api.getConfig().mongo) { - // could happen when running "mup mongo setup" - console.log( - 'Not setting up built-in mongodb since there is no mongo config' - ); - return; - } - - const mongoSessions = api.getSessions(['mongo']); - const meteorSessions = api.getSessions(['meteor']); - - if (meteorSessions.length !== 1) { - console.log( - 'To use mup built-in mongodb setup, you should have only one meteor app server. To have more app servers, use an external mongodb setup' - ); - return; - } else if (mongoSessions[0]._host !== meteorSessions[0]._host) { - console.log( - 'To use mup built-in mongodb setup, you should have both meteor app and mongodb on the same server' - ); - return; - } - - const list = nodemiral.taskList('Setup Mongo'); - - list.executeScript('Setup Environment', { - script: resolvePath(__dirname, 'assets/mongo-setup.sh') - }); - - list.copy('Copying mongodb.conf', { - src: resolvePath(__dirname, 'assets/mongodb.conf'), - dest: '/opt/mongodb/mongodb.conf' - }); - - const sessions = api.getSessions(['mongo']); - - return runTaskList(list, sessions, { verbose: argv.verbose }); -} - -export function start(api) { - log('exec => mup mongo start'); - - const mongoSessions = api.getSessions(['mongo']); - const meteorSessions = api.getSessions(['meteor']); - const config = api.getConfig().mongo; - - if ( - meteorSessions.length !== 1 || - mongoSessions[0]._host !== meteorSessions[0]._host - ) { - log('Skipping mongodb start. Incompatible config'); - return; - } - - const list = nodemiral.taskList('Start Mongo'); - - list.executeScript('Start Mongo', { - script: resolvePath(__dirname, 'assets/mongo-start.sh'), - vars: { - mongoVersion: config.version || '3.4.1' - } - }); - - const sessions = api.getSessions(['mongo']); - return runTaskList(list, sessions, { verbose: argv.verbose }); -} - -export function stop(api) { - log('exec => mup mongo stop'); - const list = nodemiral.taskList('Stop Mongo'); - - list.executeScript('stop mongo', { - script: resolvePath(__dirname, 'assets/mongo-stop.sh') - }); - - const sessions = api.getSessions(['mongo']); - return runTaskList(list, sessions, { verbose: argv.verbose }); -} diff --git a/src/mup-api.js b/src/mup-api.js index c730a9fd..e6da02a5 100644 --- a/src/mup-api.js +++ b/src/mup-api.js @@ -2,27 +2,30 @@ import chalk from 'chalk'; import fs from 'fs'; import nodemiral from 'nodemiral'; import parseJson from 'parse-json'; -import { resolvePath } from './modules/utils'; -import configValidator from './validate/index'; import path from 'path'; +import { resolvePath } from './modules/utils'; +import validateConfig from './validate/index'; export default class MupAPI { - constructor(base, filteredArgs, program) { + constructor(base, args, configPath, settingsPath, verbose) { this.base = base; - this.args = filteredArgs; + this.args = args; this.config = null; this.settings = null; this.sessions = null; - this.configPath = program['config']; - this.settingsPath = program['settings']; - this.verbose = program.verbose; - this.program = program; + this.configPath = configPath; + this.settingsPath = settingsPath; + this.verbose = verbose; } getArgs() { return this.args; } + optionEnabled(long) { + return this.args.indexOf(`--${long}`) > -1; + } + getBasePath() { return this.base; } @@ -32,11 +35,11 @@ export default class MupAPI { } validateConfig(configPath) { - let problems = configValidator(this.config); + let problems = validateConfig(this.config); if (problems.length > 0) { let red = chalk.red; - let plural = problems.length > 1 ? 's' : ''; + let plural = problems.length > 1 ? 's' : 's'; console.log(`loaded mup.js from ${configPath}`); console.log(''); @@ -68,9 +71,7 @@ export default class MupAPI { this.config = require(filePath); // eslint-disable-line global-require } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { - console.error('"mup.js" file not found at'); - console.error(` ${filePath}`); - console.error('Run "mup init" to create it.'); + console.error('"mup.js" file not found. Run "mup init" first.'); } else { console.error(e); } diff --git a/src/tasks.js b/src/tasks.js deleted file mode 100644 index 1ec876b9..00000000 --- a/src/tasks.js +++ /dev/null @@ -1,21 +0,0 @@ -export const tasks = {}; - -export default function registerTask(moduleName, name, handler) { - tasks[`${module}.${name}`] = handler; -} - -export function registerOverrides(moduleName, overrides) { - Object.keys(overrides).forEach((override) => { - let handler; - - if (tasks[`${moduleName}.${overrides[override]}`]) { - handler = tasks[`${moduleName}.${overrides[override]}`]; - } else if (tasks[overrides[override]]) { - handler = tasks[overrides[override]]; - } else { - console.log(`Handler ${overrides[override]} in module ${moduleName}`); - console.log(`to override ${override} does not exist`); - } - tasks[override] = handler; - }); -}