Auto-merge for PR #477 via VersionBot

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 commit is contained in:
resin-io-versionbot[bot] 2017-07-27 15:20:35 +00:00 committed by GitHub
commit 3ba7641d17
6 changed files with 58 additions and 59 deletions

View File

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY! automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## v6.1.0 - 2017-07-27
* 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 [Pablo Carranza Velez]
## v6.0.5 - 2017-07-27 ## v6.0.5 - 2017-07-27
* Allow building the supervisor source without optimizations for easier debugging with dindctl [Pablo Carranza Velez] * Allow building the supervisor source without optimizations for easier debugging with dindctl [Pablo Carranza Velez]

View File

@ -1,7 +1,7 @@
{ {
"name": "resin-supervisor", "name": "resin-supervisor",
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.", "description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
"version": "6.0.5", "version": "6.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,10 +29,9 @@
"buffer-equal-constant-time": "^1.0.1", "buffer-equal-constant-time": "^1.0.1",
"coffee-loader": "^0.7.3", "coffee-loader": "^0.7.3",
"coffee-script": "~1.11.0", "coffee-script": "~1.11.0",
"docker-delta": "1.0.3", "docker-delta": "1.1.1",
"docker-progress": "^2.5.0", "docker-progress": "^2.6.0",
"docker-toolbelt": "^1.3.0", "docker-toolbelt": "^3.0.1",
"dockerode": "~2.2.9",
"event-stream": "^3.0.20", "event-stream": "^3.0.20",
"express": "^4.0.0", "express": "^4.0.0",
"knex": "~0.12.3", "knex": "~0.12.3",

View File

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

View File

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

View File

@ -1,9 +1,10 @@
_ = require 'lodash' _ = require 'lodash'
Docker = require 'dockerode' Docker = require 'docker-toolbelt'
PUBNUB = require 'pubnub' PUBNUB = require 'pubnub'
Promise = require 'bluebird' Promise = require 'bluebird'
es = require 'event-stream' es = require 'event-stream'
Lock = require 'rwlock' Lock = require 'rwlock'
{ docker } = require '../docker-utils'
LOG_PUBLISH_INTERVAL = 110 LOG_PUBLISH_INTERVAL = 110
@ -19,13 +20,6 @@ initialised = new Promise (resolve) ->
exports.init = (config) -> exports.init = (config) ->
resolve(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. # Queue up any calls to publish logs whilst we wait to be initialised.
publish = do -> publish = do ->
publishQueue = [[]] publishQueue = [[]]
@ -95,9 +89,8 @@ do ->
exports.attach = (app) -> exports.attach = (app) ->
Promise.using loggerLock(app.containerId), -> Promise.using loggerLock(app.containerId), ->
if !attached[app.containerId] if !attached[app.containerId]
dockerPromise.then (docker) ->
docker.getContainer(app.containerId) docker.getContainer(app.containerId)
.logsAsync({ follow: true, stdout: true, stderr: true, timestamps: true }) .logs({ follow: true, stdout: true, stderr: true, timestamps: true })
.then (stream) -> .then (stream) ->
attached[app.containerId] = true attached[app.containerId] = true
stream.pipe(es.split()) stream.pipe(es.split())

View File

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