remove httpPort

we can just use container IP instead of all this httpPort exporting magic.
this is also required for exposing httpPaths feature (we have to otherwise
have multiple httpPorts).
This commit is contained in:
Girish Ramakrishnan
2020-11-18 23:24:34 -08:00
parent bd9c664b1a
commit d703d1cd13
13 changed files with 115 additions and 172 deletions
@@ -0,0 +1,13 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'ALTER TABLE apps DROP COLUMN httpPort')
], callback);
};
exports.down = function(db, callback) {
callback();
};
-1
View File
@@ -65,7 +65,6 @@ CREATE TABLE IF NOT EXISTS apps(
healthTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the app last responded healthTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the app last responded
containerId VARCHAR(128), containerId VARCHAR(128),
manifestJson TEXT, manifestJson TEXT,
httpPort INTEGER, // this is the nginx proxy port and not manifest.httpPort
accessRestrictionJson TEXT, // { users: [ ], groups: [ ] } accessRestrictionJson TEXT, // { users: [ ], groups: [ ] }
creationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the app was installed creationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the app was installed
updateTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the last app update was done updateTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the last app update was done
+1 -30
View File
@@ -2,7 +2,6 @@
exports = module.exports = { exports = module.exports = {
get: get, get: get,
getByHttpPort: getByHttpPort,
getByContainerId: getByContainerId, getByContainerId: getByContainerId,
add: add, add: add,
exists: exists, exists: exists,
@@ -39,7 +38,7 @@ var assert = require('assert'),
util = require('util'); util = require('util');
var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.errorJson', 'apps.runState', var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.errorJson', 'apps.runState',
'apps.health', 'apps.containerId', 'apps.manifestJson', 'apps.httpPort', 'subdomains.subdomain AS location', 'subdomains.domain', 'apps.health', 'apps.containerId', 'apps.manifestJson', 'subdomains.subdomain AS location', 'subdomains.domain',
'apps.accessRestrictionJson', 'apps.memoryLimit', 'apps.cpuShares', 'apps.accessRestrictionJson', 'apps.memoryLimit', 'apps.cpuShares',
'apps.label', 'apps.tagsJson', 'apps.taskId', 'apps.reverseProxyConfigJson', 'apps.servicesConfigJson', 'apps.label', 'apps.tagsJson', 'apps.taskId', 'apps.reverseProxyConfigJson', 'apps.servicesConfigJson',
'apps.sso', 'apps.debugModeJson', 'apps.enableBackup', 'apps.proxyAuth', 'apps.sso', 'apps.debugModeJson', 'apps.enableBackup', 'apps.proxyAuth',
@@ -155,34 +154,6 @@ function get(id, callback) {
}); });
} }
function getByHttpPort(httpPort, callback) {
assert.strictEqual(typeof httpPort, 'number');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT ' + APPS_FIELDS_PREFIXED + ','
+ 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes,'
+ 'JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues,'
+ 'JSON_ARRAYAGG(appMounts.volumeId) AS volumeIds, JSON_ARRAYAGG(appMounts.readOnly) AS volumeReadOnlys '
+ ' FROM apps'
+ ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId'
+ ' LEFT OUTER JOIN appEnvVars ON apps.id = appEnvVars.appId'
+ ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND subdomains.type = ?'
+ ' LEFT OUTER JOIN appMounts ON apps.id = appMounts.appId'
+ ' WHERE httpPort = ? GROUP BY apps.id', [ exports.SUBDOMAIN_TYPE_PRIMARY, httpPort ], function (error, result) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
if (result.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'App not found'));
database.query('SELECT ' + SUBDOMAIN_FIELDS + ' FROM subdomains WHERE appId = ? AND type = ?', [ result[0].id, exports.SUBDOMAIN_TYPE_REDIRECT ], function (error, alternateDomains) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
result[0].alternateDomains = alternateDomains;
postProcess(result[0]);
callback(null, result[0]);
});
});
}
function getByContainerId(containerId, callback) { function getByContainerId(containerId, callback) {
assert.strictEqual(typeof containerId, 'string'); assert.strictEqual(typeof containerId, 'string');
assert.strictEqual(typeof callback, 'function'); assert.strictEqual(typeof callback, 'function');
+4 -1
View File
@@ -85,8 +85,11 @@ function checkAppHealth(app, callback) {
// non-appstore apps may not have healthCheckPath // non-appstore apps may not have healthCheckPath
if (!manifest.healthCheckPath) return setHealth(app, apps.HEALTH_HEALTHY, callback); if (!manifest.healthCheckPath) return setHealth(app, apps.HEALTH_HEALTHY, callback);
const ip = safe.query(data, 'NetworkSettings.Networks.cloudron.IPAddress', null);
if (!ip) return setHealth(app, apps.HEALTH_ERROR, callback);
// poll through docker network instead of nginx to bypass any potential oauth proxy // poll through docker network instead of nginx to bypass any potential oauth proxy
var healthCheckUrl = 'http://127.0.0.1:' + app.httpPort + manifest.healthCheckPath; var healthCheckUrl = `http://${ip}:${manifest.httpPort}${manifest.healthCheckPath}`;
superagent superagent
.get(healthCheckUrl) .get(healthCheckUrl)
.set('Host', app.fqdn) // required for some apache configs with rewrite rules .set('Host', app.fqdn) // required for some apache configs with rewrite rules
+5 -38
View File
@@ -6,7 +6,6 @@ exports = module.exports = {
run: run, run: run,
// exported for testing // exported for testing
_reserveHttpPort: reserveHttpPort,
_configureReverseProxy: configureReverseProxy, _configureReverseProxy: configureReverseProxy,
_unconfigureReverseProxy: unconfigureReverseProxy, _unconfigureReverseProxy: unconfigureReverseProxy,
_createAppDir: createAppDir, _createAppDir: createAppDir,
@@ -35,7 +34,6 @@ var addons = require('./addons.js'),
eventlog = require('./eventlog.js'), eventlog = require('./eventlog.js'),
fs = require('fs'), fs = require('fs'),
manifestFormat = require('cloudron-manifestformat'), manifestFormat = require('cloudron-manifestformat'),
net = require('net'),
os = require('os'), os = require('os'),
path = require('path'), path = require('path'),
paths = require('./paths.js'), paths = require('./paths.js'),
@@ -89,24 +87,6 @@ function updateApp(app, values, callback) {
}); });
} }
function reserveHttpPort(app, callback) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof callback, 'function');
let server = net.createServer();
server.listen(0, function () {
let port = server.address().port;
updateApp(app, { httpPort: port }, function (error) {
server.close(function (/* closeError */) {
if (error) return callback(new BoxError(BoxError.NETWORK_ERROR, `Failed to allocate http port ${port}: ${error.message}`));
callback(null);
});
});
});
}
function configureReverseProxy(app, callback) { function configureReverseProxy(app, callback) {
assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof callback, 'function'); assert.strictEqual(typeof callback, 'function');
@@ -164,6 +144,7 @@ function deleteContainers(app, options, callback) {
removeLogrotateConfig.bind(null, app), removeLogrotateConfig.bind(null, app),
docker.stopContainers.bind(null, app.id), docker.stopContainers.bind(null, app.id),
docker.deleteContainers.bind(null, app.id, options), docker.deleteContainers.bind(null, app.id, options),
unconfigureReverseProxy.bind(null, app),
updateApp.bind(null, app, { containerId: null }) updateApp.bind(null, app, { containerId: null })
], callback); ], callback);
} }
@@ -486,7 +467,10 @@ function downloadImage(manifest, callback) {
function startApp(app, callback){ function startApp(app, callback){
if (app.runState === apps.RSTATE_STOPPED) return callback(); if (app.runState === apps.RSTATE_STOPPED) return callback();
docker.startContainer(app.id, callback); async.series([
docker.startContainer.bind(null, app.id),
configureReverseProxy.bind(null, app),
], callback);
} }
function install(app, args, progressCallback, callback) { function install(app, args, progressCallback, callback) {
@@ -506,7 +490,6 @@ function install(app, args, progressCallback, callback) {
// teardown for re-installs // teardown for re-installs
progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }), progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }),
unconfigureReverseProxy.bind(null, app),
deleteContainers.bind(null, app, { managedOnly: true }), deleteContainers.bind(null, app, { managedOnly: true }),
function teardownAddons(next) { function teardownAddons(next) {
// when restoring, app does not require these addons anymore. remove carefully to preserve the db passwords // when restoring, app does not require these addons anymore. remove carefully to preserve the db passwords
@@ -532,8 +515,6 @@ function install(app, args, progressCallback, callback) {
docker.deleteImage(oldManifest, done); docker.deleteImage(oldManifest, done);
}, },
reserveHttpPort.bind(null, app),
progressCallback.bind(null, { percent: 20, message: 'Downloading icon' }), progressCallback.bind(null, { percent: 20, message: 'Downloading icon' }),
downloadIcon.bind(null, app), downloadIcon.bind(null, app),
@@ -580,9 +561,6 @@ function install(app, args, progressCallback, callback) {
progressCallback.bind(null, { percent: 85, message: 'Waiting for DNS propagation' }), progressCallback.bind(null, { percent: 85, message: 'Waiting for DNS propagation' }),
exports._waitForDnsPropagation.bind(null, app), exports._waitForDnsPropagation.bind(null, app),
progressCallback.bind(null, { percent: 95, message: 'Configuring reverse proxy' }),
configureReverseProxy.bind(null, app),
progressCallback.bind(null, { percent: 100, message: 'Done' }), progressCallback.bind(null, { percent: 100, message: 'Done' }),
updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null }) updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null })
], function seriesDone(error) { ], function seriesDone(error) {
@@ -660,7 +638,6 @@ function changeLocation(app, args, progressCallback, callback) {
async.series([ async.series([
progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }), progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }),
unconfigureReverseProxy.bind(null, app),
deleteContainers.bind(null, app, { managedOnly: true }), deleteContainers.bind(null, app, { managedOnly: true }),
function (next) { function (next) {
let obsoleteDomains = oldConfig.alternateDomains.filter(function (o) { let obsoleteDomains = oldConfig.alternateDomains.filter(function (o) {
@@ -689,9 +666,6 @@ function changeLocation(app, args, progressCallback, callback) {
progressCallback.bind(null, { percent: 80, message: 'Waiting for DNS propagation' }), progressCallback.bind(null, { percent: 80, message: 'Waiting for DNS propagation' }),
exports._waitForDnsPropagation.bind(null, app), exports._waitForDnsPropagation.bind(null, app),
progressCallback.bind(null, { percent: 90, message: 'Configuring reverse proxy' }),
configureReverseProxy.bind(null, app),
progressCallback.bind(null, { percent: 100, message: 'Done' }), progressCallback.bind(null, { percent: 100, message: 'Done' }),
updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null }) updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null })
], function seriesDone(error) { ], function seriesDone(error) {
@@ -752,9 +726,7 @@ function configure(app, args, progressCallback, callback) {
async.series([ async.series([
progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }), progressCallback.bind(null, { percent: 10, message: 'Cleaning up old install' }),
unconfigureReverseProxy.bind(null, app),
deleteContainers.bind(null, app, { managedOnly: true }), deleteContainers.bind(null, app, { managedOnly: true }),
reserveHttpPort.bind(null, app),
progressCallback.bind(null, { percent: 20, message: 'Downloading icon' }), progressCallback.bind(null, { percent: 20, message: 'Downloading icon' }),
downloadIcon.bind(null, app), downloadIcon.bind(null, app),
@@ -774,9 +746,6 @@ function configure(app, args, progressCallback, callback) {
startApp.bind(null, app), startApp.bind(null, app),
progressCallback.bind(null, { percent: 90, message: 'Configuring reverse proxy' }),
configureReverseProxy.bind(null, app),
progressCallback.bind(null, { percent: 100, message: 'Done' }), progressCallback.bind(null, { percent: 100, message: 'Done' }),
updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null }) updateApp.bind(null, app, { installationState: apps.ISTATE_INSTALLED, error: null, health: null })
], function seriesDone(error) { ], function seriesDone(error) {
@@ -789,7 +758,6 @@ function configure(app, args, progressCallback, callback) {
}); });
} }
// nginx configuration is skipped because app.httpPort is expected to be available
function update(app, args, progressCallback, callback) { function update(app, args, progressCallback, callback) {
assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof args, 'object'); assert.strictEqual(typeof args, 'object');
@@ -978,7 +946,6 @@ function uninstall(app, args, progressCallback, callback) {
async.series([ async.series([
progressCallback.bind(null, { percent: 20, message: 'Deleting container' }), progressCallback.bind(null, { percent: 20, message: 'Deleting container' }),
unconfigureReverseProxy.bind(null, app),
deleteContainers.bind(null, app, {}), deleteContainers.bind(null, app, {}),
progressCallback.bind(null, { percent: 30, message: 'Teardown addons' }), progressCallback.bind(null, { percent: 30, message: 'Teardown addons' }),
+42 -29
View File
@@ -1,34 +1,35 @@
'use strict'; 'use strict';
exports = module.exports = { exports = module.exports = {
testRegistryConfig: testRegistryConfig, testRegistryConfig,
setRegistryConfig: setRegistryConfig, setRegistryConfig,
injectPrivateFields: injectPrivateFields, injectPrivateFields,
removePrivateFields: removePrivateFields, removePrivateFields,
ping: ping, ping,
info: info, info,
downloadImage: downloadImage, downloadImage,
createContainer: createContainer, createContainer,
startContainer: startContainer, startContainer,
restartContainer: restartContainer, restartContainer,
stopContainer: stopContainer, stopContainer,
stopContainerByName: stopContainer, stopContainerByName: stopContainer,
stopContainers: stopContainers, stopContainers,
deleteContainer: deleteContainer, deleteContainer,
deleteImage: deleteImage, deleteImage,
deleteContainers: deleteContainers, deleteContainers,
createSubcontainer: createSubcontainer, createSubcontainer,
getContainerIdByIp: getContainerIdByIp, getContainerIdByIp,
inspect: inspect, inspect,
getContainerIp,
inspectByName: inspect, inspectByName: inspect,
execContainer: execContainer, execContainer,
getEvents: getEvents, getEvents,
memoryUsage: memoryUsage, memoryUsage,
createVolume: createVolume, createVolume,
removeVolume: removeVolume, removeVolume,
clearVolume: clearVolume clearVolume
}; };
var addons = require('./addons.js'), var addons = require('./addons.js'),
@@ -246,11 +247,6 @@ function createSubcontainer(app, name, cmd, options, callback) {
`${envPrefix}APP_DOMAIN=${domain}` `${envPrefix}APP_DOMAIN=${domain}`
]; ];
// docker portBindings requires ports to be exposed
exposedPorts[manifest.httpPort + '/tcp'] = {};
dockerPortBindings[manifest.httpPort + '/tcp'] = [ { HostIp: '127.0.0.1', HostPort: app.httpPort + '' } ];
var portEnv = []; var portEnv = [];
for (let portName in app.portBindings) { for (let portName in app.portBindings) {
const hostPort = app.portBindings[portName]; const hostPort = app.portBindings[portName];
@@ -259,6 +255,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
var containerPort = ports[portName].containerPort || hostPort; var containerPort = ports[portName].containerPort || hostPort;
// docker portBindings requires ports to be exposed
exposedPorts[`${containerPort}/${portType}`] = {}; exposedPorts[`${containerPort}/${portType}`] = {};
portEnv.push(`${portName}=${hostPort}`); portEnv.push(`${portName}=${hostPort}`);
@@ -560,6 +557,22 @@ function inspect(containerId, callback) {
}); });
} }
function getContainerIp(containerId, callback) {
assert.strictEqual(typeof containerId, 'string');
assert.strictEqual(typeof callback, 'function');
if (constants.TEST) return callback(null, '127.0.5.5');
inspect(containerId, function (error, result) {
if (error) return callback(error);
const ip = safe.query(result, 'NetworkSettings.Networks.cloudron.IPAddress', null);
if (!ip) return callback(new BoxError(BoxError.DOCKER_ERROR, 'Error getting container IP'));
callback(null, ip);
});
}
function execContainer(containerId, options, callback) { function execContainer(containerId, options, callback) {
assert.strictEqual(typeof containerId, 'string'); assert.strictEqual(typeof containerId, 'string');
assert.strictEqual(typeof options, 'object'); assert.strictEqual(typeof options, 'object');
+2 -2
View File
@@ -147,7 +147,7 @@ server {
<% if ( endpoint === 'admin' ) { %> <% if ( endpoint === 'admin' ) { %>
proxy_pass http://127.0.0.1:3000; proxy_pass http://127.0.0.1:3000;
<% } else if ( endpoint === 'app' ) { %> <% } else if ( endpoint === 'app' ) { %>
proxy_pass http://127.0.0.1:<%= port %>; proxy_pass http://<%= ip %>:<%= port %>;
<% } else if ( endpoint === 'redirect' ) { %> <% } else if ( endpoint === 'redirect' ) { %>
return 302 https://<%= redirectTo %>$request_uri; return 302 https://<%= redirectTo %>$request_uri;
<% } %> <% } %>
@@ -245,7 +245,7 @@ server {
error_page 401 = @proxy-auth-login; error_page 401 = @proxy-auth-login;
<% } %> <% } %>
proxy_pass http://127.0.0.1:<%= port %>; proxy_pass http://<%= ip %>:<%= port %>;
<% } else if ( endpoint === 'redirect' ) { %> <% } else if ( endpoint === 'redirect' ) { %>
# redirect everything to the app. this is temporary because there is no way # redirect everything to the app. this is temporary because there is no way
# to clear a permanent redirect on the browser # to clear a permanent redirect on the browser
+41 -35
View File
@@ -38,6 +38,7 @@ var acme2 = require('./cert/acme2.js'),
constants = require('./constants.js'), constants = require('./constants.js'),
crypto = require('crypto'), crypto = require('crypto'),
debug = require('debug')('box:reverseproxy'), debug = require('debug')('box:reverseproxy'),
docker = require('./docker.js'),
domains = require('./domains.js'), domains = require('./domains.js'),
ejs = require('ejs'), ejs = require('ejs'),
eventlog = require('./eventlog.js'), eventlog = require('./eventlog.js'),
@@ -160,7 +161,7 @@ function validateCertificate(location, domainObject, certificate) {
} }
function reload(callback) { function reload(callback) {
if (process.env.BOX_ENV === 'test') return callback(); if (constants.TEST) return callback();
shell.sudo('reload', [ RELOAD_NGINX_CMD ], {}, function (error) { shell.sudo('reload', [ RELOAD_NGINX_CMD ], {}, function (error) {
if (error) return callback(new BoxError(BoxError.NGINX_ERROR, `Error reloading nginx: ${error.message}`)); if (error) return callback(new BoxError(BoxError.NGINX_ERROR, `Error reloading nginx: ${error.message}`));
@@ -433,46 +434,51 @@ function writeAppNginxConfig(app, bundle, callback) {
assert.strictEqual(typeof bundle, 'object'); assert.strictEqual(typeof bundle, 'object');
assert.strictEqual(typeof callback, 'function'); assert.strictEqual(typeof callback, 'function');
var sourceDir = path.resolve(__dirname, '..'); docker.getContainerIp(app.containerId, function (error, ip) {
var endpoint = 'app'; if (error) return callback(error);
let robotsTxtQuoted = null, hideHeaders = [], cspQuoted = null; var sourceDir = path.resolve(__dirname, '..');
const reverseProxyConfig = app.reverseProxyConfig || {}; // some of our code uses fake app objects var endpoint = 'app';
if (reverseProxyConfig.robotsTxt) robotsTxtQuoted = JSON.stringify(app.reverseProxyConfig.robotsTxt);
if (reverseProxyConfig.csp) {
cspQuoted = `"${app.reverseProxyConfig.csp}"`;
hideHeaders = [ 'Content-Security-Policy' ];
if (reverseProxyConfig.csp.includes('frame-ancestors ')) hideHeaders.push('X-Frame-Options');
}
var data = { let robotsTxtQuoted = null, hideHeaders = [], cspQuoted = null;
sourceDir: sourceDir, const reverseProxyConfig = app.reverseProxyConfig || {}; // some of our code uses fake app objects
adminOrigin: settings.adminOrigin(), if (reverseProxyConfig.robotsTxt) robotsTxtQuoted = JSON.stringify(app.reverseProxyConfig.robotsTxt);
vhost: app.fqdn, if (reverseProxyConfig.csp) {
hasIPv6: sysinfo.hasIPv6(), cspQuoted = `"${app.reverseProxyConfig.csp}"`;
port: app.httpPort, hideHeaders = [ 'Content-Security-Policy' ];
endpoint: endpoint, if (reverseProxyConfig.csp.includes('frame-ancestors ')) hideHeaders.push('X-Frame-Options');
certFilePath: bundle.certFilePath,
keyFilePath: bundle.keyFilePath,
robotsTxtQuoted,
cspQuoted,
hideHeaders,
proxyAuth: {
enabled: app.sso && app.manifest.addons && app.manifest.addons.proxyAuth,
id: app.id
} }
};
var nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data);
var nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, app.id + '.conf'); var data = {
debug('writeAppNginxConfig: writing config for "%s" to %s with options %j', app.fqdn, nginxConfigFilename, data); sourceDir: sourceDir,
adminOrigin: settings.adminOrigin(),
vhost: app.fqdn,
hasIPv6: sysinfo.hasIPv6(),
ip,
port: app.manifest.httpPort,
endpoint: endpoint,
certFilePath: bundle.certFilePath,
keyFilePath: bundle.keyFilePath,
robotsTxtQuoted,
cspQuoted,
hideHeaders,
proxyAuth: {
enabled: app.sso && app.manifest.addons && app.manifest.addons.proxyAuth,
id: app.id
}
};
var nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data);
if (!safe.fs.writeFileSync(nginxConfigFilename, nginxConf)) { var nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, app.id + '.conf');
debug('Error creating nginx config for "%s" : %s', app.fqdn, safe.error.message); debug('writeAppNginxConfig: writing config for "%s" to %s with options %j', app.fqdn, nginxConfigFilename, data);
return callback(new BoxError(BoxError.FS_ERROR, safe.error));
}
reload(callback); if (!safe.fs.writeFileSync(nginxConfigFilename, nginxConf)) {
debug('Error creating nginx config for "%s" : %s', app.fqdn, safe.error.message);
return callback(new BoxError(BoxError.FS_ERROR, safe.error));
}
reload(callback);
});
} }
function writeAppRedirectNginxConfig(app, fqdn, bundle, callback) { function writeAppRedirectNginxConfig(app, fqdn, bundle, callback) {
+6 -18
View File
@@ -14,7 +14,6 @@ var appdb = require('../appdb.js'),
expect = require('expect.js'), expect = require('expect.js'),
fs = require('fs'), fs = require('fs'),
js2xml = require('js2xmlparser').parse, js2xml = require('js2xmlparser').parse,
net = require('net'),
nock = require('nock'), nock = require('nock'),
paths = require('../paths.js'), paths = require('../paths.js'),
settings = require('../settings.js'), settings = require('../settings.js'),
@@ -87,13 +86,12 @@ var APP = {
domain: DOMAIN_0.domain, domain: DOMAIN_0.domain,
fqdn: DOMAIN_0.domain + '.' + 'applocation', fqdn: DOMAIN_0.domain + '.' + 'applocation',
manifest: MANIFEST, manifest: MANIFEST,
containerId: null, containerId: 'someid',
httpPort: 4567,
portBindings: null, portBindings: null,
accessRestriction: null, accessRestriction: null,
memoryLimit: 0, memoryLimit: 0,
mailboxDomain: DOMAIN_0.domain, mailboxDomain: DOMAIN_0.domain,
alternateDomains: [] alternateDomains: [],
}; };
var awsHostedZones; var awsHostedZones;
@@ -132,28 +130,18 @@ describe('apptask', function () {
], done); ], done);
}); });
it('reserve port', function (done) {
apptask._reserveHttpPort(APP, function (error) {
expect(error).to.not.be.ok();
expect(APP.httpPort).to.be.a('number');
var client = net.connect(APP.httpPort);
client.on('connect', function () { done(new Error('Port is not free:' + APP.httpPort)); });
client.on('error', function () { done(); });
});
});
it('configure nginx correctly', function (done) { it('configure nginx correctly', function (done) {
apptask._configureReverseProxy(APP, function () { apptask._configureReverseProxy(APP, function (error) {
expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf')); expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
// expect(error).to.be(null); // this fails because nginx cannot be restarted expect(error).to.be(null);
done(); done();
}); });
}); });
it('unconfigure nginx', function (done) { it('unconfigure nginx', function (done) {
apptask._unconfigureReverseProxy(APP, function () { apptask._unconfigureReverseProxy(APP, function (error) {
expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf')); expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
// expect(error).to.be(null); // this fails because nginx cannot be restarted expect(error).to.be(null);
done(); done();
}); });
}); });
+1
View File
@@ -112,6 +112,7 @@ describe('retention policy', function () {
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 () { it('2 daily, 1 weekly', function () {
let b = [ let b = [
{ id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, { id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() },
-14
View File
@@ -397,7 +397,6 @@ describe('database', function () {
location: 'some-location-0', location: 'some-location-0',
domain: DOMAIN_0.domain, domain: DOMAIN_0.domain,
manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' }, manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' },
httpPort: null,
containerId: null, containerId: null,
portBindings: { port: { hostPort: 5678, type: 'tcp' } }, portBindings: { port: { hostPort: 5678, type: 'tcp' } },
health: null, health: null,
@@ -869,7 +868,6 @@ describe('database', function () {
location: 'some-location-0', location: 'some-location-0',
domain: DOMAIN_0.domain, domain: DOMAIN_0.domain,
manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' }, manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' },
httpPort: null,
containerId: null, containerId: null,
portBindings: { port: { hostPort: 5678, type: 'tcp' } }, portBindings: { port: { hostPort: 5678, type: 'tcp' } },
health: null, health: null,
@@ -905,7 +903,6 @@ describe('database', function () {
location: 'some-location-1', location: 'some-location-1',
domain: DOMAIN_0.domain, domain: DOMAIN_0.domain,
manifest: { version: '0.2', dockerImage: 'docker/app1', healthCheckPath: '/', httpPort: 80, title: 'app1' }, manifest: { version: '0.2', dockerImage: 'docker/app1', healthCheckPath: '/', httpPort: 80, title: 'app1' },
httpPort: null,
containerId: null, containerId: null,
portBindings: { }, portBindings: { },
health: null, health: null,
@@ -1009,7 +1006,6 @@ describe('database', function () {
APP_0.location = 'some-other-location'; APP_0.location = 'some-other-location';
APP_0.manifest.version = '0.2'; APP_0.manifest.version = '0.2';
APP_0.accessRestriction = ''; APP_0.accessRestriction = '';
APP_0.httpPort = 1337;
APP_0.memoryLimit = 1337; APP_0.memoryLimit = 1337;
APP_0.cpuShares = 1024; APP_0.cpuShares = 1024;
@@ -1019,7 +1015,6 @@ describe('database', function () {
domain: APP_0.domain, domain: APP_0.domain,
manifest: APP_0.manifest, manifest: APP_0.manifest,
accessRestriction: APP_0.accessRestriction, accessRestriction: APP_0.accessRestriction,
httpPort: APP_0.httpPort,
memoryLimit: APP_0.memoryLimit, memoryLimit: APP_0.memoryLimit,
cpuShares: APP_0.cpuShares cpuShares: APP_0.cpuShares
}; };
@@ -1036,15 +1031,6 @@ describe('database', function () {
}); });
}); });
it('getByHttpPort succeeds', function (done) {
appdb.getByHttpPort(APP_0.httpPort, 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) { it('update of nonexisting app fails', function (done) {
appdb.update(APP_1.id, { installationState: APP_1.installationState, location: APP_1.location }, function (error) { appdb.update(APP_1.id, { installationState: APP_1.installationState, location: APP_1.location }, function (error) {
expect(error).to.be.a(BoxError); expect(error).to.be.a(BoxError);
-1
View File
@@ -74,7 +74,6 @@ var APP_0 = {
location: 'some-location-0', location: 'some-location-0',
domain: DOMAIN_0.domain, domain: DOMAIN_0.domain,
manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' }, manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' },
httpPort: null,
containerId: 'someContainerId', containerId: 'someContainerId',
portBindings: { port: 5678 }, portBindings: { port: 5678 },
health: null, health: null,
-3
View File
@@ -233,7 +233,6 @@ describe('updatechecker - app - manual (email)', function () {
} }
} }
}, },
httpPort: null,
containerId: null, containerId: null,
portBindings: { PORT: 5678 }, portBindings: { PORT: 5678 },
healthy: null, healthy: null,
@@ -342,7 +341,6 @@ describe('updatechecker - app - automatic (no email)', function () {
} }
} }
}, },
httpPort: null,
containerId: null, containerId: null,
portBindings: { PORT: 5678 }, portBindings: { PORT: 5678 },
healthy: null, healthy: null,
@@ -407,7 +405,6 @@ describe('updatechecker - app - automatic free (email)', function () {
} }
} }
}, },
httpPort: null,
containerId: null, containerId: null,
portBindings: { PORT: 5678 }, portBindings: { PORT: 5678 },
healthy: null, healthy: null,