docker-storage-gc 3.5.12 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,124 +0,0 @@
1
- { expect } = require 'chai'
2
- fs = require 'fs'
3
- tk = require 'timekeeper'
4
- es = require 'event-stream'
5
-
6
- { parseEventStream } = require '../lib/docker-event-stream'
7
- { createTree } = require '../lib/docker-image-tree'
8
-
9
- dockerUtils = require('../lib/docker.coffee')
10
-
11
- getLayerMtimes = ->
12
- dockerUtils.getDocker({})
13
- .then (docker) ->
14
- parseEventStream(docker)
15
- .then (streamParser) ->
16
- new Promise (resolve, reject) ->
17
- mtimes = null
18
- fs.createReadStream(__dirname + '/fixtures/docker-events.json')
19
- .pipe(streamParser)
20
- .on 'error', reject
21
- .pipe es.mapSync (data) ->
22
- mtimes = data
23
- .on 'end', -> resolve(mtimes)
24
- .on 'error', reject
25
-
26
- describe 'createTree', ->
27
- it.skip 'should work with empty input', ->
28
-
29
- it 'should return a tree of images', ->
30
- images = require('./fixtures/docker-images.json')
31
- containers = require('./fixtures/docker-containers.json')
32
- getLayerMtimes()
33
- .then (mtimes) ->
34
- tk.freeze(Date.UTC(2016, 0, 1))
35
- tree = createTree(images, containers, mtimes)
36
- tk.reset()
37
- output = {
38
- 'id': '0000000000000000000000000000000000000000000000000000000000000000',
39
- 'size': 0,
40
- 'repoTags': [],
41
- 'repoDigests': [],
42
- 'mtime': 1451606400000000000,
43
- 'isUsedByAContainer': false,
44
- 'children': {
45
- 'sha256:6d15899cef812e2876b9d5d43d4cd863eda7b278f7b52d00975f6a9a8e817c74': {
46
- 'id': 'sha256:6d15899cef812e2876b9d5d43d4cd863eda7b278f7b52d00975f6a9a8e817c74',
47
- 'size': 125151141,
48
- 'repoTags': [],
49
- 'repoDigests': [],
50
- 'mtime': 1451606400000000000,
51
- 'isUsedByAContainer': false,
52
- 'children': {
53
- 'sha256:e53bd4df04f86919156c4510cdc6e6c9491ec8ec226381d36aca573b46bbbbbc': {
54
- 'id': 'sha256:e53bd4df04f86919156c4510cdc6e6c9491ec8ec226381d36aca573b46bbbbbc',
55
- 'size': 0,
56
- 'repoTags': [
57
- 'project1'
58
- ],
59
- 'repoDigests': [],
60
- 'mtime': 1451606400000000000,
61
- 'isUsedByAContainer': false,
62
- 'children': {
63
- 'sha256:6d41a4a0bf8168363e29da8a5ecbf3cd6c37e3f5a043decd5e7da6e427ba869c': {
64
- 'id': 'sha256:6d41a4a0bf8168363e29da8a5ecbf3cd6c37e3f5a043decd5e7da6e427ba869c',
65
- 'size': 330389,
66
- 'repoTags': [
67
- 'project2'
68
- ],
69
- 'repoDigests': [],
70
- 'mtime': 1448576073085559863,
71
- 'isUsedByAContainer': false,
72
- 'children': {
73
- 'sha256:80dc79d29cd8618e678da508fc32f7289e6f72defb534f3f287731b1f8b355ea': {
74
- 'id': 'sha256:80dc79d29cd8618e678da508fc32f7289e6f72defb534f3f287731b1f8b355ea',
75
- 'size': 98872,
76
- 'repoTags': [],
77
- 'repoDigests': [],
78
- 'mtime': 1451606400000000000,
79
- 'isUsedByAContainer': false,
80
- 'children': {}
81
- }
82
- }
83
- }
84
- }
85
- }
86
- }
87
- },
88
- 'sha256:902b87aaaec929e80541486828959f14fa061f529ad7f37ab300d4ef9f3a0dbf': {
89
- 'id': 'sha256:902b87aaaec929e80541486828959f14fa061f529ad7f37ab300d4ef9f3a0dbf',
90
- 'size': 125151141,
91
- 'repoTags': [],
92
- 'repoDigests': [],
93
- 'mtime': 1451606400000000000,
94
- 'isUsedByAContainer': false,
95
- 'children': {
96
- 'sha256:9a61b6b1315e6b457c31a03346ab94486a2f5397f4a82219bee01eead1c34c2e': {
97
- 'id': 'sha256:9a61b6b1315e6b457c31a03346ab94486a2f5397f4a82219bee01eead1c34c2e',
98
- 'size': 0,
99
- 'repoTags': [
100
- 'resin/project3'
101
- ],
102
- 'repoDigests': [],
103
- 'mtime': 1448576073203895800,
104
- 'isUsedByAContainer': false,
105
- 'children': {}
106
- }
107
- }
108
- },
109
- 'sha256:5b0d59026729b68570d99bc4f3f7c31a2e4f2a5736435641565d93e7c25bd2c3': {
110
- 'id': 'sha256:5b0d59026729b68570d99bc4f3f7c31a2e4f2a5736435641565d93e7c25bd2c3',
111
- 'size': 125151141,
112
- 'repoTags': [
113
- 'busybox:latest'
114
- ],
115
- 'repoDigests': [
116
- 'sha256:a8cf7ff6367c2afa2a90acd081b484cbded349a7076e7bdf37a05279f276bc12'
117
- ],
118
- 'mtime': 1448576072937294800,
119
- 'isUsedByAContainer': true,
120
- 'children': {},
121
- }
122
- }
123
- }
124
- expect(tree).to.deep.equal(output)
package/test/index.coffee DELETED
@@ -1,208 +0,0 @@
1
- Bluebird = require 'bluebird'
2
- { expect } = require 'chai'
3
-
4
- DockerGC = require('../lib/index')
5
- dockerUtils = require('../lib/docker.coffee')
6
-
7
- SKIP_GC_TEST = process.env.SKIP_GC_TEST == '1' || false
8
- IMAGES = [ 'alpine:3.1', 'debian:squeeze', 'ubuntu:lucid' ]
9
-
10
- # TODO: Move it to a proper repo
11
- # Same image (same id), different repo, different digest
12
- NONE_TAG_IMAGES = ['hello-world@sha256:8e3114318a995a1ee497790535e7b88365222a21771ae7e53687ad76563e8e76',
13
- 'balenaplayground/hello-world@sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042']
14
-
15
- promiseToBool = (p) ->
16
- p.return(true).catchReturn(false)
17
-
18
- pullAsync = (docker, tag) ->
19
- console.log("[TEST] Pulling #{tag}")
20
- docker.pull(tag)
21
- .then (stream) ->
22
- new Promise (resolve, reject) ->
23
- stream.resume()
24
- stream.once('error', reject)
25
- stream.once('end', resolve)
26
-
27
- # This test case is a little weird, it requires that no other images are present on
28
- # the system to ensure that the correct one is being removed. Because of this, you
29
- # can use the SKIP_GC_TEST env var to inform the test suite not to run this test
30
- describe 'Garbage collection', ->
31
- beforeEach ->
32
- @dockerStorage = new DockerGC()
33
- # Use either local or CI docker
34
- Bluebird.join(
35
- dockerUtils.getDocker({
36
- socketPath: '/tmp/dind/docker.sock',
37
- Promise: Bluebird,
38
- })
39
- @dockerStorage.setDocker({
40
- socketPath: '/tmp/dind/docker.sock',
41
- Promise: Bluebird,
42
- })
43
- (docker) =>
44
- @dockerStorage.setupMtimeStream()
45
- @docker = docker
46
- )
47
-
48
- afterEach ->
49
- docker = @docker
50
- console.log('[afterEach] Cleaning up...')
51
- for image in IMAGES.concat(NONE_TAG_IMAGES)
52
- docker.getImage(image).remove()
53
- .catch ->
54
-
55
- it 'should remove a image by tag', ->
56
- this.timeout(600000)
57
- docker = @docker
58
- dockerStorage = @dockerStorage
59
-
60
- pullAsync(docker, IMAGES[0])
61
- .then ->
62
- docker.getImage(IMAGES[0]).inspect()
63
- .then ->
64
- dockerStorage.garbageCollect(1)
65
- .then ->
66
- promiseToBool(docker.getImage(IMAGES[0]).inspect())
67
- .then (image_found) ->
68
- expect(image_found).to.be.false
69
-
70
- it 'should remove a image by digest if its tag == none', ->
71
- this.timeout(600000)
72
- docker = @docker
73
- dockerStorage = @dockerStorage
74
-
75
- pullAsync(docker, NONE_TAG_IMAGES[0])
76
- .then ->
77
- docker.getImage(NONE_TAG_IMAGES[0]).inspect()
78
- .then ->
79
- dockerStorage.garbageCollect(1)
80
- .then ->
81
- promiseToBool(docker.getImage(NONE_TAG_IMAGES[0]).inspect())
82
- .then (image_found) ->
83
- expect(image_found).to.be.false
84
-
85
- it 'should remove a image with tag == none even if it is in several repos', ->
86
- this.timeout(600000)
87
- docker = @docker
88
- dockerStorage = @dockerStorage
89
-
90
- Bluebird.each NONE_TAG_IMAGES, (image) ->
91
- pullAsync(docker, image)
92
- .then ->
93
- docker.getImage(NONE_TAG_IMAGES[0]).inspect()
94
- .then ->
95
- dockerStorage.garbageCollect(1)
96
- .then ->
97
- Bluebird.map NONE_TAG_IMAGES, (image) ->
98
- promiseToBool(docker.getImage(image).inspect())
99
- .then (imagesFound) ->
100
- expect(imagesFound).to.deep.equal([false, false])
101
-
102
-
103
- it 'should remove all tags of an image', ->
104
- this.timeout(600000)
105
- return Promise.resolve() if SKIP_GC_TEST
106
-
107
- docker = @docker
108
-
109
- # first pull some images, so we know in which order they are referenced
110
- pullAsync(docker, IMAGES[0])
111
- .then ->
112
- docker.getImage(IMAGES[0]).tag(repo: 'some-repo', tag: 'some-tag')
113
- .then =>
114
- @dockerStorage.garbageCollect(1)
115
- .then ->
116
- promiseToBool(docker.getImage(IMAGES[0]).inspect())
117
- .then (imagesFound) ->
118
- expect(imagesFound).to.be.false
119
-
120
-
121
- it 'should remove the LRU image', ->
122
- this.timeout(600000)
123
- return Promise.resolve() if SKIP_GC_TEST
124
-
125
- docker = @docker
126
-
127
- # first pull some images, so we know in which order they are referenced
128
- pullAsync(docker, IMAGES[0])
129
- .then ->
130
- docker.getImage(IMAGES[0]).tag(repo: 'some-repo', tag: 'some-tag')
131
- .then ->
132
- Bluebird.each IMAGES.slice(1), (image) ->
133
- pullAsync(docker, image)
134
- .then =>
135
- # Attempt to remove a single byte, which will remove the LRU image,
136
- # which should be alpine
137
- @dockerStorage.garbageCollect(1)
138
- .then ->
139
- Bluebird.map IMAGES, (image) ->
140
- promiseToBool(docker.getImage(image).inspect())
141
- .then (imagesFound) ->
142
- expect(imagesFound).to.deep.equal([false, true, true])
143
-
144
- it 'should remove more than one image if necessary', ->
145
- this.timeout(600000)
146
- return Promise.resolve() if SKIP_GC_TEST
147
-
148
- docker = @docker
149
-
150
- Bluebird.each IMAGES, (image) ->
151
- pullAsync(docker, image)
152
- .then ->
153
- # Get the size of the first image, so we can add one to it to remove
154
- # the next one in addition
155
- docker.getImage(IMAGES[0]).inspect().get('Size')
156
- .then (size) =>
157
- @dockerStorage.garbageCollect(size + 1)
158
- .then ->
159
- Bluebird.map IMAGES, (image) ->
160
- promiseToBool(docker.getImage(image).inspect())
161
- .then (imagesFound) ->
162
- expect(imagesFound).to.deep.equal([false, false, true])
163
-
164
-
165
- it 'should not consider images in use', ->
166
- this.timeout(600000)
167
- containerName = 'dont-consider-images-in-use-test'
168
- return Promise.resolve() if SKIP_GC_TEST
169
-
170
- docker = @docker
171
-
172
- pullAsync(docker, IMAGES[0])
173
- .then ->
174
- docker.createContainer({
175
- Image: IMAGES[0],
176
- Tty: true,
177
- Cmd: ['sh', '-c', 'while true; do echo test; sleep 1; done'],
178
- name: containerName,
179
- HostConfig: { AutoRemove: true }
180
- })
181
- .then (container) ->
182
- container.start()
183
- .then =>
184
- @dockerStorage.garbageCollect(1)
185
- .then ->
186
- promiseToBool(docker.getImage(IMAGES[0]).inspect())
187
- .then (imageInspect) ->
188
- expect(imageInspect).to.be.true
189
- .finally ->
190
- docker.getContainer(containerName).stop()
191
-
192
- it 'should get daemon host disk usage', ->
193
- this.timeout(600000)
194
- @dockerStorage.getDaemonFreeSpace()
195
- .then (du) ->
196
- expect(du).to.be.an('object')
197
- expect(du).to.have.property('free').that.is.a('number')
198
- expect(du).to.have.property('used').that.is.a('number')
199
- expect(du).to.have.property('total').that.is.a('number')
200
-
201
- it 'should get the correct architecture for a remote host', ->
202
- @dockerStorage.getDaemonArchitecture()
203
- .then (arch) ->
204
- expect(arch).to.be.a('string')
205
-
206
- it 'should set a base image to be used', ->
207
- @dockerStorage.baseImagePromise.then (img) ->
208
- expect(img).to.be.a('string')
@@ -1,24 +0,0 @@
1
- exports.createDot = (tree) ->
2
- _createDot = (tree) ->
3
- id = (tree) -> "foo_#{tree.id[0..6]}"
4
-
5
- label = (tree) ->
6
- name = tree.repoTags[0] or '\\<none\\>:\\<none\\>'
7
- mtime = new Date(tree.mtime).toISOString()
8
-
9
- return "label=\"{ #{tree.id[0..12]} | #{name} | { #{mtime} | #{tree.size} } }\""
10
-
11
- color = (tree) ->
12
- if tree.repoTags.length is 0
13
- 'color="black"'
14
- else
15
- 'color="red"'
16
-
17
- # define the node
18
- [ "#{id(tree)} [shape=record, #{label(tree)}, #{color(tree)}]" ]
19
- # define all relations with child nodes
20
- .concat(("#{id(tree)} -> #{id(child)}" for own _, child of tree.children))
21
- # recurse to children
22
- .concat((_createDot(child) for own id, child of tree.children)...)
23
-
24
- return 'digraph {\n' + _createDot(tree).join('\n') + '\n}\n'