mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-03 04:26:44 +00:00
Keep track of target and actual device state, and make sure we keep updating the api with any differences until the two match.
This commit is contained in:
parent
e5d6235d89
commit
48c21e9275
@ -39,14 +39,12 @@ knex.init.then ->
|
|||||||
|
|
||||||
# Let API know what version we are, and our api connection info.
|
# Let API know what version we are, and our api connection info.
|
||||||
console.log('Updating supervisor version and api info')
|
console.log('Updating supervisor version and api info')
|
||||||
application.updateDeviceInfo(
|
application.updateDeviceState(
|
||||||
api_port: config.listenPort
|
api_port: config.listenPort
|
||||||
api_secret: secret
|
api_secret: secret
|
||||||
supervisor_version: utils.supervisorVersion
|
supervisor_version: utils.supervisorVersion
|
||||||
provisioning_progress: null
|
provisioning_progress: null
|
||||||
provisioning_state: ''
|
provisioning_state: ''
|
||||||
# Retry the device info update every 5s until it finally succeeds.
|
|
||||||
5000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log('Starting Apps..')
|
console.log('Starting Apps..')
|
||||||
@ -64,7 +62,7 @@ knex.init.then ->
|
|||||||
|
|
||||||
updateIpAddr = ->
|
updateIpAddr = ->
|
||||||
utils.findIpAddrs().then (ipAddrs) ->
|
utils.findIpAddrs().then (ipAddrs) ->
|
||||||
application.updateDeviceInfo(
|
application.updateDeviceState(
|
||||||
ip_address: ipAddrs.join(' ')
|
ip_address: ipAddrs.join(' ')
|
||||||
)
|
)
|
||||||
console.log('Starting periodic check for IP addresses..')
|
console.log('Starting periodic check for IP addresses..')
|
||||||
|
@ -28,7 +28,7 @@ exports.logSystemEvent = logSystemEvent = (message) ->
|
|||||||
kill = (app) ->
|
kill = (app) ->
|
||||||
logSystemEvent('Killing application ' + app.imageId)
|
logSystemEvent('Killing application ' + app.imageId)
|
||||||
utils.mixpanelTrack('Application kill', app)
|
utils.mixpanelTrack('Application kill', app)
|
||||||
updateDeviceInfo(status: 'Stopping')
|
updateDeviceState(status: 'Stopping')
|
||||||
container = docker.getContainer(app.containerId)
|
container = docker.getContainer(app.containerId)
|
||||||
console.log('Stopping and deleting container:', container)
|
console.log('Stopping and deleting container:', container)
|
||||||
tty.stop(app.id)
|
tty.stop(app.id)
|
||||||
@ -64,11 +64,11 @@ fetch = (app) ->
|
|||||||
.catch (error) ->
|
.catch (error) ->
|
||||||
utils.mixpanelTrack('Application download', app)
|
utils.mixpanelTrack('Application download', app)
|
||||||
logSystemEvent('Downloading application ' + app.imageId)
|
logSystemEvent('Downloading application ' + app.imageId)
|
||||||
updateDeviceInfo(status: 'Downloading')
|
updateDeviceState(status: 'Downloading')
|
||||||
dockerUtils.fetchImageWithProgress app.imageId, (progress) ->
|
dockerUtils.fetchImageWithProgress app.imageId, (progress) ->
|
||||||
updateDeviceInfo(download_progress: progress.percentage)
|
updateDeviceState(download_progress: progress.percentage)
|
||||||
.then ->
|
.then ->
|
||||||
updateDeviceInfo(download_progress: null)
|
updateDeviceState(download_progress: null)
|
||||||
docker.getImage(app.imageId).inspectAsync()
|
docker.getImage(app.imageId).inspectAsync()
|
||||||
|
|
||||||
exports.start = start = (app) ->
|
exports.start = start = (app) ->
|
||||||
@ -95,7 +95,7 @@ exports.start = start = (app) ->
|
|||||||
.then (imageInfo) ->
|
.then (imageInfo) ->
|
||||||
utils.mixpanelTrack('Application install', app)
|
utils.mixpanelTrack('Application install', app)
|
||||||
logSystemEvent('Installing application ' + app.imageId)
|
logSystemEvent('Installing application ' + app.imageId)
|
||||||
updateDeviceInfo(status: 'Installing')
|
updateDeviceState(status: 'Installing')
|
||||||
|
|
||||||
ports = {}
|
ports = {}
|
||||||
if portList?
|
if portList?
|
||||||
@ -129,7 +129,7 @@ exports.start = start = (app) ->
|
|||||||
.tap (container) ->
|
.tap (container) ->
|
||||||
utils.mixpanelTrack('Application start', app)
|
utils.mixpanelTrack('Application start', app)
|
||||||
logSystemEvent('Starting application ' + app.imageId)
|
logSystemEvent('Starting application ' + app.imageId)
|
||||||
updateDeviceInfo(status: 'Starting')
|
updateDeviceState(status: 'Starting')
|
||||||
ports = {}
|
ports = {}
|
||||||
if portList?
|
if portList?
|
||||||
portList.forEach (port) ->
|
portList.forEach (port) ->
|
||||||
@ -146,13 +146,13 @@ exports.start = start = (app) ->
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
.then ->
|
.then ->
|
||||||
updateDeviceInfo(commit: app.commit)
|
updateDeviceState(commit: app.commit)
|
||||||
logger.attach(app)
|
logger.attach(app)
|
||||||
.tap ->
|
.tap ->
|
||||||
utils.mixpanelTrack('Application start', app.imageId)
|
utils.mixpanelTrack('Application start', app.imageId)
|
||||||
logSystemEvent('Starting application ' + app.imageId)
|
logSystemEvent('Starting application ' + app.imageId)
|
||||||
.finally ->
|
.finally ->
|
||||||
updateDeviceInfo(status: 'Idle')
|
updateDeviceState(status: 'Idle')
|
||||||
|
|
||||||
# 0 - Idle
|
# 0 - Idle
|
||||||
# 1 - Updating
|
# 1 - Updating
|
||||||
@ -270,7 +270,7 @@ exports.update = update = ->
|
|||||||
console.log('Scheduling another update attempt due to failure: ', delayTime, err)
|
console.log('Scheduling another update attempt due to failure: ', delayTime, err)
|
||||||
setTimeout(update, delayTime)
|
setTimeout(update, delayTime)
|
||||||
.finally ->
|
.finally ->
|
||||||
updateDeviceInfo(status: 'Idle')
|
updateDeviceState(status: 'Idle')
|
||||||
if currentlyUpdating is 2
|
if currentlyUpdating is 2
|
||||||
# If an update is required then schedule it
|
# If an update is required then schedule it
|
||||||
setTimeout(update)
|
setTimeout(update)
|
||||||
@ -303,20 +303,49 @@ getDeviceID = do ->
|
|||||||
throw new Error('Could not find this device?!')
|
throw new Error('Could not find this device?!')
|
||||||
return devices[0].id
|
return devices[0].id
|
||||||
|
|
||||||
exports.updateDeviceInfo = updateDeviceInfo = (body, retry = false) ->
|
exports.updateDeviceState = updateDeviceState = do ->
|
||||||
Promise.all([
|
applyPromise = Promise.resolve()
|
||||||
|
targetState = {}
|
||||||
|
actualState = {}
|
||||||
|
|
||||||
|
getStateDiff = ->
|
||||||
|
_.omit targetState, (value, key) ->
|
||||||
|
actualState[key] is value
|
||||||
|
|
||||||
|
applyState = ->
|
||||||
|
if _.size(getStateDiff()) is 0
|
||||||
|
return
|
||||||
|
|
||||||
|
applyPromise = Promise.join(
|
||||||
knex('config').select('value').where(key: 'apiKey')
|
knex('config').select('value').where(key: 'apiKey')
|
||||||
getDeviceID()
|
getDeviceID()
|
||||||
]).spread ([{value: apiKey}], deviceID) ->
|
([{value: apiKey}], deviceID) ->
|
||||||
resinAPI.patch(
|
stateDiff = getStateDiff()
|
||||||
|
if _.size(stateDiff) is 0
|
||||||
|
return
|
||||||
|
resinAPI.patch
|
||||||
resource: 'device'
|
resource: 'device'
|
||||||
id: deviceID
|
id: deviceID
|
||||||
body: body
|
body: stateDiff
|
||||||
customOptions:
|
customOptions:
|
||||||
apikey: apiKey
|
apikey: apiKey
|
||||||
)
|
.then ->
|
||||||
|
# Update the actual state.
|
||||||
|
_.merge(actualState, stateDiff)
|
||||||
.catch (error) ->
|
.catch (error) ->
|
||||||
utils.mixpanelTrack('Device info update failure', {error, body})
|
utils.mixpanelTrack('Device info update failure', {error, stateDiff})
|
||||||
if retry isnt false
|
# Delay 5s before retrying a failed update
|
||||||
Promise.delay(retry).then ->
|
Promise.delay(5000)
|
||||||
updateDeviceInfo(body, retry)
|
)
|
||||||
|
.finally ->
|
||||||
|
# Check if any more state diffs have appeared whilst we've been processing this update.
|
||||||
|
applyState()
|
||||||
|
|
||||||
|
return (updatedState = {}, retry = false) ->
|
||||||
|
# Remove any updates that match the last we successfully sent.
|
||||||
|
_.merge(targetState, updatedState)
|
||||||
|
|
||||||
|
# Only trigger applying state if an apply isn't already in progress.
|
||||||
|
if !applyPromise.isPending()
|
||||||
|
applyState()
|
||||||
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user