Update docker-delta to 1.1.1, docker-toolbelt to 3.0.1, docker-progress to 2.6.0 to add support for deltas and overlay2

This makes the Async suffix for docker functions unnecessary. It also allows us to remove dockerode as an
explicit dependency.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
Pablo Carranza Velez 2017-07-25 17:38:42 -03:00
parent e5cac89f1b
commit 7aedd7062d
5 changed files with 53 additions and 58 deletions

View File

@ -29,10 +29,9 @@
"buffer-equal-constant-time": "^1.0.1",
"coffee-loader": "^0.7.3",
"coffee-script": "~1.11.0",
"docker-delta": "1.0.3",
"docker-progress": "^2.5.0",
"docker-toolbelt": "^1.3.0",
"dockerode": "~2.2.9",
"docker-delta": "1.1.1",
"docker-progress": "^2.6.0",
"docker-toolbelt": "^3.0.1",
"event-stream": "^3.0.20",
"express": "^4.0.0",
"knex": "~0.12.3",

View File

@ -156,9 +156,9 @@ application.kill = kill = (app, { updateDB = true, removeContainer = true } = {}
logSystemEvent(logTypes.stopApp, app)
device.updateState(status: 'Stopping')
container = docker.getContainer(app.containerId)
container.stopAsync(t: 10)
container.stop(t: 10)
.then ->
container.removeAsync(v: true) if removeContainer
container.remove(v: true) if removeContainer
return
# Bluebird throws OperationalError for errors resulting in the normal execution of a promisified function.
.catch Promise.OperationalError, (err) ->
@ -168,7 +168,7 @@ application.kill = kill = (app, { updateDB = true, removeContainer = true } = {}
# 304 means the container was already stopped - so we can just remove it
if statusCode is '304'
logSystemEvent(logTypes.stopAppNoop, app)
container.removeAsync(v: true) if removeContainer
container.remove(v: true) if removeContainer
return
# 404 means the container doesn't exist, precisely what we want! :D
if statusCode is '404'
@ -192,7 +192,7 @@ application.kill = kill = (app, { updateDB = true, removeContainer = true } = {}
application.deleteImage = deleteImage = (app) ->
logSystemEvent(logTypes.deleteImageForApp, app)
docker.getImage(app.imageId).removeAsync(force: true)
docker.getImage(app.imageId).remove(force: true)
.then ->
logSystemEvent(logTypes.deleteImageForAppSuccess, app)
.catch ImageNotFoundError, (err) ->
@ -209,7 +209,7 @@ fetch = (app, setDeviceUpdateState = true) ->
onProgress = (progress) ->
device.updateState(download_progress: progress.percentage)
docker.getImage(app.imageId).inspectAsync()
docker.getImage(app.imageId).inspect()
.catch (error) ->
device.updateState(status: 'Downloading', download_progress: 0)
@ -228,7 +228,7 @@ fetch = (app, setDeviceUpdateState = true) ->
logSystemEvent(logTypes.downloadAppSuccess, app)
device.updateState(status: 'Idle', download_progress: null)
device.setUpdateState(update_downloaded: true) if setDeviceUpdateState
docker.getImage(app.imageId).inspectAsync()
docker.getImage(app.imageId).inspect()
.catch (err) ->
logSystemEvent(logTypes.downloadAppError, app, err)
throw err
@ -268,7 +268,7 @@ application.start = start = (app) ->
if app.containerId?
# If we have a container id then check it exists and if so use it.
container = docker.getContainer(app.containerId)
containerPromise = container.inspectAsync().return(container)
containerPromise = container.inspect().return(container)
else
containerPromise = Promise.rejected()
@ -295,7 +295,7 @@ application.start = start = (app) ->
shouldMountKmod(app.imageId)
.then (shouldMount) ->
binds.push('/bin/kmod:/bin/kmod:ro') if shouldMount
docker.createContainerAsync(
docker.createContainer(
Image: app.imageId
Cmd: cmd
Tty: true
@ -317,7 +317,7 @@ application.start = start = (app) ->
.tap (container) ->
logSystemEvent(logTypes.startApp, app)
device.updateState(status: 'Starting')
container.startAsync()
container.start()
.catch (err) ->
statusCode = '' + err.statusCode
# 304 means the container was already started, precisely what we want :)
@ -335,7 +335,7 @@ application.start = start = (app) ->
throw err
.catch (err) ->
# If starting the container failed, we remove it so that it doesn't litter
container.removeAsync(v: true)
container.remove(v: true)
.then ->
app.containerId = null
knex('app').update(app).where(appId: app.appId)
@ -827,7 +827,7 @@ application.update = update = (force, scheduled = false) ->
listenToEvents = do ->
appHasDied = {}
return ->
docker.getEventsAsync()
docker.getEvents()
.then (stream) ->
stream.on 'error', (err) ->
console.error('Error on docker events stream:', err, err.stack)
@ -870,7 +870,6 @@ application.initialize = ->
module.exports = (logsChannel, offlineMode) ->
logger.init(
dockerSocket: config.dockerSocket
pubnub: config.pubnub
channel: "device-#{logsChannel}-logs"
offlineMode: offlineMode

View File

@ -1,9 +1,12 @@
config = require './config'
process.env.DOCKER_HOST ?= "unix://#{config.dockerSocket}"
Docker = require 'docker-toolbelt'
{ DockerProgress } = require 'docker-progress'
Promise = require 'bluebird'
progress = require 'request-progress'
dockerDelta = require 'docker-delta'
config = require './config'
_ = require 'lodash'
knex = require './db'
{ request } = require './request'
@ -11,14 +14,12 @@ Lock = require 'rwlock'
utils = require './utils'
rimraf = Promise.promisify(require('rimraf'))
docker = new Docker(socketPath: config.dockerSocket)
exports.docker = docker
dockerProgress = new DockerProgress(socketPath: config.dockerSocket)
exports.docker = docker = new Docker()
dockerProgress = new DockerProgress(dockerToolbelt: docker)
# Create an array of (repoTag, image_id, created) tuples like the output of `docker images`
listRepoTagsAsync = ->
docker.listImagesAsync()
listRepoTags = ->
docker.listImages()
.then (images) ->
images = _.orderBy(images, 'Created', [ false ])
ret = []
@ -32,7 +33,7 @@ listRepoTagsAsync = ->
findSimilarImage = (repoTag) ->
application = repoTag.split('/')[1]
listRepoTagsAsync()
listRepoTags()
.then (repoTags) ->
# Find the most recent image of the same application
for repoTag in repoTags
@ -46,8 +47,11 @@ findSimilarImage = (repoTag) ->
getRepoAndTag = (image) ->
docker.getRegistryAndName(image)
.then ({ registry, imageName, tagName }) ->
registry = registry.toString().replace(':443', '')
return { repo: "#{registry}/#{imageName}", tag: tagName }
if registry? and registry != 'docker.io'
registry = registry.toString().replace(':443', '') + '/'
else
registry = ''
return { repo: "#{registry}#{imageName}", tag: tagName }
do ->
_lock = new Lock()
@ -116,7 +120,7 @@ do ->
.then (id) ->
getRepoAndTag(imgDest)
.then ({ repo, tag }) ->
docker.getImage(id).tagAsync({ repo, tag, force: true })
docker.getImage(id).tag({ repo, tag, force: true })
.catch dockerDelta.OutOfSyncError, (err) ->
console.log('Falling back to delta-from-empty')
exports.rsyncImageWithProgress(imgDest, { requestTimeout, totalTimeout, uuid, apiKey, startFromEmpty: true }, onProgress)
@ -149,7 +153,7 @@ do ->
.map ({ imageId }) ->
normalizeRepoTag(imageId)
supervisorTagPromise
docker.listImagesAsync()
docker.listImages()
.map (image) ->
image.NormalizedRepoTags = Promise.map(image.RepoTags, normalizeRepoTag)
Promise.props(image)
@ -172,7 +176,7 @@ do ->
)
.then ({ images, supervisorTags, appTags, extraTags }) ->
# Cleanup containers first, so that they don't block image removal.
docker.listContainersAsync(all: true)
docker.listContainers(all: true)
.filter (containerInfo) ->
# Do not remove user apps.
normalizeRepoTag(containerInfo.Image)
@ -185,7 +189,7 @@ do ->
return true
return containerHasExited(containerInfo.Id)
.map (containerInfo) ->
docker.getContainer(containerInfo.Id).removeAsync(v: true, force: true)
docker.getContainer(containerInfo.Id).remove(v: true, force: true)
.then ->
console.log('Deleted container:', containerInfo.Id, containerInfo.Image)
.catch(_.noop)
@ -195,13 +199,13 @@ do ->
return _.includes(appTags, tag) or _.includes(supervisorTags, tag) or _.includes(extraTags, tag)
Promise.map imagesToClean, (image) ->
Promise.map image.RepoTags.concat(image.Id), (tag) ->
docker.getImage(tag).removeAsync(force: true)
docker.getImage(tag).remove(force: true)
.then ->
console.log('Deleted image:', tag, image.Id, image.RepoTags)
.catch(_.noop)
containerHasExited = (id) ->
docker.getContainer(id).inspectAsync()
docker.getContainer(id).inspect()
.then (data) ->
return not data.State.Running
@ -217,7 +221,7 @@ do ->
return repoTag
exports.getImageEnv = (id) ->
docker.getImage(id).inspectAsync()
docker.getImage(id).inspect()
.get('Config').get('Env')
.then (env) ->
# env is an array of strings that say 'key=value'

View File

@ -1,9 +1,10 @@
_ = require 'lodash'
Docker = require 'dockerode'
Docker = require 'docker-toolbelt'
PUBNUB = require 'pubnub'
Promise = require 'bluebird'
es = require 'event-stream'
Lock = require 'rwlock'
{ docker } = require '../docker-utils'
LOG_PUBLISH_INTERVAL = 110
@ -19,13 +20,6 @@ initialised = new Promise (resolve) ->
exports.init = (config) ->
resolve(config)
dockerPromise = initialised.then (config) ->
docker = Promise.promisifyAll(new Docker(socketPath: config.dockerSocket))
# Hack dockerode to promisify internal classes' prototypes
Promise.promisifyAll(docker.getImage().constructor.prototype)
Promise.promisifyAll(docker.getContainer().constructor.prototype)
return docker
# Queue up any calls to publish logs whilst we wait to be initialised.
publish = do ->
publishQueue = [[]]
@ -95,19 +89,18 @@ do ->
exports.attach = (app) ->
Promise.using loggerLock(app.containerId), ->
if !attached[app.containerId]
dockerPromise.then (docker) ->
docker.getContainer(app.containerId)
.logsAsync({ follow: true, stdout: true, stderr: true, timestamps: true })
.then (stream) ->
attached[app.containerId] = true
stream.pipe(es.split())
.on 'data', (logLine) ->
space = logLine.indexOf(' ')
if space > 0
msg = { t: logLine.substr(0, space), m: logLine.substr(space + 1) }
publish(msg)
.on 'error', (err) ->
console.error('Error on container logs', err, err.stack)
attached[app.containerId] = false
.on 'end', ->
attached[app.containerId] = false
docker.getContainer(app.containerId)
.logs({ follow: true, stdout: true, stderr: true, timestamps: true })
.then (stream) ->
attached[app.containerId] = true
stream.pipe(es.split())
.on 'data', (logLine) ->
space = logLine.indexOf(' ')
if space > 0
msg = { t: logLine.substr(0, space), m: logLine.substr(space + 1) }
publish(msg)
.on 'error', (err) ->
console.error('Error on container logs', err, err.stack)
attached[app.containerId] = false
.on 'end', ->
attached[app.containerId] = false

View File

@ -248,7 +248,7 @@ exports.fetchAndSetTargetsForDependentApps = (state, fetchFn, apiKey) ->
Promise.map toBeRemoved, (app) ->
fs.unlinkAsync(tarPath(app))
.then ->
docker.getImage(app.imageId).removeAsync()
docker.getImage(app.imageId).remove()
.catch (err) ->
console.error('Could not remove image/artifacts for dependent app', err, err.stack)
.then ->