mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-20 17:52:51 +00:00
Add /v1/stop and /v1/start endpoints
This commit is contained in:
parent
e061e855c8
commit
7161564123
@ -1,3 +1,5 @@
|
||||
# Add /v1/stop and /v1/start endpoints [Pablo]
|
||||
|
||||
# v1.7.0
|
||||
|
||||
* Add RESIN_HOST_LOG_TO_DISPLAY variable [Pablo]
|
||||
|
91
docs/API.md
91
docs/API.md
@ -300,9 +300,7 @@ $ curl -X POST --header "Content-Type:application/json" \
|
||||
|
||||
Restarts a user application container
|
||||
|
||||
When successful, responds with 200 and a
|
||||
```
|
||||
(This is implemented in Go)
|
||||
When successful, responds with 200 and an "OK"
|
||||
|
||||
#### Request body
|
||||
Has to be a JSON object with an `appId` property, corresponding to the ID of the application the device is running.
|
||||
@ -452,3 +450,90 @@ $ curl -X POST --header "Content-Type:application/json" \
|
||||
--data '{"deviceId": <deviceId>, "appId": <appId>, "method": "GET"}' \
|
||||
"https://api.resin.io/supervisor/v1/device"
|
||||
```
|
||||
|
||||
<hr>
|
||||
|
||||
### POST /v1/stop
|
||||
|
||||
Temporarily stops a user application container. A reboot or supervisor restart will cause the container to start again.
|
||||
The container is not removed with this endpoint.
|
||||
|
||||
When successful, responds with 200 and an "OK"
|
||||
|
||||
#### Request body
|
||||
Has to be a JSON object with an `appId` property, corresponding to the ID of the application the device is running.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"appId": 2167
|
||||
}
|
||||
```
|
||||
|
||||
#### Examples:
|
||||
From the app on the device:
|
||||
|
||||
```bash
|
||||
$ curl -X POST --header "Content-Type:application/json" \
|
||||
--data '{"appId": <appId>}' \
|
||||
"$RESIN_SUPERVISOR_ADDRESS/v1/stop?apikey=$RESIN_SUPERVISOR_API_KEY"
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```none
|
||||
OK
|
||||
```
|
||||
|
||||
Remotely via the API proxy:
|
||||
|
||||
```bash
|
||||
$ curl -X POST --header "Content-Type:application/json" \
|
||||
--header "Authorization: Bearer <auth token>" \
|
||||
--data '{"deviceId": <deviceId>, "appId": <appId>, "data": {"appId": <appId>}}' \
|
||||
"https://api.resin.io/supervisor/v1/stop"
|
||||
```
|
||||
|
||||
<hr>
|
||||
|
||||
### POST /v1/start
|
||||
|
||||
Starts a user application container, usually after it has been stopped with `/v1/stop`.
|
||||
|
||||
When successful, responds with 200 and an "OK"
|
||||
|
||||
#### Request body
|
||||
Has to be a JSON object with an `appId` property, corresponding to the ID of the application the device is running.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"appId": 2167
|
||||
}
|
||||
```
|
||||
|
||||
#### Examples:
|
||||
From the app on the device:
|
||||
|
||||
```bash
|
||||
$ curl -X POST --header "Content-Type:application/json" \
|
||||
--data '{"appId": <appId>}' \
|
||||
"$RESIN_SUPERVISOR_ADDRESS/v1/start?apikey=$RESIN_SUPERVISOR_API_KEY"
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```none
|
||||
OK
|
||||
```
|
||||
|
||||
Remotely via the API proxy:
|
||||
|
||||
```bash
|
||||
$ curl -X POST --header "Content-Type:application/json" \
|
||||
--header "Authorization: Bearer <auth token>" \
|
||||
--data '{"deviceId": <deviceId>, "appId": <appId>, "data": {"appId": <appId>}}' \
|
||||
"https://api.resin.io/supervisor/v1/start"
|
||||
```
|
@ -126,6 +126,39 @@ module.exports = (application) ->
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
api.post '/v1/stop', (req, res) ->
|
||||
appId = req.body.appId
|
||||
force = req.body.force
|
||||
utils.mixpanelTrack('Stop container', appId)
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
Promise.using application.lockUpdates(appId, force), ->
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
application.kill(app, true, false)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
api.post '/v1/start', (req, res) ->
|
||||
appId = req.body.appId
|
||||
utils.mixpanelTrack('Start container', appId)
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
Promise.using application.lockUpdates(appId, force), ->
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
application.start(app)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
# Expires the supervisor's API key and generates a new one.
|
||||
# It also communicates the new key to the Resin API.
|
||||
api.post '/v1/regenerate-api-key', (req, res) ->
|
||||
|
@ -96,7 +96,7 @@ logSpecialAction = (action, value, success) ->
|
||||
|
||||
application = {}
|
||||
|
||||
application.kill = kill = (app, updateDB = true) ->
|
||||
application.kill = kill = (app, updateDB = true, removeContainer = true) ->
|
||||
logSystemEvent(logTypes.stopApp, app)
|
||||
device.updateState(status: 'Stopping')
|
||||
container = docker.getContainer(app.containerId)
|
||||
@ -107,7 +107,8 @@ application.kill = kill = (app, updateDB = true) ->
|
||||
.then ->
|
||||
container.stopAsync(t: 10)
|
||||
.then ->
|
||||
container.removeAsync(v: true)
|
||||
container.removeAsync(v: true) if removeContainer
|
||||
return
|
||||
# Bluebird throws OperationalError for errors resulting in the normal execution of a promisified function.
|
||||
.catch Promise.OperationalError, (err) ->
|
||||
# Get the statusCode from the original cause and make sure statusCode its definitely a string for comparison
|
||||
@ -115,7 +116,8 @@ application.kill = kill = (app, updateDB = true) ->
|
||||
statusCode = '' + err.statusCode
|
||||
# 304 means the container was already stopped - so we can just remove it
|
||||
if statusCode is '304'
|
||||
return container.removeAsync(v: true)
|
||||
return container.removeAsync(v: true) if removeContainer
|
||||
return
|
||||
# 404 means the container doesn't exist, precisely what we want! :D
|
||||
if statusCode is '404'
|
||||
return
|
||||
@ -124,7 +126,7 @@ application.kill = kill = (app, updateDB = true) ->
|
||||
lockFile.unlockAsync(lockPath(app))
|
||||
.tap ->
|
||||
logSystemEvent(logTypes.stopAppSuccess, app)
|
||||
if updateDB == true
|
||||
if removeContainer && updateDB
|
||||
app.containerId = null
|
||||
knex('app').update(app).where(appId: app.appId)
|
||||
.catch (err) ->
|
||||
|
Loading…
x
Reference in New Issue
Block a user