diff --git a/src/apps.js b/src/apps.js index 1a883a645..81372aa38 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1393,6 +1393,7 @@ function getLogs(appId, options, callback) { } // does a re-configure when called from most states. for install/clone errors, it re-installs with an optional manifest +// re-configure can take a dockerImage but not a manifest because re-configure does not clean up addons function repair(appId, data, auditSource, callback) { assert.strictEqual(typeof appId, 'string'); assert.strictEqual(typeof data, 'object'); // { manifest } @@ -1427,6 +1428,10 @@ function repair(appId, data, auditSource, callback) { } } else { errorState = exports.ISTATE_PENDING_CONFIGURE; + if (data.dockerImage) { + let newManifest = _.extend({}, app.manifest, { dockerImage: data.dockerImage }); + task.values.manifest = newManifest; + } } addTask(appId, errorState, task, function (error, result) { diff --git a/src/routes/apps.js b/src/routes/apps.js index e8ef5829b..0b73bde4c 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -365,7 +365,11 @@ function repairApp(req, res, next) { const data = req.body; if ('manifest' in data) { - if (!data.manifest || typeof data.manifest !== 'object') return next(new HttpError(400, 'backupId must be an object')); + if (!data.manifest || typeof data.manifest !== 'object') return next(new HttpError(400, 'manifest must be an object')); + } + + if ('dockerImage' in data) { + if (!data.dockerImage || typeof data.dockerImage !== 'string') return next(new HttpError(400, 'dockerImage must be a string')); } apps.repair(req.params.id, data, auditSource.fromRequest(req), function (error, result) {