mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-06-06 09:31:40 +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.
|
# v1 endpoins only work for single-container apps as they assume the app has a single service.
|
||||||
class ApplicationManagerRouter
|
class ApplicationManagerRouter
|
||||||
constructor: (@applications) ->
|
constructor: (@applications) ->
|
||||||
{ @proxyvisor, @eventTracker, @deviceState, @_lockingIfNecessary } = @applications
|
{ @proxyvisor, @eventTracker, @deviceState, @_lockingIfNecessary, @logger } = @applications
|
||||||
@router = express.Router()
|
@router = express.Router()
|
||||||
@router.use(bodyParser.urlencoded(extended: true))
|
@router.use(bodyParser.urlencoded(extended: true))
|
||||||
@router.use(bodyParser.json())
|
@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) =>
|
@router.post '/v1/restart', (req, res) =>
|
||||||
appId = checkInt(req.body.appId)
|
appId = checkInt(req.body.appId)
|
||||||
force = checkTruthy(req.body.force)
|
force = checkTruthy(req.body.force)
|
||||||
@eventTracker.track('Restart container (v1)', { appId })
|
@eventTracker.track('Restart container (v1)', { appId })
|
||||||
if !appId?
|
if !appId?
|
||||||
return res.status(400).send('Missing app id')
|
return res.status(400).send('Missing app id')
|
||||||
@applications.getCurrentApp(appId)
|
doRestart(appId, force)
|
||||||
.then (app) =>
|
.then ->
|
||||||
service = app?.services?[0]
|
res.status(200).send('OK')
|
||||||
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')
|
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
res.status(503).send(err?.message or err or 'Unknown error')
|
||||||
|
|
||||||
@ -135,7 +161,7 @@ class ApplicationManagerRouter
|
|||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
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)
|
appId = checkInt(req.body.appId)
|
||||||
force = checkTruthy(req.body.force)
|
force = checkTruthy(req.body.force)
|
||||||
if !appId?
|
if !appId?
|
||||||
@ -143,44 +169,16 @@ class ApplicationManagerRouter
|
|||||||
If you've recently moved this device from another app,
|
If you've recently moved this device from another app,
|
||||||
please push an app and wait for it to be installed first."
|
please push an app and wait for it to be installed first."
|
||||||
return res.status(400).send(errMsg)
|
return res.status(400).send(errMsg)
|
||||||
@_lockingIfNecessary appId, { force }, =>
|
doPurge(appId, force)
|
||||||
@applications.getCurrentApp(appId)
|
.then ->
|
||||||
.then (app) =>
|
res.status(200).json(Data: 'OK', Error: '')
|
||||||
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: '')
|
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
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
|
{ force } = req.body
|
||||||
{ appId } = req.params
|
{ appId } = req.params
|
||||||
@_lockingIfNecessary appId, { force }, =>
|
doPurge(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 })
|
|
||||||
.then ->
|
.then ->
|
||||||
res.status(200).send('OK')
|
res.status(200).send('OK')
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
@ -207,20 +205,10 @@ class ApplicationManagerRouter
|
|||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
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
|
{ force } = req.body
|
||||||
{ appId } = req.params
|
{ appId } = req.params
|
||||||
@_lockingIfNecessary appId, { force }, =>
|
doRestart(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 })
|
|
||||||
.then ->
|
.then ->
|
||||||
res.status(200).send('OK')
|
res.status(200).send('OK')
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
@ -251,26 +239,6 @@ module.exports = class ApplicationManager extends EventEmitter
|
|||||||
@images.removeByDockerId(step.current.image)
|
@images.removeByDockerId(step.current.image)
|
||||||
updateMetadata: (step) =>
|
updateMetadata: (step) =>
|
||||||
@services.updateMetadata(step.current, step.target)
|
@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 } = {}) =>
|
restart: (step, { force = false, skipLock = false } = {}) =>
|
||||||
@_lockingIfNecessary step.current.appId, { force, skipLock: skipLock or step.options?.skipLock }, =>
|
@_lockingIfNecessary step.current.appId, { force, skipLock: skipLock or step.options?.skipLock }, =>
|
||||||
Promise.try =>
|
Promise.try =>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user