mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-25 16:31:05 +00:00
Store and make use of container ids.
This stores the container id for an app when creating that app, using it when it is necessary to stop/remove the app and when attempting to start it again (rather than creating a new container each time, eg restarting the pi does not create a new container any more)
This commit is contained in:
parent
550aebb163
commit
d07c6abe99
@ -42,7 +42,7 @@ knex('config').select('value').where(key: 'uuid').then ([uuid]) ->
|
|||||||
console.log('Starting Apps..')
|
console.log('Starting Apps..')
|
||||||
knex('app').select()
|
knex('app').select()
|
||||||
.then (apps) ->
|
.then (apps) ->
|
||||||
Promise.all(apps.map(application.restart))
|
Promise.all(apps.map(application.start))
|
||||||
.catch (error) ->
|
.catch (error) ->
|
||||||
console.error("Error starting apps:", error)
|
console.error("Error starting apps:", error)
|
||||||
.then ->
|
.then ->
|
||||||
|
@ -42,13 +42,7 @@ publish = do ->
|
|||||||
exports.kill = kill = (app) ->
|
exports.kill = kill = (app) ->
|
||||||
utils.mixpanelTrack('Application kill', app)
|
utils.mixpanelTrack('Application kill', app)
|
||||||
updateDeviceInfo(status: 'Stopping')
|
updateDeviceInfo(status: 'Stopping')
|
||||||
docker.listContainersAsync(all: 1)
|
container = docker.getContainer(app.containerId)
|
||||||
.then (containers) ->
|
|
||||||
Promise.all(
|
|
||||||
containers
|
|
||||||
.filter (container) -> container.Image is "#{app.imageId}:latest"
|
|
||||||
.map (container) ->
|
|
||||||
container = docker.getContainer(container.Id)
|
|
||||||
console.log('Stopping and deleting container:', container)
|
console.log('Stopping and deleting container:', container)
|
||||||
container.stopAsync()
|
container.stopAsync()
|
||||||
.then ->
|
.then ->
|
||||||
@ -64,9 +58,9 @@ exports.kill = kill = (app) ->
|
|||||||
if statusCode is '404'
|
if statusCode is '404'
|
||||||
return
|
return
|
||||||
throw err
|
throw err
|
||||||
)
|
|
||||||
.tap ->
|
.tap ->
|
||||||
utils.mixpanelTrack('Application stop', app.imageId)
|
utils.mixpanelTrack('Application stop', app.imageId)
|
||||||
|
knex('app').where('id', app.id).delete()
|
||||||
.finally ->
|
.finally ->
|
||||||
updateDeviceInfo(status: 'Idle')
|
updateDeviceInfo(status: 'Idle')
|
||||||
|
|
||||||
@ -75,6 +69,25 @@ isValidPort = (port) ->
|
|||||||
return parseFloat(port) is maybePort and maybePort > 0 and maybePort < 65535
|
return parseFloat(port) is maybePort and maybePort > 0 and maybePort < 65535
|
||||||
|
|
||||||
exports.start = start = (app) ->
|
exports.start = start = (app) ->
|
||||||
|
Promise.try ->
|
||||||
|
# Parse the env vars before trying to access them, that's because they have to be stringified for knex..
|
||||||
|
JSON.parse(app.env)
|
||||||
|
.then (env) ->
|
||||||
|
if env.PORT?
|
||||||
|
portList = env.PORT
|
||||||
|
.split(',')
|
||||||
|
.map((port) -> port.trim())
|
||||||
|
.filter(isValidPort)
|
||||||
|
|
||||||
|
if app.containerId?
|
||||||
|
# If we have a container id then check it exists and if so use it.
|
||||||
|
container = docker.getContainer(app.containerId)
|
||||||
|
containerPromise = container.inspectAsync().return(container)
|
||||||
|
else
|
||||||
|
containerPromise = Promise.rejected()
|
||||||
|
|
||||||
|
# If there is no existing container then create one instead.
|
||||||
|
containerPromise.catch ->
|
||||||
docker.getImage(app.imageId).inspectAsync()
|
docker.getImage(app.imageId).inspectAsync()
|
||||||
.catch (error) ->
|
.catch (error) ->
|
||||||
utils.mixpanelTrack('Application install', app)
|
utils.mixpanelTrack('Application install', app)
|
||||||
@ -95,14 +108,7 @@ exports.start = start = (app) ->
|
|||||||
console.log("Creating container:", app.imageId)
|
console.log("Creating container:", app.imageId)
|
||||||
updateDeviceInfo(status: 'Starting')
|
updateDeviceInfo(status: 'Starting')
|
||||||
ports = {}
|
ports = {}
|
||||||
# Parse the env vars before trying to access them, that's because they have to be stringified for knex..
|
if portList?
|
||||||
env = JSON.parse(app.env)
|
|
||||||
if env.PORT?
|
|
||||||
portList = env.PORT
|
|
||||||
.split(',')
|
|
||||||
.map((port) -> port.trim())
|
|
||||||
.filter(isValidPort)
|
|
||||||
|
|
||||||
portList.forEach (port) ->
|
portList.forEach (port) ->
|
||||||
ports[port + '/tcp'] = {}
|
ports[port + '/tcp'] = {}
|
||||||
|
|
||||||
@ -116,7 +122,7 @@ exports.start = start = (app) ->
|
|||||||
Env: _.map env, (v, k) -> k + '=' + v
|
Env: _.map env, (v, k) -> k + '=' + v
|
||||||
ExposedPorts: ports
|
ExposedPorts: ports
|
||||||
)
|
)
|
||||||
.then (container) ->
|
.tap (container) ->
|
||||||
console.log('Starting container:', app.imageId)
|
console.log('Starting container:', app.imageId)
|
||||||
ports = {}
|
ports = {}
|
||||||
if portList?
|
if portList?
|
||||||
@ -140,16 +146,16 @@ exports.start = start = (app) ->
|
|||||||
es.split()
|
es.split()
|
||||||
es.mapSync(publish)
|
es.mapSync(publish)
|
||||||
)
|
)
|
||||||
.tap ->
|
.tap (container) ->
|
||||||
utils.mixpanelTrack('Application start', app.imageId)
|
utils.mixpanelTrack('Application start', app.imageId)
|
||||||
|
app.containerId = container.id
|
||||||
|
if app.id?
|
||||||
|
knex('app').update(app).where(id: app.id)
|
||||||
|
else
|
||||||
|
knex('app').insert(app)
|
||||||
.finally ->
|
.finally ->
|
||||||
updateDeviceInfo(status: 'Idle')
|
updateDeviceInfo(status: 'Idle')
|
||||||
|
|
||||||
exports.restart = restart = (app) ->
|
|
||||||
kill(app)
|
|
||||||
.then ->
|
|
||||||
start(app)
|
|
||||||
|
|
||||||
# 0 - Idle
|
# 0 - Idle
|
||||||
# 1 - Updating
|
# 1 - Updating
|
||||||
# 2 - Update required
|
# 2 - Update required
|
||||||
@ -202,9 +208,9 @@ exports.update = update = ->
|
|||||||
console.log(remoteImages)
|
console.log(remoteImages)
|
||||||
|
|
||||||
console.log("Local apps")
|
console.log("Local apps")
|
||||||
apps = _.map(apps, (app) -> _.pick(app, ['commit', 'imageId', 'env']))
|
|
||||||
apps = _.indexBy(apps, 'imageId')
|
apps = _.indexBy(apps, 'imageId')
|
||||||
localImages = _.keys(apps)
|
localApps = _.mapValues(apps, (app) -> _.pick(app, ['commit', 'imageId', 'env']))
|
||||||
|
localImages = _.keys(localApps)
|
||||||
console.log(localImages)
|
console.log(localImages)
|
||||||
|
|
||||||
console.log("Apps to be removed")
|
console.log("Apps to be removed")
|
||||||
@ -218,28 +224,25 @@ exports.update = update = ->
|
|||||||
console.log("Apps to be updated")
|
console.log("Apps to be updated")
|
||||||
toBeUpdated = _.intersection(remoteImages, localImages)
|
toBeUpdated = _.intersection(remoteImages, localImages)
|
||||||
toBeUpdated = _.filter toBeUpdated, (imageId) ->
|
toBeUpdated = _.filter toBeUpdated, (imageId) ->
|
||||||
return !_.isEqual(remoteApps[imageId], apps[imageId])
|
return !_.isEqual(remoteApps[imageId], localApps[imageId])
|
||||||
console.log(toBeUpdated)
|
console.log(toBeUpdated)
|
||||||
|
|
||||||
# Delete all the ones to remove in one go
|
# Delete all the ones to remove in one go
|
||||||
Promise.map toBeRemoved, (imageId) ->
|
Promise.map toBeRemoved, (imageId) ->
|
||||||
kill(apps[imageId])
|
kill(apps[imageId])
|
||||||
.then ->
|
|
||||||
knex('app').where('imageId', imageId).delete()
|
|
||||||
.then ->
|
.then ->
|
||||||
# Then install the apps and add each to the db as they succeed
|
# Then install the apps and add each to the db as they succeed
|
||||||
installingPromises = toBeInstalled.map (imageId) ->
|
installingPromises = toBeInstalled.map (imageId) ->
|
||||||
app = remoteApps[imageId]
|
app = remoteApps[imageId]
|
||||||
start(app)
|
start(app)
|
||||||
.then ->
|
# And remove/recreate updated apps and update db as they succeed
|
||||||
knex('app').insert(app)
|
|
||||||
# And restart updated apps and update db as they succeed
|
|
||||||
updatingPromises = toBeUpdated.map (imageId) ->
|
updatingPromises = toBeUpdated.map (imageId) ->
|
||||||
|
localApp = apps[imageId]
|
||||||
app = remoteApps[imageId]
|
app = remoteApps[imageId]
|
||||||
utils.mixpanelTrack('Application update', app)
|
utils.mixpanelTrack('Application update', app)
|
||||||
restart(app)
|
kill(localApp)
|
||||||
.then ->
|
.then ->
|
||||||
knex('app').update(app).where(imageId: app.imageId)
|
start(app)
|
||||||
Promise.all(installingPromises.concat(updatingPromises))
|
Promise.all(installingPromises.concat(updatingPromises))
|
||||||
.then ->
|
.then ->
|
||||||
failedUpdates = 0
|
failedUpdates = 0
|
||||||
|
Loading…
Reference in New Issue
Block a user