Compare commits
11 Commits
authserver
...
v5.2.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f422b8533f | ||
|
|
234dfe59e2 | ||
|
|
9973a3c809 | ||
|
|
5aa426b8e2 | ||
|
|
70807d4551 | ||
|
|
ca6665dd20 | ||
|
|
c226b94f17 | ||
|
|
2dc7342f09 | ||
|
|
02b4b0f7d2 | ||
|
|
4267f5ea0a | ||
|
|
2e76b8bed9 |
12
CHANGES
12
CHANGES
@@ -1935,6 +1935,8 @@
|
||||
* stopping an app will stop dependent services
|
||||
* Add new wasabi s3 storage region us-east-2
|
||||
* mail: Fix bug where SRS translation was done on the main domain instead of mailing list domain
|
||||
* backups: add retention policy
|
||||
* Drop `NET_RAW` caps from container preventing sniffing of network traffic
|
||||
|
||||
[5.2.1]
|
||||
* Fix app disk graphs
|
||||
@@ -1949,3 +1951,13 @@
|
||||
* import: fix crash because encryption is unset
|
||||
* create redis with the correct label
|
||||
|
||||
[5.2.3]
|
||||
* Do not restart stopped apps
|
||||
|
||||
[5.2.4]
|
||||
* mail: enable/disable incoming mail was showing an error
|
||||
* Do not trigger backup of stopped apps. Instead, we will just retain it's existing backups
|
||||
based on retention policy
|
||||
* remove broken disk graphs
|
||||
* fix OVH backups
|
||||
|
||||
|
||||
@@ -696,6 +696,11 @@ function checkAppState(app, state) {
|
||||
if (state !== exports.ISTATE_PENDING_UNINSTALL && state !== exports.ISTATE_PENDING_RESTORE) return new BoxError(BoxError.BAD_STATE, 'Not allowed in error state');
|
||||
}
|
||||
|
||||
if (app.runState === exports.RSTATE_STOPPED) {
|
||||
// can't backup or restore since app addons are down. can't update because migration scripts won't run
|
||||
if (state === exports.ISTATE_PENDING_UPDATE || state === exports.ISTATE_PENDING_BACKUP || state === exports.ISTATE_PENDING_RESTORE) return new BoxError(BoxError.BAD_STATE, 'Not allowed in stopped state');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2001,6 +2006,7 @@ function restartAppsUsingAddons(changedAddons, callback) {
|
||||
apps = apps.filter(app => app.manifest.addons && _.intersection(Object.keys(app.manifest.addons), changedAddons).length !== 0);
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_ERROR); // remove errored apps. let them be 'repaired' by hand
|
||||
apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_RESTART); // safeguard against tasks being created non-stop restart if we crash on startup
|
||||
apps = apps.filter(app => app.runState !== exports.RSTATE_STOPPED); // don't start stopped apps
|
||||
|
||||
async.eachSeries(apps, function (app, iteratorDone) {
|
||||
debug(`restartAppsUsingAddons: marking ${app.fqdn} for restart`);
|
||||
|
||||
@@ -1026,6 +1026,10 @@ function backupBoxWithAppBackupIds(appBackupIds, tag, progressCallback, callback
|
||||
|
||||
function canBackupApp(app) {
|
||||
// only backup apps that are installed or specific pending states
|
||||
|
||||
// stopped apps cannot be backed up because addons might be down (redis)
|
||||
if (app.runState === apps.RSTATE_STOPPED) return false;
|
||||
|
||||
// we used to check the health here but that doesn't work for stopped apps. it's better to just fail
|
||||
// and inform the user if the backup fails and the app addons have not been setup yet.
|
||||
return app.installationState === apps.ISTATE_INSTALLED ||
|
||||
@@ -1141,7 +1145,16 @@ function backupAppWithTag(app, tag, options, progressCallback, callback) {
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
if (!canBackupApp(app)) return callback(); // nothing to do
|
||||
if (!canBackupApp(app)) { // if we cannot backup, reuse it's most recent backup
|
||||
getByAppIdPaged(1, 1, app.id, function (error, results) {
|
||||
if (error) return callback(error);
|
||||
if (results.length === 0) return callback(null, null); // no backup to re-use
|
||||
|
||||
callback(null, results[0].id);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
settings.getBackupConfig(function (error, backupConfig) {
|
||||
if (error) return callback(error);
|
||||
|
||||
23
src/cron.js
23
src/cron.js
@@ -1,11 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
// IMPORTANT: These patterns are together because they spin tasks which acquire a lock
|
||||
// If the patterns overlap all the time, then the task may not ever get a chance to run!
|
||||
const DEFAULT_CLEANUP_BACKUPS_PATTERN = '00 30 1,3,5,23 * * *',
|
||||
DEFAULT_BOX_ENSURE_BACKUP_PATTERN_LT_6HOURS = '00 45 1,7,13,19 * * *',
|
||||
DEFAULT_BOX_ENSURE_BACKUP_PATTERN_GT_6HOURS = '00 45 1,3,5,23 * * *',
|
||||
DEFAULT_BOX_AUTOUPDATE_PATTERN = '00 00 1,3,5,23 * * *',
|
||||
DEFAULT_APP_AUTOUPDATE_PATTERN = '00 15 1,3,5,23 * * *';
|
||||
|
||||
exports = module.exports = {
|
||||
startJobs: startJobs,
|
||||
startJobs,
|
||||
|
||||
stopJobs: stopJobs,
|
||||
stopJobs,
|
||||
|
||||
handleSettingsChanged: handleSettingsChanged
|
||||
handleSettingsChanged,
|
||||
|
||||
DEFAULT_BOX_AUTOUPDATE_PATTERN,
|
||||
DEFAULT_APP_AUTOUPDATE_PATTERN
|
||||
};
|
||||
|
||||
var appHealthMonitor = require('./apphealthmonitor.js'),
|
||||
@@ -98,7 +109,7 @@ function startJobs(callback) {
|
||||
});
|
||||
|
||||
gJobs.cleanupBackups = new CronJob({
|
||||
cronTime: '00 45 1,3,5,23 * * *', // every 6 hours. try not to overlap with ensureBackup job
|
||||
cronTime: DEFAULT_CLEANUP_BACKUPS_PATTERN,
|
||||
onTick: backups.startCleanupTask.bind(null, auditSource.CRON, NOOP_CALLBACK),
|
||||
start: true
|
||||
});
|
||||
@@ -177,9 +188,9 @@ function backupConfigChanged(value, tz) {
|
||||
if (gJobs.backup) gJobs.backup.stop();
|
||||
let pattern;
|
||||
if (value.intervalSecs <= 6 * 60 * 60) {
|
||||
pattern = '00 00 1,7,13,19 * * *'; // no option but to backup in the middle of the day
|
||||
pattern = DEFAULT_BOX_ENSURE_BACKUP_PATTERN_LT_6HOURS; // no option but to backup in the middle of the day
|
||||
} else {
|
||||
pattern = '00 00 1,3,5,23 * * *'; // avoid middle of the day backups
|
||||
pattern = DEFAULT_BOX_ENSURE_BACKUP_PATTERN_GT_6HOURS; // avoid middle of the day backups. it's 45 to not overlap auto-updates
|
||||
}
|
||||
|
||||
gJobs.backup = new CronJob({
|
||||
|
||||
@@ -131,8 +131,8 @@ var addons = require('./addons.js'),
|
||||
|
||||
let gDefaults = (function () {
|
||||
var result = { };
|
||||
result[exports.APP_AUTOUPDATE_PATTERN_KEY] = '00 30 1,3,5,23 * * *';
|
||||
result[exports.BOX_AUTOUPDATE_PATTERN_KEY] = '00 00 1,3,5,23 * * *';
|
||||
result[exports.APP_AUTOUPDATE_PATTERN_KEY] = cron.DEFAULT_APP_AUTOUPDATE_PATTERN;
|
||||
result[exports.BOX_AUTOUPDATE_PATTERN_KEY] = cron.DEFAULT_BOX_AUTOUPDATE_PATTERN;
|
||||
result[exports.TIME_ZONE_KEY] = 'America/Los_Angeles';
|
||||
result[exports.CLOUDRON_NAME_KEY] = 'Cloudron';
|
||||
result[exports.DYNAMIC_DNS_KEY] = false;
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('Settings', function () {
|
||||
it('can get default app_autoupdate_pattern', function (done) {
|
||||
settings.getAppAutoupdatePattern(function (error, pattern) {
|
||||
expect(error).to.be(null);
|
||||
expect(pattern).to.be('00 30 1,3,5,23 * * *');
|
||||
expect(pattern).to.be('00 15 1,3,5,23 * * *');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -83,7 +83,6 @@ function checkAppUpdates(options, callback) {
|
||||
|
||||
async.eachSeries(result, function (app, iteratorDone) {
|
||||
if (app.appStoreId === '') return iteratorDone(); // appStoreId can be '' for dev apps
|
||||
if (app.runState === apps.RSTATE_STOPPED) return iteratorDone(); // stopped apps won't run migration scripts and shouldn't be updated
|
||||
|
||||
appstore.getAppUpdate(app, options, function (error, updateInfo) {
|
||||
if (error) {
|
||||
|
||||
Reference in New Issue
Block a user