diff --git a/CHANGES b/CHANGES index fa92c1680..0891de2ff 100644 --- a/CHANGES +++ b/CHANGES @@ -2046,7 +2046,6 @@ * Add note that password reset and invite links expire in 24 hours [5.5.0] -* **IMPORTANT:** DO NOT UPGRADE WITHOUT A BACKUP - PostgreSQL UPGRADE REQUIRES A VALID BACKUP. * postgresql: update to PostgreSQL 11 * postgresql: add citext extension to whitelist for loomio * postgresql: add btree_gist,postgres_fdw extensions for gitlab diff --git a/src/addons.js b/src/addons.js index b4d34c812..d8538d809 100644 --- a/src/addons.js +++ b/src/addons.js @@ -749,6 +749,43 @@ function importDatabase(addon, callback) { // not clear, if repair workflow should be part of addon or per-app appdb.update(app.id, { installationState: apps.ISTATE_ERROR, error: { message: error.message } }, iteratorCallback); }); + }, function (error) { + safe.fs.unlinkSync(path.join(paths.ADDON_CONFIG_DIR, `exported-${addon}`)); // clean up for future migrations + + callback(error); + }); + }); +} + +function exportDatabase(addon, callback) { + assert.strictEqual(typeof addon, 'string'); + assert.strictEqual(typeof callback, 'function'); + + debug(`exportDatabase: Exporting ${addon}`); + + if (fs.existsSync(path.join(paths.ADDON_CONFIG_DIR, `exported-${addon}`))) { + debug(`exportDatabase: Already exported addon ${addon} in previous run`); + return callback(null); + } + + appdb.getAll(function (error, apps) { + if (error) return callback(error); + + async.eachSeries(apps, function iterator (app, iteratorCallback) { + if (!app.manifest.adddons || !(addon in app.manifest.addons)) return iteratorCallback(); // app doesn't use the addon + + debug(`exportDatabase: Exporting addon ${addon} of app ${app.id}`); + + ADDONS[addon].backup(app, app.manifest.addons[addon], function (error) { + if (error) { + debug(`exportDatabase: Error exporting ${addon} of app ${app.id}.`, error); + return iteratorCallback(error); + } + + safe.fs.writeFileSync(path.join(paths.ADDON_CONFIG_DIR, `exported-${addon}`), '', 'utf8'); + + shell.sudo('exportDatabase', [ RMADDONDIR_CMD, addon ], {}, iteratorCallback); + }); }, callback); }); } @@ -1131,7 +1168,7 @@ function startMysql(existingInfra, callback) { const upgrading = existingInfra.version !== 'none' && requiresUpgrade(existingInfra.images.mysql.tag, tag); if (upgrading) debug('startMysql: mysql will be upgraded'); - const upgradeFunc = upgrading ? shell.sudo.bind(null, 'startMysql', [ RMADDONDIR_CMD, 'mysql' ], {}) : (next) => next(); + const upgradeFunc = upgrading ? exportDatabase.bind(null, 'mysql') : (next) => next(); upgradeFunc(function (error) { if (error) return callback(error); @@ -1348,7 +1385,7 @@ function startPostgresql(existingInfra, callback) { const upgrading = existingInfra.version !== 'none' && requiresUpgrade(existingInfra.images.postgresql.tag, tag); if (upgrading) debug('startPostgresql: postgresql will be upgraded'); - const upgradeFunc = upgrading ? shell.sudo.bind(null, 'startPostgresql', [ RMADDONDIR_CMD, 'postgresql' ], {}) : (next) => next(); + const upgradeFunc = upgrading ? exportDatabase.bind(null, 'postgresql') : (next) => next(); upgradeFunc(function (error) { if (error) return callback(error); @@ -1562,7 +1599,7 @@ function startMongodb(existingInfra, callback) { const upgrading = existingInfra.version !== 'none' && requiresUpgrade(existingInfra.images.mongodb.tag, tag); if (upgrading) debug('startMongodb: mongodb will be upgraded'); - const upgradeFunc = upgrading ? shell.sudo.bind(null, 'startMongodb', [ RMADDONDIR_CMD, 'mongodb' ], {}) : (next) => next(); + const upgradeFunc = upgrading ? exportDatabase.bind(null, 'mongodb') : (next) => next(); upgradeFunc(function (error) { if (error) return callback(error);