diff --git a/src/apps.js b/src/apps.js index c323f1799..b53c67a97 100644 --- a/src/apps.js +++ b/src/apps.js @@ -58,6 +58,7 @@ exports = module.exports = { restoreInstalledApps: restoreInstalledApps, configureInstalledApps: configureInstalledApps, schedulePendingTasks: schedulePendingTasks, + restartAppsUsingAddons: restartAppsUsingAddons, getDataDir: getDataDir, getIconPath: getIconPath, @@ -1986,6 +1987,34 @@ function configureInstalledApps(callback) { }); } +function restartAppsUsingAddons(changedAddons, callback) { + assert(Array.isArray(changedAddons)); + assert.strictEqual(typeof callback, 'function'); + + getAll(function (error, apps) { + if (error) return callback(error); + + 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 + + async.eachSeries(apps, function (app, iteratorDone) { + debug(`restartAppsUsingAddons: marking ${app.fqdn} for restart`); + + const task = { + args: {}, + values: { runState: exports.RSTATE_RUNNING } + }; + addTask(app.id, exports.ISTATE_PENDING_RESTART, task, function (error, result) { + if (error) debug(`restartAppsUsingAddons: error marking ${app.fqdn} for restart: ${JSON.stringify(error)}`); + else debug(`restartAppsUsingAddons: marked ${app.id} for restart with taskId ${result.taskId}`); + + iteratorDone(); // ignore error + }); + }, callback); + }); +} + // auto-restart app tasks after a crash function schedulePendingTasks(callback) { assert.strictEqual(typeof callback, 'function'); diff --git a/src/platform.js b/src/platform.js index fc8a30dee..f854b40f8 100644 --- a/src/platform.js +++ b/src/platform.js @@ -164,7 +164,19 @@ function startApps(existingInfra, callback) { reverseProxy.removeAppConfigs(); // should we change the cert location, nginx will not start apps.configureInstalledApps(callback); } else { - debug('startApps: apps are already uptodate'); - callback(); + let changedAddons = []; + if (infra.images.mysql.tag !== existingInfra.images.mysql.tag) changedAddons.push('mysql'); + if (infra.images.postgresql.tag !== existingInfra.images.postgresql.tag) changedAddons.push('postgresql'); + if (infra.images.mongodb.tag !== existingInfra.images.mongodb.tag) changedAddons.push('mongodb'); + if (infra.images.redis.tag !== existingInfra.images.redis.tag) changedAddons.push('redis'); + + if (changedAddons.length) { + // restart apps if docker image changes since the IP changes and any "persistent" connections fail + debug(`startApps: changedAddons: ${JSON.stringify(changedAddons)}`); + apps.restartAppsUsingAddons(changedAddons, callback); + } else { + debug('startApps: apps are already uptodate'); + callback(); + } } }