diff --git a/migrations/20190828030723-apps-rename-installationProgress-errorMessage.js b/migrations/20190828030723-apps-rename-installationProgress-errorJson.js similarity index 68% rename from migrations/20190828030723-apps-rename-installationProgress-errorMessage.js rename to migrations/20190828030723-apps-rename-installationProgress-errorJson.js index b883ea448..3101c81cd 100644 --- a/migrations/20190828030723-apps-rename-installationProgress-errorMessage.js +++ b/migrations/20190828030723-apps-rename-installationProgress-errorJson.js @@ -1,14 +1,14 @@ 'use strict'; exports.up = function(db, callback) { - db.runSql('ALTER TABLE apps CHANGE installationProgress errorMessage TEXT', [], function (error) { + db.runSql('ALTER TABLE apps CHANGE installationProgress errorJson TEXT', [], function (error) { if (error) console.error(error); callback(error); }); }; exports.down = function(db, callback) { - db.runSql('ALTER TABLE apps CHANGE errorMessage installationProgress TEXT', [], function (error) { + db.runSql('ALTER TABLE apps CHANGE errorJson installationProgress TEXT', [], function (error) { if (error) console.error(error); callback(error); }); diff --git a/migrations/schema.sql b/migrations/schema.sql index 716d433f2..c2198c2a5 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -89,7 +89,7 @@ CREATE TABLE IF NOT EXISTS apps( tagsJson VARCHAR(2048), // array of tags dataDir VARCHAR(256) UNIQUE, taskId INTEGER, // current task - errorMessage TEXT, + errorJson TEXT, FOREIGN KEY(taskId) REFERENCES tasks(id), PRIMARY KEY(id)); diff --git a/src/addons.js b/src/addons.js index fc1a139f6..151eda66a 100644 --- a/src/addons.js +++ b/src/addons.js @@ -644,7 +644,7 @@ function importDatabase(addon, callback) { if (!error) return iteratorCallback(); debug(`importDatabase: Error importing ${addon} of app ${app.id}. Marking as errored`, error); - appdb.update(app.id, { installationState: appdb.ISTATE_ERROR, errorMessage: error.message }, iteratorCallback); + appdb.update(app.id, { installationState: appdb.ISTATE_ERROR, error: { message: error.message } }, iteratorCallback); }); }, callback); }); diff --git a/src/appdb.js b/src/appdb.js index 698382bc9..7f30179c4 100644 --- a/src/appdb.js +++ b/src/appdb.js @@ -60,7 +60,7 @@ var assert = require('assert'), safe = require('safetydance'), util = require('util'); -var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.errorMessage', '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.accessRestrictionJson', 'apps.memoryLimit', 'apps.label', 'apps.tagsJson', 'apps.taskId', @@ -129,6 +129,9 @@ function postProcess(result) { // in the db, we store dataDir as unique/nullable result.dataDir = result.dataDir || ''; + result.error = safe.JSON.parse(result.errorJson); + delete result.errorJson; + result.taskId = result.taskId ? String(result.taskId) : null; } @@ -441,7 +444,7 @@ function updateWithConstraints(id, app, constraints, callback) { var fields = [ ], values = [ ]; for (var p in app) { - if (p === 'manifest' || p === 'tags' || p === 'accessRestriction' || p === 'debugMode') { + if (p === 'manifest' || p === 'tags' || p === 'accessRestriction' || p === 'debugMode' || p === 'error') { fields.push(`${p}Json = ?`); values.push(JSON.stringify(app[p])); } else if (p !== 'portBindings' && p !== 'location' && p !== 'domain' && p !== 'alternateDomains' && p !== 'env') { diff --git a/src/apptask.js b/src/apptask.js index 2d3cd1c11..7ac378e6d 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -593,7 +593,7 @@ function install(app, restoreConfig, progressCallback, callback) { ], function seriesDone(error) { if (error) { debugApp(app, 'error installing app: %s', error); - return updateApp(app, { installationState: appdb.ISTATE_ERROR, errorMessage: error.message }, callback.bind(null, error)); + return updateApp(app, { installationState: appdb.ISTATE_ERROR, error: { message: error.message } }, callback.bind(null, error)); } callback(null); }); @@ -611,11 +611,11 @@ function backup(app, progressCallback, callback) { }), progressCallback.bind(null, { percent: 100, message: 'Done' }), - updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, errorMessage: '' }) + updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, error: null }) ], function seriesDone(error) { if (error) { debugApp(app, 'error backing up app: %s', error); - return updateApp(app, { installationState: appdb.ISTATE_INSTALLED, errorMessage: error.message }, callback.bind(null, error)); // return to installed state intentionally + return updateApp(app, { installationState: appdb.ISTATE_INSTALLED, error: { message: error.message } }, callback.bind(null, error)); // return to installed state intentionally } callback(null); }); @@ -692,11 +692,11 @@ function configure(app, oldConfig, progressCallback, callback) { configureReverseProxy.bind(null, app), progressCallback.bind(null, { percent: 100, message: 'Done' }), - updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, errorMessage: '', health: null }) + updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, error: null, health: null }) ], function seriesDone(error) { if (error) { debugApp(app, 'error reconfiguring : %s', error); - return updateApp(app, { installationState: appdb.ISTATE_ERROR, errorMessage: error.message }, callback.bind(null, error)); + return updateApp(app, { installationState: appdb.ISTATE_ERROR, error: { message: error.message }}, callback.bind(null, error)); } callback(null); }); @@ -798,14 +798,14 @@ function update(app, updateConfig, progressCallback, callback) { runApp.bind(null, app, progressCallback), progressCallback.bind(null, { percent: 100, message: 'Done' }), - updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, errorMessage: '', health: null, updateTime: new Date() }) + updateApp.bind(null, app, { installationState: appdb.ISTATE_INSTALLED, error: null, health: null, updateTime: new Date() }) ], function seriesDone(error) { if (error && error.backupError) { debugApp(app, 'update aborted because backup failed', error); - updateApp(app, { installationState: appdb.ISTATE_INSTALLED, errorMessage: '', health: null }, callback.bind(null, error)); + updateApp(app, { installationState: appdb.ISTATE_INSTALLED, error: null, health: null }, callback.bind(null, error)); } else if (error) { debugApp(app, 'Error updating app: %s', error); - updateApp(app, { installationState: appdb.ISTATE_ERROR, errorMessage: error.message, updateTime: new Date() }, callback.bind(null, error)); + updateApp(app, { installationState: appdb.ISTATE_ERROR, error: { message: error.message }, updateTime: new Date() }, callback.bind(null, error)); } else { if (updateConfig.skipNotification) return callback(); @@ -859,7 +859,7 @@ function uninstall(app, progressCallback, callback) { ], function seriesDone(error) { if (error) { debugApp(app, 'error uninstalling app: %s', error); - return updateApp(app, { installationState: appdb.ISTATE_ERROR, errorMessage: error.message }, callback.bind(null, error)); + return updateApp(app, { installationState: appdb.ISTATE_ERROR, error: { message: error.message } }, callback.bind(null, error)); } callback(null); }); diff --git a/src/test/database-test.js b/src/test/database-test.js index a1436e501..e7dcdf058 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -389,7 +389,7 @@ describe('database', function () { id: 'appid-0', appStoreId: 'appStoreId-0', installationState: appdb.ISTATE_PENDING_INSTALL, - errorMessage: null, + error: null, runState: null, location: 'some-location-0', domain: DOMAIN_0.domain, @@ -967,7 +967,7 @@ describe('database', function () { id: 'appid-0', appStoreId: 'appStoreId-0', installationState: appdb.ISTATE_PENDING_INSTALL, - errorMessage: null, + error: null, runState: null, location: 'some-location-0', domain: DOMAIN_0.domain, @@ -998,7 +998,7 @@ describe('database', function () { id: 'appid-1', appStoreId: 'appStoreId-1', installationState: appdb.ISTATE_PENDING_INSTALL, // app health tests rely on this initial state - errorMessage: null, + error: null, runState: null, location: 'some-location-1', domain: DOMAIN_0.domain, diff --git a/src/test/ldap-test.js b/src/test/ldap-test.js index a64f2e6c4..064e8e673 100644 --- a/src/test/ldap-test.js +++ b/src/test/ldap-test.js @@ -64,7 +64,7 @@ var APP_0 = { id: 'appid-0', appStoreId: 'appStoreId-0', installationState: appdb.ISTATE_INSTALLED, - errorMessage: null, + error: null, runState: appdb.RSTATE_RUNNING, location: 'some-location-0', domain: DOMAIN_0.domain, diff --git a/src/test/updatechecker-test.js b/src/test/updatechecker-test.js index 142e0c494..bd1870e22 100644 --- a/src/test/updatechecker-test.js +++ b/src/test/updatechecker-test.js @@ -216,7 +216,7 @@ describe('updatechecker - app - manual (email)', function () { id: 'appid-0', appStoreId: 'io.cloudron.app', installationState: appdb.ISTATE_PENDING_INSTALL, - errorMessage: null, + error: null, runState: null, location: 'some-location-0', domain: DOMAIN_0.domain, @@ -323,7 +323,7 @@ describe('updatechecker - app - automatic (no email)', function () { id: 'appid-0', appStoreId: 'io.cloudron.app', installationState: appdb.ISTATE_PENDING_INSTALL, - errorMessage: null, + error: null, runState: null, location: 'some-location-0', domain: DOMAIN_0.domain, @@ -386,7 +386,7 @@ describe('updatechecker - app - automatic free (email)', function () { id: 'appid-0', appStoreId: 'io.cloudron.app', installationState: appdb.ISTATE_PENDING_INSTALL, - errorMessage: null, + error: null, runState: null, location: 'some-location-0', domain: DOMAIN_0.domain,