docker-api 1.31.0 → 1.32.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,149 +0,0 @@
1
- #!/bin/sh
2
- set -e
3
-
4
- ### BEGIN INIT INFO
5
- # Provides: docker
6
- # Required-Start: $syslog $remote_fs
7
- # Required-Stop: $syslog $remote_fs
8
- # Should-Start: cgroupfs-mount cgroup-lite
9
- # Should-Stop: cgroupfs-mount cgroup-lite
10
- # Default-Start: 2 3 4 5
11
- # Default-Stop: 0 1 6
12
- # Short-Description: Create lightweight, portable, self-sufficient containers.
13
- # Description:
14
- # Docker is an open-source project to easily create lightweight, portable,
15
- # self-sufficient containers from any application. The same container that a
16
- # developer builds and tests on a laptop can run at scale, in production, on
17
- # VMs, bare metal, OpenStack clusters, public clouds and more.
18
- ### END INIT INFO
19
-
20
- export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
21
-
22
- BASE=$(basename $0)
23
-
24
- # modify these in /etc/default/$BASE (/etc/default/docker)
25
- DOCKER=/usr/bin/$BASE
26
- # This is the pid file managed by docker itself
27
- DOCKER_PIDFILE=/var/run/$BASE.pid
28
- # This is the pid file created/managed by start-stop-daemon
29
- DOCKER_SSD_PIDFILE=/var/run/$BASE-ssd.pid
30
- DOCKER_LOGFILE=/var/log/$BASE.log
31
- DOCKER_OPTS=
32
- DOCKER_DESC="Docker"
33
-
34
- # Get lsb functions
35
- . /lib/lsb/init-functions
36
-
37
- if [ -f /etc/default/$BASE ]; then
38
- . /etc/default/$BASE
39
- fi
40
-
41
- # Check docker is present
42
- if [ ! -x $DOCKER ]; then
43
- log_failure_msg "$DOCKER not present or not executable"
44
- exit 1
45
- fi
46
-
47
- check_init() {
48
- # see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it directly)
49
- if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then
50
- log_failure_msg "$DOCKER_DESC is managed via upstart, try using service $BASE $1"
51
- exit 1
52
- fi
53
- }
54
-
55
- fail_unless_root() {
56
- if [ "$(id -u)" != '0' ]; then
57
- log_failure_msg "$DOCKER_DESC must be run as root"
58
- exit 1
59
- fi
60
- }
61
-
62
- cgroupfs_mount() {
63
- # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
64
- if grep -v '^#' /etc/fstab | grep -q cgroup \
65
- || [ ! -e /proc/cgroups ] \
66
- || [ ! -d /sys/fs/cgroup ]; then
67
- return
68
- fi
69
- if ! mountpoint -q /sys/fs/cgroup; then
70
- mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
71
- fi
72
- (
73
- cd /sys/fs/cgroup
74
- for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
75
- mkdir -p $sys
76
- if ! mountpoint -q $sys; then
77
- if ! mount -n -t cgroup -o $sys cgroup $sys; then
78
- rmdir $sys || true
79
- fi
80
- fi
81
- done
82
- )
83
- }
84
-
85
- case "$1" in
86
- start)
87
- check_init
88
-
89
- fail_unless_root
90
-
91
- cgroupfs_mount
92
-
93
- touch "$DOCKER_LOGFILE"
94
- chgrp docker "$DOCKER_LOGFILE"
95
-
96
- ulimit -n 1048576
97
- if [ "$BASH" ]; then
98
- ulimit -u 1048576
99
- else
100
- ulimit -p 1048576
101
- fi
102
-
103
- log_begin_msg "Starting $DOCKER_DESC: $BASE"
104
- start-stop-daemon --start --background \
105
- --no-close \
106
- --exec "$DOCKER" \
107
- --pidfile "$DOCKER_SSD_PIDFILE" \
108
- --make-pidfile \
109
- -- \
110
- -d -p "$DOCKER_PIDFILE" \
111
- $DOCKER_OPTS \
112
- >> "$DOCKER_LOGFILE" 2>&1
113
- log_end_msg $?
114
- ;;
115
-
116
- stop)
117
- check_init
118
- fail_unless_root
119
- log_begin_msg "Stopping $DOCKER_DESC: $BASE"
120
- start-stop-daemon --stop --pidfile "$DOCKER_SSD_PIDFILE"
121
- log_end_msg $?
122
- ;;
123
-
124
- restart)
125
- check_init
126
- fail_unless_root
127
- docker_pid=`cat "$DOCKER_SSD_PIDFILE" 2>/dev/null`
128
- [ -n "$docker_pid" ] \
129
- && ps -p $docker_pid > /dev/null 2>&1 \
130
- && $0 stop
131
- $0 start
132
- ;;
133
-
134
- force-reload)
135
- check_init
136
- fail_unless_root
137
- $0 restart
138
- ;;
139
-
140
- status)
141
- check_init
142
- status_of_proc -p "$DOCKER_SSD_PIDFILE" "$DOCKER" "$DOCKER_DESC"
143
- ;;
144
-
145
- *)
146
- echo "Usage: service docker {start|stop|restart|status}"
147
- exit 1
148
- ;;
149
- esac
@@ -1,61 +0,0 @@
1
- description "Docker daemon"
2
-
3
- start on (local-filesystems and net-device-up IFACE!=lo)
4
- stop on runlevel [!2345]
5
- limit nofile 524288 1048576
6
- limit nproc 524288 1048576
7
-
8
- respawn
9
-
10
- kill timeout 20
11
-
12
- pre-start script
13
- # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
14
- if grep -v '^#' /etc/fstab | grep -q cgroup \
15
- || [ ! -e /proc/cgroups ] \
16
- || [ ! -d /sys/fs/cgroup ]; then
17
- exit 0
18
- fi
19
- if ! mountpoint -q /sys/fs/cgroup; then
20
- mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
21
- fi
22
- (
23
- cd /sys/fs/cgroup
24
- for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
25
- mkdir -p $sys
26
- if ! mountpoint -q $sys; then
27
- if ! mount -n -t cgroup -o $sys cgroup $sys; then
28
- rmdir $sys || true
29
- fi
30
- fi
31
- done
32
- )
33
- end script
34
-
35
- script
36
- # modify these in /etc/default/$UPSTART_JOB (/etc/default/docker)
37
- DOCKER=/usr/bin/$UPSTART_JOB
38
- DOCKER_OPTS=
39
- if [ -f /etc/default/$UPSTART_JOB ]; then
40
- . /etc/default/$UPSTART_JOB
41
- fi
42
- exec "$DOCKER" -d $DOCKER_OPTS
43
- end script
44
-
45
- # Don't emit "started" event until docker.sock is ready.
46
- # See https://github.com/docker/docker/issues/6647
47
- post-start script
48
- DOCKER_OPTS=
49
- if [ -f /etc/default/$UPSTART_JOB ]; then
50
- . /etc/default/$UPSTART_JOB
51
- fi
52
- if ! printf "%s" "$DOCKER_OPTS" | grep -qE -e '-H|--host'; then
53
- while ! [ -e /var/run/docker.sock ]; do
54
- initctl status $UPSTART_JOB | grep -qE "(stop|respawn)/" && exit 1
55
- echo "Waiting for /var/run/docker.sock"
56
- sleep 0.1
57
- done
58
- echo "/var/run/docker.sock is up"
59
- fi
60
- end script
61
-
@@ -1,35 +0,0 @@
1
- #!/bin/bash
2
- set -x
3
- set -e
4
-
5
- # argv[0]
6
- DOCKER_VERSION=$1
7
-
8
- # disable travis default installation
9
- service docker stop
10
- apt-get -y --purge remove docker-engine
11
-
12
- # install gpg key for docker rpo
13
- apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv 58118E89F3A912897C070ADBF76221572C52609D
14
-
15
- # enable docker repo
16
- echo 'deb "https://apt.dockerproject.org/repo" ubuntu-trusty main' >> /etc/apt/sources.list.d/docker-main.list
17
- apt-get update -o Dir::Etc::sourcelist='sources.list.d/docker-main.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'
18
- apt-cache gencaches
19
-
20
- # install package
21
- apt-get -y --force-yes install docker-engine=${DOCKER_VERSION}-0~trusty
22
- echo 'DOCKER_OPTS="-H unix:///var/run/docker.sock --pidfile=/var/run/docker.pid"' > /etc/default/docker
23
- cat /etc/default/docker
24
-
25
- # docker 1.6 packages did not come with init files
26
- if [[ $DOCKER_VERSION == 1.6.* ]]
27
- then
28
- cp script/docker.conf /etc/init/docker.conf
29
- cp script/docker /etc/init.d/docker
30
- chmod +x /etc/init.d/docker
31
- else
32
- service docker stop
33
- fi
34
-
35
- service docker start
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Connection do
4
- subject { described_class.new('http://localhost:4243', {}) }
5
-
6
- describe '#initialize' do
7
- let(:url) { 'http://localhost:4243' }
8
- let(:options) { {} }
9
- subject { described_class.new(url, options) }
10
-
11
- context 'when the first argument is not a String' do
12
- let(:url) { :lol_not_a_string }
13
-
14
- it 'raises an error' do
15
- expect { subject }.to raise_error(Docker::Error::ArgumentError)
16
- end
17
- end
18
-
19
- context 'when the first argument is a String' do
20
- context 'and the url is a unix socket' do
21
- let(:url) { 'unix:///var/run/docker.sock' }
22
-
23
- it 'sets the socket path in the options' do
24
- expect(subject.url).to eq('unix:///')
25
- expect(subject.options).to include(:socket => '/var/run/docker.sock')
26
- end
27
- end
28
-
29
- context 'but the second argument is not a Hash' do
30
- let(:options) { :lol_not_a_hash }
31
-
32
- it 'raises an error' do
33
- expect { subject }.to raise_error(Docker::Error::ArgumentError)
34
- end
35
- end
36
-
37
- context 'and the second argument is a Hash' do
38
- it 'sets the url and options' do
39
- expect(subject.url).to eq url
40
- expect(subject.options).to eq options
41
- end
42
- end
43
- end
44
-
45
- context 'url conversion to uri' do
46
- context 'when the url does not contain a scheme' do
47
- let(:url) { 'localhost:4243' }
48
-
49
- it 'adds the scheme to the url' do
50
- expect(subject.url).to eq "http://#{url}"
51
- end
52
- end
53
-
54
- context 'when the url is a complete uri' do
55
- let(:url) { 'http://localhost:4243' }
56
-
57
- it 'leaves the url intact' do
58
- expect(subject.url).to eq url
59
- end
60
- end
61
- end
62
- end
63
-
64
- describe '#resource' do
65
- its(:resource) { should be_a Excon::Connection }
66
- end
67
-
68
- describe '#request' do
69
- let(:method) { :get }
70
- let(:path) { '/test' }
71
- let(:query) { { :all => true } }
72
- let(:options) { { :expects => 201, :lol => true } }
73
- let(:body) { rand(10000000) }
74
- let(:resource) { double(:resource) }
75
- let(:response) { double(:response, :body => body) }
76
- let(:expected_hash) {
77
- {
78
- :method => method,
79
- :path => "/v#{Docker::API_VERSION}#{path}",
80
- :query => query,
81
- :headers => { 'Content-Type' => 'text/plain',
82
- 'User-Agent' => "Swipely/Docker-API #{Docker::VERSION}",
83
- },
84
- :expects => 201,
85
- :idempotent => true,
86
- :lol => true
87
- }
88
- }
89
-
90
- before do
91
- allow(subject).to receive(:resource).and_return(resource)
92
- expect(resource).to receive(:request).
93
- with(expected_hash).
94
- and_return(response)
95
- end
96
-
97
- it 'sends #request to #resource with the compiled params' do
98
- expect(subject.request(method, path, query, options)).to eq body
99
- end
100
- end
101
-
102
- [:get, :put, :post, :delete].each do |method|
103
- describe "##{method}" do
104
- it 'is delegated to #request' do
105
- expect(subject).to receive(:request).with(method)
106
- subject.public_send(method)
107
- end
108
- end
109
- end
110
-
111
- describe '#to_s' do
112
- let(:url) { 'http://google.com:4000' }
113
- let(:options) { {} }
114
- let(:expected_string) {
115
- "Docker::Connection { :url => #{url}, :options => #{options} }"
116
- }
117
- subject { described_class.new(url, options) }
118
-
119
- it 'returns a pretty version with the url and port' do
120
- expect(subject.to_s).to eq expected_string
121
- end
122
- end
123
- end
@@ -1,870 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Docker::Container do
4
- describe '#to_s' do
5
- subject {
6
- described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
7
- }
8
-
9
- let(:id) { 'bf119e2' }
10
- let(:connection) { Docker.connection }
11
- let(:expected_string) {
12
- "Docker::Container { :id => #{id}, :connection => #{connection} }"
13
- }
14
- before do
15
- {
16
- :@id => id,
17
- :@connection => connection
18
- }.each { |k, v| subject.instance_variable_set(k, v) }
19
- end
20
-
21
- its(:to_s) { should == expected_string }
22
- end
23
-
24
- describe '#json' do
25
- subject {
26
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
27
- }
28
- let(:description) { subject.json }
29
- after(:each) { subject.remove }
30
-
31
- it 'returns the description as a Hash' do
32
- expect(description).to be_a Hash
33
- expect(description['Id']).to start_with(subject.id)
34
- end
35
- end
36
-
37
- describe '#streaming_logs' do
38
- let(:options) { {} }
39
- subject do
40
- described_class.create(
41
- {'Cmd' => ['/bin/bash', '-lc', 'echo hello'], 'Image' => 'debian:wheezy'}.merge(options)
42
- )
43
- end
44
-
45
- before(:each) { subject.tap(&:start).wait }
46
- after(:each) { subject.remove }
47
-
48
- context 'when not selecting any stream' do
49
- let(:non_destination) { subject.streaming_logs }
50
- it 'raises a client error' do
51
- expect { non_destination }.to raise_error(Docker::Error::ClientError)
52
- end
53
- end
54
-
55
- context 'when selecting stdout' do
56
- let(:stdout) { subject.streaming_logs(stdout: 1) }
57
- it 'returns blank logs' do
58
- expect(stdout).to be_a String
59
- expect(stdout).to match("hello")
60
- end
61
- end
62
-
63
- context 'when using a tty' do
64
- let(:options) { { 'Tty' => true } }
65
-
66
- let(:output) { subject.streaming_logs(stdout: 1, tty: 1) }
67
- it 'returns `hello`' do
68
- expect(output).to be_a(String)
69
- expect(output).to match("hello")
70
- end
71
- end
72
-
73
- context 'when passing a block' do
74
- let(:lines) { [] }
75
- let(:output) { subject.streaming_logs(stdout: 1, follow: 1) { |s,c| lines << c } }
76
- it 'returns `hello`' do
77
- expect(output).to be_a(String)
78
- expect(output).to match("hello")
79
- expect(lines.join).to match("hello")
80
- end
81
- end
82
- end
83
-
84
- describe '#stats', docker_1_9: true do
85
- subject {
86
- described_class.create('Cmd' => "echo hello", 'Image' => 'debian:wheezy')
87
- }
88
- after(:each) { subject.remove }
89
-
90
- context "when requesting container stats" do
91
- let(:output) { subject.stats }
92
- it "returns a Hash" do
93
- expect(output).to be_a Hash
94
- end
95
- end
96
- end
97
-
98
- describe '#logs' do
99
- subject {
100
- described_class.create('Cmd' => "echo hello", 'Image' => 'debian:wheezy')
101
- }
102
- after(:each) { subject.remove }
103
-
104
- context "when not selecting any stream" do
105
- let(:non_destination) { subject.logs }
106
- it 'raises a client error' do
107
- expect { non_destination }.to raise_error(Docker::Error::ClientError)
108
- end
109
- end
110
-
111
- context "when selecting stdout" do
112
- let(:stdout) { subject.logs(stdout: 1) }
113
- it 'returns blank logs' do
114
- expect(stdout).to be_a String
115
- expect(stdout).to eq ""
116
- end
117
- end
118
- end
119
-
120
- describe '#create' do
121
- subject {
122
- described_class.create({
123
- 'Cmd' => %w[true],
124
- 'Image' => 'debian:wheezy'
125
- }.merge(opts))
126
- }
127
-
128
- context 'when creating a container named bob' do
129
- let(:opts) { {"name" => "bob"} }
130
- after(:each) { subject.remove }
131
-
132
- it 'should have name set to bob' do
133
- expect(subject.json["Name"]).to eq("/bob")
134
- end
135
- end
136
- end
137
-
138
- describe '#rename' do
139
- subject {
140
- described_class.create({
141
- 'name' => 'foo',
142
- 'Cmd' => %w[true],
143
- 'Image' => 'debian:wheezy'
144
- })
145
- }
146
-
147
- before { subject.start }
148
- after(:each) { subject.tap(&:wait).remove }
149
-
150
- it 'renames the container' do
151
- subject.rename('bar')
152
- expect(subject.json["Name"]).to match(%r{bar})
153
- end
154
- end
155
-
156
- describe "#update", :docker_1_10 do
157
- subject {
158
- described_class.create({
159
- "name" => "foo",
160
- "Cmd" => %w[true],
161
- "Image" => "debian:wheezy",
162
- "HostConfig" => {
163
- "CpuShares" => 60000
164
- }
165
- })
166
- }
167
-
168
- before { subject.start }
169
- after(:each) { subject.tap(&:wait).remove }
170
-
171
- it "updates the container" do
172
- subject.refresh!
173
- expect(subject.info.fetch("Config").fetch("CpuShares")).to eq 60000
174
- subject.update("CpuShares" => 50000)
175
- subject.refresh!
176
- expect(subject.info.fetch("Config").fetch("CpuShares")).to eq 50000
177
- end
178
- end
179
-
180
- describe '#changes' do
181
- subject {
182
- described_class.create(
183
- 'Cmd' => %w[rm -rf /root],
184
- 'Image' => 'debian:wheezy'
185
- )
186
- }
187
- let(:changes) { subject.changes }
188
-
189
- before { subject.tap(&:start).tap(&:wait) }
190
- after(:each) { subject.tap(&:wait).remove }
191
-
192
- it 'returns the changes as an array' do
193
- expect(changes).to eq [
194
- {
195
- "Path" => "/root",
196
- "Kind" => 2
197
- },
198
- ]
199
- end
200
- end
201
-
202
- describe '#top' do
203
- let(:dir) {
204
- File.join(File.dirname(__FILE__), '..', 'fixtures', 'top')
205
- }
206
- let(:image) { Docker::Image.build_from_dir(dir) }
207
- let(:top) { sleep 1; container.top }
208
- let!(:container) { image.run('/while') }
209
- after do
210
- container.kill!.remove
211
- image.remove
212
- end
213
-
214
- it 'returns the top commands as an Array' do
215
- expect(top).to be_a Array
216
- expect(top).to_not be_empty
217
- expect(top.first.keys).to include('PID')
218
- end
219
- end
220
-
221
- describe '#copy' do
222
- let(:image) { Docker::Image.create('fromImage' => 'debian:wheezy') }
223
- subject { image.run('touch /test').tap { |c| c.wait } }
224
-
225
- after(:each) { subject.remove }
226
-
227
- context 'when the file does not exist' do
228
- it 'raises an error' do
229
- expect { subject.copy('/lol/not/a/real/file') { |chunk| puts chunk } }
230
- .to raise_error
231
- end
232
- end
233
-
234
- context 'when the input is a file' do
235
- it 'yields each chunk of the tarred file' do
236
- chunks = []
237
- subject.copy('/test') { |chunk| chunks << chunk }
238
- chunks = chunks.join("\n")
239
- expect(chunks).to be_include('test')
240
- end
241
- end
242
-
243
- context 'when the input is a directory' do
244
- it 'yields each chunk of the tarred directory' do
245
- chunks = []
246
- subject.copy('/etc/logrotate.d') { |chunk| chunks << chunk }
247
- chunks = chunks.join("\n")
248
- expect(%w[apt dpkg]).to be_all { |file| chunks.include?(file) }
249
- end
250
- end
251
- end
252
-
253
- describe '#archive_in', :docker_1_8 do
254
- let(:license_path) { File.absolute_path(File.join(__FILE__, '..', '..', '..', 'LICENSE')) }
255
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
256
- let(:committed_image) { subject.commit }
257
- let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
258
- let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
259
-
260
- after do
261
- subject.remove
262
- end
263
-
264
- context 'when the input is a tar' do
265
- after do
266
- ls_container.remove
267
- committed_image.remove
268
- end
269
-
270
- it 'file exists in the container' do
271
- subject.archive_in(license_path, '/', overwrite: false)
272
- expect(output).to include('LICENSE')
273
- end
274
- end
275
- end
276
-
277
- describe '#archive_in_stream', :docker_1_8 do
278
- let(:tar) { StringIO.new(Docker::Util.create_tar('/lol' => 'TEST')) }
279
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
280
- let(:committed_image) { subject.commit }
281
- let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
282
- let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
283
-
284
- after do
285
- subject.remove
286
- end
287
-
288
- context 'when the input is a tar' do
289
- after do
290
- ls_container.remove
291
- committed_image.remove
292
- end
293
-
294
- it 'file exists in the container' do
295
- subject.archive_in_stream('/', overwrite: false) { tar.read }
296
- expect(output).to include('lol')
297
- end
298
- end
299
-
300
- context 'when the input would overwrite a directory with a file' do
301
- let(:tar) { StringIO.new(Docker::Util.create_tar('/etc' => 'TEST')) }
302
-
303
- it 'raises an error' do
304
- # Docs say this should return a client error: clearly wrong
305
- # https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/
306
- # #extract-an-archive-of-files-or-folders-to-a-directory-in-a-container
307
- expect {
308
- subject.archive_in_stream('/', overwrite: false) { tar.read }
309
- }.to raise_error(Docker::Error::ServerError)
310
- end
311
- end
312
- end
313
-
314
- describe '#archive_out', :docker_1_8 do
315
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['touch','/test']) }
316
-
317
- after { subject.remove }
318
-
319
- context 'when the file does not exist' do
320
- it 'raises an error' do
321
- subject.start
322
- subject.wait
323
-
324
- expect { subject.archive_out('/lol') { |chunk| puts chunk } }
325
- .to raise_error(Docker::Error::NotFoundError)
326
- end
327
- end
328
-
329
- context 'when the input is a file' do
330
- it 'yields each chunk of the tarred file' do
331
- subject.start; subject.wait
332
-
333
- chunks = []
334
- subject.archive_out('/test') { |chunk| chunks << chunk }
335
- chunks = chunks.join("\n")
336
- expect(chunks).to be_include('test')
337
- end
338
- end
339
-
340
- context 'when the input is a directory' do
341
- it 'yields each chunk of the tarred directory' do
342
- subject.start; subject.wait
343
-
344
- chunks = []
345
- subject.archive_out('/etc/logrotate.d') { |chunk| chunks << chunk }
346
- chunks = chunks.join("\n")
347
- expect(%w[apt dpkg]).to be_all { |file| chunks.include?(file) }
348
- end
349
- end
350
- end
351
-
352
- describe "#read_file", :docker_1_8 do
353
- subject {
354
- Docker::Container.create(
355
- "Image" => "debian:wheezy",
356
- "Cmd" => ["/bin/bash", "-c", "echo \"Hello world\" > /test"]
357
- )
358
- }
359
-
360
- after { subject.remove }
361
-
362
- before do
363
- subject.start
364
- subject.wait
365
- end
366
-
367
- it "reads contents from files" do
368
- expect(subject.read_file("/test")).to eq "Hello world\n"
369
- end
370
- end
371
-
372
- describe "#store_file", :docker_1_8 do
373
- subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ["ls"]) }
374
-
375
- after { subject.remove }
376
-
377
- it "stores content in files" do
378
- subject.store_file("/test", "Hello\nWorld")
379
- expect(subject.read_file("/test")).to eq "Hello\nWorld"
380
- end
381
- end
382
-
383
- describe '#export' do
384
- subject { described_class.create('Cmd' => %w[/true],
385
- 'Image' => 'tianon/true') }
386
- before { subject.start }
387
- after { subject.tap(&:wait).remove }
388
-
389
- it 'yields each chunk' do
390
- first = nil
391
- subject.export do |chunk|
392
- first ||= chunk
393
- end
394
- expect(first[257..261]).to eq "ustar" # Make sure the export is a tar.
395
- end
396
- end
397
-
398
- describe '#attach' do
399
- subject {
400
- described_class.create(
401
- 'Cmd' => ['bash','-c','sleep 2; echo hello'],
402
- 'Image' => 'debian:wheezy'
403
- )
404
- }
405
-
406
- before { subject.start }
407
- after(:each) { subject.stop.remove }
408
-
409
- context 'with normal sized chunks' do
410
- it 'yields each chunk' do
411
- chunk = nil
412
- subject.attach do |stream, c|
413
- chunk ||= c
414
- end
415
- expect(chunk).to eq("hello\n")
416
- end
417
- end
418
-
419
- context 'with very small chunks' do
420
- before do
421
- Docker.options = { :chunk_size => 1 }
422
- end
423
-
424
- after do
425
- Docker.options = {}
426
- end
427
-
428
- it 'yields each chunk' do
429
- chunk = nil
430
- subject.attach do |stream, c|
431
- chunk ||= c
432
- end
433
- expect(chunk).to eq("hello\n")
434
- end
435
- end
436
- end
437
-
438
- describe '#attach with stdin' do
439
- it 'yields the output' do
440
- container = described_class.create(
441
- 'Cmd' => %w[cat],
442
- 'Image' => 'debian:wheezy',
443
- 'OpenStdin' => true,
444
- 'StdinOnce' => true
445
- )
446
- chunk = nil
447
- container
448
- .tap(&:start)
449
- .attach(stdin: StringIO.new("foo\nbar\n")) do |stream, c|
450
- chunk ||= c
451
- end
452
- container.tap(&:wait).remove
453
-
454
- expect(chunk).to eq("foo\nbar\n")
455
- end
456
- end
457
-
458
- describe '#start' do
459
- subject {
460
- described_class.create(
461
- 'Cmd' => %w[test -d /foo],
462
- 'Image' => 'debian:wheezy',
463
- 'Volumes' => {'/foo' => {}}
464
- )
465
- }
466
- let(:all) { Docker::Container.all(all: true) }
467
-
468
- before { subject.start('Binds' => ["/tmp:/foo"]) }
469
- after(:each) { subject.remove }
470
-
471
- it 'starts the container' do
472
- expect(all.map(&:id)).to be_any { |id| id.start_with?(subject.id) }
473
- expect(subject.wait(10)['StatusCode']).to be_zero
474
- end
475
- end
476
-
477
- describe '#stop' do
478
- subject {
479
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
480
- }
481
-
482
- before { subject.tap(&:start).stop('timeout' => '10') }
483
- after { subject.remove }
484
-
485
- it 'stops the container' do
486
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
487
- id.start_with?(subject.id)
488
- }
489
- expect(described_class.all.map(&:id)).to be_none { |id|
490
- id.start_with?(subject.id)
491
- }
492
- end
493
- end
494
-
495
- describe '#exec' do
496
- subject {
497
- described_class.create(
498
- 'Cmd' => %w[sleep 20],
499
- 'Image' => 'debian:wheezy'
500
- ).start
501
- }
502
- after { subject.kill!.remove }
503
-
504
- context 'when passed only a command' do
505
- let(:output) { subject.exec(['bash','-c','sleep 2; echo hello']) }
506
-
507
- it 'returns the stdout/stderr messages and exit code' do
508
- expect(output).to eq([["hello\n"], [], 0])
509
- end
510
- end
511
-
512
- context 'when detach is true' do
513
- let(:output) { subject.exec(['date'], detach: true) }
514
-
515
- it 'returns the Docker::Exec object' do
516
- expect(output).to be_a Docker::Exec
517
- expect(output.id).to_not be_nil
518
- end
519
- end
520
-
521
- context 'when passed a block' do
522
- it 'streams the stdout/stderr messages' do
523
- chunk = nil
524
- subject.exec(['bash','-c','sleep 2; echo hello']) do |stream, c|
525
- chunk ||= c
526
- end
527
- expect(chunk).to eq("hello\n")
528
- end
529
- end
530
-
531
- context 'when stdin object is passed' do
532
- let(:output) { subject.exec(['cat'], stdin: StringIO.new("hello")) }
533
-
534
- it 'returns the stdout/stderr messages' do
535
- expect(output).to eq([["hello"],[],0])
536
- end
537
- end
538
-
539
- context 'when tty is true' do
540
- let(:command) { [
541
- "bash", "-c",
542
- "if [ -t 1 ]; then echo -n \"I'm a TTY!\"; fi"
543
- ] }
544
- let(:output) { subject.exec(command, tty: true) }
545
-
546
- it 'returns the raw stdout/stderr output' do
547
- expect(output).to eq([["I'm a TTY!"], [], 0])
548
- end
549
- end
550
- end
551
-
552
- describe '#kill' do
553
- let(:command) { ['/bin/bash', '-c', 'while [ 1 ]; do echo hello; done'] }
554
- subject {
555
- described_class.create('Cmd' => command, 'Image' => 'debian:wheezy')
556
- }
557
-
558
- before { subject.start }
559
- after(:each) {subject.remove }
560
-
561
- it 'kills the container' do
562
- subject.kill
563
- expect(described_class.all.map(&:id)).to be_none { |id|
564
- id.start_with?(subject.id)
565
- }
566
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
567
- id.start_with?(subject.id)
568
- }
569
- end
570
-
571
- context 'with a kill signal' do
572
- let(:command) {
573
- [
574
- '/bin/bash',
575
- '-c',
576
- 'trap echo SIGTERM; while [ 1 ]; do echo hello; done'
577
- ]
578
- }
579
- it 'kills the container' do
580
- subject.kill(:signal => "SIGTERM")
581
- expect(described_class.all.map(&:id)).to be_any { |id|
582
- id.start_with?(subject.id)
583
- }
584
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
585
- id.start_with?(subject.id)
586
- }
587
-
588
- subject.kill(:signal => "SIGKILL")
589
- expect(described_class.all.map(&:id)).to be_none { |id|
590
- id.start_with?(subject.id)
591
- }
592
- expect(described_class.all(:all => true).map(&:id)).to be_any { |id|
593
- id.start_with?(subject.id)
594
- }
595
- end
596
- end
597
- end
598
-
599
- describe '#delete' do
600
- subject {
601
- described_class.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
602
- }
603
-
604
- it 'deletes the container' do
605
- subject.delete(:force => true)
606
- expect(described_class.all.map(&:id)).to be_none { |id|
607
- id.start_with?(subject.id)
608
- }
609
- end
610
- end
611
-
612
- describe '#restart' do
613
- subject {
614
- described_class.create('Cmd' => %w[sleep 10], 'Image' => 'debian:wheezy')
615
- }
616
-
617
- before { subject.start }
618
- after { subject.kill!.remove }
619
-
620
- it 'restarts the container' do
621
- expect(described_class.all.map(&:id)).to be_any { |id|
622
- id.start_with?(subject.id)
623
- }
624
- subject.stop
625
- expect(described_class.all.map(&:id)).to be_none { |id|
626
- id.start_with?(subject.id)
627
- }
628
- subject.restart('timeout' => '10')
629
- expect(described_class.all.map(&:id)).to be_any { |id|
630
- id.start_with?(subject.id)
631
- }
632
- end
633
- end
634
-
635
- describe '#pause' do
636
- subject {
637
- described_class.create(
638
- 'Cmd' => %w[sleep 50],
639
- 'Image' => 'debian:wheezy'
640
- ).start
641
- }
642
- after { subject.unpause.kill!.remove }
643
-
644
- it 'pauses the container' do
645
- subject.pause
646
- expect(described_class.get(subject.id).info['State']['Paused']).to be true
647
- end
648
- end
649
-
650
- describe '#unpause' do
651
- subject {
652
- described_class.create(
653
- 'Cmd' => %w[sleep 50],
654
- 'Image' => 'debian:wheezy'
655
- ).start
656
- }
657
- before { subject.pause }
658
- after { subject.kill!.remove }
659
-
660
- it 'unpauses the container' do
661
- subject.unpause
662
- expect(
663
- described_class.get(subject.id).info['State']['Paused']
664
- ).to be false
665
- end
666
- end
667
-
668
- describe '#wait' do
669
- subject {
670
- described_class.create(
671
- 'Cmd' => %w[tar nonsense],
672
- 'Image' => 'debian:wheezy'
673
- )
674
- }
675
-
676
- before { subject.start }
677
- after(:each) { subject.remove }
678
-
679
- it 'waits for the command to finish' do
680
- expect(subject.wait['StatusCode']).to_not be_zero
681
- end
682
-
683
- context 'when an argument is given' do
684
- subject { described_class.create('Cmd' => %w[sleep 5],
685
- 'Image' => 'debian:wheezy') }
686
-
687
- it 'sets the :read_timeout to that amount of time' do
688
- expect(subject.wait(6)['StatusCode']).to be_zero
689
- end
690
-
691
- context 'and a command runs for too long' do
692
- it 'raises a ServerError' do
693
- expect{subject.wait(4)}.to raise_error(Docker::Error::TimeoutError)
694
- subject.tap(&:wait)
695
- end
696
- end
697
- end
698
- end
699
-
700
- describe '#run' do
701
- let(:run_command) { subject.run('ls') }
702
-
703
- context 'when the Container\'s command does not return status code of 0' do
704
- subject { described_class.create('Cmd' => %w[false],
705
- 'Image' => 'debian:wheezy') }
706
-
707
- after do
708
- subject.remove
709
- end
710
-
711
- it 'raises an error' do
712
- expect { run_command }
713
- .to raise_error(Docker::Error::UnexpectedResponseError)
714
- end
715
- end
716
-
717
- context 'when the Container\'s command returns a status code of 0' do
718
- subject { described_class.create('Cmd' => %w[pwd],
719
- 'Image' => 'debian:wheezy') }
720
- after do
721
- subject.remove
722
- image = run_command.json['Image']
723
- run_command.remove
724
- Docker::Image.get(image).history.each do |layer|
725
- next unless layer['CreatedBy'] == 'pwd'
726
- Docker::Image.get(layer['Id']).remove(:noprune => true)
727
- end
728
- end
729
-
730
- it 'creates a new container to run the specified command' do
731
- expect(run_command.wait['StatusCode']).to be_zero
732
- end
733
- end
734
- end
735
-
736
- describe '#commit' do
737
- subject {
738
- described_class.create('Cmd' => %w[true], 'Image' => 'debian:wheezy')
739
- }
740
- let(:image) { subject.commit }
741
-
742
- after(:each) do
743
- subject.remove
744
- image.remove
745
- end
746
-
747
- it 'creates a new Image from the Container\'s changes' do
748
- subject.tap(&:start).wait
749
-
750
- expect(image).to be_a Docker::Image
751
- expect(image.id).to_not be_nil
752
- end
753
-
754
- context 'if run is passed, it saves the command in the image' do
755
- let(:image) { subject.commit }
756
- let(:container) { image.run('pwd') }
757
-
758
- it 'saves the command' do
759
- container.wait
760
- expect(container.attach(logs: true, stream: false)).to eql [["/\n"],[]]
761
- container.remove
762
- end
763
- end
764
- end
765
-
766
- describe '.create' do
767
- subject { described_class }
768
-
769
- context 'when the Container does not yet exist' do
770
- context 'when the HTTP request does not return a 200' do
771
- before do
772
- Docker.options = { :mock => true }
773
- Excon.stub({ :method => :post }, { :status => 400 })
774
- end
775
- after do
776
- Excon.stubs.shift
777
- Docker.options = {}
778
- end
779
-
780
- it 'raises an error' do
781
- expect { subject.create }.to raise_error(Docker::Error::ClientError)
782
- end
783
- end
784
-
785
- context 'when the HTTP request returns a 200' do
786
- let(:options) do
787
- {
788
- "Cmd" => ["date"],
789
- "Image" => "debian:wheezy",
790
- }
791
- end
792
- let(:container) { subject.create(options) }
793
- after { container.remove }
794
-
795
- it 'sets the id' do
796
- expect(container).to be_a Docker::Container
797
- expect(container.id).to_not be_nil
798
- expect(container.connection).to_not be_nil
799
- end
800
- end
801
- end
802
- end
803
-
804
- describe '.get' do
805
- subject { described_class }
806
-
807
- context 'when the HTTP response is not a 200' do
808
- before do
809
- Docker.options = { :mock => true }
810
- Excon.stub({ :method => :get }, { :status => 500 })
811
- end
812
- after do
813
- Excon.stubs.shift
814
- Docker.options = {}
815
- end
816
-
817
- it 'raises an error' do
818
- expect { subject.get('randomID') }
819
- .to raise_error(Docker::Error::ServerError)
820
- end
821
- end
822
-
823
- context 'when the HTTP response is a 200' do
824
- let(:container) {
825
- subject.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
826
- }
827
- after { container.remove }
828
-
829
- it 'materializes the Container into a Docker::Container' do
830
- expect(subject.get(container.id)).to be_a Docker::Container
831
- end
832
- end
833
-
834
- end
835
-
836
- describe '.all' do
837
- subject { described_class }
838
-
839
- context 'when the HTTP response is not a 200' do
840
- before do
841
- Docker.options = { :mock => true }
842
- Excon.stub({ :method => :get }, { :status => 500 })
843
- end
844
- after do
845
- Excon.stubs.shift
846
- Docker.options = {}
847
- end
848
-
849
- it 'raises an error' do
850
- expect { subject.all }
851
- .to raise_error(Docker::Error::ServerError)
852
- end
853
- end
854
-
855
- context 'when the HTTP response is a 200' do
856
- let(:container) {
857
- subject.create('Cmd' => ['ls'], 'Image' => 'debian:wheezy')
858
- }
859
- before { container }
860
- after { container.remove }
861
-
862
- it 'materializes each Container into a Docker::Container' do
863
- expect(subject.all(:all => true)).to be_all { |container|
864
- container.is_a?(Docker::Container)
865
- }
866
- expect(subject.all(:all => true).length).to_not be_zero
867
- end
868
- end
869
- end
870
- end