Avoid stopping the VPN until a remote target state has been fetched, and retry applying config variables when they fail

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
Pablo Carranza Velez 2017-12-08 00:16:34 -08:00
parent 481888fc8b
commit 8fc1a0935b
2 changed files with 34 additions and 12 deletions

View File

@ -466,6 +466,7 @@ apiPollInterval = (val) ->
console.log('New API poll interval: ' + val) console.log('New API poll interval: ' + val)
clearInterval(updateStatus.intervalHandle) clearInterval(updateStatus.intervalHandle)
application.poll() application.poll()
return true
setLocalMode = (val) -> setLocalMode = (val) ->
mode = checkTruthy(val) ? false mode = checkTruthy(val) ? false
@ -490,6 +491,7 @@ setLocalMode = (val) ->
unlockAndStart(app) unlockAndStart(app)
.then -> .then ->
application.localMode = mode application.localMode = mode
.return(true)
specialActionConfigVars = [ specialActionConfigVars = [
[ 'RESIN_SUPERVISOR_LOCAL_MODE', setLocalMode ] [ 'RESIN_SUPERVISOR_LOCAL_MODE', setLocalMode ]
@ -501,16 +503,20 @@ specialActionConfigVars = [
executedSpecialActionConfigVars = {} executedSpecialActionConfigVars = {}
executeSpecialActionsAndHostConfig = (conf, oldConf) -> executeSpecialActionsAndHostConfig = (conf, oldConf, opts) ->
updatedValues = _.clone(oldConf)
needsReboot = false
Promise.mapSeries specialActionConfigVars, ([ key, specialActionCallback ]) -> Promise.mapSeries specialActionConfigVars, ([ key, specialActionCallback ]) ->
if (conf[key]? or oldConf[key]?) and specialActionCallback? if (conf[key]? or oldConf[key]?) and specialActionCallback?
# This makes the Special Action Envs only trigger their functions once. # This makes the Special Action Envs only trigger their functions once.
if executedSpecialActionConfigVars[key] != conf[key] if executedSpecialActionConfigVars[key] != conf[key]
logSpecialAction(key, conf[key]) logSpecialAction(key, conf[key])
Promise.try -> Promise.try ->
specialActionCallback(conf[key]) specialActionCallback(conf[key], logSystemMessage, opts)
.then -> .then (updated) ->
executedSpecialActionConfigVars[key] = conf[key] if updated
updatedValues[key] = conf[key]
executedSpecialActionConfigVars[key] = conf[key]
logSpecialAction(key, conf[key], true) logSpecialAction(key, conf[key], true)
.then -> .then ->
hostConfigVars = _.pickBy conf, (val, key) -> hostConfigVars = _.pickBy conf, (val, key) ->
@ -519,14 +525,22 @@ executeSpecialActionsAndHostConfig = (conf, oldConf) ->
return _.startsWith(key, device.hostConfigConfigVarPrefix) return _.startsWith(key, device.hostConfigConfigVarPrefix)
if !_.isEqual(hostConfigVars, oldHostConfigVars) if !_.isEqual(hostConfigVars, oldHostConfigVars)
device.setHostConfig(hostConfigVars, oldHostConfigVars, logSystemMessage) device.setHostConfig(hostConfigVars, oldHostConfigVars, logSystemMessage)
.then (changedHostConfig) ->
needsReboot = changedHostConfig
if changedHostConfig
_.forEach oldHostConfigVars, (val, key) ->
delete updatedValues[key]
_.assign(updatedValues, hostConfigVars)
.then ->
return { updatedValues, needsReboot }
getAndApplyDeviceConfig = -> getAndApplyDeviceConfig = ({ initial = false } = {}) ->
deviceConfig.get() deviceConfig.get()
.then ({ values, targetValues }) -> .then ({ values, targetValues }) ->
executeSpecialActionsAndHostConfig(targetValues, values) executeSpecialActionsAndHostConfig(targetValues, values, { initial })
.tap -> .tap ({ updatedValues }) ->
deviceConfig.set({ values: targetValues }) if !_.isEqual(values, targetValues) deviceConfig.set({ values: updatedValues }) if !_.isEqual(values, updatedValues)
.then (needsReboot) -> .then ({ needsReboot }) ->
if needsReboot if needsReboot
logSystemMessage('Rebooting', {}, 'Reboot') logSystemMessage('Rebooting', {}, 'Reboot')
Promise.delay(1000) Promise.delay(1000)
@ -922,7 +936,7 @@ application.initialize = ->
listenToEvents() listenToEvents()
migrateContainerIdApps() migrateContainerIdApps()
.then -> .then ->
getAndApplyDeviceConfig() getAndApplyDeviceConfig(initial: true)
.then -> .then ->
knex('app').whereNot(markedForDeletion: true).orWhereNull('markedForDeletion').select() knex('app').whereNot(markedForDeletion: true).orWhereNull('markedForDeletion').select()
.map (app) -> .map (app) ->

View File

@ -184,12 +184,14 @@ exports.enableConnectivityCheck = (val) ->
enabled = checkTruthy(val) ? true enabled = checkTruthy(val) ? true
disableCheck(!enabled) disableCheck(!enabled)
console.log("Connectivity check enabled: #{enabled}") console.log("Connectivity check enabled: #{enabled}")
return true
# Callback function to enable/disable logs # Callback function to enable/disable logs
exports.resinLogControl = (val) -> exports.resinLogControl = (val) ->
logEnabled = checkTruthy(val) ? true logEnabled = checkTruthy(val) ? true
logger.disableLogPublishing(!logEnabled) logger.disableLogPublishing(!logEnabled)
console.log('Logs enabled: ' + val) console.log('Logs enabled: ' + val)
return true
emptyHostRequest = request.defaults({ headers: Host: '' }) emptyHostRequest = request.defaults({ headers: Host: '' })
gosuperRequest = (method, endpoint, options = {}, callback) -> gosuperRequest = (method, endpoint, options = {}, callback) ->
@ -210,14 +212,20 @@ exports.gosuper = gosuper =
getAsync: Promise.promisify(gosuperGet, multiArgs: true) getAsync: Promise.promisify(gosuperGet, multiArgs: true)
# Callback function to enable/disable VPN # Callback function to enable/disable VPN
exports.vpnControl = (val) -> exports.vpnControl = (val, logMessage, { initial = false } = {}) ->
enable = checkTruthy(val) ? true enable = checkTruthy(val) ? true
# If it's the initial run, we always want the VPN enabled, so we ignore calls to disable it
if initial and !enable
return Promise.resolve(false)
gosuper.postAsync('/v1/vpncontrol', { json: true, body: Enable: enable }) gosuper.postAsync('/v1/vpncontrol', { json: true, body: Enable: enable })
.spread (response, body) -> .spread (response, body) ->
if response.statusCode == 202 if response.statusCode == 202
console.log('VPN enabled: ' + enable) console.log('VPN enabled: ' + enable)
return true
else else
console.log('Error: ' + body + ' response:' + response.statusCode) logMessage("Error (#{response.statusCode}) toggling VPN: #{body}", {}, 'Toggle VPN error')
return false
.catchReturn(false)
exports.AppNotFoundError = class AppNotFoundError extends TypedError exports.AppNotFoundError = class AppNotFoundError extends TypedError