Add /v1/stop and /v1/start endpoints

This commit is contained in:
Pablo Carranza Velez 2016-04-08 16:51:39 -03:00
parent e061e855c8
commit 7161564123
4 changed files with 129 additions and 7 deletions

View File

@ -1,3 +1,5 @@
# Add /v1/stop and /v1/start endpoints [Pablo]
# v1.7.0
* Add RESIN_HOST_LOG_TO_DISPLAY variable [Pablo]

View File

@ -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"
```

View File

@ -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) ->

View File

@ -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) ->