balena-supervisor/src/compose.coffee

55 lines
1.9 KiB
CoffeeScript
Raw Normal View History

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.pullImage(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')