webgme-engine
Version:
WebGME server and Client API without a GUI
248 lines (223 loc) • 10.3 kB
JavaScript
/*eslint-env node*/
/*eslint no-console: 0*/
/**
* @module Bin:RunPlugin
* @author lattmann / https://github.com/lattmann
* @author pmeijer / https://github.com/pmeijer
*/
;
var main;
main = function (argv, callback) {
var path = require('path'),
configDir = path.join(process.cwd(), 'config'),
gmeConfig = require(configDir),
webgme = require('../../index'),
MongoURI = require('mongo-uri'),
Command = require('commander').Command,
logger = webgme.Logger.create('gme:bin:runplugin', gmeConfig.bin.log),
Q = require('q'),
program = new Command(),
params,
storage,
projectAccess,
gmeAuth,
STORAGE_CONSTANTS = webgme.requirejs('common/storage/constants'),
PluginCliManager = webgme.PluginCliManager,
deferred = Q.defer(),
project,
projectName,
pluginName,
pluginConfig,
err,
pluginResult,
userName;
function list(val) {
return val ? val.split(',') : [];
}
webgme.addToRequireJsPaths(gmeConfig);
program
.version('2.2.0')
.arguments('<pluginName> <projectName>')
.option('-b, --branchName [string]', 'Name of the branch to load and save to.', 'master')
.option('-c, --commitHash [string]', 'Commit hash to run from, if set branch will only be used for update.')
.option('-a, --activeNode [string]', 'ID/Path to active node.', '')
.option('-s, --activeSelection [string]', 'IDs/Paths of selected nodes (comma separated with no spaces).', list)
.option('-n, --namespace [string]',
'Namespace the plugin should run under.', '')
.option('-m, --mongo-database-uri [url]',
'URI of the MongoDB [default from the configuration file]', gmeConfig.mongo.uri)
.option('-u, --user [string]', 'the user of the command [if not given we use the default user]. Note that if ' +
'this is used together with the --serverUrl option the password can be provided by adding a semicolon.',
gmeConfig.authentication.guestAccount)
.option('-o, --owner [string]', 'the owner of the project [by default, the user is the owner]')
.option('-w, --writeBlobFilesDir [string]',
'If defined will also write blob-files to %cwd%/%writeBlobFilesDir%')
.option('-j, --pluginConfigPath [string]',
'Path to json file with plugin options that should be overwritten.', '')
.option('-l, --serverUrl [string]', 'If specified the plugin will connect to the storage via ' +
'a running webgme server, example "http://localhost:8888". Note that if a different user than the ' +
'guest is used the password needs to be added after a semicolon, e.g. "-u someUser:pass".')
.on('--help', function () {
var i,
env = process.env.NODE_ENV || 'default';
console.log(' Examples:');
console.log();
console.log(' $ node run_plugin.js PluginGenerator TestProject');
console.log(' $ node run_plugin.js PluginGenerator TestProject -b branch1 -j pluginConfig.json');
console.log(' $ node run_plugin.js MinimalWorkingExample TestProject -a /1/b');
console.log(' $ node run_plugin.js MinimalWorkingExample TestProject -s /1,/1/c,/d');
console.log(' $ node run_plugin.js MinimalWorkingExample TestProject -c #123..');
console.log(' $ node run_plugin.js MinimalWorkingExample TestProject -w plugin-blobs');
console.log(' $ node run_plugin.js MinimalWorkingExample TestProject -b b1 -c ' +
'#def8861ca16237e6756ee22d27678d979bd2fcde');
console.log(' $ node run_plugin.js PluginGenerator TestProject --serverUrl http://localhost:8888');
console.log();
console.log(' Plugin paths using ' + configDir + path.sep + 'config.' + env + '.js :');
console.log();
for (i = 0; i < gmeConfig.plugin.basePaths.length; i += 1) {
console.log(' "' + gmeConfig.plugin.basePaths[i] + '"');
}
})
.parse(argv);
if (program.args.length < 2) {
if (!global.TESTING) {
program.help();
}
deferred.reject(new Error('A project and pluginName must be specified.'));
return deferred.promise.nodeify(callback);
}
// this line throws a TypeError for invalid databaseConnectionString
MongoURI.parse(program.mongoDatabaseUri);
gmeConfig.mongo.uri = program.mongoDatabaseUri;
pluginName = program.args[0];
projectName = program.args[1];
logger.info('Executing ' + pluginName + ' plugin on ' + projectName + ' in branch ' +
program.branchName + '.');
if (program.pluginConfigPath) {
try {
pluginConfig = require(path.resolve(program.pluginConfigPath));
} catch (e) {
deferred.reject(e);
return deferred.promise.nodeify(callback);
}
} else {
pluginConfig = {};
}
userName = program.user.split(':')[0];
webgme.getGmeAuth(gmeConfig)
.then(function (gmeAuth_) {
gmeAuth = gmeAuth_;
storage = webgme.getStorage(logger, gmeConfig, gmeAuth);
return storage.openDatabase();
})
.then(function () {
params = {
projectId: '',
username: userName
};
logger.info('Database is opened.');
if (program.owner) {
params.projectId = program.owner + STORAGE_CONSTANTS.PROJECT_ID_SEP + projectName;
} else {
params.projectId = userName + STORAGE_CONSTANTS.PROJECT_ID_SEP + projectName;
}
return storage.openProject(params);
})
.then(function (project_) {
logger.info('Project is opened.');
var projectAuthParams = {
entityType: gmeAuth.authorizer.ENTITY_TYPES.PROJECT,
};
project = project_;
project.setUser(userName);
return gmeAuth.authorizer.getAccessRights(params.username, params.projectId, projectAuthParams);
})
.then(function (access) {
logger.info('User has the following rights to the project: ', access);
projectAccess = access;
return project.getBranchHash(program.branchName);
})
.then(function (commitHash) {
var executeDeferred = Q.defer(),
context = {
activeNode: program.activeNode,
activeSelection: program.activeSelection || [],
branchName: program.branchName,
commitHash: program.commitHash || commitHash,
namespace: program.namespace
},
pluginManager;
if (program.serverUrl) {
logger.info('serverUrl was specified "', program.serverUrl, '" will request token for user.');
webgme.utils.requestWebGMEToken(gmeConfig, userName, program.user.split(':')[1], program.serverUrl)
.then(function (token) {
var WorkerRequests = require('../server/worker/workerrequests'),
wr = new WorkerRequests(logger, gmeConfig, program.serverUrl);
context.project = project.projectId;
wr.executePlugin({webgme: token}, undefined, pluginName,
{
managerConfig: context,
pluginConfig: pluginConfig,
},
function (err_, pluginResult_) {
err = err_;
pluginResult = pluginResult_;
executeDeferred.resolve();
}
);
})
.catch(executeDeferred.reject);
} else {
pluginManager = new PluginCliManager(project, logger, gmeConfig, {
writeBlobFilesDir: program.writeBlobFilesDir
});
pluginManager.projectAccess = projectAccess;
pluginManager.executePlugin(pluginName, pluginConfig, context,
function (err_, pluginResult_) {
err = err_;
pluginResult = pluginResult_;
executeDeferred.resolve();
}
);
}
return executeDeferred.promise;
})
.catch(function (err_) {
err = err_;
})
.finally(function () {
logger.debug('Closing database connections...');
return Q.allSettled([storage.closeDatabase(), gmeAuth.unload()])
.finally(function () {
logger.debug('Closed.');
if (pluginResult) {
// The caller of this will have to check the result.success..
deferred.resolve(pluginResult);
} else if (err) {
deferred.reject(err instanceof Error ? err : new Error(err));
} else {
deferred.reject(new Error('No error nor any plugin result was returned!?'));
}
});
});
return deferred.promise.nodeify(callback);
};
module.exports = {
main: main
};
if (require.main === module) {
main(process.argv)
.then(function (pluginResult) {
if (pluginResult.success === true) {
console.info('execution was successful:', JSON.stringify(pluginResult, null, 2));
process.exit(0);
} else {
console.error('execution failed:', JSON.stringify(pluginResult, null, 2));
process.exit(1);
}
})
.catch(function (err) {
console.error('Could not open the project or branch', err);
process.exit(1);
});
}