mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-20 14:13:08 +00:00
Make v1 restart and purge work for multicontainer apps too
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
parent
2b223f55fa
commit
cba3a8e5fe
@ -48,27 +48,53 @@ fetchAction = (service) ->
|
||||
# v1 endpoins only work for single-container apps as they assume the app has a single service.
|
||||
class ApplicationManagerRouter
|
||||
constructor: (@applications) ->
|
||||
{ @proxyvisor, @eventTracker, @deviceState, @_lockingIfNecessary } = @applications
|
||||
{ @proxyvisor, @eventTracker, @deviceState, @_lockingIfNecessary, @logger } = @applications
|
||||
@router = express.Router()
|
||||
@router.use(bodyParser.urlencoded(extended: true))
|
||||
@router.use(bodyParser.json())
|
||||
|
||||
doRestart = (appId, force) =>
|
||||
@_lockingIfNecessary appId, { force }, =>
|
||||
@deviceState.getCurrentForComparison()
|
||||
.then (currentState) =>
|
||||
app = currentState.local.apps[appId]
|
||||
stoppedApp = _.cloneDeep(app)
|
||||
stoppedApp.services = []
|
||||
currentState.local.apps[appId] = stoppedApp
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
.then =>
|
||||
currentState.local.apps[appId] = app
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
|
||||
doPurge = (appId, force) =>
|
||||
@logger.logSystemMessage("Purging data for app #{appId}", { appId }, 'Purge data')
|
||||
@_lockingIfNecessary appId, { force }, =>
|
||||
@deviceState.getCurrentForComparison()
|
||||
.then (currentState) =>
|
||||
app = currentState.local.apps[appId]
|
||||
purgedApp = _.cloneDeep(app)
|
||||
purgedApp.services = []
|
||||
purgedApp.volumes = {}
|
||||
currentState.local.apps[appId] = purgedApp
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
.then =>
|
||||
currentState.local.apps[appId] = app
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
.tap =>
|
||||
@logger.logSystemMessage('Purged data', { appId }, 'Purge data success')
|
||||
.catch (err) =>
|
||||
@logger.logSystemMessage("Error purging data: #{err}", { appId, error: err }, 'Purge data error')
|
||||
throw err
|
||||
|
||||
@router.post '/v1/restart', (req, res) =>
|
||||
appId = checkInt(req.body.appId)
|
||||
force = checkTruthy(req.body.force)
|
||||
@eventTracker.track('Restart container (v1)', { appId })
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
@applications.getCurrentApp(appId)
|
||||
.then (app) =>
|
||||
service = app?.services?[0]
|
||||
if !service?
|
||||
return res.status(400).send('App not found')
|
||||
if app.services.length > 1
|
||||
return res.status(400).send('v1 endpoints are only allowed on single-container apps')
|
||||
@applications.executeStepAction(serviceAction('restart', service.serviceId, service, service), { force })
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
doRestart(appId, force)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -135,7 +161,7 @@ class ApplicationManagerRouter
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@router.post '/v1/purge', (req, res) =>
|
||||
@router.post '/v1/purge', (req, res) ->
|
||||
appId = checkInt(req.body.appId)
|
||||
force = checkTruthy(req.body.force)
|
||||
if !appId?
|
||||
@ -143,44 +169,16 @@ class ApplicationManagerRouter
|
||||
If you've recently moved this device from another app,
|
||||
please push an app and wait for it to be installed first."
|
||||
return res.status(400).send(errMsg)
|
||||
@_lockingIfNecessary appId, { force }, =>
|
||||
@applications.getCurrentApp(appId)
|
||||
.then (app) =>
|
||||
service = app?.services?[0]
|
||||
if !service?
|
||||
return res.status(400).send('App not found')
|
||||
if app.services.length > 1
|
||||
return res.status(400).send('v1 endpoints are only allowed on single-container apps')
|
||||
@applications.executeStepAction(serviceAction('kill', service.serviceId, service, null, skipLock: true), { force })
|
||||
.then =>
|
||||
@applications.executeStepAction({
|
||||
action: 'purge'
|
||||
appId: app.appId
|
||||
options:
|
||||
skipLock: true
|
||||
}, { force })
|
||||
.then =>
|
||||
@applications.executeStepAction(serviceAction('start', service.serviceId, null, service, skipLock: true), { force })
|
||||
.then ->
|
||||
res.status(200).json(Data: 'OK', Error: '')
|
||||
doPurge(appId, force)
|
||||
.then ->
|
||||
res.status(200).json(Data: 'OK', Error: '')
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@router.post '/v2/applications/:appId/purge', (req, res) =>
|
||||
@router.post '/v2/applications/:appId/purge', (req, res) ->
|
||||
{ force } = req.body
|
||||
{ appId } = req.params
|
||||
@_lockingIfNecessary appId, { force }, =>
|
||||
@deviceState.getCurrentForComparison()
|
||||
.then (currentState) =>
|
||||
app = currentState.local.apps[appId]
|
||||
purgedApp = _.cloneDeep(app)
|
||||
purgedApp.services = []
|
||||
purgedApp.volumes = {}
|
||||
currentState.local.apps[appId] = purgedApp
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
.then =>
|
||||
currentState.local.apps[appId] = app
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
doPurge(appId, force)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch (err) ->
|
||||
@ -207,20 +205,10 @@ class ApplicationManagerRouter
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@router.post '/v2/applications/:appId/restart', (req, res) =>
|
||||
@router.post '/v2/applications/:appId/restart', (req, res) ->
|
||||
{ force } = req.body
|
||||
{ appId } = req.params
|
||||
@_lockingIfNecessary appId, { force }, =>
|
||||
@deviceState.getCurrentForComparison()
|
||||
.then (currentState) =>
|
||||
app = currentState.local.apps[appId]
|
||||
stoppedApp = _.cloneDeep(app)
|
||||
stoppedApp.services = []
|
||||
currentState.local.apps[appId] = stoppedApp
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
.then =>
|
||||
currentState.local.apps[appId] = app
|
||||
@deviceState.applyIntermediateTarget(currentState, { skipLock: true })
|
||||
doRestart(appId, force)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch (err) ->
|
||||
@ -251,26 +239,6 @@ module.exports = class ApplicationManager extends EventEmitter
|
||||
@images.removeByDockerId(step.current.image)
|
||||
updateMetadata: (step) =>
|
||||
@services.updateMetadata(step.current, step.target)
|
||||
purge: (step, { force = false, skipLock = false } = {}) =>
|
||||
appId = step.appId
|
||||
@logger.logSystemMessage("Purging data for app #{appId}", { appId }, 'Purge data')
|
||||
@_lockingIfNecessary appId, { force, skipLock: skipLock or step.options?.skipLock }, =>
|
||||
@getCurrentApp(appId)
|
||||
.then (app) =>
|
||||
if !_.isEmpty(app?.services)
|
||||
throw new Error('Attempt to purge app with running services')
|
||||
if _.isEmpty(app?.volumes)
|
||||
@logger.logSystemMessage('No volumes to purge', { appId }, 'Purge data noop')
|
||||
return
|
||||
Promise.mapSeries _.toPairs(app.volumes ? {}), ([ name, config ]) =>
|
||||
@volumes.remove({ name, appId })
|
||||
.then =>
|
||||
@volumes.create({ name, config, appId })
|
||||
.then =>
|
||||
@logger.logSystemMessage('Purged data', { appId }, 'Purge data success')
|
||||
.catch (err) =>
|
||||
@logger.logSystemMessage("Error purging data: #{err}", { appId, error: err }, 'Purge data error')
|
||||
throw err
|
||||
restart: (step, { force = false, skipLock = false } = {}) =>
|
||||
@_lockingIfNecessary step.current.appId, { force, skipLock: skipLock or step.options?.skipLock }, =>
|
||||
Promise.try =>
|
||||
|
Loading…
Reference in New Issue
Block a user