mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-31 00:23:57 +00:00
Allow the supervisor to work in offline mode
A supervisorOfflineMode true-ish attribute in config.json will cause that: * If unprovisioned, the supervisor won't try to provision on Resin * The update cycle will not start as the device won't consider itself provisioned * Logs will not be sent to pubnub * Mixpanel events won't be tracked * The device state won't be updated to the Resin API This change will also make the Supervisor API work with an unprovisioned device.
This commit is contained in:
parent
d652e13005
commit
98d9aca92d
@ -1,3 +1,4 @@
|
|||||||
|
* Allow the supervisor to work in offline mode [Pablo]
|
||||||
* Fix duplicate logs issue [Kostas]
|
* Fix duplicate logs issue [Kostas]
|
||||||
* **[Breaking]** Do not bind mount /run/dbus to /run/dbus [Pablo]
|
* **[Breaking]** Do not bind mount /run/dbus to /run/dbus [Pablo]
|
||||||
* Default to not bind mounting kmod if container distro can't be found [Pablo]
|
* Default to not bind mounting kmod if container distro can't be found [Pablo]
|
||||||
|
@ -20,16 +20,17 @@ knex.init.then ->
|
|||||||
utils.mixpanelProperties.uuid = uuid
|
utils.mixpanelProperties.uuid = uuid
|
||||||
|
|
||||||
api = require './api'
|
api = require './api'
|
||||||
application = require('./application')(logsChannel)
|
application = require('./application')(logsChannel, bootstrap.offlineMode)
|
||||||
device = require './device'
|
device = require './device'
|
||||||
|
|
||||||
|
console.log('Starting API server..')
|
||||||
|
apiServer = api(application).listen(config.listenPort)
|
||||||
|
apiServer.timeout = config.apiTimeout
|
||||||
|
|
||||||
bootstrap.done
|
bootstrap.done
|
||||||
.then ->
|
.then ->
|
||||||
device.getOSVersion()
|
device.getOSVersion()
|
||||||
.then (osVersion) ->
|
.then (osVersion) ->
|
||||||
console.log('Starting API server..')
|
|
||||||
apiServer = api(application).listen(config.listenPort)
|
|
||||||
apiServer.timeout = config.apiTimeout
|
|
||||||
# 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')
|
||||||
device.updateState(
|
device.updateState(
|
||||||
|
@ -703,10 +703,11 @@ application.initialize = ->
|
|||||||
application.poll()
|
application.poll()
|
||||||
application.update()
|
application.update()
|
||||||
|
|
||||||
module.exports = (logsChannel) ->
|
module.exports = (logsChannel, offlineMode) ->
|
||||||
logger.init(
|
logger.init(
|
||||||
dockerSocket: config.dockerSocket
|
dockerSocket: config.dockerSocket
|
||||||
pubnub: config.pubnub
|
pubnub: config.pubnub
|
||||||
channel: "device-#{logsChannel}-logs"
|
channel: "device-#{logsChannel}-logs"
|
||||||
|
offlineMode: offlineMode
|
||||||
)
|
)
|
||||||
return application
|
return application
|
||||||
|
@ -64,12 +64,12 @@ bootstrap = ->
|
|||||||
.tap ->
|
.tap ->
|
||||||
bootstrapper.doneBootstrapping()
|
bootstrapper.doneBootstrapping()
|
||||||
|
|
||||||
readConfigAndEnsureUUID = ->
|
readConfig = ->
|
||||||
# Load config file
|
|
||||||
fs.readFileAsync(configPath, 'utf8')
|
fs.readFileAsync(configPath, 'utf8')
|
||||||
.then(JSON.parse)
|
.then(JSON.parse)
|
||||||
.then (configFromFile) ->
|
|
||||||
userConfig = configFromFile
|
readConfigAndEnsureUUID = ->
|
||||||
|
Promise.try ->
|
||||||
return userConfig.uuid if userConfig.uuid?
|
return userConfig.uuid if userConfig.uuid?
|
||||||
deviceRegister.generateUUID()
|
deviceRegister.generateUUID()
|
||||||
.then (uuid) ->
|
.then (uuid) ->
|
||||||
@ -84,6 +84,8 @@ readConfigAndEnsureUUID = ->
|
|||||||
|
|
||||||
bootstrapOrRetry = ->
|
bootstrapOrRetry = ->
|
||||||
utils.mixpanelTrack('Device bootstrap')
|
utils.mixpanelTrack('Device bootstrap')
|
||||||
|
# If we're in offline mode, we don't start the provisioning process so bootstrap.done will never fulfill
|
||||||
|
return if bootstrapper.offlineMode
|
||||||
bootstrap().catch (err) ->
|
bootstrap().catch (err) ->
|
||||||
utils.mixpanelTrack('Device bootstrap failed, retrying', { error: err, delay: config.bootstrapRetryDelay })
|
utils.mixpanelTrack('Device bootstrap failed, retrying', { error: err, delay: config.bootstrapRetryDelay })
|
||||||
setTimeout(bootstrapOrRetry, config.bootstrapRetryDelay)
|
setTimeout(bootstrapOrRetry, config.bootstrapRetryDelay)
|
||||||
@ -95,10 +97,15 @@ bootstrapper.done = new Promise (resolve) ->
|
|||||||
|
|
||||||
bootstrapper.bootstrapped = false
|
bootstrapper.bootstrapped = false
|
||||||
bootstrapper.startBootstrapping = ->
|
bootstrapper.startBootstrapping = ->
|
||||||
knex('config').select('value').where(key: 'uuid')
|
# Load config file
|
||||||
|
readConfig()
|
||||||
|
.then (configFromFile) ->
|
||||||
|
userConfig = configFromFile
|
||||||
|
bootstrapper.offlineMode = Boolean(userConfig.supervisorOfflineMode)
|
||||||
|
knex('config').select('value').where(key: 'uuid')
|
||||||
.then ([ uuid ]) ->
|
.then ([ uuid ]) ->
|
||||||
if uuid?.value
|
if uuid?.value
|
||||||
bootstrapper.doneBootstrapping()
|
bootstrapper.doneBootstrapping() if !bootstrapper.offlineMode
|
||||||
return uuid.value
|
return uuid.value
|
||||||
console.log('New device detected. Bootstrapping..')
|
console.log('New device detected. Bootstrapping..')
|
||||||
readConfigAndEnsureUUID()
|
readConfigAndEnsureUUID()
|
||||||
|
@ -9,6 +9,7 @@ configPath = '/boot/config.json'
|
|||||||
request = Promise.promisifyAll(require('request'))
|
request = Promise.promisifyAll(require('request'))
|
||||||
execAsync = Promise.promisify(require('child_process').exec)
|
execAsync = Promise.promisify(require('child_process').exec)
|
||||||
fs = Promise.promisifyAll(require('fs'))
|
fs = Promise.promisifyAll(require('fs'))
|
||||||
|
bootstrap = require './bootstrap'
|
||||||
|
|
||||||
exports.getID = do ->
|
exports.getID = do ->
|
||||||
deviceIdPromise = null
|
deviceIdPromise = null
|
||||||
@ -17,10 +18,14 @@ exports.getID = do ->
|
|||||||
deviceIdPromise ?= Promise.rejected()
|
deviceIdPromise ?= Promise.rejected()
|
||||||
# Only fetch the device id once (when successful, otherwise retry for each request)
|
# Only fetch the device id once (when successful, otherwise retry for each request)
|
||||||
deviceIdPromise = deviceIdPromise.catch ->
|
deviceIdPromise = deviceIdPromise.catch ->
|
||||||
Promise.all([
|
# Wait for bootstrapping to be done before querying the Resin API
|
||||||
knex('config').select('value').where(key: 'apiKey')
|
# This will also block users of getID (like applyState below until this is resolved)
|
||||||
knex('config').select('value').where(key: 'uuid')
|
bootstrap.done
|
||||||
])
|
.then ->
|
||||||
|
Promise.all([
|
||||||
|
knex('config').select('value').where(key: 'apiKey')
|
||||||
|
knex('config').select('value').where(key: 'uuid')
|
||||||
|
])
|
||||||
.spread ([{ value: apiKey }], [{ value: uuid }]) ->
|
.spread ([{ value: apiKey }], [{ value: uuid }]) ->
|
||||||
resinApi.get(
|
resinApi.get(
|
||||||
resource: 'device'
|
resource: 'device'
|
||||||
|
@ -23,6 +23,9 @@ publish = do ->
|
|||||||
publishQueue = []
|
publishQueue = []
|
||||||
|
|
||||||
initialised.then (config) ->
|
initialised.then (config) ->
|
||||||
|
if config.offlineMode
|
||||||
|
publish = _.noop
|
||||||
|
return
|
||||||
pubnub = PUBNUB.init(config.pubnub)
|
pubnub = PUBNUB.init(config.pubnub)
|
||||||
channel = config.channel
|
channel = config.channel
|
||||||
|
|
||||||
|
@ -18,10 +18,14 @@ tagExtra = process.env.SUPERVISOR_TAG_EXTRA
|
|||||||
version += '+' + tagExtra if !_.isEmpty(tagExtra)
|
version += '+' + tagExtra if !_.isEmpty(tagExtra)
|
||||||
exports.supervisorVersion = version
|
exports.supervisorVersion = version
|
||||||
|
|
||||||
mixpanelClient = mixpanel.init(config.mixpanelToken)
|
configJson = require('/boot/config.json')
|
||||||
|
if Boolean(configJson.supervisorOfflineMode)
|
||||||
|
mixpanelClient = mixpanel.init(config.mixpanelToken)
|
||||||
|
else
|
||||||
|
mixpanelClient = { track: _.noop }
|
||||||
|
|
||||||
exports.mixpanelProperties = mixpanelProperties =
|
exports.mixpanelProperties = mixpanelProperties =
|
||||||
username: require('/boot/config.json').username
|
username: configJson.username
|
||||||
|
|
||||||
exports.mixpanelTrack = (event, properties = {}) ->
|
exports.mixpanelTrack = (event, properties = {}) ->
|
||||||
# Allow passing in an error directly and having it assigned to the error property.
|
# Allow passing in an error directly and having it assigned to the error property.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user