mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-20 09:46:19 +00:00
Application management code in its own module
This commit is contained in:
parent
614b24c796
commit
637d68921f
@ -1,10 +1,8 @@
|
||||
Promise = require 'bluebird'
|
||||
fs = Promise.promisifyAll require 'fs'
|
||||
url = require 'url'
|
||||
knex = require './db'
|
||||
utils = require './utils'
|
||||
express = require 'express'
|
||||
request = Promise.promisify require 'request'
|
||||
application = require './application'
|
||||
|
||||
api = express()
|
||||
|
||||
@ -24,22 +22,9 @@ api.post('/v1/blink', (req, res) ->
|
||||
)
|
||||
|
||||
api.post('/v1/update', (req, res) ->
|
||||
console.log("Got application update")
|
||||
application.update()
|
||||
res.send(204)
|
||||
Promise.all([
|
||||
knex('config').select('value').where(key: 'apiKey')
|
||||
knex('config').select('value').where(key: 'uuid')
|
||||
]).then(([[apiKey], [uuid]]) ->
|
||||
apiKey = apiKey.value
|
||||
uuid = uuid.value
|
||||
request(
|
||||
method: 'GET'
|
||||
url: url.resolve(process.env.API_ENDPOINT, "/ewa/application?$filter=device/uuid eq '#{uuid}'&apikey=#{apiKey}")
|
||||
json: true
|
||||
).spread((request, body) ->
|
||||
for app in body.d
|
||||
console.log("Got application", app)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
module.exports = api
|
||||
|
@ -46,8 +46,14 @@ Promise.all([newUuid, oldUuid]).then(([newUuid, [oldUuid]]) ->
|
||||
|
||||
console.log('Starting Apps..')
|
||||
knex('app').select().then((apps) ->
|
||||
Promise.all(apps.map(application.start))
|
||||
Promise.all(apps.map((app) -> app.imageId).map(application.restart))
|
||||
).catch((error) ->
|
||||
console.log(error)
|
||||
console.error("Error starting apps:", error)
|
||||
).then(->
|
||||
console.log('Starting periodic check for updates..')
|
||||
setInterval(->
|
||||
application.update()
|
||||
, 15 * 60 * 1000) # Every 15 mins
|
||||
application.update()
|
||||
)
|
||||
)
|
||||
|
@ -1,32 +1,59 @@
|
||||
Promise = require 'bluebird'
|
||||
Docker = require 'dockerode'
|
||||
JSONStream = require 'JSONStream'
|
||||
_ = require 'lodash'
|
||||
es = require 'event-stream'
|
||||
url = require 'url'
|
||||
http = require 'http'
|
||||
knex = require './db'
|
||||
path = require 'path'
|
||||
Docker = require 'dockerode'
|
||||
Promise = require 'bluebird'
|
||||
request = Promise.promisify require 'request'
|
||||
JSONStream = require 'JSONStream'
|
||||
|
||||
docker = Promise.promisifyAll(new Docker(socketPath: '/hostrun/docker.sock'))
|
||||
# Hack dockerode to promisify internal classes' prototype
|
||||
# Hack dockerode to promisify internal classes' prototypes
|
||||
Promise.promisifyAll(docker.getImage().__proto__)
|
||||
Promise.promisifyAll(docker.getContainer().__proto__)
|
||||
|
||||
exports.start = (app) ->
|
||||
docker.getImage(app.imageId).inspectAsync().catch(->
|
||||
exports.kill = kill = (app) ->
|
||||
docker.listContainersAsync(all: 1).then((containers) ->
|
||||
Promise.all(
|
||||
containers
|
||||
.filter((container) ->
|
||||
return container.Image is "#{app}:latest"
|
||||
)
|
||||
.map((container) -> docker.getContainer(container.Id))
|
||||
.map((container) ->
|
||||
console.log("Stopping and deleting container:", container)
|
||||
container.stopAsync().then(->
|
||||
container.removeAsync()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
exports.start = start = (app) ->
|
||||
docker.getImage(app).inspectAsync().catch((error) ->
|
||||
console.log(error)
|
||||
deferred = Promise.defer()
|
||||
options =
|
||||
method: 'POST'
|
||||
path: "/v1.8/images/create?fromImage=#{app.imageId}"
|
||||
path: "/v1.8/images/create?fromImage=#{app}"
|
||||
socketPath: '/hostrun/docker.sock'
|
||||
|
||||
req = http.request(options, (res) ->
|
||||
if res.statusCode isnt 200
|
||||
return deferred.reject()
|
||||
|
||||
res.pipe(JSONStream.parse('error'))
|
||||
.pipe(es.mapSync((error) ->
|
||||
deferred.reject(error)
|
||||
))
|
||||
if res.headers['content-type'] is 'application/json'
|
||||
res.pipe(JSONStream.parse('error'))
|
||||
.pipe(es.mapSync((error) ->
|
||||
deferred.reject(error)
|
||||
))
|
||||
else
|
||||
res.pipe(es.wait((error, text) -> deferred.reject(text)))
|
||||
|
||||
res.on('end', ->
|
||||
deferred.resolve()
|
||||
if res.statusCode is 200
|
||||
deferred.resolve()
|
||||
else
|
||||
deferred.reject(res.statusCode)
|
||||
)
|
||||
)
|
||||
req.end()
|
||||
@ -34,5 +61,56 @@ exports.start = (app) ->
|
||||
|
||||
return deferred.promise
|
||||
).then(->
|
||||
docker.runAsync(app.imageId, ['/bin/bash', '-c', '/start web'], process.stdout, true)
|
||||
console.log("Creating container:", app)
|
||||
docker.createContainerAsync(
|
||||
Image: app
|
||||
Cmd: ['/bin/bash', '-c', '/start web']
|
||||
)
|
||||
).then((container) ->
|
||||
container.startAsync()
|
||||
)
|
||||
|
||||
exports.restart = restart = (app) ->
|
||||
kill(app).then(->
|
||||
start(app)
|
||||
)
|
||||
|
||||
exports.update = ->
|
||||
Promise.all([
|
||||
knex('config').select('value').where(key: 'apiKey')
|
||||
knex('config').select('value').where(key: 'uuid')
|
||||
knex('app').select()
|
||||
]).then(([[apiKey], [uuid], apps]) ->
|
||||
apiKey = apiKey.value
|
||||
uuid = uuid.value
|
||||
request(
|
||||
method: 'GET'
|
||||
url: url.resolve(process.env.API_ENDPOINT, "/ewa/application?$filter=device/uuid eq '#{uuid}'&apikey=#{apiKey}")
|
||||
json: true
|
||||
).spread((request, body) ->
|
||||
console.log("Remote apps")
|
||||
remoteApps = ("registry.resin.io:5000/#{path.basename(app.git_repository, '.git')}/#{app.commit}" for app in body.d)
|
||||
console.log(remoteApps)
|
||||
|
||||
console.log("Local apps")
|
||||
localApps = (app.imageId for app in apps)
|
||||
console.log(localApps)
|
||||
|
||||
console.log("Apps to be removed")
|
||||
toBeRemoved = _.difference(localApps, remoteApps)
|
||||
console.log(toBeRemoved)
|
||||
|
||||
console.log("Apps to be installed")
|
||||
toBeInstalled = _.difference(remoteApps, localApps)
|
||||
console.log(toBeInstalled)
|
||||
|
||||
Promise.all(toBeRemoved.map(kill)).then(->
|
||||
Promise.all(toBeInstalled.map(start))
|
||||
).then(->
|
||||
knex('app').whereIn('imageId', toBeRemoved).delete().then(->
|
||||
knex('app').insert(({imageId: app} for app in toBeInstalled))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user