From 9ae4f02bc508af9a21caf553f0587d2b1381285d Mon Sep 17 00:00:00 2001 From: Pablo Carranza Velez Date: Tue, 7 Mar 2017 18:09:55 -0300 Subject: [PATCH] Allow setting the supervisor to a "local mode" which stops apps and prevents cleanup A RESIN_SUPERVISOR_LOCAL_MODE variable is introduced. When this variable is "1", all apps are stopped and the update cycle stops executing changes other than deviceConfig changes and the proxyvisor. Change-Type: minor Signed-off-by: Pablo Carranza Velez --- src/application.coffee | 50 ++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/application.coffee b/src/application.coffee index 89f5debf..50fda3fe 100644 --- a/src/application.coffee +++ b/src/application.coffee @@ -111,6 +111,7 @@ logTypes = application = {} application.UpdatesLockedError = UpdatesLockedError +application.localMode = false application.logSystemMessage = logSystemMessage = (message, obj, eventName) -> logger.log({ m: message, s: 1 }) @@ -403,24 +404,47 @@ apiPollInterval = (val) -> clearInterval(updateStatus.intervalHandle) application.poll() -specialActionConfigVars = - 'RESIN_SUPERVISOR_VPN_CONTROL': utils.vpnControl - 'RESIN_SUPERVISOR_CONNECTIVITY_CHECK': utils.enableConnectivityCheck - 'RESIN_SUPERVISOR_POLL_INTERVAL': apiPollInterval - 'RESIN_SUPERVISOR_LOG_CONTROL': utils.resinLogControl +setLocalMode = (val) -> + mode = (val == '1') + Promise.try -> + if mode and !application.localMode + logSystemMessage('Entering local mode, app will be forcefully stopped', {}, 'Enter local mode') + Promise.map utils.getKnexApps(), (theApp) -> + Promise.using application.lockUpdates(theApp.appId, true), -> + # There's a slight chance the app changed after the previous select + # So we fetch it again now the lock is acquired + utils.getKnexApp(theApp.appId) + .then (app) -> + application.kill(app, removeContainer: false) if app? + else if !mode and application.localMode + logSystemMessage('Exiting local mode, app will be resumed', {}, 'Exit local mode') + Promise.map utils.getKnexApps(), (app) -> + unlockAndStart(app) + .then -> + application.localMode = mode + +specialActionConfigVars = [ + [ 'RESIN_SUPERVISOR_LOCAL_MODE', setLocalMode ] + [ 'RESIN_SUPERVISOR_VPN_CONTROL', utils.vpnControl ] + [ 'RESIN_SUPERVISOR_CONNECTIVITY_CHECK', utils.enableConnectivityCheck ] + [ 'RESIN_SUPERVISOR_POLL_INTERVAL', apiPollInterval ] + [ 'RESIN_SUPERVISOR_LOG_CONTROL', utils.resinLogControl ] +] executedSpecialActionConfigVars = {} executeSpecialActionsAndHostConfig = (conf, oldConf) -> - Promise.try -> - _.map specialActionConfigVars, (specialActionCallback, key) -> - if conf[key]? && specialActionCallback? - # This makes the Special Action Envs only trigger their functions once. - if executedSpecialActionConfigVars[key] != conf[key] - logSpecialAction(key, conf[key]) + Promise.mapSeries specialActionConfigVars, ([ key, specialActionCallback ]) -> + if conf[key]? && specialActionCallback? + # This makes the Special Action Envs only trigger their functions once. + if executedSpecialActionConfigVars[key] != conf[key] + logSpecialAction(key, conf[key]) + Promise.try -> specialActionCallback(conf[key]) + .then -> executedSpecialActionConfigVars[key] = conf[key] logSpecialAction(key, conf[key], true) + .then -> hostConfigVars = _.pickBy conf, (val, key) -> return _.startsWith(key, device.hostConfigConfigVarPrefix) oldHostConfigVars = _.pickBy oldConf, (val, key) -> @@ -648,6 +672,7 @@ application.update = update = (force, scheduled = false) -> logSystemMessage("Error applying device configuration: #{err}", { error: err }, 'Set device configuration error') .return(allAppIds) .map (appId) -> + return if application.localMode Promise.try -> needsDownload = _.includes(toBeDownloaded, appId) if _.includes(toBeRemoved, appId) @@ -704,6 +729,7 @@ application.update = update = (force, scheduled = false) -> .then -> proxyvisor.sendUpdates() .then -> + return if application.localMode updateStatus.failed = 0 device.setUpdateState(update_pending: false, update_downloaded: false, update_failed: false) # We cleanup here as we want a point when we have a consistent apps/images state, rather than potentially at a @@ -769,7 +795,7 @@ application.initialize = -> .then -> knex('app').select() .map (app) -> - unlockAndStart(app) + unlockAndStart(app) if !application.localMode .catch (error) -> console.error('Error starting apps:', error) .then ->