docker-api 1.24.1 → 1.25.0

Sign up to get free protection for your applications and to get access to all the features.
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: