/* global it:false */ /* global describe:false */ /* global before:false */ /* global after:false */ 'use strict'; const appdb = require('../appdb.js'), apps = require('../apps.js'), async = require('async'), BoxError = require('../boxerror.js'), database = require('../database'), domains = require('../domains.js'), expect = require('expect.js'), reverseProxy = require('../reverseproxy.js'), _ = require('underscore'); const DOMAIN_0 = { domain: 'foobar.com', zoneName: 'foobar.com', provider: 'digitalocean', config: { token: 'abcd' }, tlsConfig: { provider: 'fallback' }, wellKnown: null }; DOMAIN_0.fallbackCertificate = reverseProxy.generateFallbackCertificateSync(DOMAIN_0.domain); const auditSource = { ip: '1.2.3.4' }; const DOMAIN_1 = { domain: 'foo.cloudron.io', zoneName: 'cloudron.io', provider: 'manual', config: null, tlsConfig: { provider: 'fallback' }, wellKnown: null }; DOMAIN_1.fallbackCertificate = reverseProxy.generateFallbackCertificateSync(DOMAIN_1.domain); describe('database', function () { before(function (done) { async.series([ database.initialize, database._clear ], done); }); after(function (done) { async.series([ database._clear, database.uninitialize ], done); }); describe('apps', function () { var APP_0 = { id: 'appid-0', appStoreId: 'appStoreId-0', installationState: apps.ISTATE_PENDING_INSTALL, error: null, runState: 'running', location: 'some-location-0', domain: DOMAIN_0.domain, manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' }, containerId: null, containerIp: null, portBindings: { port: { hostPort: 5678, type: 'tcp' } }, health: null, accessRestriction: null, memoryLimit: 4294967296, cpuShares: 256, sso: true, debugMode: null, reverseProxyConfig: {}, enableBackup: true, enableMailbox: true, alternateDomains: [], aliasDomains: [], env: { 'CUSTOM_KEY': 'CUSTOM_VALUE' }, mailboxName: 'talktome', mailboxDomain: DOMAIN_0.domain, enableAutomaticUpdate: true, dataDir: null, tags: [], label: null, taskId: null, mounts: [], proxyAuth: false, servicesConfig: {}, hasIcon: false, hasAppStoreIcon: false }; var APP_1 = { id: 'appid-1', appStoreId: 'appStoreId-1', installationState: apps.ISTATE_PENDING_INSTALL, // app health tests rely on this initial state error: null, runState: 'running', location: 'some-location-1', domain: DOMAIN_0.domain, manifest: { version: '0.2', dockerImage: 'docker/app1', healthCheckPath: '/', httpPort: 80, title: 'app1' }, containerId: null, containerIp: null, portBindings: { }, health: null, accessRestriction: { users: [ 'foobar' ] }, memoryLimit: 0, cpuShares: 512, sso: true, debugMode: null, reverseProxyConfig: {}, enableBackup: true, alternateDomains: [], aliasDomains: [], env: {}, enableMailbox: true, mailboxName: 'callme', mailboxDomain: DOMAIN_0.domain, enableAutomaticUpdate: true, dataDir: null, tags: [], label: null, taskId: null, mounts: [], proxyAuth: false, servicesConfig: {}, hasIcon: false, hasAppStoreIcon: false }; before(function (done) { async.series([ database._clear, domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, auditSource) ], done); }); after(function (done) { database._clear(done); }); it('add fails due to missing arguments', function () { expect(function () { appdb.add(APP_0.id, APP_0.manifest, APP_0.installationState, function () {}); }).to.throwError(); expect(function () { appdb.add(APP_0.id, function () {}); }).to.throwError(); }); it('exists returns false', function (done) { appdb.exists(APP_0.id, function (error, exists) { expect(error).to.be(null); expect(exists).to.be(false); done(); }); }); it('add succeeds', function (done) { appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.portBindings, APP_0, function (error) { expect(error).to.be(null); done(); }); }); it('exists succeeds', function (done) { appdb.exists(APP_0.id, function (error, exists) { expect(error).to.be(null); expect(exists).to.be(true); done(); }); }); it('getPortBindings succeeds', function (done) { appdb.getPortBindings(APP_0.id, function (error, bindings) { expect(error).to.be(null); expect(bindings).to.be.an(Object); expect(bindings).to.be.eql({ port: { hostPort: '5678', type: 'tcp' } }); done(); }); }); it('add of same app fails', function (done) { appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, [], APP_0, function (error) { expect(error).to.be.a(BoxError); expect(error.reason).to.be(BoxError.ALREADY_EXISTS); done(); }); }); it('get succeeds', function (done) { appdb.get(APP_0.id, function (error, result) { expect(error).to.be(null); expect(result).to.be.an('object'); expect(_.omit(result, ['creationTime', 'updateTime', 'ts', 'healthTime', 'resetTokenCreationTime'])).to.be.eql(APP_0); done(); }); }); it('get of nonexisting code fails', function (done) { appdb.get(APP_1.id, function (error, result) { expect(error).to.be.a(BoxError); expect(error.reason).to.be(BoxError.NOT_FOUND); expect(result).to.not.be.ok(); done(); }); }); it('update succeeds', function (done) { APP_0.installationState = 'some-other-status'; APP_0.location = 'some-other-location'; APP_0.manifest.version = '0.2'; APP_0.accessRestriction = ''; APP_0.memoryLimit = 1337; APP_0.cpuShares = 1024; var data = { installationState: APP_0.installationState, location: APP_0.location, domain: APP_0.domain, manifest: APP_0.manifest, accessRestriction: APP_0.accessRestriction, memoryLimit: APP_0.memoryLimit, cpuShares: APP_0.cpuShares }; appdb.update(APP_0.id, data, function (error) { expect(error).to.be(null); appdb.get(APP_0.id, function (error, result) { expect(error).to.be(null); expect(result).to.be.an('object'); expect(_.omit(result, ['creationTime', 'updateTime', 'ts', 'healthTime','resetTokenCreationTime'])).to.be.eql(APP_0); done(); }); }); }); it('update of nonexisting app fails', function (done) { appdb.update(APP_1.id, { installationState: APP_1.installationState, location: APP_1.location }, function (error) { expect(error).to.be.a(BoxError); expect(error.reason).to.be(BoxError.NOT_FOUND); done(); }); }); it('add second app succeeds', function (done) { appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, [], APP_1, function (error) { expect(error).to.be(null); done(); }); }); it('getAll succeeds', function (done) { appdb.getAll(function (error, result) { expect(error).to.be(null); expect(result).to.be.an(Array); expect(result.length).to.be(2); expect(_.omit(result[0], ['creationTime', 'updateTime','ts', 'healthTime', 'resetTokenCreationTime'])).to.be.eql(APP_0); expect(_.omit(result[1], ['creationTime', 'updateTime','ts', 'healthTime', 'resetTokenCreationTime'])).to.be.eql(APP_1); done(); }); }); it('delete succeeds', function (done) { appdb.del(APP_0.id, function (error) { expect(error).to.be(null); done(); }); }); it('getPortBindings should be empty', function (done) { appdb.getPortBindings(APP_0.id, function (error, bindings) { expect(error).to.be(null); expect(bindings).to.be.an(Object); expect(bindings).to.be.eql({ }); done(); }); }); it('cannot delete previously delete record', function (done) { appdb.del(APP_0.id, function (error) { expect(error).to.be.a(BoxError); expect(error.reason).to.be(BoxError.NOT_FOUND); done(); }); }); it('can set app as healthy', function (done) { appdb.setHealth(APP_1.id, apps.HEALTH_HEALTHY, new Date(), function (error) { expect(error).to.be(null); done(); }); }); it('cannot set health of unknown app', function (done) { appdb.setHealth('randomId', apps.HEALTH_HEALTHY, new Date(), function (error) { expect(error).to.be.ok(); done(); }); }); }); describe('importFromFile', function () { before(function (done) { async.series([ database.initialize, database._clear ], done); }); it('cannot import from non-existent file', function (done) { database.importFromFile('/does/not/exist', function (error) { expect(error).to.be.ok(); done(); }); }); it('can export to file', function (done) { // arch only has maria db which lacks some mysqldump options we need, this is only here to allow running the tests :-/ if (require('child_process').execSync('/usr/bin/mysqldump --version').toString().indexOf('MariaDB') !== -1) return done(); database.exportToFile('/tmp/box.mysqldump', function (error) { expect(error).to.be(null); done(); }); }); it('can import from file', function (done) { // arch only has maria db which lacks some mysqldump options we need, this is only here to allow running the tests :-/ if (require('child_process').execSync('/usr/bin/mysqldump --version').toString().indexOf('MariaDB') !== -1) return done(); database.importFromFile('/tmp/box.mysqldump', function (error) { expect(error).to.be(null); done(); }); }); }); });