docker-api 1.24.1 → 1.25.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4eb0ec248a62d64d52b5e1d49ef35658ff87dd2f
4
- data.tar.gz: 508bd10f526845a4fef711128bbe0f4dcfc9cb7a
3
+ metadata.gz: 51ab297af71a35ec5bec2a56f102f2257dbd473a
4
+ data.tar.gz: 390dabb2d80beacd900b88ea4a9a7e6e687fae5d
5
5
  SHA512:
6
- metadata.gz: dc1552959429f61de607f5f16dac0430a4137347037e54bc48c6e0d9b0d0828e3d618cca3b35def203e93707884c734bd8a712f22e1e5370a0111f836924dd85
7
- data.tar.gz: 49dc4aa6bbf5bee5aed08e2e9ad1c349d34351682befc6142ed32c69ad7c3cc1f478b19d31ff56253e45145337b336ca06c88d3320959de3ec79ce971be6428b
6
+ metadata.gz: 74ec3e736efb4a8c4f962ee449710513887b0b8753b9484b91f418ce705d31817fdf34f09b873beea9f3b9ba3b6a64541faa103949ad6ebbd0fc28651a49ab8f
7
+ data.tar.gz: dc566c61d644bafefb390c18301c497b69c0fd2abf60a26992e8184c6751563b95df66d47a23d14f5b254e5872c4ad2ecb1e88ae4536ca846b07e975c151ee7b
@@ -1,6 +1,5 @@
1
1
  sudo: required
2
- services:
3
- - docker
2
+ dist: trusty
4
3
  cache: bundler
5
4
  language: ruby
6
5
  rvm:
@@ -8,3 +7,12 @@ rvm:
8
7
  - 2.0
9
8
  - 2.1
10
9
  - 2.2
10
+ env:
11
+ - DOCKER_VERSION=1.6.2
12
+ - DOCKER_VERSION=1.7.1
13
+ - DOCKER_VERSION=1.8.3
14
+ - DOCKER_VERSION=1.9.1
15
+ before_install: ./script/install_dependencies.sh
16
+ before_script:
17
+ - export PATH=/opt/docker:$PATH
18
+ - docker version
data/README.md CHANGED
@@ -119,7 +119,7 @@ Docker.authenticate!('username' => 'docker-fan-boi', 'password' => 'i<3docker',
119
119
 
120
120
  ## Images
121
121
 
122
- Just about every method here has a one-to-one mapping with the [Images](https://docs.docker.com/reference/api/docker_remote_api_v1.12/#22-images) section of the API. If an API call accepts query parameters, these can be passed as an Hash to it's corresponding method. Also, note that `Docker::Image.new` is a private method, so you must use `.create`, `.build`, `.build_from_dir`, `build_from_tar`, or `.import` to make an instance.
122
+ Just about every method here has a one-to-one mapping with the [Images](https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#2-2-images) section of the API. If an API call accepts query parameters, these can be passed as an Hash to it's corresponding method. Also, note that `Docker::Image.new` is a private method, so you must use `.create`, `.build`, `.build_from_dir`, `build_from_tar`, or `.import` to make an instance.
123
123
 
124
124
  ```ruby
125
125
  require 'docker'
@@ -255,7 +255,7 @@ Docker::Image.search('term' => 'sshd')
255
255
 
256
256
  ## Containers
257
257
 
258
- Much like the Images, this object also has a one-to-one mapping with the [Containers](https://docs.docker.com/reference/api/docker_remote_api_v1.12/#21-containers) section of the API. Also like Images, `.new` is a private method, so you must use `.create` to make an instance.
258
+ Much like the Images, this object also has a one-to-one mapping with the [Containers](https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#2-1-containers) section of the API. Also like Images, `.new` is a private method, so you must use `.create` to make an instance.
259
259
 
260
260
  ```ruby
261
261
  require 'docker'
@@ -488,8 +488,8 @@ end
488
488
 
489
489
  ## Not supported (yet)
490
490
 
491
- * Generating a tarball of images and metadata for a repository specified by a name: https://docs.docker.com/reference/api/docker_remote_api_v1.12/#get-a-tarball-containing-all-images-and-tags-in-a-repository
492
- * Load a tarball generated from docker that contains all the images and metadata of a repository: https://docs.docker.com/reference/api/docker_remote_api_v1.12/#load-a-tarball-with-a-set-of-images-and-tags-into-docker
491
+ * Generating a tarball of images and metadata for a repository specified by a name: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#get-a-tarball-containing-all-images-and-tags-in-a-repository
492
+ * Load a tarball generated from docker that contains all the images and metadata of a repository: https://docs.docker.com/engine/reference/api/docker_remote_api_v1.14/#load-a-tarball-with-a-set-of-images-and-tags-into-docker
493
493
 
494
494
  License
495
495
  -----
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ ENV['PATH'] = "/opt/docker/:#{ENV['PATH']}" if ENV['CI'] == 'true'
2
3
 
3
4
  require 'rake'
4
5
  require 'docker'
@@ -23,6 +23,7 @@ module Docker
23
23
  require 'docker/connection'
24
24
  require 'docker/base'
25
25
  require 'docker/container'
26
+ require 'docker/network'
26
27
  require 'docker/event'
27
28
  require 'docker/exec'
28
29
  require 'docker/image'
@@ -238,6 +238,37 @@ class Docker::Container
238
238
  self
239
239
  end
240
240
 
241
+ def archive_out(path, &block)
242
+ connection.get(
243
+ path_for(:archive),
244
+ { 'path' => path },
245
+ :response_block => block
246
+ )
247
+ self
248
+ end
249
+
250
+ def archive_in(inputs, output_path, opts = {})
251
+ file_hash = Docker::Util.file_hash_from_paths([*inputs])
252
+ tar = StringIO.new(Docker::Util.create_tar(file_hash))
253
+ archive_in_stream(output_path, opts) do
254
+ tar.read(Excon.defaults[:chunk_size]).to_s
255
+ end
256
+ end
257
+
258
+ def archive_in_stream(output_path, opts = {}, &block)
259
+ overwrite = opts[:overwrite] || opts['overwrite'] || false
260
+
261
+ connection.put(
262
+ path_for(:archive),
263
+ { 'path' => output_path, 'noOverwriteDirNonDir' => !overwrite },
264
+ :headers => {
265
+ 'Content-Type' => 'application/x-tar'
266
+ },
267
+ &block
268
+ )
269
+ self
270
+ end
271
+
241
272
  # Create a new Container.
242
273
  def self.create(opts = {}, conn = Docker.connection)
243
274
  name = opts.delete('name')
@@ -0,0 +1,78 @@
1
+ # This class represents a Docker Network.
2
+ class Docker::Network
3
+ include Docker::Base
4
+
5
+ def connect(container, opts = {})
6
+ Docker::Util.parse_json(
7
+ connection.post(path_for('connect'), opts,
8
+ body: { container: container }.to_json)
9
+ )
10
+ reload
11
+ end
12
+
13
+ def disconnect(container, opts = {})
14
+ Docker::Util.parse_json(
15
+ connection.post(path_for('disconnect'), opts,
16
+ body: { container: container }.to_json)
17
+ )
18
+ reload
19
+ end
20
+
21
+ def remove(opts = {})
22
+ connection.delete(path_for, opts)
23
+ nil
24
+ end
25
+ alias_method :delete, :remove
26
+
27
+ def json(opts = {})
28
+ Docker::Util.parse_json(connection.get(path_for, opts))
29
+ end
30
+
31
+ def to_s
32
+ "Docker::Network { :id => #{id}, :info => #{info.inspect}, "\
33
+ ":connection => #{connection} }"
34
+ end
35
+
36
+ def reload
37
+ network_json = @connection.get("/networks/#{URI.encode(@id)}")
38
+ hash = Docker::Util.parse_json(network_json) || {}
39
+ @info = hash
40
+ end
41
+
42
+ class << self
43
+ def create(name, opts = {}, conn = Docker.connection)
44
+ default_opts = {
45
+ 'Name' => name,
46
+ 'CheckDuplicate' => true
47
+ }
48
+ resp = conn.post('/networks/create', {},
49
+ body: default_opts.merge(opts).to_json)
50
+ response_hash = Docker::Util.parse_json(resp) || {}
51
+ get(response_hash['Id']) || {}
52
+ end
53
+
54
+ def get(id, opts = {}, conn = Docker.connection)
55
+ network_json = conn.get("/networks/#{URI.encode(id)}", opts)
56
+ hash = Docker::Util.parse_json(network_json) || {}
57
+ new(conn, hash)
58
+ end
59
+
60
+ def all(opts = {}, conn = Docker.connection)
61
+ hashes = Docker::Util.parse_json(conn.get('/networks', opts)) || []
62
+ hashes.map { |hash| new(conn, hash) }
63
+ end
64
+
65
+ def remove(id, opts = {}, conn = Docker.connection)
66
+ conn.delete("/networks/#{URI.encode(id)}", opts)
67
+ nil
68
+ end
69
+ alias_method :delete, :remove
70
+ end
71
+
72
+ # Convenience method to return the path for a particular resource.
73
+ def path_for(resource = nil)
74
+ ["/networks/#{id}", resource].compact.join('/')
75
+ end
76
+
77
+ private :path_for
78
+ end
@@ -1,6 +1,6 @@
1
1
  module Docker
2
2
  # The version of the docker-api gem.
3
- VERSION = '1.24.1'
3
+ VERSION = '1.25.0'
4
4
 
5
5
  # The version of the compatible Docker remote API.
6
6
  API_VERSION = '1.16'
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Update bundler
5
+ gem install bundler
6
+
7
+ # Install docker
8
+ sudo mkdir -p /opt/docker
9
+ sudo curl -fo /opt/docker/docker "https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}"
10
+ sudo chmod +x /opt/docker/docker
11
+
12
+ running=0
13
+ for x in {1..3}
14
+ do
15
+ [[ $running != 1 ]] || break
16
+ sudo rm -rf /var/run/docker.pid
17
+ sudo /opt/docker/docker -d -D &
18
+ DOCKER_PID=$!
19
+ sleep 5
20
+ echo "Checking if docker is running"
21
+ ps -p $DOCKER_PID && running=1 || echo "Couldn't start docker, retrying"
22
+ done
23
+ echo "Docker running, continuing"
@@ -131,11 +131,11 @@ describe Docker::Container do
131
131
  }
132
132
 
133
133
  before { subject.start }
134
- after(:each) { subject.kill!.remove }
134
+ after(:each) { subject.tap(&:wait).remove }
135
135
 
136
136
  it 'renames the container' do
137
137
  subject.rename('bar')
138
- expect(subject.json["Name"]).to eq("/bar")
138
+ expect(subject.json["Name"]).to match(%r{bar})
139
139
  end
140
140
  end
141
141
 
@@ -212,6 +212,105 @@ describe Docker::Container do
212
212
  end
213
213
  end
214
214
 
215
+ describe '#archive_in', :docker_1_8 do
216
+ let(:license_path) { File.absolute_path(File.join(__FILE__, '..', '..', '..', 'LICENSE')) }
217
+ subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
218
+ let(:committed_image) { subject.commit }
219
+ let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
220
+ let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
221
+
222
+ after do
223
+ subject.remove
224
+ end
225
+
226
+ context 'when the input is a tar' do
227
+ after do
228
+ ls_container.remove
229
+ committed_image.remove
230
+ end
231
+
232
+ it 'file exists in the container' do
233
+ subject.archive_in(license_path, '/', overwrite: false)
234
+ expect(output).to include('LICENSE')
235
+ end
236
+ end
237
+ end
238
+
239
+ describe '#archive_in_stream', :docker_1_8 do
240
+ let(:tar) { StringIO.new(Docker::Util.create_tar('/lol' => 'TEST')) }
241
+ subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['/bin/sh']) }
242
+ let(:committed_image) { subject.commit }
243
+ let(:ls_container) { committed_image.run('ls /').tap(&:wait) }
244
+ let(:output) { ls_container.streaming_logs(stdout: true, stderr: true) }
245
+
246
+ after do
247
+ subject.remove
248
+ end
249
+
250
+ context 'when the input is a tar' do
251
+ after do
252
+ ls_container.remove
253
+ committed_image.remove
254
+ end
255
+
256
+ it 'file exists in the container' do
257
+ subject.archive_in_stream('/', overwrite: false) { tar.read }
258
+ expect(output).to include('lol')
259
+ end
260
+ end
261
+
262
+ context 'when the input would overwrite a directory with a file' do
263
+ let(:tar) { StringIO.new(Docker::Util.create_tar('/etc' => 'TEST')) }
264
+
265
+ it 'raises an error' do
266
+ # Docs say this should return a client error: clearly wrong
267
+ # https://docs.docker.com/engine/reference/api/docker_remote_api_v1.21/
268
+ # #extract-an-archive-of-files-or-folders-to-a-directory-in-a-container
269
+ expect {
270
+ subject.archive_in_stream('/', overwrite: false) { tar.read }
271
+ }.to raise_error(Docker::Error::ServerError)
272
+ end
273
+ end
274
+ end
275
+
276
+ describe '#archive_out', :docker_1_8 do
277
+ subject { Docker::Container.create('Image' => 'debian:wheezy', 'Cmd' => ['touch','/test']) }
278
+
279
+ after { subject.remove }
280
+
281
+ context 'when the file does not exist' do
282
+ it 'raises an error' do
283
+ subject.start
284
+ subject.wait
285
+
286
+ expect { subject.archive_out('/lol') { |chunk| puts chunk } }
287
+ .to raise_error(Docker::Error::NotFoundError)
288
+ end
289
+ end
290
+
291
+ context 'when the input is a file' do
292
+ it 'yields each chunk of the tarred file' do
293
+ subject.start; subject.wait
294
+
295
+ chunks = []
296
+ subject.archive_out('/test') { |chunk| chunks << chunk }
297
+ chunks = chunks.join("\n")
298
+ expect(chunks).to be_include('test')
299
+ end
300
+ end
301
+
302
+ context 'when the input is a directory' do
303
+ it 'yields each chunk of the tarred directory' do
304
+ subject.start; subject.wait
305
+
306
+ chunks = []
307
+ subject.archive_out('/etc/logrotate.d') { |chunk| chunks << chunk }
308
+ chunks = chunks.join("\n")
309
+ expect(%w[apt dpkg]).to be_all { |file| chunks.include?(file) }
310
+ end
311
+ end
312
+ end
313
+
215
314
  describe '#export' do
216
315
  subject { described_class.create('Cmd' => %w[/true],
217
316
  'Image' => 'tianon/true') }
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe Docker::Network, docker_1_9: true do
4
+ let(:name) do |example|
5
+ example.description.downcase.gsub('\s', '-')
6
+ end
7
+
8
+ describe '#to_s' do
9
+ subject { described_class.new(Docker.connection, info) }
10
+ let(:connection) { Docker.connection }
11
+
12
+ let(:id) do
13
+ 'a6c5ffd25e07a6c906accf804174b5eb6a9d2f9e07bccb8f5aa4f4de5be6d01d'
14
+ end
15
+
16
+ let(:info) do
17
+ {
18
+ 'Name' => 'bridge',
19
+ 'Scope' => 'local',
20
+ 'Driver' => 'bridge',
21
+ 'IPAM' => {
22
+ 'Driver' => 'default',
23
+ 'Config' => [{ 'Subnet' => '172.17.0.0/16' }]
24
+ },
25
+ 'Containers' => {},
26
+ 'Options' => {
27
+ 'com.docker.network.bridge.default_bridge' => 'true',
28
+ 'com.docker.network.bridge.enable_icc' => 'true',
29
+ 'com.docker.network.bridge.enable_ip_masquerade' => 'true',
30
+ 'com.docker.network.bridge.host_binding_ipv4' => '0.0.0.0',
31
+ 'com.docker.network.bridge.name' => 'docker0',
32
+ 'com.docker.network.driver.mtu' => '1500'
33
+ },
34
+ 'id' => id
35
+ }
36
+ end
37
+
38
+ let(:expected_string) do
39
+ "Docker::Network { :id => #{id}, :info => #{info.inspect}, "\
40
+ ":connection => #{connection} }"
41
+ end
42
+
43
+ its(:to_s) { should == expected_string }
44
+ end
45
+
46
+ describe '.create' do
47
+ let!(:id) { subject.id }
48
+ subject { described_class.create(name) }
49
+ after { described_class.remove(id) }
50
+
51
+ it 'creates a Network' do
52
+ expect(Docker::Network.all.map(&:id)).to include(id)
53
+ end
54
+ end
55
+
56
+ describe '.remove' do
57
+ let(:id) { subject.id }
58
+ subject { described_class.create(name) }
59
+
60
+ it 'removes the Network' do
61
+ described_class.remove(id)
62
+ expect(Docker::Network.all.map(&:id)).to_not include(id)
63
+ end
64
+ end
65
+
66
+ describe '.get' do
67
+ after do
68
+ described_class.remove(name)
69
+ end
70
+
71
+ let!(:network) { described_class.create(name) }
72
+
73
+ it 'returns a network' do
74
+ expect(Docker::Network.get(name).id).to eq(network.id)
75
+ end
76
+ end
77
+
78
+ describe '.all' do
79
+ let!(:networks) do
80
+ 5.times.map { |i| described_class.create("#{name}-#{i}") }
81
+ end
82
+
83
+ after do
84
+ networks.each(&:remove)
85
+ end
86
+
87
+ it 'should return all networks' do
88
+ expect(Docker::Network.all.map(&:id)).to include(*networks.map(&:id))
89
+ end
90
+ end
91
+
92
+ describe '#connect' do
93
+ let!(:container) do
94
+ Docker::Container.create(
95
+ 'Cmd' => %w(sleep 10),
96
+ 'Image' => 'debian:wheezy'
97
+ )
98
+ end
99
+ subject { described_class.create(name) }
100
+
101
+ before(:each) { container.start }
102
+ after(:each) do
103
+ container.kill!.remove
104
+ subject.remove
105
+ end
106
+
107
+ it 'connects a container to a network' do
108
+ subject.connect(container.id)
109
+ expect(subject.info['Containers']).to include(container.id)
110
+ end
111
+ end
112
+
113
+ describe '#disconnect' do
114
+ let!(:container) do
115
+ Docker::Container.create(
116
+ 'Cmd' => %w(sleep 10),
117
+ 'Image' => 'debian:wheezy'
118
+ )
119
+ end
120
+
121
+ subject { described_class.create(name) }
122
+
123
+ before(:each) do
124
+ container.start
125
+ sleep 1
126
+ subject.connect(container.id)
127
+ end
128
+
129
+ after(:each) do
130
+ container.kill!.remove
131
+ subject.remove
132
+ end
133
+
134
+ it 'connects a container to a network' do
135
+ subject.disconnect(container.id)
136
+ expect(subject.info['Containers']).not_to include(container.id)
137
+ end
138
+ end
139
+
140
+ describe '#remove' do
141
+ let(:id) { subject.id }
142
+ let(:name) { 'test-network-remove' }
143
+ subject { described_class.create(name) }
144
+
145
+ it 'removes the Network' do
146
+ subject.remove
147
+ expect(Docker::Network.all.map(&:id)).to_not include(id)
148
+ end
149
+ end
150
+ end
@@ -22,4 +22,15 @@ RSpec.configure do |config|
22
22
  config.color = true
23
23
  config.formatter = :documentation
24
24
  config.tty = true
25
+
26
+ case ENV['DOCKER_VERSION']
27
+ when /1\.6/
28
+ config.filter_run_excluding :docker_1_8 => true
29
+ config.filter_run_excluding :docker_1_9 => true
30
+ when /1\.7/
31
+ config.filter_run_excluding :docker_1_8 => true
32
+ config.filter_run_excluding :docker_1_9 => true
33
+ when /1\.8/
34
+ config.filter_run_excluding :docker_1_9 => true
35
+ end
25
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.24.1
4
+ version: 1.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swipely, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-07 00:00:00.000000000 Z
11
+ date: 2016-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: excon
@@ -182,10 +182,12 @@ files:
182
182
  - lib/docker/image.rb
183
183
  - lib/docker/messages.rb
184
184
  - lib/docker/messages_stack.rb
185
+ - lib/docker/network.rb
185
186
  - lib/docker/rake_task.rb
186
187
  - lib/docker/util.rb
187
188
  - lib/docker/version.rb
188
189
  - lib/excon/middlewares/hijack.rb
190
+ - script/install_dependencies.sh
189
191
  - spec/docker/connection_spec.rb
190
192
  - spec/docker/container_spec.rb
191
193
  - spec/docker/event_spec.rb
@@ -193,6 +195,7 @@ files:
193
195
  - spec/docker/image_spec.rb
194
196
  - spec/docker/messages_spec.rb
195
197
  - spec/docker/messages_stack.rb
198
+ - spec/docker/network_spec.rb
196
199
  - spec/docker/util_spec.rb
197
200
  - spec/docker_spec.rb
198
201
  - spec/fixtures/build_from_dir/Dockerfile
@@ -219,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
222
  version: '0'
220
223
  requirements: []
221
224
  rubyforge_project:
222
- rubygems_version: 2.2.2
225
+ rubygems_version: 2.4.5
223
226
  signing_key:
224
227
  specification_version: 4
225
228
  summary: A simple REST client for the Docker Remote API
@@ -231,10 +234,10 @@ test_files:
231
234
  - spec/docker/image_spec.rb
232
235
  - spec/docker/messages_spec.rb
233
236
  - spec/docker/messages_stack.rb
237
+ - spec/docker/network_spec.rb
234
238
  - spec/docker/util_spec.rb
235
239
  - spec/docker_spec.rb
236
240
  - spec/fixtures/build_from_dir/Dockerfile
237
241
  - spec/fixtures/export.tar
238
242
  - spec/fixtures/top/Dockerfile
239
243
  - spec/spec_helper.rb
240
- has_rdoc: