mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 10:01:55 +00:00
Merge pull request #172 from resin-io/151-compose
Add endpoints for docker-compose up and down
This commit is contained in:
commit
52ef519ebc
@ -1,3 +1,5 @@
|
||||
* Add endpoints for docker-compose up and down [Pablo]
|
||||
|
||||
# v1.11.6
|
||||
|
||||
* Fixed deltas for older docker daemon versions [petrosagg]
|
||||
|
@ -1,11 +1,22 @@
|
||||
FROM resin/amd64-alpine-node:0.10.44-slim
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 0b8184817097eb670b92cbdac6cb9f7f2e9fe384c0b1060cb9b3d1a475fcbea6
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apk add --update \
|
||||
btrfs-progs \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo "$DOCKER_COMPOSE_SHA256 docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz" > docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-amd64 /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-alpine-amd64-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apk del curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Copy supervisord configuration files
|
||||
|
@ -1,11 +1,22 @@
|
||||
FROM resin/armhf-alpine-node:0.10.44-slim
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 3e5d0a36f06d9f7a93eb20c1dee67da623b07a322168538ea80d65c8581f5567
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apk add --update \
|
||||
btrfs-progs \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo "$DOCKER_COMPOSE_SHA256 docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz" > docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-armhf /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apk del curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Copy supervisord configuration files
|
||||
|
@ -1,11 +1,22 @@
|
||||
FROM resin/i386-alpine-node:0.10.44-slim
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 160ba547bfd4dc967ec4f1927550f2d832316fad492e0e6f8d374da89ddac779
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apk add --update \
|
||||
btrfs-progs \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo "$DOCKER_COMPOSE_SHA256 docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}.tar.gz" > docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-i386 /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-alpine-i386-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apk del curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Copy supervisord configuration files
|
||||
|
@ -1,11 +1,22 @@
|
||||
FROM resin/armhf-alpine-node:0.10.44-slim
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 3e5d0a36f06d9f7a93eb20c1dee67da623b07a322168538ea80d65c8581f5567
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apk add --update \
|
||||
btrfs-progs \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo "$DOCKER_COMPOSE_SHA256 docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz" > docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-alpine-armhf /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-alpine-armhf-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apk del curl \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Copy supervisord configuration files
|
||||
|
@ -2,14 +2,25 @@ FROM resin/amd64-node:0.10.40-slim
|
||||
|
||||
COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 37df85ee18bf0e2a8d71cbfb8198b1c06cc388f19118be7bdfc4d6db112af834
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apt-get -q update \
|
||||
&& apt-get install -qqy \
|
||||
btrfs-tools \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
--no-install-recommends \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo $DOCKER_COMPOSE_SHA256 docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz > docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-amd64 /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-amd64-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apt-get purge -qqy curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
|
@ -2,14 +2,25 @@ FROM resin/armel-node:0.10.40-slim
|
||||
|
||||
COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 a1025fed97536e2698798ea277a014ec5e1eae816a8cf3155ecbe9679e3e7bac
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apt-get -q update \
|
||||
&& apt-get install -qqy \
|
||||
btrfs-tools \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
--no-install-recommends \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo $DOCKER_COMPOSE_SHA256 docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}.tar.gz > docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armel /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-armel-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apt-get purge -qqy curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
|
@ -2,14 +2,25 @@ FROM resin/armv7hf-node:0.10.40-slim
|
||||
|
||||
COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 3f0b8c69c66a2daa5fbb0c127cb76ca95d7125827a9c43dd3c36f9bc2ed6e0e5
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apt-get -q update \
|
||||
&& apt-get install -qqy \
|
||||
btrfs-tools \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
--no-install-recommends \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo $DOCKER_COMPOSE_SHA256 docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz > docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armhf /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apt-get purge -qqy curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
|
@ -2,14 +2,25 @@ FROM resin/i386-node:0.10.40-slim
|
||||
|
||||
COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 b926fd9a2a9d89358f1353867706f94558a62caaf3aa72bf10bcbbe31e1a44f0
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apt-get -q update \
|
||||
&& apt-get install -qqy \
|
||||
btrfs-tools \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
--no-install-recommends \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo $DOCKER_COMPOSE_SHA256 docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}.tar.gz > docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-i386 /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-i386-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apt-get purge -qqy curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
|
@ -2,14 +2,25 @@ FROM resin/rpi-node:0.10.40-slim
|
||||
|
||||
COPY 01_nodoc /etc/dpkg/dpkg.cfg.d/
|
||||
|
||||
ENV DOCKER_COMPOSE_VERSION 1.7.1
|
||||
ENV DOCKER_COMPOSE_SHA256 3f0b8c69c66a2daa5fbb0c127cb76ca95d7125827a9c43dd3c36f9bc2ed6e0e5
|
||||
|
||||
# Supervisor apt dependencies
|
||||
RUN apt-get -q update \
|
||||
&& apt-get install -qqy \
|
||||
btrfs-tools \
|
||||
ca-certificates \
|
||||
curl \
|
||||
rsync \
|
||||
supervisor \
|
||||
--no-install-recommends \
|
||||
&& curl -sLO http://resin-packages.s3.amazonaws.com/docker-compose/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& echo $DOCKER_COMPOSE_SHA256 docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz > docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& sha256sum -c docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz.sha256 \
|
||||
&& tar xzf docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}.tar.gz \
|
||||
&& mv docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}/docker-compose-linux-armhf /usr/bin/docker-compose \
|
||||
&& rm -rf docker-compose-linux-armhf-${DOCKER_COMPOSE_VERSION}* \
|
||||
&& apt-get purge -qqy curl \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/
|
||||
|
||||
|
@ -30,7 +30,8 @@
|
||||
"resin-register-device": "^2.0.0",
|
||||
"rwlock": "^5.0.0",
|
||||
"sqlite3": "3.0.9",
|
||||
"typed-error": "~0.1.0"
|
||||
"typed-error": "~0.1.0",
|
||||
"yamljs": "^0.2.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.10.22"
|
||||
|
@ -1,6 +1,5 @@
|
||||
Promise = require 'bluebird'
|
||||
utils = require './utils'
|
||||
knex = require './db'
|
||||
express = require 'express'
|
||||
bodyParser = require 'body-parser'
|
||||
bufferEq = require 'buffer-equal-constant-time'
|
||||
@ -9,6 +8,7 @@ config = require './config'
|
||||
device = require './device'
|
||||
dockerUtils = require './docker-utils'
|
||||
_ = require 'lodash'
|
||||
compose = require './compose'
|
||||
|
||||
module.exports = (application) ->
|
||||
api = express()
|
||||
@ -57,10 +57,8 @@ module.exports = (application) ->
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
Promise.using application.lockUpdates(appId, true), ->
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
utils.getKnexApp(appId)
|
||||
.then (app) ->
|
||||
application.kill(app)
|
||||
.then ->
|
||||
new Promise (resolve, reject) ->
|
||||
@ -70,6 +68,8 @@ module.exports = (application) ->
|
||||
.pipe(res)
|
||||
.finally ->
|
||||
application.start(app)
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -88,15 +88,15 @@ module.exports = (application) ->
|
||||
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')
|
||||
utils.getKnexApp(appId)
|
||||
.then (app) ->
|
||||
application.kill(app)
|
||||
.then ->
|
||||
application.start(app)
|
||||
.then ->
|
||||
res.status(200).send('OK')
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -107,13 +107,13 @@ module.exports = (application) ->
|
||||
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')
|
||||
utils.getKnexApp(appId)
|
||||
.tap (app) ->
|
||||
application.kill(app, true, false)
|
||||
.then ->
|
||||
res.json(_.pick(app, 'containerId'))
|
||||
.then (app) ->
|
||||
res.json(_.pick(app, 'containerId'))
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -123,13 +123,13 @@ module.exports = (application) ->
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
Promise.using application.lockUpdates(appId), ->
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
utils.getKnexApp(appId)
|
||||
.tap (app) ->
|
||||
application.start(app)
|
||||
.then ->
|
||||
res.json(_.pick(app, 'containerId'))
|
||||
.then (app) ->
|
||||
res.json(_.pick(app, 'containerId'))
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -140,14 +140,14 @@ module.exports = (application) ->
|
||||
return res.status(400).send('Missing app id')
|
||||
Promise.using application.lockUpdates(appId, true), ->
|
||||
columns = [ 'appId', 'containerId', 'commit', 'imageId', 'env' ]
|
||||
knex('app').select(columns).where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
utils.getKnexApp(appId, columns)
|
||||
.then (app) ->
|
||||
# Don't return keys on the endpoint
|
||||
app.env = _.omit(JSON.parse(app.env), config.privateAppEnvVars)
|
||||
# Don't return data that will be of no use to the user
|
||||
res.json(app)
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
@ -175,6 +175,42 @@ module.exports = (application) ->
|
||||
unparsedRouter.delete '/v1/containers/:id', dockerUtils.deleteContainer
|
||||
unparsedRouter.get '/v1/containers', dockerUtils.listContainers
|
||||
|
||||
unparsedRouter.post '/v1/apps/:appId/compose/up', (req, res) ->
|
||||
appId = req.params.appId
|
||||
onStatus = (status) ->
|
||||
status = JSON.stringify(status) if _.isObject(status)
|
||||
res.write(status)
|
||||
utils.getKnexApp(appId)
|
||||
.then (app) ->
|
||||
res.status(200)
|
||||
compose.up(application.composePath(appId), onStatus)
|
||||
.catch (err) ->
|
||||
console.log('Error on compose up:', err, err.stack)
|
||||
.finally ->
|
||||
res.end()
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
unparsedRouter.post '/v1/apps/:appId/compose/down', (req, res) ->
|
||||
appId = req.params.appId
|
||||
onStatus = (status) ->
|
||||
status = JSON.stringify(status) if _.isObject(status)
|
||||
res.write(status)
|
||||
utils.getKnexApp(appId)
|
||||
.then (app) ->
|
||||
res.status(200)
|
||||
compose.down(application.composePath(appId), onStatus)
|
||||
.catch (err) ->
|
||||
console.log('Error on compose down:', err, err.stack)
|
||||
.finally ->
|
||||
res.end()
|
||||
.catch utils.AppNotFoundError, (e) ->
|
||||
return res.status(400).send(e.message)
|
||||
.catch (err) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
api.use(unparsedRouter)
|
||||
api.use(parsedRouter)
|
||||
|
||||
|
@ -311,6 +311,9 @@ killmePath = (app) ->
|
||||
appId = app.appId ? app
|
||||
return "/mnt/root#{config.dataPath}/#{appId}/resin-kill-me"
|
||||
|
||||
application.composePath = (appId) ->
|
||||
return "/mnt/root#{config.dataPath}/#{appId}/docker-compose.yml"
|
||||
|
||||
# At boot, all apps should be unlocked *before* start to prevent a deadlock
|
||||
application.unlockAndStart = unlockAndStart = (app) ->
|
||||
lockFile.unlockAsync(lockPath(app))
|
||||
@ -389,13 +392,6 @@ wrapAsError = (err) ->
|
||||
return err if _.isError(err)
|
||||
return new Error(err.message ? err)
|
||||
|
||||
select = (appId) ->
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
return app
|
||||
|
||||
# Wait for app to signal it's ready to die, or timeout to complete.
|
||||
# timeout defaults to 1 minute.
|
||||
waitToKill = (app, timeout) ->
|
||||
@ -432,7 +428,7 @@ updateStrategies =
|
||||
.then ->
|
||||
Promise.using lockUpdates(localApp, force), ->
|
||||
logSystemEvent(logTypes.updateApp, app) if localApp.imageId == app.imageId
|
||||
select(localApp.appId)
|
||||
utils.getKnexApp(localApp.appId)
|
||||
.then(kill)
|
||||
.then ->
|
||||
start(app)
|
||||
@ -442,7 +438,7 @@ updateStrategies =
|
||||
'kill-then-download': ({ localApp, app, needsDownload, force }) ->
|
||||
Promise.using lockUpdates(localApp, force), ->
|
||||
logSystemEvent(logTypes.updateApp, app) if localApp.imageId == app.imageId
|
||||
select(localApp.appId)
|
||||
utils.getKnexApp(localApp.appId)
|
||||
.then(kill)
|
||||
.then ->
|
||||
fetch(app) if needsDownload
|
||||
@ -453,7 +449,7 @@ updateStrategies =
|
||||
throw err
|
||||
'hand-over': ({ localApp, app, needsDownload, force, timeout }) ->
|
||||
Promise.using lockUpdates(localApp, force), ->
|
||||
select(localApp.appId)
|
||||
utils.getKnexApp(localApp.appId)
|
||||
.then (localApp) ->
|
||||
Promise.try ->
|
||||
fetch(app) if needsDownload
|
||||
@ -574,10 +570,8 @@ application.update = update = (force) ->
|
||||
# If an env var shouldn't cause a restart but requires an action, we should still
|
||||
# save the new env to the DB
|
||||
if !_.includes(toBeUpdated, appId) and !_.includes(toBeInstalled, appId)
|
||||
knex('app').select().where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
utils.getKnexApp(appId)
|
||||
.then (app) ->
|
||||
app.env = JSON.stringify(remoteAppEnvs[appId])
|
||||
knex('app').update(app).where({ appId })
|
||||
.then (needsReboot) ->
|
||||
@ -592,7 +586,7 @@ application.update = update = (force) ->
|
||||
Promise.using lockUpdates(localApps[appId], force), ->
|
||||
# We get the app from the DB again in case someone restarted it
|
||||
# (which would have changed its containerId)
|
||||
select(appId)
|
||||
utils.getKnexApp(appId)
|
||||
.then(kill)
|
||||
.then ->
|
||||
knex('app').where('appId', appId).delete()
|
||||
|
54
src/compose.coffee
Normal file
54
src/compose.coffee
Normal file
@ -0,0 +1,54 @@
|
||||
Promise = require 'bluebird'
|
||||
YAML = require 'yamljs'
|
||||
_ = require 'lodash'
|
||||
dockerUtils = require './docker-utils'
|
||||
{ docker } = dockerUtils
|
||||
fs = Promise.promisifyAll(require('fs'))
|
||||
spawn = require('child_process').spawn
|
||||
|
||||
runComposeCommand = (composeArgs, path, onStatus) ->
|
||||
onStatus ?= console.log.bind(console)
|
||||
reportStatus = (status) ->
|
||||
try onStatus(status)
|
||||
new Promise (resolve, reject) ->
|
||||
child = spawn('docker-compose', ['-f', path].concat(composeArgs), stdio: 'pipe')
|
||||
.on 'error', reject
|
||||
.on 'exit', (code) ->
|
||||
return reject(new Error("docker-compose exited with code #{code}")) if code isnt 0
|
||||
resolve()
|
||||
child.stdout.on 'data', (data) ->
|
||||
reportStatus(status: '' + data)
|
||||
child.stderr.on 'data', (data) ->
|
||||
reportStatus(status: '' + data)
|
||||
.catch (err) ->
|
||||
msg = err?.message or err
|
||||
reportStatus(error: msg)
|
||||
throw err
|
||||
|
||||
# Runs docker-compose up using the compose YAML at "path".
|
||||
# Reports status and errors in JSON to the onStatus function.
|
||||
exports.up = (path, onStatus) ->
|
||||
onStatus ?= console.log.bind(console)
|
||||
reportStatus = (status) ->
|
||||
try onStatus(status)
|
||||
fs.readFileAsync(path)
|
||||
.then (data) ->
|
||||
YAML.parse(data.toString())
|
||||
.then (composeSpec) ->
|
||||
if composeSpec.version? && composeSpec.version == '2'
|
||||
services = composeSpec.services
|
||||
else
|
||||
services = composeSpec
|
||||
throw new Error('No services found') if !_.isObject(services)
|
||||
servicesArray = _.pairs(services)
|
||||
Promise.each servicesArray, ([ serviceName, service ]) ->
|
||||
throw new Error("Service #{serviceName} has no image specified.") if !service.image
|
||||
docker.getImage(service.image).inspectAsync()
|
||||
.catch ->
|
||||
dockerUtils.pullAndProtectImage(service.image, reportStatus)
|
||||
.then ->
|
||||
runComposeCommand(['up', '-d'], path, onStatus)
|
||||
|
||||
# Runs docker-compose down using the compose YAML at "path".
|
||||
# Reports status and errors in JSON to the onStatus function.
|
||||
exports.down = _.partial(runComposeCommand, 'down')
|
@ -200,6 +200,13 @@ do ->
|
||||
.catch (err) ->
|
||||
res.status(500).send(err?.message or err or 'Unknown error')
|
||||
|
||||
exports.pullAndProtectImage = (image, onProgress) ->
|
||||
repoTag = buildRepoTag(image)
|
||||
Promise.using writeLockImages(), ->
|
||||
knex('image').insert({ repoTag })
|
||||
.then ->
|
||||
dockerProgress.pull(repoTag, onProgress)
|
||||
|
||||
exports.loadImage = (req, res) ->
|
||||
Promise.using writeLockImages(), ->
|
||||
docker.listImagesAsync()
|
||||
|
@ -10,6 +10,7 @@ url = require 'url'
|
||||
randomHexString = require './lib/random-hex-string'
|
||||
request = Promise.promisifyAll require 'request'
|
||||
logger = require './lib/logger'
|
||||
TypedError = require 'typed-error'
|
||||
|
||||
# Parses package.json and returns resin-supervisor's version
|
||||
version = require('../package.json').version
|
||||
@ -180,3 +181,13 @@ exports.vpnControl = (val) ->
|
||||
console.log('VPN enabled: ' + enable)
|
||||
else
|
||||
console.log('Error: ' + body + ' response:' + response.statusCode)
|
||||
|
||||
exports.AppNotFoundError = class AppNotFoundError extends TypedError
|
||||
|
||||
exports.getKnexApp = (appId, columns) ->
|
||||
knex('app').select(columns).where({ appId })
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new AppNotFoundError('App not found')
|
||||
return app
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user