diff --git a/app/controllers/infra.js b/app/controllers/infra.js new file mode 100644 index 0000000..b9d0f48 --- /dev/null +++ b/app/controllers/infra.js @@ -0,0 +1,89 @@ +'use strict'; +var CJM = require('carbono-json-messages'); +var uuid = require('node-uuid'); +var bo = require('../lib/mission-control-bo'); + +module.exports = function (app, etcdManager) { + + this.createContainer = function(req, res, next) { + + var projectId = req.body.projectId; + var machineAlias = req.body.machineAlias; + + // Check data consistency + // @todo Create an definitive helper for handling errors. + // There are too much repeated code in the repositories. + if (!projectId || !machineAlias) { + var cjm = new CJM({apiVersion: '1.0'}); + res.status(400); + var error = { + code: 400, + message: 'Missing mandatory parameters', + errors: 'projectId and machineAlias should have an valid value', + }; + cjm.setError(error); + res.json(cjm); + res.end(); + return; + }; + + // Get the IPE module URL + var ipeURL = etcdManager.getIpeUrl(); + if (!ipeURL) { + var cjm = new CJM({apiVersion: '1.0'}); + var error = { + code: 500, + message: 'Internal data is missing', + errors: 'ipeURL is not set in etcdManager, I can\'t send the request!' + }; + res.status(500); + cjm.setError(error); + res.json(cjm); + res.end(); + return; + }; + + // Now we can make the call to the business object. + bo.createUserContainer(ipeURL, projectId, machineAlias, + /** + * Callback function + */ + function (err, ret) { + var cjm = new CJM({apiVersion: '1.0'}); + try { + if (err) { + res.status(400); + var error = { + code: 400, + message: 'Could not create container', + errors: err, + }; + cjm.setError(error); + } else { + // Probably an empty answer, but let's send it anyway + cjm.setData( + { + id: uuid.v4(), + items: [ret], + } + ); + } + res.json(cjm); + res.end(); + } catch (e) { + // Unknown error... + var error = { + code: 500, + message: 'Unknown internal error', + errors: e, + }; + cjm.setError(error); + res.json(cjm); + res.status(500).end(); + } + } + ); + }; + + return this; +}; diff --git a/app/lib/mission-control-bo.js b/app/lib/mission-control-bo.js index 37a94d2..1d33301 100644 --- a/app/lib/mission-control-bo.js +++ b/app/lib/mission-control-bo.js @@ -1,6 +1,7 @@ 'use strict'; var CM = require('./code-machine-cli'); var dcm = require('./ide-development-container-manager-cli'); +var ipe = require('./mogno-ipe-client'); /** * Pedir uma maquina pro dcm e nesse momento criar uma @@ -41,3 +42,20 @@ exports.createDevContainer = function (dcmURL, project, cb) { cb(err, res, cm); }); }; + +/** + * Sends an message to the IPE module requesting an specific machine to be + * instantiated + */ +exports.createUserContainer = function (ipeURL, project, machineAlias, cb) { + + // NOTE: The machineAlias is not necessarily the docker image name. + // This is the place where we sholud map machineAlias to image name + // (Assuming the b.o. is the one who knows everything) + var dockerImage = machineAlias; + + ipe.create(ipeURL, project, dockerImage, function (err, res) { + // Nothing else to do? + cb(err, res); + }); +}; diff --git a/app/lib/mogno-ipe-client.js b/app/lib/mogno-ipe-client.js new file mode 100644 index 0000000..11ab093 --- /dev/null +++ b/app/lib/mogno-ipe-client.js @@ -0,0 +1,76 @@ +'use strict'; +var request = require('request'); +var CJM = require('carbono-json-messages'); + +/** + * Creates and/or retrieves an docker instance and + * returns a callback function. + * + * @todo Parse errors and throw them. + * @todo Use carbono-json-messages + * + * @param {string} ipeURL - URL retrieved from etcd. + * @param {string} proj - Id of the project + * @param {onbject} cb - Callback function that receives errors and/or + * other information + * + * @return function (err, res) + */ +exports.create = function (ipeURL, proj, alias, cb) { + if (ipeURL) { + var url = ipeURL + '/container'; + var headers = { + 'Content-Type': 'application/json', + }; + var aux = { + apiVersion: '1.0', + id: 'xyzzy-wyzzy', + data: { + id: '1337', + items: + [ + { + projectId: proj, + machineAlias: alias + }, + ], + }, + }; + var load = { + url: url, + headers: headers, + json: aux, + }; + + /** + * Callback function that tries to parse (JSON) the body object + * + * @param {Object} err - Error object + * @param {Object} httpResponse - Response object + * @param {string} body - String containing a JSON structure + */ + var _cb = function (err, httpResponse, body) { + try { + body = JSON.parse(body); + } catch (err) { + this.err = err; + } + cb(err, body); + }; + request.post(load, _cb); + + } else { + // If there is no IPE reference, nothing can be done. Sends an Error. + var cjm = new CJM({apiVersion: '1.0'}); + try { + var err = { + code: 400, + message: 'ipeURL is required for this operation', + }; + cjm.setError(err); + cb(cjm, null); + } catch (e) { + cb(e, null); + } + } +}; diff --git a/app/routes/infra.js b/app/routes/infra.js new file mode 100644 index 0000000..aceecd1 --- /dev/null +++ b/app/routes/infra.js @@ -0,0 +1,8 @@ +'use strict'; +module.exports = function (app) { + var infra = app.controllers.infra; + + app.get('/createContainer', infra.createContainer); + + return this; +};