tooltwist
Version:
Tooltwist Command Line Interface
434 lines (355 loc) • 12 kB
JavaScript
#! /usr/bin/env node
/*
* This is the main entry point, and is normally linked from the 'tooltwist' command.
*/
var Server = require('./server'),
Prerequisites = require('./prerequisites'),
Controller = require('./controller'),
Login = require('./login'),
Generate = require('./generate'),
Templates = require('./templates'),
Webdesign = require('./webdesign'),
open = require('open'),
DO = require('./digital-ocean'),
Log = require('./log'),
Config = require('./config'),
Clean = require('./clean'),
Gradle = require('./gradle'),
FipPairing = require('./fipPairing'),
Init = require('./init'),
path = require('path'),
stdio = require('stdio');
// Definition of command line parameters
var ops = stdio.getopt({
'help': {
key: 'h',
description: 'Display this help message.'
},
'quiet': {
key: 'q',
args: 0,
description: 'Log errors only.'
},
'info': {
key: 'i',
args: 0,
description: 'Set log level to info.'
},
'debug': {
key: 'd',
args: 0,
description: 'Log in debug mode.'
},
'digital-ocean': {
//key: 'f',
args: 0,
description: 'Init a new server a Digital Ocean.'
},
'nopull': {
key: 'n',
args: 0,
description: 'Skip git pull from webdesign repository.'
},
'force-designer': {
key: 'f',
args: 0,
description: 'Override the config file and use Designer mode.'
},
'version': {
key: 'v',
args: 0,
description: 'Print version info.'
},
}, "\n\n\
The default command reads the specification file '" + Config.CONFIG_FILE + "' and runs the\n\
Designer, deploys to a remote server, or runs a build for the ToolTwist Controller.\n\n\
\
USAGE: node tooltwist [OPTIONS] init [designer|deploy|controller|server]\n\n\
Create a default project specification file (" + Config.CONFIG_FILE + ")\n\n\
\
USAGE: node tooltwist [OPTIONS] example-templates\n\n\
Creates directory tooltwist.templates and populates it with example templates.\n\
If examples already exist they will be overwritten.\n\n\
\
USAGE: node login\n\n\
Login to remote server (deploy mode only).\n\n\
\
USAGE: node tooltwist [OPTIONS] generate <webdesign-project>\n\n\
Generate navpoints (internal use only).\n\n\
\
USAGE: node tooltwist clean\n\n\
Remove generated files (but not webdesign).\n\n\
");
/**
* ---------- Here is the main function ----------
*/
(function main() {
// Maybe display help.
if (ops.help) {
ops.printHelp();
process.exit(1);
}
// Maybe display the version number.
if (ops.version) {
var package = require('../package');
version = package.version;
console.log('\n Tooltwist-cli version "' + version + '"\n');
process.exit(0);
}
// Set the logging level
if (ops.debug) {
Log.setLevel(Log.DEBUG)
} else if (ops.info) {
Log.setLevel(Log.INFO)
} else if (ops.quiet) {
Log.setLevel(Log.QUIET)
} else {
Log.setLevel(Log.DEFAULT)
}
console.log();
// Perhaps the command is 'tooltwist init ...'
if (ops.args && ops.args.length > 0 && ops.args[0] == 'init') {
return Init.handleInitCommandLine(ops);
}
// The nopull option causes the 'git pull' to be bypassed.
if (ops.nopull) {
Config.setNoPull(true);
}
// Check the config file exists
Config.findConfig();
// Log.info('found = ' + Config.wasFound());
// Log.info('inCurrentDirectory = ' + Config.isInCurrentDirectory());
// Log.info('config = ' + Config.getConfig());
// Log.info('projectRoot = ' + Config.PROJECT_ROOT);
if (ops.args && ops.args.length > 0 && ops.args[0] == 'clean') {
// remove generated files, but not webdesign.
return Clean.clean();
}
if (ops.args && ops.args.length > 0 && ops.args[0] === 'fip-pairing') {
// Pair the image directory on this machine with a remote server.
return FipPairing.fromCommandLine(ops.args);
}
// Check for 'init' option.
if (ops.args && ops.args[0] == 'init') {
return Init.handleInitCommandLine(ops);
//ZZZZZZZZZZZZ Can't get here
/*
* Initialise the tooltwist.js file.
* If the 'server' option is used, we might need to instantiate a server.
*/
// Check we don't already have a specification file.
if (Config.wasFound()) {
Log.error();
Log.error('\tERROR: Specification already exists at ' + Config.getConfigPath() + '.\n');
process.exit(1);
}
if (ops.args.length == 1) {
// Default is designer mode
Config.createDefaultConfigFile('designer', null);
} else if (ops.args.length == 2) {
// mode has been specified
switch (ops.args[1]){
case 'designer':
case 'deploy':
case 'controller':
Config.createDefaultConfigFile(ops.args[1], null);
break;
case 'server':
if (ops['digital-ocean']) {
/*
* Create new a server at Digital Ocean.
*/
console.log('Initializing a Digital Ocean server');
return DO.createServer(function(err, server){
if (err) {
console.log('An error occurred creating the new server: ', err)
process.exit(1);
}
// Display a nice message
var name = server.name;
var host = server.ip_address;
console.log();
console.log('\tA new droplet named \'' + name + '\' has been created at Digital Ocean.');
console.log('\tYou may log in using the command:');
console.log();
console.log('\t ssh tooltwist@' + host);
console.log();
console.log('\tA configuration file (tooltwist.js) defines deployment to this server.');
console.log('\tAfter adjusting the configuration, deployment can be done using the command');
console.log();
console.log('\t tooltwist (with no parameters).');
console.log();
console.log();
// Create a config file and exit
Config.createDefaultConfigFile('deploy', host);
});
}
}
}
ops.printHelp();
process.exit(1);
}
// Check the config file was found
if ( !Config.wasFound()) {
Log.error();
Log.error('\tERROR: ' + Config.CONFIG_FILE + ' could not be found.');
Log.error();
Log.error('Tip: use \'tooltwist init\' to create a default config file.\n');
process.exit(1);
}
var config = Config.getConfig();
if (!config.mode) config.mode = "unknown";
// // See if we want to initialise the config file (tooltwist.js)
// //Log.debug('ops=', ops)
// if (ops.args && ops.args[0] == 'init') {
// if (ops.args.length != 2) usage();
// var projectName = ops.args[1];
// newProject(projectName); // Does not return
// }
if (ops.args && ops.args.length > 0) {
var operation = ops.args[0];
} else {
ops.printHelp();
process.exit(1);
}
// Check for non-plugin operations
if (operation.indexOf('e') === 0) { // example-templates
return Templates.createExampleTemplates(config);
} else if (operation.indexOf('lo') === 0) { // login
return Login.login();
}
// See what build-related operaation is required
if (operation.indexOf('d') === 0) { // designer
// Designer is always ok. Override the mode.
config.mode = 'designer'
Config.setOperation(operation)
} else if (operation.indexOf('g') === 0) { // generate
// For generate, use the default plugin.
Config.setOperation(config.mode)
} else if (operation === config.mode) {
// Use this mode
Config.setOperation(operation)
} else {
// Operation incompatible with the config file.
Log.error();
Log.error('Sorry, operation \'' + operation + '\' is not defined in tooltwist.js.');
Log.error('Did you mean \'' + config.mode + '\'?\n')
process.exit(1);
}
// process.exit(1)
/*
* Check for force-designer mode.
* When debugging controller problems, this allows the server to remain
* running while we check generate, Grunt or instll problems. Note that
* this must be located below the 'generate' command handling above.
*/
if (ops['force-designer']) {
Config.IS_CONTROLLER = false;
}
// Check we have the gradle wrapper. This is a standard Gradle
// script that installs gradle if it not already installed.
Gradle.checkGradleWrapper(Config.BUILD_DIR);
// Check we have the packages we need already installed.
Prerequisites.check(function(exist) {
if (!exist) {
// Missing pre-requisites (already reported), so bomb out.
Log.error('Exiting.\n\n')
process.exit(1);
}
// Do any required preparation before building.
Config.plugin.beforePhase1();
if (operation === "controller") {
// CONTROLLER MODE
// We are generating for a controller. Use the old config files to determine everything.
Controller.Controller();
Config.REPO = Controller.WEBDESIGN_REMOTEURL;
Config.BRANCH = Controller.WEBDESIGN_VERSION;
} else if (operation === "deploy") {
// DEPLOY MODE
// We are generating for a controller. Use our tooltwist.js to determine everything.
Controller.init_fromConfig(config);
Config.REPO = config['designer'].repo;
Config.BRANCH = config['designer'].branch;
} else if (operation === "designer") {
// // DESIGNER MODE
// var repo = config['designer'].repo;
// //ZZZ check is set
// var branch = config['designer'].branch;
// // ZZZ check works if undefined
} else {
// Unknown mode
// Log.error('Error: unknown mode in tooltwist.js: ' + config.mode);
// Log.error('Try "designer", "deploy" or "controller".\n');
// process.exit(1);
}
/*
* The generate command generates navpoints, images, etc.
*/
if (operation == 'generate') {
if (ops.args.length != 2){
ops.printHelp();
process.exit(1);
}
var webdesignProject = ops.args[1];
Config.setProjectName(webdesignProject);
Log.debug("Webdesign project is " + webdesignProject)
// Controller.initFromController();
// var repo = Controller.WEBDESIGN_REMOTEURL;
// var branch = Controller.WEBDESIGN_VERSION;
return Generate.generate();
}
Log.log('---------------------------------------------------------------------------');
Log.log(' MODE: ' + Config.MODE);
Log.log('REPOSITORY: ' + Config.REPO);
Log.log(' BRANCH: ' + Config.BRANCH);
Log.log('TT VERSION: ' + Config.TOOLTWIST_VERSION);
if (config.mode === "controller") {
Log.log();
Log.log(' LAUNCHPAD: ' + Controller.LAUNCHPAD_NAME);
Log.log('SERVERSLOT: ' + Controller.PRODUCTION_SLOT_NAME);
}
if (config.mode === "deploy" || config.mode === "controller") {
Log.log(' TARGET: ' + Controller.PRODUCTION_SERVER);
Log.log(' DIRECTORY: ' + Controller.PRODUCTION_SERVER_HOME);
}
Log.log('---------------------------------------------------------------------------');
// Update the webdesign project, either cloning it or pulling it if it already exists.
Webdesign.findWebdesignProject(Config.REPO, function(project) {
if (project) {
// We found the project - update it.
if (Config.NO_PULL) {
// Don't pull
Log.log('Not updating webdesign project.')
return Webdesign.checkBranch(project, Config.BRANCH, haveProject);
}
Log.log();
Log.log('Updating webdesign project.')
return Webdesign.pullWebdesignProject(project, Config.BRANCH, haveProject);
} else {
// No project found
if (Config.REPO) {
// No project, but we have a repo specified, so clone it.
Log.log('Cloning webdesign project.')
Log.info('cloning into ' + Config.WEBDESIGN_DIR + '.')
return Webdesign.cloneWebdesignProject(Config.REPO, Config.BRANCH, haveProject);
} else {
// No project found for us to use.
Log.error('Error: No project found for this repository.')
process.exit(1);
}
}
});
});
/**
* This function is called once we find the required webdesign project.
*/
function haveProject(project) {
Log.debug();
Log.debug('haveProject(' + project + ')');
// Remember the current project
Config.setProjectName(project);
// Start the server (phase 1).
// Phase 2 will happen within Phase 1, amd will generate if we are in deploy or controller mode, etc.
Server.phase1(project);
}
})(); // end of main()