diff --git a/src/routes/test/apps-test.js b/src/routes/test/apps-test.js index bb4f8dd4c..7a2ada76f 100644 --- a/src/routes/test/apps-test.js +++ b/src/routes/test/apps-test.js @@ -22,6 +22,7 @@ var Server = require('../../server.js'), appdb = require('../../appdb.js'), url = require('url'), Docker = require('dockerode'), + net = require('net'), config = require('../../../config.js'); var SERVER_URL = 'http://localhost:' + config.port; @@ -344,3 +345,153 @@ describe('App installation', function () { }); }); +describe('App installation - port bindings', function () { + this.timeout(10000); + + var hockServer; + + before(function (done) { + setup(function (error) { + if (error) return done(error); + + hock(parseInt(url.parse(config.appServerUrl).port, 10), function (error, server) { + if (error) return done(error); + var manifest = JSON.parse(fs.readFileSync(__dirname + '/test.app', 'utf8')); + hockServer = server; + + hockServer + .get('/api/v1/app/' + APP_ID + '/manifest') + .reply(200, manifest, { 'Content-Type': 'application/json' }) + .post('/api/v1/subdomains?token=' + config.token, { subdomain: APP_LOCATION }) + .reply(200, { }, { 'Content-Type': 'application/json' }) + .delete('/api/v1/subdomain/' + APP_LOCATION + '?token=' + config.token) + .reply(200, { }, { 'Content-Type': 'application/json' }); + done(); + }); + }); + }); + + after(function (done) { + cleanup(function (error) { + if (error) return done(error); + hockServer.close(done); + }); + }); + + var appInfo = null; + + it('can install test app', function (done) { + var count = 0; + function checkInstallStatus() { + request.get(SERVER_URL + '/api/v1/app/' + APP_ID) + .query({ access_token: token }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + if (res.body.installationState === appdb.ISTATE_INSTALLED) { appInfo = res.body; return done(null); } + if (res.body.installationState === appdb.ISTATE_ERROR) return done(new Error('Install error')); + if (++count > 20) return done(new Error('Timedout')); + setTimeout(checkInstallStatus, 400); + }); + } + + request.post(SERVER_URL + '/api/v1/app/install') + .query({ access_token: token }) + .send({ app_id: APP_ID, password: PASSWORD, location: APP_LOCATION, portBindings: { "7778" : "7171" } }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + checkInstallStatus(); + }); + }); + + it('installation - container created', function (done) { + expect(appInfo.containerId).to.be.ok(); + docker.getContainer(appInfo.containerId).inspect(function (error, data) { + expect(error).to.not.be.ok(); + expect(data.Config.ExposedPorts['7777/tcp']).to.eql({ }); + expect(data.Config.Env).to.contain('ECHO_SERVER_PORT=7171'); + expect(data.HostConfig.PortBindings['7778/tcp'][0].HostPort).to.eql('7171'); + expect(data.Volumes['/app/data']).to.eql(config.appDataRoot + '/' + APP_ID); + done(); + }); + }); + + it('installation - nginx config', function (done) { + expect(fs.existsSync(config.nginxAppConfigDir + '/' + APP_LOCATION + '.conf')); + done(); + }); + + it('installation - registered subdomain', function (done) { + // this is checked in unregister subdomain testcase + done(); + }); + + it('installation - volume created', function (done) { + expect(fs.existsSync(config.appDataRoot + '/' + APP_ID)); + done(); + }); + + it('installation - http is up and running', function (done) { + setTimeout(function () { + request.get('http://localhost:' + appInfo.httpPort + appInfo.manifest.health_check_url) + .end(function (err, res) { + expect(!err).to.be.ok(); + expect(res.statusCode).to.equal(200); + done(); + }); + }, 2000); // give some time for docker to settle + }); + + it('installation - tcp port mapping works', function (done) { + var client = net.connect(7171); + client.on('data', function (data) { + expect(data.toString()).to.eql('ECHO_SERVER_PORT=7171'); + done(); + }); + client.on('error', done); + }); + + it('can uninstall app', function (done) { + var count = 0; + function checkUninstallStatus() { + request.get(SERVER_URL + '/api/v1/app/' + APP_ID) + .query({ access_token: token }) + .end(function (err, res) { + if (res.statusCode === 404) return done(null); + if (++count > 20) return done(new Error('Timedout')); + setTimeout(checkUninstallStatus, 400); + }); + } + + request.post(SERVER_URL + '/api/v1/app/' + APP_ID + '/uninstall') + .query({ access_token: token }) + .end(function (err, res) { + expect(res.statusCode).to.equal(200); + checkUninstallStatus(); + }); + }); + + it('uninstalled - container destroyed', function (done) { + docker.getContainer(appInfo.containerId).inspect(function (error, data) { + expect(error).to.be.ok(); + done(); + }); + }); + + it('uninstalled - volume destroyed', function (done) { + expect(!fs.existsSync(config.appDataRoot + '/' + APP_ID)); + done(); + }); + + it('uninstalled - unregistered subdomain', function (done) { + hockServer.done(function (error) { // checks if all the hockServer APIs were called + expect(!error).to.be.ok(); + done(); + }); + }); + + it('uninstalled - removed nginx', function (done) { + expect(!fs.existsSync(config.nginxAppConfigDir + '/' + APP_LOCATION + '.conf')); + done(); + }); +}); + diff --git a/src/routes/test/test.app b/src/routes/test/test.app index b628226c0..0dab83ffc 100644 --- a/src/routes/test/test.app +++ b/src/routes/test/test.app @@ -1,10 +1,16 @@ { "name": "test", - "version": "0.1", - "docker_image": "girish/test:0.1", + "version": "0.2", + "docker_image": "girish/test:0.2", "home_url": "/", "health_check_url": "/", "http_port": 7777, + "tcp_ports": { + "7778": { + "description": "Echo server", + "environment_variable": "ECHO_SERVER_PORT" + } + }, "suggested_locations": [ "ngircd", "irc"