docker-api 1.1.2 → 1.2.0

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