docker-api 1.1.2 → 1.2.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.
data/README.md CHANGED
@@ -120,7 +120,7 @@ Docker::Image.build("from base\nrun touch /test")
120
120
  # => Docker::Image { :id => b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
121
121
 
122
122
  # Create an Image from a Dockerfile.
123
- Dockerfile::Image.build_from_dir('.')
123
+ Docker::Image.build_from_dir('.')
124
124
  # => Docker::Image { :id => 1266dc19e, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
125
125
 
126
126
  # Load all Images on your Docker server.
@@ -183,10 +183,20 @@ container.wait(15)
183
183
  container.attach(:stream => true, :stdout => true, :stderr => true, :logs => true)
184
184
  # => "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nselinux\nsrv\nsys\ntmp\nusr\nvar"
185
185
 
186
+ # If you wish to stream the attach method, a block may be supplied.
187
+ container = Docker::Container.create('Image' => 'base', 'Cmd' => %[find / -name *])
188
+ container.tap(&:start).attach { |chunk| puts chunk }
189
+ # => nil
190
+
186
191
  # Create an Image from a Container's changes.
187
192
  container.commit
188
193
  # => Docker::Image { :id => eaeb8d00efdf, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
189
194
 
195
+ # Commit the Container and run a new command. The second argument is the number
196
+ # of seconds the Container should wait before stopping its current command.
197
+ container.run('pwd', 10)
198
+ # => Docker::Image { :id => 4427be4199ac, :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }
199
+
190
200
  # Request all of the Containers. By default, will only return the running Containers.
191
201
  Docker::Container.all(:all => true)
192
202
  # => [Docker::Container { :id => , :connection => Docker::Connection { :url => http://localhost, :options => {:port=>4243} } }]
data/lib/docker.rb CHANGED
@@ -40,12 +40,12 @@ module Docker
40
40
 
41
41
  # Get the version of Go, Docker, and optionally the Git commit.
42
42
  def version
43
- Util.parse_json(connection.request(:get, '/version'))
43
+ Util.parse_json(connection.get('/version'))
44
44
  end
45
45
 
46
46
  # Get more information about the Docker server.
47
47
  def info
48
- Util.parse_json(connection.request(:get, '/info'))
48
+ Util.parse_json(connection.get('/info'))
49
49
  end
50
50
 
51
51
  # Login to the Docker registry.
@@ -25,12 +25,32 @@ class Docker::Container
25
25
  # Restart the Container
26
26
  request :post, :restart
27
27
 
28
+ # For each method, `m`, define a method called `m?` that attempts the method,
29
+ # but catches all Server errors.
30
+ [:stop, :start, :kill, :restart].each do |method|
31
+ define_method :"#{method}?" do |*args|
32
+ begin; public_send(method, *args); rescue ServerError; end
33
+ end
34
+ end
35
+
28
36
  # Wait for the current command to finish executing.
29
37
  def wait(time = 60)
30
38
  resp = connection.post("/containers/#{id}/wait", nil, :read_timeout => time)
31
39
  Docker::Util.parse_json(resp)
32
40
  end
33
41
 
42
+ # Given a command and an optional number of seconds to wait for the currently
43
+ # executing command, creates a new Container to run the specified command. If
44
+ # the command that is currently executing does not return a 0 status code, an
45
+ # UnexpectedResponseError is raised.
46
+ def run(cmd, time = 1000)
47
+ if (code = tap(&:start?).wait(time)['StatusCode']).zero?
48
+ commit.run(cmd).tap(&:start?)
49
+ else
50
+ raise UnexpectedResponseError, "Command returned status code #{code}."
51
+ end
52
+ end
53
+
34
54
  # Export the Container as a tar.
35
55
  def export(&block)
36
56
  connection.get("/containers/#{id}/export", nil, :response_block => block)
@@ -38,15 +58,16 @@ class Docker::Container
38
58
  end
39
59
 
40
60
  # Attach to a container's standard streams / logs.
41
- def attach(options = {})
61
+ def attach(options = {}, &block)
42
62
  options = { :stream => true, :stdout => true }.merge(options)
43
- connection.post("/containers/#{id}/attach", options)
63
+ connection.post("/containers/#{id}/attach", options,
64
+ :response_block => block)
44
65
  end
45
66
 
46
67
  # Create an Image from a Container's change.s
47
68
  def commit(options = {})
48
69
  options.merge!('container' => self.id[0..7])
49
- hash = JSON.parse(connection.request(:post, '/commit', options))
70
+ hash = Docker::Util.parse_json(connection.post('/commit', options))
50
71
  Docker::Image.send(:new, :id => hash['Id'], :connection => self.connection)
51
72
  end
52
73
  end
data/lib/docker/image.rb CHANGED
@@ -47,7 +47,7 @@ class Docker::Image
47
47
 
48
48
  # Remove the Image from the server.
49
49
  def remove
50
- connection.request(:delete, "/images/#{self.id}", nil)
50
+ connection.delete("/images/#{self.id}")
51
51
  end
52
52
 
53
53
  class << self
@@ -56,7 +56,7 @@ class Docker::Image
56
56
  # Given a query like `{ :term => 'sshd' }`, queries the Docker Registry for
57
57
  # a corresponiding Image.
58
58
  def search(query = {}, connection = Docker.connection)
59
- body = connection.request(:get, '/images/search', query)
59
+ body = connection.get('/images/search', query)
60
60
  hashes = Docker::Util.parse_json(body) || []
61
61
  hashes.map { |hash| new(:id => hash['Name'], :connection => connection) }
62
62
  end
@@ -106,7 +106,7 @@ class Docker::Image
106
106
  def create_tar(input)
107
107
  output = StringIO.new
108
108
  Gem::Package::TarWriter.new(output) do |tar|
109
- tar.add_file('Dockerfile', '640') { |tar_file| tar_file.write(input) }
109
+ tar.add_file('Dockerfile', 0640) { |tar_file| tar_file.write(input) }
110
110
  end
111
111
  output.tap(&:rewind)
112
112
  end
@@ -1,6 +1,6 @@
1
1
  module Docker
2
2
  # The version of the docker-api gem.
3
- VERSION = '1.1.2'
3
+ VERSION = '1.2.0'
4
4
 
5
5
  # The version of the compatible Docker remote API.
6
6
  API_VERSION = '1.3'
@@ -162,6 +162,28 @@ describe Docker::Container do
162
162
  end
163
163
  end
164
164
 
165
+ describe '#run' do
166
+ let(:run_command) { subject.run('ls') }
167
+ context 'when the Container\'s command does not return status code of 0' do
168
+ subject { described_class.create('Cmd' => %w[lol not a real command],
169
+ 'Image' => 'base') }
170
+
171
+ it 'raises an error', :vcr do
172
+ expect { run_command }
173
+ .to raise_error(Docker::Error::UnexpectedResponseError)
174
+ end
175
+ end
176
+
177
+ context 'when the Container\'s command returns a status code of 0' do
178
+ subject { described_class.create('Cmd' => %w[pwd],
179
+ 'Image' => 'base') }
180
+
181
+ it 'creates a new container to run the specified command', :vcr do
182
+ run_command.wait['StatusCode'].should be_zero
183
+ end
184
+ end
185
+ end
186
+
165
187
  describe '#commit' do
166
188
  subject { described_class.create('Cmd' => %w[true], 'Image' => 'base') }
167
189
  let(:image) { subject.commit }
@@ -0,0 +1,93 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:4243/v1.3/containers/create
6
+ body:
7
+ encoding: UTF-8
8
+ string: ! '{"Cmd":["lol","not","a","real","command"],"Image":"base"}'
9
+ headers:
10
+ Content-Type:
11
+ - text/plain
12
+ User-Agent:
13
+ - Docker-Client/0.4.6
14
+ response:
15
+ status:
16
+ code: 201
17
+ message: ''
18
+ headers:
19
+ !binary "Q29udGVudC1UeXBl":
20
+ - !binary |-
21
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
22
+ !binary "Q29udGVudC1MZW5ndGg=":
23
+ - !binary |-
24
+ MjE=
25
+ !binary "RGF0ZQ==":
26
+ - !binary |-
27
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
28
+ body:
29
+ encoding: US-ASCII
30
+ string: ! '{"Id":"054d9a6611f8"}'
31
+ http_version:
32
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
33
+ - request:
34
+ method: post
35
+ uri: http://localhost:4243/v1.3/containers/054d9a6611f8/start
36
+ body:
37
+ encoding: US-ASCII
38
+ string: ''
39
+ headers:
40
+ Content-Type:
41
+ - text/plain
42
+ User-Agent:
43
+ - Docker-Client/0.4.6
44
+ response:
45
+ status:
46
+ code: 204
47
+ message: ''
48
+ headers:
49
+ !binary "Q29udGVudC1UeXBl":
50
+ - !binary |-
51
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
52
+ !binary "Q29udGVudC1MZW5ndGg=":
53
+ - !binary |-
54
+ MA==
55
+ !binary "RGF0ZQ==":
56
+ - !binary |-
57
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
58
+ body:
59
+ encoding: US-ASCII
60
+ string: ''
61
+ http_version:
62
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
63
+ - request:
64
+ method: post
65
+ uri: http://localhost:4243/v1.3/containers/054d9a6611f8/wait
66
+ body:
67
+ encoding: US-ASCII
68
+ string: ''
69
+ headers:
70
+ Content-Type:
71
+ - text/plain
72
+ User-Agent:
73
+ - Docker-Client/0.4.6
74
+ response:
75
+ status:
76
+ code: 200
77
+ message: ''
78
+ headers:
79
+ !binary "Q29udGVudC1UeXBl":
80
+ - !binary |-
81
+ YXBwbGljYXRpb24vanNvbg==
82
+ !binary "Q29udGVudC1MZW5ndGg=":
83
+ - !binary |-
84
+ MTg=
85
+ !binary "RGF0ZQ==":
86
+ - !binary |-
87
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
88
+ body:
89
+ encoding: US-ASCII
90
+ string: ! '{"StatusCode":127}'
91
+ http_version:
92
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
93
+ recorded_with: VCR 2.5.0
@@ -0,0 +1,246 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:4243/v1.3/containers/create
6
+ body:
7
+ encoding: UTF-8
8
+ string: ! '{"Cmd":["pwd"],"Image":"base"}'
9
+ headers:
10
+ Content-Type:
11
+ - text/plain
12
+ User-Agent:
13
+ - Docker-Client/0.4.6
14
+ response:
15
+ status:
16
+ code: 201
17
+ message: ''
18
+ headers:
19
+ !binary "Q29udGVudC1UeXBl":
20
+ - !binary |-
21
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
22
+ !binary "Q29udGVudC1MZW5ndGg=":
23
+ - !binary |-
24
+ MjE=
25
+ !binary "RGF0ZQ==":
26
+ - !binary |-
27
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
28
+ body:
29
+ encoding: US-ASCII
30
+ string: ! '{"Id":"92e4950e0b05"}'
31
+ http_version:
32
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
33
+ - request:
34
+ method: post
35
+ uri: http://localhost:4243/v1.3/containers/92e4950e0b05/start
36
+ body:
37
+ encoding: US-ASCII
38
+ string: ''
39
+ headers:
40
+ Content-Type:
41
+ - text/plain
42
+ User-Agent:
43
+ - Docker-Client/0.4.6
44
+ response:
45
+ status:
46
+ code: 204
47
+ message: ''
48
+ headers:
49
+ !binary "Q29udGVudC1UeXBl":
50
+ - !binary |-
51
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
52
+ !binary "Q29udGVudC1MZW5ndGg=":
53
+ - !binary |-
54
+ MA==
55
+ !binary "RGF0ZQ==":
56
+ - !binary |-
57
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
58
+ body:
59
+ encoding: US-ASCII
60
+ string: ''
61
+ http_version:
62
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
63
+ - request:
64
+ method: post
65
+ uri: http://localhost:4243/v1.3/containers/92e4950e0b05/wait
66
+ body:
67
+ encoding: US-ASCII
68
+ string: ''
69
+ headers:
70
+ Content-Type:
71
+ - text/plain
72
+ User-Agent:
73
+ - Docker-Client/0.4.6
74
+ response:
75
+ status:
76
+ code: 200
77
+ message: ''
78
+ headers:
79
+ !binary "Q29udGVudC1UeXBl":
80
+ - !binary |-
81
+ YXBwbGljYXRpb24vanNvbg==
82
+ !binary "Q29udGVudC1MZW5ndGg=":
83
+ - !binary |-
84
+ MTY=
85
+ !binary "RGF0ZQ==":
86
+ - !binary |-
87
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
88
+ body:
89
+ encoding: US-ASCII
90
+ string: ! '{"StatusCode":0}'
91
+ http_version:
92
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
93
+ - request:
94
+ method: post
95
+ uri: http://localhost:4243/v1.3/commit?container=92e4950e
96
+ body:
97
+ encoding: US-ASCII
98
+ string: ''
99
+ headers:
100
+ Content-Type:
101
+ - text/plain
102
+ User-Agent:
103
+ - Docker-Client/0.4.6
104
+ response:
105
+ status:
106
+ code: 201
107
+ message: ''
108
+ headers:
109
+ !binary "Q29udGVudC1UeXBl":
110
+ - !binary |-
111
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
112
+ !binary "Q29udGVudC1MZW5ndGg=":
113
+ - !binary |-
114
+ MjE=
115
+ !binary "RGF0ZQ==":
116
+ - !binary |-
117
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
118
+ body:
119
+ encoding: US-ASCII
120
+ string: ! '{"Id":"6ae8d5f26636"}'
121
+ http_version:
122
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
123
+ - request:
124
+ method: post
125
+ uri: http://localhost:4243/v1.3/containers/create
126
+ body:
127
+ encoding: UTF-8
128
+ string: ! '{"Image":"6ae8d5f26636","Cmd":["ls"]}'
129
+ headers:
130
+ Content-Type:
131
+ - text/plain
132
+ User-Agent:
133
+ - Docker-Client/0.4.6
134
+ response:
135
+ status:
136
+ code: 201
137
+ message: ''
138
+ headers:
139
+ !binary "Q29udGVudC1UeXBl":
140
+ - !binary |-
141
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
142
+ !binary "Q29udGVudC1MZW5ndGg=":
143
+ - !binary |-
144
+ MjE=
145
+ !binary "RGF0ZQ==":
146
+ - !binary |-
147
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
148
+ body:
149
+ encoding: US-ASCII
150
+ string: ! '{"Id":"fd4be0998e51"}'
151
+ http_version:
152
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
153
+ - request:
154
+ method: post
155
+ uri: http://localhost:4243/v1.3/containers/fd4be0998e51/start
156
+ body:
157
+ encoding: US-ASCII
158
+ string: ''
159
+ headers:
160
+ Content-Type:
161
+ - text/plain
162
+ User-Agent:
163
+ - Docker-Client/0.4.6
164
+ response:
165
+ status:
166
+ code: 204
167
+ message: ''
168
+ headers:
169
+ !binary "Q29udGVudC1UeXBl":
170
+ - !binary |-
171
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
172
+ !binary "Q29udGVudC1MZW5ndGg=":
173
+ - !binary |-
174
+ MA==
175
+ !binary "RGF0ZQ==":
176
+ - !binary |-
177
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
178
+ body:
179
+ encoding: US-ASCII
180
+ string: ''
181
+ http_version:
182
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
183
+ - request:
184
+ method: post
185
+ uri: http://localhost:4243/v1.3/containers/fd4be0998e51/start
186
+ body:
187
+ encoding: US-ASCII
188
+ string: ''
189
+ headers:
190
+ Content-Type:
191
+ - text/plain
192
+ User-Agent:
193
+ - Docker-Client/0.4.6
194
+ response:
195
+ status:
196
+ code: 500
197
+ message: ''
198
+ headers:
199
+ !binary "Q29udGVudC1UeXBl":
200
+ - !binary |-
201
+ dGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA==
202
+ !binary "Q29udGVudC1MZW5ndGg=":
203
+ - !binary |-
204
+ MTM4
205
+ !binary "RGF0ZQ==":
206
+ - !binary |-
207
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxNyBHTVQ=
208
+ body:
209
+ encoding: US-ASCII
210
+ string: ! 'Error starting container fd4be0998e51: The container fd4be0998e511070f4c5d3ce6906210f758d900c56d88169dbe37f21a9fafed7
211
+ is already running.
212
+
213
+ '
214
+ http_version:
215
+ recorded_at: Fri, 28 Jun 2013 16:55:17 GMT
216
+ - request:
217
+ method: post
218
+ uri: http://localhost:4243/v1.3/containers/fd4be0998e51/wait
219
+ body:
220
+ encoding: US-ASCII
221
+ string: ''
222
+ headers:
223
+ Content-Type:
224
+ - text/plain
225
+ User-Agent:
226
+ - Docker-Client/0.4.6
227
+ response:
228
+ status:
229
+ code: 200
230
+ message: ''
231
+ headers:
232
+ !binary "Q29udGVudC1UeXBl":
233
+ - !binary |-
234
+ YXBwbGljYXRpb24vanNvbg==
235
+ !binary "Q29udGVudC1MZW5ndGg=":
236
+ - !binary |-
237
+ MTY=
238
+ !binary "RGF0ZQ==":
239
+ - !binary |-
240
+ RnJpLCAyOCBKdW4gMjAxMyAxNjo1NToxOCBHTVQ=
241
+ body:
242
+ encoding: US-ASCII
243
+ string: ! '{"StatusCode":0}'
244
+ http_version:
245
+ recorded_at: Fri, 28 Jun 2013 16:55:18 GMT
246
+ recorded_with: VCR 2.5.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-27 00:00:00.000000000 Z
12
+ date: 2013-07-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: excon
@@ -198,6 +198,8 @@ files:
198
198
  - spec/vcr/Docker_Container/_json/returns_the_description_as_a_Hash.yml
199
199
  - spec/vcr/Docker_Container/_kill/kills_the_container.yml
200
200
  - spec/vcr/Docker_Container/_restart/restarts_the_container.yml
201
+ - spec/vcr/Docker_Container/_run/when_the_Container_s_command_does_not_return_status_code_of_0/raises_an_error.yml
202
+ - spec/vcr/Docker_Container/_run/when_the_Container_s_command_returns_a_status_code_of_0/creates_a_new_container_to_run_the_specified_command.yml
201
203
  - spec/vcr/Docker_Container/_start/starts_the_container.yml
202
204
  - spec/vcr/Docker_Container/_stop/stops_the_container.yml
203
205
  - spec/vcr/Docker_Container/_wait/waits_for_the_command_to_finish.yml
@@ -262,6 +264,8 @@ test_files:
262
264
  - spec/vcr/Docker_Container/_json/returns_the_description_as_a_Hash.yml
263
265
  - spec/vcr/Docker_Container/_kill/kills_the_container.yml
264
266
  - spec/vcr/Docker_Container/_restart/restarts_the_container.yml
267
+ - spec/vcr/Docker_Container/_run/when_the_Container_s_command_does_not_return_status_code_of_0/raises_an_error.yml
268
+ - spec/vcr/Docker_Container/_run/when_the_Container_s_command_returns_a_status_code_of_0/creates_a_new_container_to_run_the_specified_command.yml
265
269
  - spec/vcr/Docker_Container/_start/starts_the_container.yml
266
270
  - spec/vcr/Docker_Container/_stop/stops_the_container.yml
267
271
  - spec/vcr/Docker_Container/_wait/waits_for_the_command_to_finish.yml