mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-18 18:56:24 +00:00
Pin a device to a commit when preload has a pinDevice field
Change-type: minor Closes: #668 Signed-off-by: Cameron Diver <cameron@resin.io>
This commit is contained in:
parent
2a6d5557e4
commit
089f31cb5d
@ -198,6 +198,20 @@ module.exports = class APIBinder
|
||||
@config.set(configToUpdate)
|
||||
.then =>
|
||||
@eventTracker.track('Device bootstrap success')
|
||||
# Check if we need to pin the device, regardless of if we provisioned
|
||||
.then =>
|
||||
@config.get('pinDevice')
|
||||
.then(JSON.parse)
|
||||
.tapCatch ->
|
||||
console.log('Warning: Malformed pinDevice value in supervisor database')
|
||||
.catchReturn(null)
|
||||
.then (pinValue) =>
|
||||
if pinValue?
|
||||
if !pinValue.app? or !pinValue.commit?
|
||||
console.log("Malformed pinDevice fields in supervisor database: #{pinValue}")
|
||||
return
|
||||
console.log('Attempting to pin device to preloaded release...')
|
||||
@pinDevice(pinValue)
|
||||
|
||||
_provisionOrRetry: (retryDelay) =>
|
||||
@eventTracker.track('Device bootstrap')
|
||||
@ -214,9 +228,10 @@ module.exports = class APIBinder
|
||||
'provisioned'
|
||||
'bootstrapRetryDelay'
|
||||
'apiKey'
|
||||
'pinDevice'
|
||||
])
|
||||
.tap (conf) =>
|
||||
if !conf.provisioned or conf.apiKey?
|
||||
if !conf.provisioned or conf.apiKey? or conf.pinDevice?
|
||||
@_provisionOrRetry(conf.bootstrapRetryDelay)
|
||||
|
||||
provisionDependentDevice: (device) =>
|
||||
@ -263,6 +278,34 @@ module.exports = class APIBinder
|
||||
body: updatedFields
|
||||
.timeout(conf.apiTimeout)
|
||||
|
||||
pinDevice: ({ app, commit }) =>
|
||||
@config.get('deviceId')
|
||||
.then (deviceId) =>
|
||||
@resinApi.get
|
||||
resource: 'release'
|
||||
options:
|
||||
filter:
|
||||
belongs_to__application: app
|
||||
commit: commit
|
||||
status: 'success'
|
||||
select: 'id'
|
||||
.then (release) =>
|
||||
releaseId = _.get(release, '[0].id')
|
||||
if !releaseId?
|
||||
throw new Error('Cannot continue pinning preloaded device! No release found!')
|
||||
@resinApi.patch
|
||||
resource: 'device'
|
||||
id: deviceId
|
||||
body:
|
||||
should_be_running__release: releaseId
|
||||
.then =>
|
||||
# Set the config value for pinDevice to null, so that we know the
|
||||
# task has been completed
|
||||
@config.remove('pinDevice')
|
||||
.tapCatch (e) ->
|
||||
console.log('Could not pin device to release!')
|
||||
console.log('Error: ', e)
|
||||
|
||||
_sendLogsRequest: (uuid, data) =>
|
||||
reqBody = _.map(data, (msg) -> _.mapKeys(msg, (v, k) -> _.snakeCase(k)))
|
||||
@config.get('resinApiEndpoint')
|
||||
|
@ -151,6 +151,8 @@ module.exports = class Config extends EventEmitter
|
||||
lockOverride: { source: 'db', mutable: true, default: 'false' }
|
||||
legacyAppsPresent: { source: 'db', mutable: true, default: 'false' }
|
||||
nativeLogger: { source: 'db', mutable: true, default: 'true' }
|
||||
# A JSON value, which is either null, or { app: number, commit: string }
|
||||
pinDevice: { source: 'db', mutable: true, default: 'null' }
|
||||
}
|
||||
|
||||
@configJsonCache = {}
|
||||
|
@ -313,11 +313,17 @@ module.exports = class DeviceState extends EventEmitter
|
||||
fs.readFileAsync(appsPath, 'utf8')
|
||||
.then(JSON.parse)
|
||||
.then (stateFromFile) =>
|
||||
commitToPin = null
|
||||
appToPin = null
|
||||
if !_.isEmpty(stateFromFile)
|
||||
if _.isArray(stateFromFile)
|
||||
# This is a legacy apps.json
|
||||
stateFromFile = @_convertLegacyAppsJson(stateFromFile)
|
||||
images = _.flatMap stateFromFile.apps, (app, appId) =>
|
||||
# multi-app warning!
|
||||
# The following will need to be changed once running multiple applications is possible
|
||||
commitToPin = app.commit
|
||||
appToPin = appId
|
||||
_.map app.services, (service, serviceId) =>
|
||||
svc = {
|
||||
imageName: service.image
|
||||
@ -341,6 +347,16 @@ module.exports = class DeviceState extends EventEmitter
|
||||
@setTarget({
|
||||
local: stateFromFile
|
||||
})
|
||||
.then =>
|
||||
if stateFromFile.pinDevice
|
||||
# multi-app warning!
|
||||
# The following will need to be changed once running multiple applications is possible
|
||||
if commitToPin? and appToPin?
|
||||
@config.set
|
||||
pinDevice: JSON.stringify {
|
||||
commit: commitToPin,
|
||||
app: appToPin,
|
||||
}
|
||||
.catch (err) =>
|
||||
@eventTracker.track('Loading preloaded apps failed', { error: err })
|
||||
|
||||
|
@ -235,6 +235,19 @@ describe 'deviceState', ->
|
||||
@deviceState.applications.images.save.restore()
|
||||
@deviceState.deviceConfig.getCurrent.restore()
|
||||
|
||||
it 'stores info for pinning a device after loading an apps.json with a pinDevice field', ->
|
||||
stub(@deviceState.applications.images, 'save').returns(Promise.resolve())
|
||||
stub(@deviceState.deviceConfig, 'getCurrent').returns(Promise.resolve(mockedInitialConfig))
|
||||
@deviceState.loadTargetFromFile(process.env.ROOT_MOUNTPOINT + '/apps-pin.json')
|
||||
.then =>
|
||||
@deviceState.applications.images.save.restore()
|
||||
@deviceState.deviceConfig.getCurrent.restore()
|
||||
|
||||
@config.get('pinDevice').then (pinnedString) ->
|
||||
pinned = JSON.parse(pinnedString)
|
||||
expect(pinned).to.have.property('app').that.equals('1234')
|
||||
expect(pinned).to.have.property('commit').that.equals('abcdef')
|
||||
|
||||
it 'emits a change event when a new state is reported', ->
|
||||
@deviceState.reportCurrentState({ someStateDiff: 'someValue' })
|
||||
expect(@deviceState).to.emit('change')
|
||||
|
26
test/data/apps-pin.json
Normal file
26
test/data/apps-pin.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "aDevice",
|
||||
"config": {
|
||||
"RESIN_HOST_CONFIG_gpu_mem": "256",
|
||||
"RESIN_HOST_LOG_TO_DISPLAY": "0"
|
||||
},
|
||||
"apps": {
|
||||
"1234": {
|
||||
"name": "superapp",
|
||||
"commit": "abcdef",
|
||||
"releaseId": 1,
|
||||
"services": {
|
||||
"23": {
|
||||
"imageId": 12345,
|
||||
"serviceName": "someservice",
|
||||
"image": "registry2.resin.io/superapp/abcdef",
|
||||
"labels": {
|
||||
"io.resin.something": "bar"
|
||||
},
|
||||
"environment": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"pinDevice": true
|
||||
}
|
Loading…
Reference in New Issue
Block a user