diff --git a/CHANGELOG.md b/CHANGELOG.md index 26739444..0eef30c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* Implement delete-then-download update strategy [Pablo] * Bump node-docker-delta to 0.0.12 [Pablo, Kostas] # v2.2.1 diff --git a/src/application.coffee b/src/application.coffee index ff6256f0..f5299cc8 100644 --- a/src/application.coffee +++ b/src/application.coffee @@ -17,6 +17,8 @@ fs = Promise.promisifyAll(require('fs')) JSONStream = require 'JSONStream' class UpdatesLockedError extends TypedError +ImageNotFoundError = (err) -> + return "#{err.statusCode}" is '404' { docker } = dockerUtils @@ -51,6 +53,19 @@ logTypes = eventName: 'Application install error' humanName: 'Failed to install application' + deleteImageForApp: + eventName: 'Application image removal' + humanName: 'Deleting image for application' + deleteImageForAppSuccess: + eventName: 'Application image removed' + humanName: 'Deleted image for application' + deleteImageForAppError: + eventName: 'Application image removal error' + humanName: 'Failed to delete image for application' + imageAlreadyDeleted: + eventName: 'Image already deleted' + humanName: 'Image already deleted for application' + startApp: eventName: 'Application start' humanName: 'Starting application' @@ -136,6 +151,17 @@ application.kill = kill = (app, updateDB = true, removeContainer = true) -> logSystemEvent(logTypes.stopAppError, app, err) throw err +application.deleteImage = deleteImage = (app) -> + logSystemEvent(logTypes.deleteImageForApp, app) + docker.getImage(app.imageId).removeAsync(force: true) + .then -> + logSystemEvent(logTypes.deleteImageForAppSuccess, app) + .catch ImageNotFoundError, (err) -> + logSystemEvent(logTypes.imageAlreadyDeleted, app) + .catch (err) -> + logSystemEvent(logTypes.deleteImageForAppError, app, err) + throw err + isValidPort = (port) -> maybePort = parseInt(port, 10) return parseFloat(port) is maybePort and maybePort > 0 and maybePort < 65535 @@ -452,6 +478,19 @@ updateStrategies = .catch (err) -> logSystemEvent(logTypes.updateAppError, app, err) unless err instanceof UpdatesLockedError throw err + 'delete-then-download': ({ localApp, app, needsDownload, force }) -> + Promise.using lockUpdates(localApp, force), -> + logSystemEvent(logTypes.updateApp, app) if localApp.imageId == app.imageId + utils.getKnexApp(localApp.appId) + .tap(kill) + .then(deleteImage) + .then -> + fetch(app) if needsDownload + .then -> + start(app) + .catch (err) -> + logSystemEvent(logTypes.updateAppError, app, err) unless err instanceof UpdatesLockedError + throw err 'hand-over': ({ localApp, app, needsDownload, force, timeout }) -> Promise.using lockUpdates(localApp, force), -> utils.getKnexApp(localApp.appId)