docker-api 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.cane +0 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +3 -0
  4. data/README.md +215 -0
  5. data/Rakefile +16 -0
  6. data/docker-api.gemspec +27 -0
  7. data/lib/docker.rb +60 -0
  8. data/lib/docker/connection.rb +65 -0
  9. data/lib/docker/container.rb +54 -0
  10. data/lib/docker/error.rb +23 -0
  11. data/lib/docker/image.rb +73 -0
  12. data/lib/docker/model.rb +88 -0
  13. data/lib/docker/multipart.rb +30 -0
  14. data/lib/docker/version.rb +3 -0
  15. data/spec/docker/connection_spec.rb +67 -0
  16. data/spec/docker/container_spec.rb +529 -0
  17. data/spec/docker/image_spec.rb +379 -0
  18. data/spec/docker_spec.rb +58 -0
  19. data/spec/spec_helper.rb +14 -0
  20. data/spec/support/vcr.rb +11 -0
  21. data/spec/vcr/Docker/_info/returns_the_info_as_a_Hash.yml +31 -0
  22. data/spec/vcr/Docker/_version/returns_the_version_as_a_Hash.yml +31 -0
  23. data/spec/vcr/Docker_Container/_all/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +333 -0
  24. data/spec/vcr/Docker_Container/_attach/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/yields_each_chunk.yml +81 -0
  25. data/spec/vcr/Docker_Container/_changes/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/returns_the_changes_as_an_array.yml +115 -0
  26. data/spec/vcr/Docker_Container/_commit/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/creates_a_new_Image_from_the_Container_s_changes.yml +87 -0
  27. data/spec/vcr/Docker_Container/_create_/when_the_Container_does_not_yet_exist_and_the_body_is_a_Hash/when_the_HTTP_request_returns_a_200/sets_the_id.yml +31 -0
  28. data/spec/vcr/Docker_Container/_export/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/yields_each_chunk.yml +97 -0
  29. data/spec/vcr/Docker_Container/_json/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/returns_the_description_as_a_Hash.yml +59 -0
  30. data/spec/vcr/Docker_Container/_kill/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/kills_the_container.yml +232 -0
  31. data/spec/vcr/Docker_Container/_restart/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/restarts_the_container.yml +201 -0
  32. data/spec/vcr/Docker_Container/_start/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/starts_the_container.yml +89 -0
  33. data/spec/vcr/Docker_Container/_stop/when_the_Container_has_been_created/when_the_HTTP_response_status_is_204/stops_the_container.yml +259 -0
  34. data/spec/vcr/Docker_Container/_wait/when_the_Container_has_been_created/when_the_HTTP_response_status_is_200/waits_for_the_command_to_finish.yml +87 -0
  35. data/spec/vcr/Docker_Image/_all/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +59 -0
  36. data/spec/vcr/Docker_Image/_build/with_a_valid_Dockerfile/builds_an_image.yml +45 -0
  37. data/spec/vcr/Docker_Image/_build/with_an_invalid_Dockerfile/throws_a_UnexpectedResponseError.yml +38 -0
  38. data/spec/vcr/Docker_Image/_create_/when_the_Image_does_not_yet_exist_and_the_body_is_a_Hash/when_the_HTTP_request_returns_a_200/sets_the_id.yml +31 -0
  39. data/spec/vcr/Docker_Image/_history/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/returns_the_history_of_the_Image.yml +59 -0
  40. data/spec/vcr/Docker_Image/_insert/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/inserts_the_file.yml +59 -0
  41. data/spec/vcr/Docker_Image/_json/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/returns_additional_information_about_image_image.yml +60 -0
  42. data/spec/vcr/Docker_Image/_remove/when_the_Image_has_been_created/when_the_HTTP_response_status_is_204/nils_out_the_id.yml +59 -0
  43. data/spec/vcr/Docker_Image/_search/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +64 -0
  44. data/spec/vcr/Docker_Image/_tag/when_the_Image_has_been_created/when_the_HTTP_response_status_is_200/tags_the_image_with_the_repo_name.yml +59 -0
  45. metadata +281 -0
@@ -0,0 +1,379 @@
1
+ require 'spec_helper'
2
+
3
+ describe Docker::Image do
4
+ describe '#initialize' do
5
+ subject { described_class }
6
+
7
+ context 'with no argument' do
8
+ let(:image) { subject.new }
9
+
10
+ it 'sets the id to nil' do
11
+ image.id.should be_nil
12
+ end
13
+
14
+ it 'keeps the default Connection' do
15
+ image.connection.should == Docker.connection
16
+ end
17
+ end
18
+
19
+ context 'with an argument' do
20
+ let(:id) { 'a7c2ee4' }
21
+ let(:image) { subject.new(:id => id) }
22
+
23
+ it 'sets the id to the argument' do
24
+ image.id.should == id
25
+ end
26
+
27
+ it 'keeps the default Connection' do
28
+ image.connection.should == Docker.connection
29
+ end
30
+ end
31
+
32
+ context 'with two arguments' do
33
+ context 'when the second argument is not a Docker::Connection' do
34
+ let(:id) { 'abc123f' }
35
+ let(:connection) { :not_a_connection }
36
+ let(:image) { subject.new(:id => id, :connection => connection) }
37
+
38
+ it 'raises an error' do
39
+ expect { image }.to raise_error(Docker::Error::ArgumentError)
40
+ end
41
+ end
42
+
43
+ context 'when the second argument is a Docker::Connection' do
44
+ let(:id) { 'cb3f14a' }
45
+ let(:connection) { Docker::Connection.new }
46
+ let(:image) { subject.new(:id => id, :connection => connection) }
47
+
48
+ it 'initializes the Image' do
49
+ image.id.should == id
50
+ image.connection.should == connection
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ describe '#to_s' do
57
+ let(:id) { 'bf119e2' }
58
+ let(:connection) { Docker::Connection.new }
59
+ let(:expected_string) do
60
+ "Docker::Image { :id => #{id}, :connection => #{connection} }"
61
+ end
62
+ subject { described_class.new(:id => id, :connection => connection) }
63
+
64
+ its(:to_s) { should == expected_string }
65
+ end
66
+
67
+ describe '#created?' do
68
+ context 'when the id is nil' do
69
+ its(:created?) { should be_false }
70
+ end
71
+
72
+ context 'when the id is present' do
73
+ subject { described_class.new(:id => 'a732ebf') }
74
+
75
+ its(:created?) { should be_true }
76
+ end
77
+ end
78
+
79
+ describe '#create!' do
80
+ context 'when the Image has already been created' do
81
+ subject { described_class.new(:id => '5e88b2a') }
82
+
83
+ it 'raises an error' do
84
+ expect { subject.create! }
85
+ .to raise_error(Docker::Error::StateError)
86
+ end
87
+ end
88
+
89
+ context 'when the body is not a Hash' do
90
+ it 'raises an error' do
91
+ expect { subject.create!(:not_a_hash) }
92
+ .to raise_error(Docker::Error::ArgumentError)
93
+ end
94
+ end
95
+
96
+ context 'when the Image does not yet exist and the body is a Hash' do
97
+ context 'when the HTTP request does not return a 200' do
98
+ before { Excon.stub({ :method => :post }, { :status => 400 }) }
99
+ after { Excon.stubs.shift }
100
+
101
+ it 'raises an error' do
102
+ expect { subject.create! }.to raise_error(Docker::Error::ClientError)
103
+ end
104
+ end
105
+
106
+ context 'when the HTTP request returns a 200' do
107
+ it 'sets the id', :vcr do
108
+ expect { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
109
+ .to change { subject.id }
110
+ .from(nil)
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '#remove' do
117
+ context 'when the Image has not been created' do
118
+ it 'raises an error' do
119
+ expect { subject.remove }.to raise_error Docker::Error::StateError
120
+ end
121
+ end
122
+
123
+ context 'when the Image has been created' do
124
+ context 'when the HTTP response status is not 204' do
125
+ before do
126
+ subject.stub(:created?).and_return(true)
127
+ Excon.stub({ :method => :delete }, { :status => 500 })
128
+ end
129
+ after { Excon.stubs.shift }
130
+
131
+ it 'raises an error' do
132
+ expect { subject.remove }
133
+ .to raise_error(Docker::Error::ServerError)
134
+ end
135
+ end
136
+
137
+ context 'when the HTTP response status is 204' do
138
+ before { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
139
+
140
+ it 'nils out the id', :vcr do
141
+ expect { subject.remove }
142
+ .to change { subject.id }
143
+ .to nil
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ describe "#insert" do
150
+ context 'when the Image has not been created' do
151
+ it 'raises an error' do
152
+ expect { subject.insert }.to raise_error Docker::Error::StateError
153
+ end
154
+ end
155
+
156
+ context 'when the Image has been created' do
157
+ context 'when the HTTP response status is not 200' do
158
+ before do
159
+ subject.stub(:created?).and_return(true)
160
+ Excon.stub({ :method => :post }, { :status => 500 })
161
+ end
162
+ after { Excon.stubs.shift }
163
+
164
+ it 'raises an error' do
165
+ expect { subject.insert }
166
+ .to raise_error(Docker::Error::ServerError)
167
+ end
168
+ end
169
+
170
+ context 'when the HTTP response status is 200' do
171
+ before { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
172
+
173
+ it 'inserts the file', :vcr do
174
+ expect { subject.insert('path' => '/', 'url' => 'lol') }
175
+ .to_not raise_error
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ describe "#push" do
182
+ context 'when the Image has not been created' do
183
+ it 'raises an error' do
184
+ expect { subject.push }.to raise_error Docker::Error::StateError
185
+ end
186
+ end
187
+
188
+ context 'when the Image has been created' do
189
+ context 'when the HTTP response status is not 200' do
190
+ before do
191
+ subject.stub(:created?).and_return(true)
192
+ Excon.stub({ :method => :post }, { :status => 500 })
193
+ end
194
+ after { Excon.stubs.shift }
195
+
196
+ it 'raises an error' do
197
+ expect { subject.push }
198
+ .to raise_error(Docker::Error::ServerError)
199
+ end
200
+ end
201
+
202
+ context 'when the HTTP response status is 200' do
203
+ it 'pushes the Image', :vcr do
204
+ pending 'I don\'t want to push the Image to the Docker Registry'
205
+ subject.create!('fromRepo' => 'base', 'fromSrc' => '-')
206
+ subject.push
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ describe "#tag" do
213
+ context 'when the Image has not been created' do
214
+ it 'raises an error' do
215
+ expect { subject.tag }.to raise_error Docker::Error::StateError
216
+ end
217
+ end
218
+
219
+ context 'when the Image has been created' do
220
+ context 'when the HTTP response status is not 200' do
221
+ before do
222
+ subject.stub(:created?).and_return(true)
223
+ Excon.stub({ :method => :post }, { :status => 500 })
224
+ end
225
+ after { Excon.stubs.shift }
226
+
227
+ it 'raises an error' do
228
+ expect { subject.tag }
229
+ .to raise_error(Docker::Error::ServerError)
230
+ end
231
+ end
232
+
233
+ context 'when the HTTP response status is 200' do
234
+ before { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
235
+
236
+ it 'tags the image with the repo name', :vcr do
237
+ expect { subject.tag(:repo => 'base2', :force => true) }
238
+ .to_not raise_error
239
+ end
240
+ end
241
+ end
242
+ end
243
+
244
+ describe "#json" do
245
+ context 'when the Image has not been created' do
246
+ it 'raises an error' do
247
+ expect { subject.json }.to raise_error Docker::Error::StateError
248
+ end
249
+ end
250
+
251
+ context 'when the Image has been created' do
252
+ context 'when the HTTP response status is not 200' do
253
+ before do
254
+ subject.stub(:created?).and_return(true)
255
+ Excon.stub({ :method => :get }, { :status => 500 })
256
+ end
257
+ after { Excon.stubs.shift }
258
+
259
+ it 'raises an error' do
260
+ expect { subject.json }
261
+ .to raise_error(Docker::Error::ServerError)
262
+ end
263
+ end
264
+
265
+ context 'when the HTTP response status is 200' do
266
+ let(:json) { subject.json }
267
+ before { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
268
+
269
+ it 'returns additional information about image image', :vcr do
270
+ json.should be_a Hash
271
+ json['id'].should start_with subject.id
272
+ json['comment'].should == 'Imported from -'
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ describe "#history" do
279
+ context 'when the Image has not been created' do
280
+ it 'raises an error' do
281
+ expect { subject.history }.to raise_error Docker::Error::StateError
282
+ end
283
+ end
284
+
285
+ context 'when the Image has been created' do
286
+ context 'when the HTTP response status is not 200' do
287
+ before do
288
+ subject.stub(:created?).and_return(true)
289
+ Excon.stub({ :method => :get }, { :status => 500 })
290
+ end
291
+ after { Excon.stubs.shift }
292
+
293
+ it 'raises an error' do
294
+ expect { subject.history }
295
+ .to raise_error(Docker::Error::ServerError)
296
+ end
297
+ end
298
+
299
+ context 'when the HTTP response status is 200' do
300
+ let(:history) { subject.history }
301
+ before { subject.create!('fromRepo' => 'base', 'fromSrc' => '-') }
302
+
303
+ it 'returns the history of the Image', :vcr do
304
+ history.should be_a Array
305
+ history.length.should_not be_zero
306
+ history.should be_all { |elem| elem.is_a? Hash }
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+ describe '.all' do
313
+ subject { described_class }
314
+
315
+ context 'when the HTTP response is not a 200' do
316
+ before { Excon.stub({ :method => :get }, { :status => 500 }) }
317
+ after { Excon.stubs.shift }
318
+
319
+ it 'raises an error' do
320
+ expect { subject.all }
321
+ .to raise_error(Docker::Error::ServerError)
322
+ end
323
+ end
324
+
325
+ context 'when the HTTP response is a 200' do
326
+ let(:images) { subject.all(:all => true) }
327
+ before { subject.new.create!('fromRepo' => 'base', 'fromSrc' => '-') }
328
+ it 'materializes each Container into a Docker::Container', :vcr do
329
+ images.should be_all { |image|
330
+ !image.id.nil? && image.is_a?(described_class)
331
+ }
332
+ images.length.should_not be_zero
333
+ end
334
+ end
335
+ end
336
+
337
+ describe '.search' do
338
+ subject { described_class }
339
+
340
+ context 'when the HTTP response is not a 200' do
341
+ before { Excon.stub({ :method => :get }, { :status => 500 }) }
342
+ after { Excon.stubs.shift }
343
+
344
+ it 'raises an error' do
345
+ expect { subject.search }
346
+ .to raise_error(Docker::Error::ServerError)
347
+ end
348
+ end
349
+
350
+ context 'when the HTTP response is a 200' do
351
+ it 'materializes each Container into a Docker::Container', :vcr do
352
+ subject.new.create!('fromRepo' => 'base', 'fromSrc' => '-')
353
+ subject.search('term' => 'sshd').should be_all { |image|
354
+ !image.id.nil? && image.is_a?(described_class)
355
+ }
356
+ end
357
+ end
358
+ end
359
+
360
+ describe '.build' do
361
+ subject { described_class }
362
+ context 'with an invalid Dockerfile' do
363
+ it 'throws a UnexpectedResponseError', :vcr do
364
+ expect { subject.build('lololol') }
365
+ .to raise_error(Docker::Error::UnexpectedResponseError)
366
+ end
367
+ end
368
+
369
+ context 'with a valid Dockerfile', :vcr do
370
+ let(:image) { subject.build("from base\n") }
371
+
372
+ it 'builds an image' do
373
+ image.should be_a Docker::Image
374
+ image.id.should_not be_nil
375
+ image.connection.should be_a Docker::Connection
376
+ end
377
+ end
378
+ end
379
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Docker do
4
+ subject { Docker }
5
+
6
+ it { should be_a Module }
7
+ its(:options) { should == { :port => 4243 } }
8
+ its(:url) { should == 'http://localhost' }
9
+ its(:connection) { should be_a Docker::Connection }
10
+
11
+ describe '#reset_connection!' do
12
+ before { subject.connection }
13
+ it 'sets the @connection to nil' do
14
+ expect { subject.reset_connection! }
15
+ .to change { subject.instance_variable_get(:@connection) }
16
+ .to nil
17
+ end
18
+ end
19
+
20
+ [:options=, :url=].each do |method|
21
+ describe "##{method}" do
22
+ after(:all) do
23
+ subject.options = { :port => 4243 }
24
+ subject.url = 'http://localhost'
25
+ end
26
+ it 'calls #reset_connection!' do
27
+ subject.should_receive(:reset_connection!)
28
+ subject.public_send(method, {})
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#version' do
34
+ let(:version) { subject.version }
35
+ it 'returns the version as a Hash', :vcr do
36
+ version.should be_a Hash
37
+ version.keys.sort.should == %w[GoVersion Version]
38
+ end
39
+ end
40
+
41
+ describe '#info' do
42
+ let(:info) { subject.info }
43
+ let(:keys) do
44
+ ["Containers", "Debug", "Images", "MemoryLimit", "NFd", "NGoroutines"]
45
+ end
46
+
47
+ it 'returns the info as a Hash', :vcr do
48
+ info.should be_a Hash
49
+ info.keys.sort.should == keys
50
+ end
51
+ end
52
+
53
+ describe '#auth' do
54
+ it 'logs in' do
55
+ pending
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'rspec'
4
+ require 'docker'
5
+
6
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.mock_with :rspec
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.color_enabled = true
12
+ config.formatter = :documentation
13
+ config.tty = true
14
+ end