mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-31 08:25:36 +00:00
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:
parent
e5cac89f1b
commit
7aedd7062d
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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 ->
|
||||
|
Loading…
x
Reference in New Issue
Block a user