mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-29 18:18:52 +00:00
Auto-merge for PR #532 via VersionBot
Avoid stopping the VPN until a remote target state has been fetched, …
This commit is contained in:
commit
29616a6c29
@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file
|
||||
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## v6.4.9 - 2017-12-11
|
||||
|
||||
* Apply config.txt changes when the new config is empty, to fix deleting config.txt values #532 [Pablo Carranza Velez]
|
||||
* Avoid stopping the VPN until a remote target state has been fetched, and retry applying config variables when they fail #532 [Pablo Carranza Velez]
|
||||
|
||||
## v6.4.8 - 2017-12-01
|
||||
|
||||
* When listenPort is not specified, use 48484 as default #529 [Pablo Carranza Velez]
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "resin-supervisor",
|
||||
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
|
||||
"version": "6.4.8",
|
||||
"version": "6.4.9",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -141,11 +141,17 @@ logSystemEvent = (logType, app = {}, error) ->
|
||||
return
|
||||
|
||||
logSpecialAction = (action, value, success) ->
|
||||
if success
|
||||
if !value?
|
||||
msg = "Cleared config variable #{action}"
|
||||
if success?
|
||||
if success
|
||||
if !value?
|
||||
msg = "Cleared config variable #{action}"
|
||||
else
|
||||
msg = "Applied config variable #{action} = #{value}"
|
||||
else
|
||||
msg = "Applied config variable #{action} = #{value}"
|
||||
if !value?
|
||||
msg = "Config variable #{action} not cleared yet"
|
||||
else
|
||||
msg = "Config variable #{action} = #{value} not applied yet"
|
||||
else
|
||||
if !value?
|
||||
msg = "Clearing config variable #{action}"
|
||||
@ -466,6 +472,7 @@ apiPollInterval = (val) ->
|
||||
console.log('New API poll interval: ' + val)
|
||||
clearInterval(updateStatus.intervalHandle)
|
||||
application.poll()
|
||||
return true
|
||||
|
||||
setLocalMode = (val) ->
|
||||
mode = checkTruthy(val) ? false
|
||||
@ -490,6 +497,7 @@ setLocalMode = (val) ->
|
||||
unlockAndStart(app)
|
||||
.then ->
|
||||
application.localMode = mode
|
||||
.return(true)
|
||||
|
||||
specialActionConfigVars = [
|
||||
[ 'RESIN_SUPERVISOR_LOCAL_MODE', setLocalMode ]
|
||||
@ -498,20 +506,25 @@ specialActionConfigVars = [
|
||||
[ 'RESIN_SUPERVISOR_POLL_INTERVAL', apiPollInterval ]
|
||||
[ 'RESIN_SUPERVISOR_LOG_CONTROL', utils.resinLogControl ]
|
||||
]
|
||||
specialActionConfigKeys = _.map(specialActionConfigVars, 0)
|
||||
|
||||
executedSpecialActionConfigVars = {}
|
||||
|
||||
executeSpecialActionsAndHostConfig = (conf, oldConf) ->
|
||||
executeSpecialActionsAndHostConfig = (conf, oldConf, opts) ->
|
||||
updatedValues = _.pickBy _.clone(oldConf), (val, key) ->
|
||||
_.startsWith(key, device.hostConfigConfigVarPrefix) or _.includes(specialActionConfigKeys, key)
|
||||
needsReboot = false
|
||||
Promise.mapSeries specialActionConfigVars, ([ key, specialActionCallback ]) ->
|
||||
if (conf[key]? or oldConf[key]?) and 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 ->
|
||||
# This makes the Special Action Envs only trigger their functions once.
|
||||
if specialActionCallback? and executedSpecialActionConfigVars[key] != conf[key]
|
||||
logSpecialAction(key, conf[key])
|
||||
Promise.try ->
|
||||
specialActionCallback(conf[key], logSystemMessage, opts)
|
||||
.then (updated) ->
|
||||
if updated
|
||||
updatedValues[key] = conf[key]
|
||||
executedSpecialActionConfigVars[key] = conf[key]
|
||||
logSpecialAction(key, conf[key], true)
|
||||
logSpecialAction(key, conf[key], updated)
|
||||
.then ->
|
||||
hostConfigVars = _.pickBy conf, (val, key) ->
|
||||
return _.startsWith(key, device.hostConfigConfigVarPrefix)
|
||||
@ -519,14 +532,22 @@ executeSpecialActionsAndHostConfig = (conf, oldConf) ->
|
||||
return _.startsWith(key, device.hostConfigConfigVarPrefix)
|
||||
if !_.isEqual(hostConfigVars, oldHostConfigVars)
|
||||
device.setHostConfig(hostConfigVars, oldHostConfigVars, logSystemMessage)
|
||||
.then (changedHostConfig) ->
|
||||
needsReboot = changedHostConfig
|
||||
if changedHostConfig
|
||||
for own key of oldHostConfigVars
|
||||
delete updatedValues[key]
|
||||
_.assign(updatedValues, hostConfigVars)
|
||||
.then ->
|
||||
return { updatedValues, needsReboot }
|
||||
|
||||
getAndApplyDeviceConfig = ->
|
||||
getAndApplyDeviceConfig = ({ initial = false } = {}) ->
|
||||
deviceConfig.get()
|
||||
.then ({ values, targetValues }) ->
|
||||
executeSpecialActionsAndHostConfig(targetValues, values)
|
||||
.tap ->
|
||||
deviceConfig.set({ values: targetValues }) if !_.isEqual(values, targetValues)
|
||||
.then (needsReboot) ->
|
||||
executeSpecialActionsAndHostConfig(targetValues, values, { initial })
|
||||
.tap ({ updatedValues }) ->
|
||||
deviceConfig.set({ values: updatedValues }) if !_.isEqual(values, updatedValues)
|
||||
.then ({ needsReboot }) ->
|
||||
if needsReboot
|
||||
logSystemMessage('Rebooting', {}, 'Reboot')
|
||||
Promise.delay(1000)
|
||||
@ -758,12 +779,16 @@ application.update = update = (force, scheduled = false) ->
|
||||
remoteDeviceConfig = {}
|
||||
_.map remoteAppIds, (appId) ->
|
||||
_.merge(remoteDeviceConfig, JSON.parse(remoteApps[appId].config))
|
||||
remoteDeviceHostConfig = _.pickBy(remoteDeviceConfig, (val, key) -> _.startsWith(key, device.hostConfigConfigVarPrefix))
|
||||
remoteSpecialActionValues = _.pickBy(remoteDeviceConfig, (val, key) -> _.includes(specialActionConfigKeys, key))
|
||||
# This prevents saving values like RESIN_SUPERVISOR_DELTA, that (for now) actually belong to app config, to the deviceConfig table
|
||||
relevantDeviceConfig = _.assign({}, remoteDeviceHostConfig, remoteSpecialActionValues)
|
||||
deviceConfig.get()
|
||||
.then ({ values, targetValues }) ->
|
||||
# If the new device config is different from the target values we had, or if
|
||||
# for some reason it hasn't been applied yet (values don't match target), we apply it.
|
||||
if !_.isEqual(targetValues, remoteDeviceConfig) or !_.isEqual(targetValues, values)
|
||||
deviceConfig.set({ targetValues: remoteDeviceConfig })
|
||||
if !_.isEqual(targetValues, remoteDeviceConfig) or !_.isEqual(targetValues, values) or _.some(remoteSpecialActionValues, (v, k) -> executedSpecialActionConfigVars[k] != v)
|
||||
deviceConfig.set({ targetValues: relevantDeviceConfig })
|
||||
.then ->
|
||||
getAndApplyDeviceConfig()
|
||||
.catch (err) ->
|
||||
@ -922,7 +947,7 @@ application.initialize = ->
|
||||
listenToEvents()
|
||||
migrateContainerIdApps()
|
||||
.then ->
|
||||
getAndApplyDeviceConfig()
|
||||
getAndApplyDeviceConfig(initial: true)
|
||||
.then ->
|
||||
knex('app').whereNot(markedForDeletion: true).orWhereNull('markedForDeletion').select()
|
||||
.map (app) ->
|
||||
|
@ -119,7 +119,7 @@ setBootConfig = (env, oldEnv, logMessage) ->
|
||||
.then (deviceType) ->
|
||||
throw new Error('This is not a Raspberry Pi') if !_.startsWith(deviceType, 'raspberry')
|
||||
Promise.join parseBootConfigFromEnv(env), parseBootConfigFromEnv(oldEnv), fs.readFileAsync(bootConfigPath, 'utf8'), (configFromApp, oldConfigFromApp, configTxt ) ->
|
||||
throw new Error('No boot config to change') if _.isEmpty(configFromApp) or _.isEqual(configFromApp, oldConfigFromApp)
|
||||
throw new Error('No boot config to change') if _.isEqual(configFromApp, oldConfigFromApp)
|
||||
configFromFS = {}
|
||||
configPositions = []
|
||||
configStatements = configTxt.split(/\r?\n/)
|
||||
@ -140,7 +140,7 @@ setBootConfig = (env, oldEnv, logMessage) ->
|
||||
toBeChanged = _.intersection(keysFromApp, keysFromFS)
|
||||
toBeChanged = _.filter toBeChanged, (key) ->
|
||||
configFromApp[key] != configFromFS[key]
|
||||
throw new Error('Nothing to change') if _.isEmpty(toBeChanged) and _.isEmpty(toBeAdded)
|
||||
throw new Error('Nothing to change') if _.isEmpty(toBeChanged) and _.isEmpty(toBeAdded) and _.isEmpty(toBeDeleted)
|
||||
|
||||
logMessage("Applying boot config: #{JSON.stringify(configFromApp)}", {}, 'Apply boot config in progress')
|
||||
# We add the keys to be added first so they are out of any filters
|
||||
|
@ -184,12 +184,14 @@ exports.enableConnectivityCheck = (val) ->
|
||||
enabled = checkTruthy(val) ? true
|
||||
disableCheck(!enabled)
|
||||
console.log("Connectivity check enabled: #{enabled}")
|
||||
return true
|
||||
|
||||
# Callback function to enable/disable logs
|
||||
exports.resinLogControl = (val) ->
|
||||
logEnabled = checkTruthy(val) ? true
|
||||
logger.disableLogPublishing(!logEnabled)
|
||||
console.log('Logs enabled: ' + val)
|
||||
return true
|
||||
|
||||
emptyHostRequest = request.defaults({ headers: Host: '' })
|
||||
gosuperRequest = (method, endpoint, options = {}, callback) ->
|
||||
@ -210,14 +212,20 @@ exports.gosuper = gosuper =
|
||||
getAsync: Promise.promisify(gosuperGet, multiArgs: true)
|
||||
|
||||
# Callback function to enable/disable VPN
|
||||
exports.vpnControl = (val) ->
|
||||
exports.vpnControl = (val, logMessage, { initial = false } = {}) ->
|
||||
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 })
|
||||
.spread (response, body) ->
|
||||
if response.statusCode == 202
|
||||
console.log('VPN enabled: ' + enable)
|
||||
return true
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user