fix tests
This commit is contained in:
@@ -6,6 +6,7 @@ const appdb = require('./appdb.js'),
|
||||
async = require('async'),
|
||||
auditSource = require('./auditsource.js'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
constants = require('./constants.js'),
|
||||
debug = require('debug')('box:apphealthmonitor'),
|
||||
docker = require('./docker.js'),
|
||||
eventlog = require('./eventlog.js'),
|
||||
@@ -187,6 +188,8 @@ function run(intervalSecs, callback) {
|
||||
assert.strictEqual(typeof intervalSecs, 'number');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
if (constants.TEST) return;
|
||||
|
||||
if (!gStartTime) gStartTime = new Date();
|
||||
|
||||
async.series([
|
||||
|
||||
@@ -6,8 +6,6 @@ exports = module.exports = {
|
||||
run,
|
||||
|
||||
// exported for testing
|
||||
_configureReverseProxy: configureReverseProxy,
|
||||
_unconfigureReverseProxy: unconfigureReverseProxy,
|
||||
_createAppDir: createAppDir,
|
||||
_deleteAppDir: deleteAppDir,
|
||||
_verifyManifest: verifyManifest,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert'),
|
||||
const assert = require('assert'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
database = require('./database.js'),
|
||||
safe = require('safetydance'),
|
||||
util = require('util');
|
||||
safe = require('safetydance');
|
||||
|
||||
var BACKUPS_FIELDS = [ 'id', 'identifier', 'creationTime', 'packageVersion', 'type', 'dependsOn', 'state', 'manifestJson', 'format', 'preserveSecs', 'encryptionVersion' ];
|
||||
const BACKUPS_FIELDS = [ 'id', 'identifier', 'creationTime', 'packageVersion', 'type', 'dependsOn', 'state', 'manifestJson', 'format', 'preserveSecs', 'encryptionVersion' ];
|
||||
|
||||
exports = module.exports = {
|
||||
add,
|
||||
|
||||
@@ -146,7 +146,7 @@ function testConfig(backupConfig, callback) {
|
||||
assert.strictEqual(typeof backupConfig, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var func = api(backupConfig.provider);
|
||||
const func = api(backupConfig.provider);
|
||||
if (!func) return callback(new BoxError(BoxError.BAD_FIELD, 'unknown storage provider', { field: 'provider' }));
|
||||
|
||||
if (backupConfig.format !== 'tgz' && backupConfig.format !== 'rsync') return callback(new BoxError(BoxError.BAD_FIELD, 'unknown format', { field: 'format' }));
|
||||
|
||||
@@ -185,12 +185,12 @@ function validateCertificate(location, domainObject, certificate) {
|
||||
}
|
||||
|
||||
function reload(callback) {
|
||||
if (constants.TEST) return callback();
|
||||
if (constants.TEST) return callback(null);
|
||||
|
||||
shell.sudo('reload', [ RESTART_SERVICE_CMD, 'nginx' ], {}, function (error) {
|
||||
if (error) return callback(new BoxError(BoxError.NGINX_ERROR, `Error reloading nginx: ${error.message}`));
|
||||
|
||||
callback();
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ exports = module.exports = {
|
||||
resumeJobs
|
||||
};
|
||||
|
||||
let apps = require('./apps.js'),
|
||||
const apps = require('./apps.js'),
|
||||
assert = require('assert'),
|
||||
async = require('async'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
@@ -119,6 +119,8 @@ function stopJobs(appId, appState, callback) {
|
||||
}
|
||||
|
||||
function sync() {
|
||||
if (constants.TEST) return;
|
||||
|
||||
apps.getAll(function (error, allApps) {
|
||||
if (error) return debug(`sync: error getting app list. ${error.message}`);
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ exports = module.exports = {
|
||||
LICENSE_KEY: 'license_key',
|
||||
LANGUAGE_KEY: 'language',
|
||||
CLOUDRON_ID_KEY: 'cloudron_id',
|
||||
CLOUDRON_TOKEN_KEY: 'cloudron_token',
|
||||
CLOUDRON_TOKEN_KEY: 'cloudron_token', // apstore token
|
||||
FIREWALL_BLOCKLIST_KEY: 'firewall_blocklist',
|
||||
|
||||
API_SERVER_ORIGIN_KEY: 'api_server_origin',
|
||||
|
||||
@@ -123,13 +123,13 @@ function checkDiskSpace(callback) {
|
||||
|
||||
debug('Checking disk space');
|
||||
|
||||
getDisks(function (error, disks) {
|
||||
getDisks(async function (error, disks) {
|
||||
if (error) {
|
||||
debug('checkDiskSpace: error getting disks %s', error.message);
|
||||
return callback();
|
||||
}
|
||||
|
||||
var oos = disks.disks.some(function (entry) {
|
||||
const oos = disks.disks.some(function (entry) {
|
||||
// ignore other filesystems but where box, app and platform data is
|
||||
if (entry.filesystem !== disks.boxDataDisk
|
||||
&& entry.filesystem !== disks.platformDataDisk
|
||||
@@ -142,7 +142,9 @@ function checkDiskSpace(callback) {
|
||||
|
||||
debug('checkDiskSpace: disk space checked. ok: %s', !oos);
|
||||
|
||||
notifications.alert(notifications.ALERT_DISK_SPACE, 'Server is running out of disk space', oos ? JSON.stringify(disks.disks, null, 4) : '', callback);
|
||||
await notifications.alert(notifications.ALERT_DISK_SPACE, 'Server is running out of disk space', oos ? JSON.stringify(disks.disks, null, 4) : '');
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var accesscontrol = require('../accesscontrol.js'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('access control', function () {
|
||||
describe('verifyToken', function () {
|
||||
// FIXME
|
||||
});
|
||||
|
||||
describe('hasRole', function () {
|
||||
// FIXME
|
||||
});
|
||||
});
|
||||
@@ -5,25 +5,13 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
database = require('../database.js'),
|
||||
acme2 = require('../acme2.js'),
|
||||
const acme2 = require('../acme2.js'),
|
||||
common = require('./common.js'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('Acme2', function () {
|
||||
before(function (done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
});
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
describe('getChallengeSubdomain', function () {
|
||||
it('non-wildcard', function () {
|
||||
|
||||
@@ -7,44 +7,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
appstore = require('../appstore.js'),
|
||||
database = require('../database.js'),
|
||||
const appstore = require('../appstore.js'),
|
||||
common = require('./common.js'),
|
||||
expect = require('expect.js'),
|
||||
nock = require('nock'),
|
||||
settings = require('../settings.js'),
|
||||
settingsdb = require('../settingsdb.js');
|
||||
|
||||
const DASHBOARD_DOMAIN = 'appstore-test.example.com';
|
||||
const APPSTORE_TOKEN = 'appstoretoken';
|
||||
const APP_ID = 'appid';
|
||||
const APPSTORE_APP_ID = 'appstoreappid';
|
||||
const MOCK_API_SERVER_ORIGIN = 'http://localhost:6060';
|
||||
|
||||
function setup(done) {
|
||||
nock.cleanAll();
|
||||
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings._setApiServerOrigin.bind(null, MOCK_API_SERVER_ORIGIN),
|
||||
settings.setDashboardLocation.bind(null, DASHBOARD_DOMAIN, 'my.' + DASHBOARD_DOMAIN),
|
||||
settings.initCache
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
nock.cleanAll();
|
||||
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
describe('Appstore', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
beforeEach(nock.cleanAll);
|
||||
|
||||
@@ -53,7 +29,7 @@ describe('Appstore', function () {
|
||||
});
|
||||
|
||||
it('can purchase an app', function (done) {
|
||||
var scope1 = nock(MOCK_API_SERVER_ORIGIN)
|
||||
var scope1 = nock(common.MOCK_API_SERVER_ORIGIN)
|
||||
.post(`/api/v1/cloudronapps?accessToken=${APPSTORE_TOKEN}`, function () { return true; })
|
||||
.reply(201, {});
|
||||
|
||||
@@ -66,11 +42,11 @@ describe('Appstore', function () {
|
||||
});
|
||||
|
||||
it('unpurchase succeeds if app was never purchased', function (done) {
|
||||
var scope1 = nock(MOCK_API_SERVER_ORIGIN)
|
||||
var scope1 = nock(common.MOCK_API_SERVER_ORIGIN)
|
||||
.get(`/api/v1/cloudronapps/${APP_ID}?accessToken=${APPSTORE_TOKEN}`)
|
||||
.reply(404, {});
|
||||
|
||||
var scope2 = nock(MOCK_API_SERVER_ORIGIN)
|
||||
var scope2 = nock(common.MOCK_API_SERVER_ORIGIN)
|
||||
.delete(`/api/v1/cloudronapps/${APP_ID}?accessToken=${APPSTORE_TOKEN}`, function () { return true; })
|
||||
.reply(204, {});
|
||||
|
||||
@@ -84,11 +60,11 @@ describe('Appstore', function () {
|
||||
});
|
||||
|
||||
it('can unpurchase an app', function (done) {
|
||||
var scope1 = nock(MOCK_API_SERVER_ORIGIN)
|
||||
var scope1 = nock(common.MOCK_API_SERVER_ORIGIN)
|
||||
.get(`/api/v1/cloudronapps/${APP_ID}?accessToken=${APPSTORE_TOKEN}`)
|
||||
.reply(200, {});
|
||||
|
||||
var scope2 = nock(MOCK_API_SERVER_ORIGIN)
|
||||
var scope2 = nock(common.MOCK_API_SERVER_ORIGIN)
|
||||
.delete(`/api/v1/cloudronapps/${APP_ID}?accessToken=${APPSTORE_TOKEN}`, function () { return true; })
|
||||
.reply(204, {});
|
||||
|
||||
|
||||
@@ -5,131 +5,18 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var appdb = require('../appdb.js'),
|
||||
apps = require('../apps.js'),
|
||||
apptask = require('../apptask.js'),
|
||||
async = require('async'),
|
||||
blobs = require('../blobs.js'),
|
||||
database = require('../database.js'),
|
||||
domains = require('../domains.js'),
|
||||
const apptask = require('../apptask.js'),
|
||||
common = require('./common.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
paths = require('../paths.js'),
|
||||
settings = require('../settings.js'),
|
||||
userdb = require('../userdb.js'),
|
||||
_ = require('underscore');
|
||||
|
||||
var MANIFEST = {
|
||||
'id': 'io.cloudron.test',
|
||||
'author': 'The Presidents Of the United States Of America',
|
||||
'title': 'test title',
|
||||
'description': 'test description',
|
||||
'tagline': 'test rocks',
|
||||
'website': 'http://test.cloudron.io',
|
||||
'contactEmail': 'test@cloudron.io',
|
||||
'version': '0.1.0',
|
||||
'manifestVersion': 1,
|
||||
'dockerImage': 'cloudron/test:25.2.0',
|
||||
'healthCheckPath': '/',
|
||||
'httpPort': 7777,
|
||||
'tcpPorts': {
|
||||
'ECHO_SERVER_PORT': {
|
||||
'title': 'Echo Server Port',
|
||||
'description': 'Echo server',
|
||||
'containerPort': 7778
|
||||
}
|
||||
},
|
||||
'addons': {
|
||||
'oauth': { },
|
||||
'redis': { },
|
||||
'mysql': { },
|
||||
'postgresql': { }
|
||||
}
|
||||
};
|
||||
|
||||
const DOMAIN_0 = {
|
||||
domain: 'example.com',
|
||||
zoneName: 'example.com',
|
||||
provider: 'route53',
|
||||
config: {
|
||||
accessKeyId: 'accessKeyId',
|
||||
secretAccessKey: 'secretAccessKey',
|
||||
endpoint: 'http://localhost:5353'
|
||||
},
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'letsencrypt-staging' },
|
||||
wellKnown: null
|
||||
};
|
||||
|
||||
let AUDIT_SOURCE = { ip: '1.2.3.4' };
|
||||
|
||||
var ADMIN = {
|
||||
id: 'admin123',
|
||||
username: 'admin123',
|
||||
password: 'secret',
|
||||
email: 'admin@me.com',
|
||||
fallbackEmail: 'admin@me.com',
|
||||
salt: 'morton',
|
||||
createdAt: 'sometime back',
|
||||
resetToken: '',
|
||||
displayName: '',
|
||||
role: 'owner',
|
||||
source: ''
|
||||
};
|
||||
|
||||
var APP = {
|
||||
id: 'appid',
|
||||
appStoreId: 'appStoreId',
|
||||
installationState: apps.ISTATE_PENDING_INSTALL,
|
||||
runState: 'running',
|
||||
location: 'applocation',
|
||||
domain: DOMAIN_0.domain,
|
||||
fqdn: DOMAIN_0.domain + '.' + 'applocation',
|
||||
manifest: MANIFEST,
|
||||
containerId: 'someid',
|
||||
portBindings: null,
|
||||
accessRestriction: null,
|
||||
memoryLimit: 0,
|
||||
mailboxDomain: DOMAIN_0.domain,
|
||||
alternateDomains: [],
|
||||
aliasDomains: []
|
||||
};
|
||||
const { APP } = common;
|
||||
|
||||
describe('apptask', function () {
|
||||
before(function (done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
blobs.initSecrets,
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE),
|
||||
userdb.add.bind(null, ADMIN.id, ADMIN),
|
||||
appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.domain, APP.portBindings, APP)
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
});
|
||||
|
||||
it('configure nginx correctly', function (done) {
|
||||
apptask._configureReverseProxy(APP, function (error) {
|
||||
expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unconfigure nginx', function (done) {
|
||||
apptask._unconfigureReverseProxy(APP, function (error) {
|
||||
expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
it('create volume', function (done) {
|
||||
apptask._createAppDir(APP, function (error) {
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var appdb = require('../appdb.js'),
|
||||
async = require('async'),
|
||||
const async = require('async'),
|
||||
backupdb = require('../backupdb.js'),
|
||||
backups = require('../backups.js'),
|
||||
BoxError = require('../boxerror.js'),
|
||||
createTree = require('./common.js').createTree,
|
||||
database = require('../database'),
|
||||
common = require('./common.js'),
|
||||
DataLayout = require('../datalayout.js'),
|
||||
domains = require('../domains.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
@@ -25,6 +22,8 @@ var appdb = require('../appdb.js'),
|
||||
settings = require('../settings.js'),
|
||||
tasks = require('../tasks.js');
|
||||
|
||||
const { createTree, APP } = common;
|
||||
|
||||
function createBackup(callback) {
|
||||
backups.startBackupTask({ username: 'test' }, function (error, taskId) { // this call does not wait for the backup!
|
||||
if (error) return callback(error);
|
||||
@@ -42,7 +41,8 @@ function createBackup(callback) {
|
||||
if (error) return callback(error);
|
||||
if (result.length !== 1) return callback(new Error('result is not of length 1'));
|
||||
|
||||
callback(null, result[0]);
|
||||
// the task progress and the db entry is set in the worker. wait for 2 seconds for backup lock to get released in parent process
|
||||
setTimeout(() => callback(null, result[0]), 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -71,119 +71,13 @@ function cleanupBackups(callback) {
|
||||
});
|
||||
}
|
||||
|
||||
describe('retention policy', function () {
|
||||
it('keeps latest', function () {
|
||||
let backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('latest');
|
||||
});
|
||||
|
||||
it('does not keep latest', function () {
|
||||
let backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: false }, []);
|
||||
expect(backup.keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
it('always keeps forever policy', function () {
|
||||
let backup = { creationTime: new Date() };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: -1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('keepWithinSecs');
|
||||
});
|
||||
|
||||
it('preserveSecs takes precedence', function () {
|
||||
let backup = { creationTime: new Date(), preserveSecs: 3000 };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('preserveSecs');
|
||||
});
|
||||
|
||||
it('1 daily', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(20, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily');
|
||||
expect(b[1].keepReason).to.be(undefined);
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
// if you are debugging this test, it's because of some timezone issue with all the hour substraction!
|
||||
it('2 daily, 1 weekly', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_ERROR, creationTime: moment().subtract(32, 'h').toDate() },
|
||||
{ id: '5', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(50, 'h').toDate() },
|
||||
{ id: '6', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 2, keepWeekly: 1, keepLatest: false }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily'); // today
|
||||
expect(b[1].keepReason).to.be('keepWeekly'); // today
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[4].discardReason).to.be('error'); // errored
|
||||
expect(b[5].discardReason).to.be('creating-too-long'); // creating for too long
|
||||
expect(b[6].keepReason).to.be(undefined); // outside retention policy
|
||||
});
|
||||
|
||||
it('2 daily, 3 monthly, 1 yearly', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_CREATING, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_ERROR, creationTime: moment().toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '5', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() },
|
||||
{ id: '6', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(49, 'h').toDate() },
|
||||
{ id: '7', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(51, 'd').toDate() },
|
||||
{ id: '8', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(84, 'd').toDate() },
|
||||
{ id: '9', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() },
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 2, keepMonthly: 3, keepYearly: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('creating');
|
||||
expect(b[1].discardReason).to.be('error'); // errored
|
||||
expect(b[2].keepReason).to.be('keepDaily');
|
||||
expect(b[3].keepReason).to.be('keepMonthly');
|
||||
expect(b[4].keepReason).to.be('keepYearly');
|
||||
expect(b[5].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[6].discardReason).to.be('creating-too-long'); // errored
|
||||
expect(b[7].keepReason).to.be('keepMonthly');
|
||||
expect(b[8].keepReason).to.be('keepMonthly');
|
||||
expect(b[9].keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('backups', function () {
|
||||
const DOMAIN_0 = {
|
||||
domain: 'example.com',
|
||||
zoneName: 'example.com',
|
||||
provider: 'manual',
|
||||
config: { },
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'fallback' },
|
||||
wellKnown: null
|
||||
};
|
||||
const AUDIT_SOURCE = { ip: '1.2.3.4' };
|
||||
|
||||
const manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok', addons: { } };
|
||||
|
||||
before(function (done) {
|
||||
const BACKUP_DIR = path.join(os.tmpdir(), 'cloudron-backup-test');
|
||||
|
||||
async.series([
|
||||
common.setup,
|
||||
fs.mkdir.bind(null, BACKUP_DIR, { recursive: true }),
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE),
|
||||
settingsdb.set.bind(null, settings.BACKUP_CONFIG_KEY, JSON.stringify({
|
||||
provider: 'filesystem',
|
||||
password: 'supersecret',
|
||||
@@ -194,10 +88,96 @@ describe('backups', function () {
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
database._clear
|
||||
], done);
|
||||
after(common.cleanup);
|
||||
|
||||
describe('retention policy', function () {
|
||||
it('keeps latest', function () {
|
||||
let backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('latest');
|
||||
});
|
||||
|
||||
it('does not keep latest', function () {
|
||||
let backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: false }, []);
|
||||
expect(backup.keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
it('always keeps forever policy', function () {
|
||||
let backup = { creationTime: new Date() };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: -1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('keepWithinSecs');
|
||||
});
|
||||
|
||||
it('preserveSecs takes precedence', function () {
|
||||
let backup = { creationTime: new Date(), preserveSecs: 3000 };
|
||||
backups._applyBackupRetentionPolicy([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('preserveSecs');
|
||||
});
|
||||
|
||||
it('1 daily', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(20, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily');
|
||||
expect(b[1].keepReason).to.be(undefined);
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
// if you are debugging this test, it's because of some timezone issue with all the hour substraction!
|
||||
it('2 daily, 1 weekly', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_ERROR, creationTime: moment().subtract(32, 'h').toDate() },
|
||||
{ id: '5', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(50, 'h').toDate() },
|
||||
{ id: '6', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 2, keepWeekly: 1, keepLatest: false }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily'); // today
|
||||
expect(b[1].keepReason).to.be('keepWeekly'); // today
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[4].discardReason).to.be('error'); // errored
|
||||
expect(b[5].discardReason).to.be('creating-too-long'); // creating for too long
|
||||
expect(b[6].keepReason).to.be(undefined); // outside retention policy
|
||||
});
|
||||
|
||||
it('2 daily, 3 monthly, 1 yearly', function () {
|
||||
let b = [
|
||||
{ id: '0', state: backups.BACKUP_STATE_CREATING, creationTime: moment().toDate() },
|
||||
{ id: '1', state: backups.BACKUP_STATE_ERROR, creationTime: moment().toDate() },
|
||||
{ id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
|
||||
{ id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() },
|
||||
{ id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() },
|
||||
{ id: '5', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() },
|
||||
{ id: '6', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(49, 'h').toDate() },
|
||||
{ id: '7', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(51, 'd').toDate() },
|
||||
{ id: '8', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(84, 'd').toDate() },
|
||||
{ id: '9', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() },
|
||||
];
|
||||
backups._applyBackupRetentionPolicy(b, { keepDaily: 2, keepMonthly: 3, keepYearly: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('creating');
|
||||
expect(b[1].discardReason).to.be('error'); // errored
|
||||
expect(b[2].keepReason).to.be('keepDaily');
|
||||
expect(b[3].keepReason).to.be('keepMonthly');
|
||||
expect(b[4].keepReason).to.be('keepYearly');
|
||||
expect(b[5].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[6].discardReason).to.be('creating-too-long'); // errored
|
||||
expect(b[7].keepReason).to.be('keepMonthly');
|
||||
expect(b[8].keepReason).to.be('keepMonthly');
|
||||
expect(b[9].keepReason).to.be(undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('cleanup', function () {
|
||||
@@ -215,7 +195,7 @@ describe('backups', function () {
|
||||
|
||||
var BACKUP_0_APP_0 = { // backup of installed app
|
||||
id: 'backup-app-00',
|
||||
identifier: 'app0',
|
||||
identifier: APP.id,
|
||||
encryptionVersion: null,
|
||||
packageVersion: '1.0.0',
|
||||
type: backups.BACKUP_TYPE_APP,
|
||||
@@ -255,7 +235,7 @@ describe('backups', function () {
|
||||
packageVersion: '1.0.0',
|
||||
type: backups.BACKUP_TYPE_APP,
|
||||
state: backups.BACKUP_STATE_NORMAL,
|
||||
identifier: 'app0',
|
||||
identifier: APP.id,
|
||||
dependsOn: [],
|
||||
manifest: null,
|
||||
format: 'tgz'
|
||||
@@ -273,14 +253,6 @@ describe('backups', function () {
|
||||
format: 'tgz'
|
||||
};
|
||||
|
||||
before(function (done) {
|
||||
appdb.add('app0', 'appStoreId', manifest, 'location', DOMAIN_0.domain, [ ] /* portBindings */, { installationState: 'installed', runState: 'running', mailboxDomain: DOMAIN_0.domain }, done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
appdb.del('app0', done);
|
||||
});
|
||||
|
||||
it('succeeds without backups', function (done) {
|
||||
cleanupBackups(done);
|
||||
});
|
||||
@@ -289,7 +261,7 @@ describe('backups', function () {
|
||||
async.eachSeries([[ BACKUP_0, BACKUP_0_APP_0, BACKUP_0_APP_1 ], [ BACKUP_1, BACKUP_1_APP_0, BACKUP_1_APP_1 ]], function (backup, callback) {
|
||||
// space out backups
|
||||
setTimeout(function () {
|
||||
async.each(backup, (b, done) => backupdb.add(b.id, b, done), callback);
|
||||
async.eachSeries(backup, (b, done) => backupdb.add(b.id, b, done), callback);
|
||||
}, 2000);
|
||||
}, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
@@ -347,6 +319,7 @@ describe('backups', function () {
|
||||
backupdb.getByTypePaged(backups.BACKUP_TYPE_APP, 1, 1000, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result.length).to.equal(3);
|
||||
result = result.sort((r1, r2) => r1.id.localeCompare(r2.id));
|
||||
expect(result[0].id).to.be(BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved
|
||||
expect(result[1].id).to.be(BACKUP_1_APP_0.id); // referenced by box
|
||||
expect(result[2].id).to.be(BACKUP_1_APP_1.id); // referenced by box
|
||||
@@ -360,7 +333,7 @@ describe('backups', function () {
|
||||
});
|
||||
|
||||
describe('fs meta data', function () {
|
||||
var tmpdir;
|
||||
let tmpdir;
|
||||
before(function () {
|
||||
tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'backups-test'));
|
||||
});
|
||||
@@ -407,9 +380,9 @@ describe('backups', function () {
|
||||
});
|
||||
|
||||
describe('filesystem', function () {
|
||||
var backupInfo1;
|
||||
let backupInfo1;
|
||||
|
||||
var backupConfig = {
|
||||
const backupConfig = {
|
||||
provider: 'filesystem',
|
||||
backupFolder: path.join(os.tmpdir(), 'backups-test-filesystem'),
|
||||
format: 'tgz',
|
||||
@@ -428,8 +401,9 @@ describe('backups', function () {
|
||||
done();
|
||||
});
|
||||
|
||||
it('fails to set backup config for non-existing folder', function (done) {
|
||||
settings.setBackupConfig(backupConfig, function (error) {
|
||||
it('fails to set backup config for bad folder', function (done) {
|
||||
const tmp = Object.assign({}, backupConfig, { backupFolder: '/root/oof' });
|
||||
settings.setBackupConfig(tmp, function (error) {
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
|
||||
@@ -438,11 +412,11 @@ describe('backups', function () {
|
||||
});
|
||||
|
||||
it('succeeds to set backup config', function (done) {
|
||||
fs.mkdirSync(backupConfig.backupFolder, { recursive: true });
|
||||
|
||||
settings.setBackupConfig(backupConfig, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
expect(fs.existsSync(path.join(backupConfig.backupFolder, 'snapshot'))).to.be(true); // auto-created
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs'),
|
||||
const appdb = require('../appdb.js'),
|
||||
apps = require('../apps.js'),
|
||||
async = require('async'),
|
||||
blobs = require('../blobs.js'),
|
||||
database = require('../database.js'),
|
||||
domains = require('../domains.js'),
|
||||
fs = require('fs'),
|
||||
mailer = require('../mailer.js'),
|
||||
nock = require('nock'),
|
||||
path = require('path'),
|
||||
rimraf = require('rimraf');
|
||||
rimraf = require('rimraf'),
|
||||
settings = require('../settings.js'),
|
||||
settingsdb = require('../settingsdb.js'),
|
||||
users = require('../users.js');
|
||||
|
||||
const MANIFEST = {
|
||||
'id': 'io.cloudron.test',
|
||||
'author': 'The Presidents Of the United States Of America',
|
||||
'title': 'test title',
|
||||
'description': 'test description',
|
||||
'tagline': 'test rocks',
|
||||
'website': 'http://test.cloudron.io',
|
||||
'contactEmail': 'test@cloudron.io',
|
||||
'version': '0.1.0',
|
||||
'manifestVersion': 1,
|
||||
'dockerImage': 'cloudron/test:25.2.0',
|
||||
'healthCheckPath': '/',
|
||||
'httpPort': 7777,
|
||||
'tcpPorts': {
|
||||
'ECHO_SERVER_PORT': {
|
||||
'title': 'Echo Server Port',
|
||||
'description': 'Echo server',
|
||||
'containerPort': 7778
|
||||
}
|
||||
},
|
||||
'addons': {
|
||||
'oauth': { },
|
||||
'redis': { },
|
||||
'mysql': { },
|
||||
'postgresql': { }
|
||||
}
|
||||
};
|
||||
|
||||
const DOMAIN = {
|
||||
domain: 'example.com',
|
||||
zoneName: 'example.com',
|
||||
provider: 'route53',
|
||||
config: {
|
||||
accessKeyId: 'accessKeyId',
|
||||
secretAccessKey: 'secretAccessKey',
|
||||
endpoint: 'http://localhost:5353'
|
||||
},
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'letsencrypt-staging' },
|
||||
wellKnown: null
|
||||
};
|
||||
|
||||
const AUDIT_SOURCE = { ip: '1.2.3.4' };
|
||||
|
||||
const ADMIN = {
|
||||
id: 'admin123',
|
||||
username: 'admin123',
|
||||
password: 'secret123',
|
||||
email: 'admin@me.com',
|
||||
fallbackEmail: 'admin@me.com',
|
||||
salt: 'morton',
|
||||
createdAt: 'sometime back',
|
||||
resetToken: '',
|
||||
displayName: '',
|
||||
role: 'owner',
|
||||
source: ''
|
||||
};
|
||||
|
||||
const APP = {
|
||||
id: 'appid',
|
||||
appStoreId: 'appStoreId',
|
||||
installationState: apps.ISTATE_PENDING_INSTALL,
|
||||
runState: 'running',
|
||||
location: 'applocation',
|
||||
domain: DOMAIN.domain,
|
||||
fqdn: DOMAIN.domain + '.' + 'applocation',
|
||||
manifest: MANIFEST,
|
||||
containerId: 'someid',
|
||||
portBindings: null,
|
||||
accessRestriction: null,
|
||||
memoryLimit: 0,
|
||||
mailboxDomain: DOMAIN.domain,
|
||||
alternateDomains: [],
|
||||
aliasDomains: []
|
||||
};
|
||||
|
||||
exports = module.exports = {
|
||||
createTree: createTree
|
||||
createTree,
|
||||
setup,
|
||||
cleanup,
|
||||
|
||||
MOCK_API_SERVER_ORIGIN: 'http://localhost:6060',
|
||||
DASHBOARD_DOMAIN: 'test.example.com',
|
||||
DASHBOARD_FQDN: 'my.test.example.com',
|
||||
|
||||
APP,
|
||||
ADMIN,
|
||||
AUDIT_SOURCE,
|
||||
DOMAIN,
|
||||
MANIFEST,
|
||||
APPSTORE_TOKEN: 'atoken'
|
||||
};
|
||||
|
||||
function createTree(root, obj) {
|
||||
@@ -30,3 +130,29 @@ function createTree(root, obj) {
|
||||
createSubTree(obj, root);
|
||||
}
|
||||
|
||||
function setup(done) {
|
||||
nock.cleanAll();
|
||||
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings._setApiServerOrigin.bind(null, exports.MOCK_API_SERVER_ORIGIN),
|
||||
settings.setDashboardLocation.bind(null, exports.DASHBOARD_DOMAIN, exports.DASHBOARD_FQDN),
|
||||
settings.initCache,
|
||||
blobs.initSecrets,
|
||||
domains.add.bind(null, DOMAIN.domain, DOMAIN, AUDIT_SOURCE),
|
||||
users.createOwner.bind(null, ADMIN.username, ADMIN.password, ADMIN.email, ADMIN.displayName, AUDIT_SOURCE),
|
||||
appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.domain, APP.portBindings, APP),
|
||||
settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, exports.APPSTORE_TOKEN), // appstore token
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
nock.cleanAll();
|
||||
mailer._mailQueue = [];
|
||||
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ var USER_0 = {
|
||||
email: 'safe@me.com',
|
||||
fallbackEmail: 'safer@me.com',
|
||||
salt: 'morton',
|
||||
createdAt: 'sometime back',
|
||||
creationTime: Date.now(),
|
||||
resetToken: hat(256),
|
||||
displayName: '',
|
||||
twoFactorAuthenticationEnabled: false,
|
||||
@@ -52,7 +52,7 @@ var USER_1 = {
|
||||
email: 'safe2@me.com',
|
||||
fallbackEmail: 'safer2@me.com',
|
||||
salt: 'tata',
|
||||
createdAt: 'sometime back',
|
||||
creationTime: Date.now(),
|
||||
resetToken: '',
|
||||
displayName: 'Herbert 1',
|
||||
twoFactorAuthenticationEnabled: false,
|
||||
@@ -71,7 +71,7 @@ var USER_2 = {
|
||||
email: 'safe3@me.com',
|
||||
fallbackEmail: 'safer3@me.com',
|
||||
salt: 'tata',
|
||||
createdAt: 'sometime back',
|
||||
creationTime: Date.now(),
|
||||
resetToken: '',
|
||||
displayName: 'Herbert 2',
|
||||
twoFactorAuthenticationEnabled: false,
|
||||
|
||||
@@ -7,46 +7,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
AWS = require('aws-sdk'),
|
||||
GCDNS = require('@google-cloud/dns').DNS,
|
||||
database = require('../database.js'),
|
||||
const AWS = require('aws-sdk'),
|
||||
common = require('./common.js'),
|
||||
domains = require('../domains.js'),
|
||||
expect = require('expect.js'),
|
||||
GCDNS = require('@google-cloud/dns').DNS,
|
||||
nock = require('nock'),
|
||||
querystring = require('querystring'),
|
||||
settings = require('../settings.js'),
|
||||
util = require('util'),
|
||||
_ = require('underscore');
|
||||
|
||||
var DOMAIN_0 = {
|
||||
domain: 'example-dns-test.com',
|
||||
zoneName: 'example-dns-test.com',
|
||||
provider: 'noop',
|
||||
config: {},
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'fallback' },
|
||||
wellKnown: null
|
||||
};
|
||||
|
||||
var AUDIT_SOURCE = { ip: '1.2.3.4' };
|
||||
const { AUDIT_SOURCE, DOMAIN } = common;
|
||||
const DOMAIN_0 = Object.assign({}, DOMAIN); // make a copy
|
||||
|
||||
describe('dns provider', function () {
|
||||
before(function (done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE)
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
});
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
describe('noop', function () {
|
||||
before(function (done) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var constants = require('../constants.js'),
|
||||
const constants = require('../constants.js'),
|
||||
dockerProxy = require('../dockerproxy.js'),
|
||||
exec = require('child_process').exec,
|
||||
expect = require('expect.js');
|
||||
|
||||
@@ -7,30 +7,22 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async'),
|
||||
common = require('./common.js'),
|
||||
database = require('../database.js'),
|
||||
delay = require('delay'),
|
||||
eventlog = require('../eventlog.js'),
|
||||
expect = require('expect.js'),
|
||||
notifications = require('../notifications.js');
|
||||
|
||||
function setup(done) {
|
||||
// ensure data/config/mount paths
|
||||
database.initialize(function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
describe('Eventlog', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
before(function (done) {
|
||||
async.series([
|
||||
common.setup,
|
||||
eventlog._clear // domain add events
|
||||
], done);
|
||||
});
|
||||
|
||||
after(common.cleanup);
|
||||
|
||||
var eventId;
|
||||
|
||||
@@ -38,6 +30,7 @@ describe('Eventlog', function () {
|
||||
const id = await eventlog.add('some.event', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
expect(id).to.be.a('string');
|
||||
|
||||
console.log(id);
|
||||
eventId = id;
|
||||
});
|
||||
|
||||
@@ -126,7 +119,7 @@ describe('Eventlog', function () {
|
||||
await notifications._add(eventId, 'title', 'some message');
|
||||
}
|
||||
|
||||
await delay(2000);
|
||||
await delay(3000);
|
||||
|
||||
const id = await eventlog.add('some.event', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var BoxError = require('../boxerror.js'),
|
||||
const BoxError = require('../boxerror.js'),
|
||||
common = require('./common.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
network = require('../network.js'),
|
||||
paths = require('../paths.js');
|
||||
|
||||
describe('Network', function () {
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
describe('Blocklist', function () {
|
||||
|
||||
before(function () {
|
||||
@@ -32,7 +37,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('\n');
|
||||
expect(result).to.equal('');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -45,7 +50,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('192.168.178.1\n');
|
||||
expect(result).to.equal('192.168.178.1');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -58,7 +63,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n');
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -71,7 +76,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1\n');
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -84,7 +89,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('192.168.178.1/24\n');
|
||||
expect(result).to.equal('192.168.178.1/24');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -97,7 +102,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('2001:db8::\n');
|
||||
expect(result).to.equal('2001:db8::');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -146,7 +151,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('192.168.178.1\n');
|
||||
expect(result).to.equal('192.168.178.1');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -159,7 +164,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('2001:db8:1234::1\n');
|
||||
expect(result).to.equal('2001:db8:1234::1');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -172,7 +177,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('192.168.178.1/32\n');
|
||||
expect(result).to.equal('192.168.178.1/32');
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -185,7 +190,7 @@ describe('Network', function () {
|
||||
|
||||
network.getBlocklist(function (error, result) {
|
||||
expect(error).to.equal(null);
|
||||
expect(result).to.equal('2001:db8:1234::\n');
|
||||
expect(result).to.equal('2001:db8:1234::');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async'),
|
||||
BoxError = require('../boxerror.js'),
|
||||
database = require('../database.js'),
|
||||
const BoxError = require('../boxerror.js'),
|
||||
common = require('./common.js'),
|
||||
delay = require('delay'),
|
||||
expect = require('expect.js'),
|
||||
notifications = require('../notifications.js'),
|
||||
safe = require('safetydance');
|
||||
@@ -20,23 +20,9 @@ const EVENT_0 = {
|
||||
data: {}
|
||||
};
|
||||
|
||||
function setup(done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
describe('Notifications', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
let notificationIds = [];
|
||||
|
||||
@@ -46,6 +32,7 @@ describe('Notifications', function () {
|
||||
expect(error).to.equal(null);
|
||||
expect(id).to.be.a('string');
|
||||
notificationIds.push(id);
|
||||
await delay(1000);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -65,9 +52,9 @@ describe('Notifications', function () {
|
||||
it('can list notifications', async function () {
|
||||
const result = await notifications.list({}, 1, 10);
|
||||
expect(result.length).to.be(3);
|
||||
expect(result[0].title).to.be('title 0');
|
||||
expect(result[0].title).to.be('title 2');
|
||||
expect(result[1].title).to.be('title 1');
|
||||
expect(result[2].title).to.be('title 2');
|
||||
expect(result[2].title).to.be('title 0');
|
||||
});
|
||||
|
||||
it('can update notification', async function () {
|
||||
|
||||
@@ -5,45 +5,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async'),
|
||||
blobs = require('../blobs.js'),
|
||||
database = require('../database.js'),
|
||||
const common = require('./common.js'),
|
||||
domains = require('../domains.js'),
|
||||
expect = require('expect.js'),
|
||||
reverseProxy = require('../reverseproxy.js'),
|
||||
settings = require('../settings.js');
|
||||
fs = require('fs'),
|
||||
paths = require('../paths.js'),
|
||||
reverseProxy = require('../reverseproxy.js');
|
||||
|
||||
const DOMAIN_0 = {
|
||||
domain: 'example-reverseproxy-test.com',
|
||||
zoneName: 'example-reverseproxy-test.com',
|
||||
provider: 'noop',
|
||||
config: {},
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'fallback' },
|
||||
wellKnown: null
|
||||
};
|
||||
|
||||
let AUDIT_SOURCE = { ip: '1.2.3.4' };
|
||||
|
||||
function setup(done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
blobs.initSecrets,
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE),
|
||||
settings.initCache
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
const { DOMAIN, AUDIT_SOURCE, APP } = common;
|
||||
const DOMAIN_0 = Object.assign({}, DOMAIN);
|
||||
|
||||
describe('Certificates', function () {
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
describe('validateCertificate', function () {
|
||||
let foobarDomain = {
|
||||
domain: 'foobar.com',
|
||||
@@ -169,14 +144,9 @@ describe('Certificates', function () {
|
||||
before(function (done) {
|
||||
DOMAIN_0.tlsConfig = { provider: 'letsencrypt-prod' };
|
||||
|
||||
async.series([
|
||||
setup,
|
||||
domains.update.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE)
|
||||
], done);
|
||||
domains.update(DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE, done);
|
||||
});
|
||||
|
||||
after(cleanup);
|
||||
|
||||
it('returns prod acme in prod cloudron', function (done) {
|
||||
reverseProxy._getAcmeApi(DOMAIN_0, function (error, api, options) {
|
||||
expect(error).to.be(null);
|
||||
@@ -200,14 +170,9 @@ describe('Certificates', function () {
|
||||
before(function (done) {
|
||||
DOMAIN_0.tlsConfig = { provider: 'letsencrypt-staging' };
|
||||
|
||||
async.series([
|
||||
setup,
|
||||
domains.update.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE)
|
||||
], done);
|
||||
domains.update(DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE, done);
|
||||
});
|
||||
|
||||
after(cleanup);
|
||||
|
||||
it('returns staging acme in prod cloudron', function (done) {
|
||||
reverseProxy._getAcmeApi(DOMAIN_0, function (error, api, options) {
|
||||
expect(error).to.be(null);
|
||||
@@ -226,4 +191,22 @@ describe('Certificates', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('configureApp', function () {
|
||||
it('configure nginx correctly', function (done) {
|
||||
reverseProxy.configureApp(APP, AUDIT_SOURCE, function (error) {
|
||||
expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unconfigure nginx', function (done) {
|
||||
reverseProxy.unconfigureApp(APP, function (error) {
|
||||
expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,28 +6,13 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async'),
|
||||
database = require('../database.js'),
|
||||
const common = require('./common.js'),
|
||||
expect = require('expect.js'),
|
||||
system = require('../system.js');
|
||||
|
||||
function setup(done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
describe('System', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
it('can get disks', function (done) {
|
||||
system.getDisks(function (error, disks) {
|
||||
|
||||
@@ -6,30 +6,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
database = require('../database.js'),
|
||||
const common = require('./common.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
paths = require('../paths.js'),
|
||||
tasks = require('../tasks.js');
|
||||
|
||||
function setup(done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear
|
||||
], done);
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
async.series([
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
|
||||
describe('task', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
it('can run valid task - success', function (done) {
|
||||
tasks.add(tasks._TASK_IDENTITY, [ 'ping' ], function (error, taskId) {
|
||||
|
||||
@@ -5,16 +5,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var expect = require('expect.js'),
|
||||
const expect = require('expect.js'),
|
||||
translation = require('../translation.js');
|
||||
|
||||
describe('translation', function () {
|
||||
|
||||
describe('translate', function () {
|
||||
before(function (done) {
|
||||
done();
|
||||
});
|
||||
|
||||
it('nonexisting token', function () {
|
||||
var out = translation.translate('Foo {{ bar }}', {}, {});
|
||||
expect(out).to.contain('{{ bar }}');
|
||||
|
||||
@@ -5,252 +5,145 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var appdb = require('../appdb.js'),
|
||||
apps = require('../apps.js'),
|
||||
async = require('async'),
|
||||
const common = require('./common.js'),
|
||||
constants = require('../constants.js'),
|
||||
cron = require('../cron.js'),
|
||||
database = require('../database.js'),
|
||||
domains = require('../domains.js'),
|
||||
expect = require('expect.js'),
|
||||
mailer = require('../mailer.js'),
|
||||
nock = require('nock'),
|
||||
paths = require('../paths.js'),
|
||||
safe = require('safetydance'),
|
||||
semver = require('semver'),
|
||||
settings = require('../settings.js'),
|
||||
settingsdb = require('../settingsdb.js'),
|
||||
updatechecker = require('../updatechecker.js'),
|
||||
users = require('../users.js');
|
||||
updatechecker = require('../updatechecker.js');
|
||||
|
||||
// owner
|
||||
var USER_0 = {
|
||||
username: 'username0',
|
||||
password: 'Username0pass?1234',
|
||||
email: 'user0@email.com',
|
||||
displayName: 'User 0',
|
||||
source: '',
|
||||
permissions: null
|
||||
};
|
||||
|
||||
const DASHBOARD_DOMAIN = 'updatechecker-test.example.com';
|
||||
|
||||
const DOMAIN_0 = {
|
||||
domain: 'example.com',
|
||||
zoneName: 'example.com',
|
||||
config: {},
|
||||
provider: 'manual',
|
||||
fallbackCertificate: null,
|
||||
tlsConfig: { provider: 'fallback' },
|
||||
wellKnown: null
|
||||
};
|
||||
|
||||
var AUDIT_SOURCE = {
|
||||
ip: '1.2.3.4'
|
||||
};
|
||||
const { APP, APPSTORE_TOKEN, MOCK_API_SERVER_ORIGIN } = common;
|
||||
|
||||
const UPDATE_VERSION = semver.inc(constants.VERSION, 'major');
|
||||
|
||||
function checkMails(number, done) {
|
||||
// mails are enqueued async
|
||||
setTimeout(function () {
|
||||
expect(mailer._mailQueue.length).to.equal(number);
|
||||
mailer._mailQueue = [];
|
||||
done();
|
||||
}, 500);
|
||||
}
|
||||
describe('updatechecker', function () {
|
||||
before(common.setup);
|
||||
after(common.cleanup);
|
||||
|
||||
function cleanup(done) {
|
||||
mailer._mailQueue = [];
|
||||
safe.fs.unlinkSync(paths.UPDATE_CHECKER_FILE);
|
||||
describe('box', function () {
|
||||
before(function (done) {
|
||||
safe.fs.unlinkSync(paths.UPDATE_CHECKER_FILE);
|
||||
|
||||
async.series([
|
||||
cron.stopJobs,
|
||||
database._clear,
|
||||
database.uninitialize
|
||||
], done);
|
||||
}
|
||||
settings.setAutoupdatePattern(constants.AUTOUPDATE_PATTERN_NEVER, done);
|
||||
});
|
||||
|
||||
describe('updatechecker - box', function () {
|
||||
before(function (done) {
|
||||
safe.fs.unlinkSync(paths.UPDATE_CHECKER_FILE);
|
||||
it('no updates', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
mailer._mailQueue = [];
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, automatic: false })
|
||||
.reply(204, { } );
|
||||
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings._setApiServerOrigin.bind(null, 'http://localhost:4444'),
|
||||
settings.setDashboardLocation.bind(null, DASHBOARD_DOMAIN, 'my.' + DASHBOARD_DOMAIN),
|
||||
cron.startJobs,
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE),
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
users.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE),
|
||||
settings.setAutoupdatePattern.bind(null, constants.AUTOUPDATE_PATTERN_NEVER),
|
||||
settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, 'atoken'),
|
||||
], done);
|
||||
});
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box).to.not.be.ok();
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(cleanup);
|
||||
it('new version', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
it('no updates', function (done) {
|
||||
nock.cleanAll();
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, automatic: false })
|
||||
.reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig' } );
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', automatic: false })
|
||||
.reply(204, { } );
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box.version).to.be(UPDATE_VERSION);
|
||||
expect(updatechecker.getUpdateInfo().box.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box).to.not.be.ok();
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
it('bad response offers whatever was last valid', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
checkMails(0, done);
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, automatic: false })
|
||||
.reply(404, { version: '2.0.0-pre.0', changelog: [''], sourceTarballUrl: 'box-pre.tar.gz' } );
|
||||
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box.version).to.be(UPDATE_VERSION);
|
||||
expect(updatechecker.getUpdateInfo().box.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('new version', function (done) {
|
||||
nock.cleanAll();
|
||||
describe('app', function () {
|
||||
before(function (done) {
|
||||
safe.fs.unlinkSync(paths.UPDATE_CHECKER_FILE);
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', automatic: false })
|
||||
.reply(200, { version: UPDATE_VERSION, changelog: [''], sourceTarballUrl: 'box.tar.gz', sourceTarballSigUrl: 'box.tar.gz.sig', boxVersionsUrl: 'box.versions', boxVersionsSigUrl: 'box.versions.sig' } );
|
||||
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box.version).to.be(UPDATE_VERSION);
|
||||
expect(updatechecker.getUpdateInfo().box.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
|
||||
checkMails(1, done);
|
||||
settings.setAutoupdatePattern(constants.AUTOUPDATE_PATTERN_NEVER, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('bad response offers whatever was last valid', function (done) {
|
||||
nock.cleanAll();
|
||||
it('no updates', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/boxupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', automatic: false })
|
||||
.reply(404, { version: '2.0.0-pre.0', changelog: [''], sourceTarballUrl: 'box-pre.tar.gz' } );
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, appId: APP.appStoreId, appVersion: APP.manifest.version, automatic: false })
|
||||
.reply(204, { } );
|
||||
|
||||
updatechecker.checkForUpdates({ automatic: false }, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo().box.version).to.be(UPDATE_VERSION);
|
||||
expect(updatechecker.getUpdateInfo().box.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({});
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
checkMails(0, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updatechecker - app', function () {
|
||||
var APP_0 = {
|
||||
id: 'appid-0',
|
||||
appStoreId: 'io.cloudron.app',
|
||||
installationState: apps.ISTATE_PENDING_INSTALL,
|
||||
error: null,
|
||||
runState: 'running',
|
||||
location: 'some-location-0',
|
||||
domain: DOMAIN_0.domain,
|
||||
manifest: {
|
||||
version: '1.0.0', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0',
|
||||
tcpPorts: {
|
||||
PORT: {
|
||||
description: 'this is a port that i expose',
|
||||
containerPort: '1234'
|
||||
}
|
||||
}
|
||||
},
|
||||
containerId: null,
|
||||
portBindings: { PORT: 5678 },
|
||||
healthy: null,
|
||||
accessRestriction: null,
|
||||
memoryLimit: 0,
|
||||
mailboxName: 'mail',
|
||||
mailboxDomain: DOMAIN_0.domain
|
||||
};
|
||||
|
||||
before(function (done) {
|
||||
mailer._mailQueue = [];
|
||||
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
settings._setApiServerOrigin.bind(null, 'http://localhost:4444'),
|
||||
cron.startJobs,
|
||||
domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE),
|
||||
settings.setDashboardLocation.bind(null, DOMAIN_0.domain, 'my.' + DOMAIN_0.domain),
|
||||
users.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE),
|
||||
appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0),
|
||||
settings.setAutoupdatePattern.bind(null, constants.AUTOUPDATE_PATTERN_NEVER),
|
||||
settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, 'atoken'),
|
||||
], done);
|
||||
});
|
||||
|
||||
after(cleanup);
|
||||
|
||||
it('no updates', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version, automatic: false })
|
||||
.reply(204, { } );
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({});
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
|
||||
checkMails(0, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('bad response', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version, automatic: false })
|
||||
.reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } );
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({});
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
|
||||
checkMails(0, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('offers new version', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock('http://localhost:4444')
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: 'atoken', appId: APP_0.appStoreId, appVersion: APP_0.manifest.version, automatic: false })
|
||||
.reply(200, { manifest: { version: '2.0.0', changelog: '* some changes' } } );
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({ 'appid-0': { manifest: { version: '2.0.0', changelog: '* some changes' }, unstable: false } });
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
|
||||
checkMails(1, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('does not offer old version', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({ });
|
||||
checkMails(0, done);
|
||||
it('bad response', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, appId: APP.appStoreId, appVersion: APP.manifest.version, automatic: false })
|
||||
.reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } );
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({});
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('offers new version', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
var scope = nock(MOCK_API_SERVER_ORIGIN)
|
||||
.get('/api/v1/appupdate')
|
||||
.query({ boxVersion: constants.VERSION, accessToken: APPSTORE_TOKEN, appId: APP.appStoreId, appVersion: APP.manifest.version, automatic: false })
|
||||
.reply(200, { manifest: { version: '2.0.0', changelog: '* some changes' } } );
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({ 'appid': { manifest: { version: '2.0.0', changelog: '* some changes' }, unstable: false } });
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not offer old version', function (done) {
|
||||
nock.cleanAll();
|
||||
|
||||
updatechecker._checkAppUpdates({ automatic: false }, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
expect(updatechecker.getUpdateInfo()).to.eql({ });
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ function setUpdateInfo(state) {
|
||||
// appid -> update info { creationDate, manifest }
|
||||
// box -> { version, changelog, upgrade, sourceTarballUrl }
|
||||
state.version = 2;
|
||||
safe.fs.writeFileSync(paths.UPDATE_CHECKER_FILE, JSON.stringify(state, null, 4), 'utf8');
|
||||
if (!safe.fs.writeFileSync(paths.UPDATE_CHECKER_FILE, JSON.stringify(state, null, 4), 'utf8')) debug(`setUpdateInfo: Error writing to update checker file: ${safe.error.message}`);
|
||||
}
|
||||
|
||||
function getUpdateInfo() {
|
||||
@@ -74,7 +74,7 @@ function checkBoxUpdates(options, callback) {
|
||||
|
||||
debug('checkBoxUpdates: checking for updates');
|
||||
|
||||
appstore.getBoxUpdate(options, function (error, updateInfo) {
|
||||
appstore.getBoxUpdate(options, async function (error, updateInfo) {
|
||||
if (error) return callback(error);
|
||||
|
||||
let state = getUpdateInfo();
|
||||
@@ -90,7 +90,7 @@ function checkBoxUpdates(options, callback) {
|
||||
|
||||
if (state.box && state.box.version === updateInfo.version) {
|
||||
debug(`checkBoxUpdates: Skipping notification of box update ${updateInfo.version} as user was already notified`);
|
||||
return callback();
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
debug(`checkBoxUpdates: ${updateInfo.version} is available`);
|
||||
@@ -99,14 +99,13 @@ function checkBoxUpdates(options, callback) {
|
||||
|
||||
const message = `Changelog:\n${changelog}\n\nGo to the settings view to update.\n\n`;
|
||||
|
||||
notifications.alert(notifications.ALERT_BOX_UPDATE, `Cloudron v${updateInfo.version} is available`, message, function (error) {
|
||||
if (error) return callback(error);
|
||||
[error] = await safe(notifications.alert(notifications.ALERT_BOX_UPDATE, `Cloudron v${updateInfo.version} is available`, message));
|
||||
if (error) return callback(error);
|
||||
|
||||
state.box = updateInfo;
|
||||
setUpdateInfo(state);
|
||||
state.box = updateInfo;
|
||||
setUpdateInfo(state);
|
||||
|
||||
callback();
|
||||
});
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user