docker-api 1.15.0 → 1.16.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 +4 -4
- data/README.md +26 -1
- data/Rakefile +37 -0
- data/TESTING.md +61 -0
- data/lib/docker.rb +8 -1
- data/lib/docker/container.rb +44 -80
- data/lib/docker/exec.rb +98 -0
- data/lib/docker/image.rb +4 -3
- data/lib/docker/util.rb +79 -0
- data/lib/docker/version.rb +2 -2
- data/spec/docker/container_spec.rb +192 -56
- data/spec/docker/event_spec.rb +4 -4
- data/spec/docker/exec_spec.rb +197 -0
- data/spec/docker/image_spec.rb +131 -102
- data/spec/docker_spec.rb +37 -27
- data/spec/fixtures/build_from_dir/Dockerfile +2 -2
- data/spec/fixtures/export.tar +0 -0
- data/spec/fixtures/top/Dockerfile +2 -2
- data/spec/spec_helper.rb +10 -0
- data/spec/support/vcr.rb +5 -0
- data/spec/vcr/Docker/_authenticate_/with_valid_credentials/logs_in_and_sets_the_creds.yml +6 -8
- data/spec/vcr/Docker/_info/returns_the_info_as_a_Hash.yml +7 -9
- data/spec/vcr/Docker/_validate_version/when_nothing_is_raised/validate_version_/.yml +7 -9
- data/spec/vcr/Docker/_version/returns_the_version_as_a_Hash.yml +7 -9
- data/spec/vcr/Docker_Container/_all/when_the_HTTP_response_is_a_200/materializes_each_Container_into_a_Docker_Container.yml +46 -139
- data/spec/vcr/Docker_Container/_attach/with_normal_sized_chunks/yields_each_chunk.yml +62 -20
- data/spec/vcr/Docker_Container/_attach/with_very_small_chunks/yields_each_chunk.yml +62 -20
- data/spec/vcr/Docker_Container/_changes/returns_the_changes_as_an_array.yml +71 -28
- data/spec/vcr/Docker_Container/_commit/creates_a_new_Image_from_the_Container_s_changes.yml +69 -23
- data/spec/vcr/Docker_Container/_copy/when_the_file_does_not_exist/raises_an_error.yml +134 -0
- data/spec/vcr/Docker_Container/_copy/when_the_input_is_a_directory/yields_each_chunk_of_the_tarred_directory.yml +73 -290
- data/spec/vcr/Docker_Container/_copy/when_the_input_is_a_file/yields_each_chunk_of_the_tarred_file.yml +51 -211
- data/spec/vcr/Docker_Container/_create/when_creating_a_container_named_bob/should_have_name_set_to_bob.yml +36 -17
- data/spec/vcr/Docker_Container/_create/when_the_Container_does_not_yet_exist/when_the_HTTP_request_returns_a_200/sets_the_id.yml +30 -9
- data/spec/vcr/Docker_Container/_delete/deletes_the_container.yml +17 -23
- data/spec/vcr/Docker_Container/_exec/when_detach_is_true/returns_the_Docker_Exec_object.yml +151 -0
- data/spec/vcr/Docker_Container/_exec/when_passed_a_block/streams_the_stdout/stderr_messages.yml +153 -0
- data/spec/vcr/Docker_Container/_exec/when_passed_only_a_command/returns_the_stdout/stderr_messages.yml +153 -0
- data/spec/vcr/Docker_Container/_exec/when_stdin_object_is_passed/returns_the_stdout/stderr_messages.yml +100 -0
- data/spec/vcr/Docker_Container/_exec/when_tty_is_true/returns_the_raw_stdout/stderr_output.yml +152 -0
- data/spec/vcr/Docker_Container/_export/yields_each_chunk.yml +263 -28
- data/spec/vcr/Docker_Container/_get/when_the_HTTP_response_is_a_200/materializes_the_Container_into_a_Docker_Container.yml +36 -17
- data/spec/vcr/Docker_Container/_json/returns_the_description_as_a_Hash.yml +36 -17
- data/spec/vcr/Docker_Container/_kill/kills_the_container.yml +55 -53
- data/spec/vcr/Docker_Container/_kill/with_a_kill_signal/kills_the_container.yml +74 -96
- data/spec/vcr/Docker_Container/_logs/when_not_selecting_any_stream/raises_a_client_error.yml +84 -81
- data/spec/vcr/Docker_Container/_logs/when_selecting_stdout/returns_blank_logs.yml +34 -15
- data/spec/vcr/Docker_Container/_pause/pauses_the_container.yml +98 -45
- data/spec/vcr/Docker_Container/_restart/restarts_the_container.yml +88 -56
- data/spec/vcr/Docker_Container/_run/when_the_Container_s_command_does_not_return_status_code_of_0/raises_an_error.yml +39 -22
- data/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 +212 -60
- data/spec/vcr/Docker_Container/_start/starts_the_container.yml +45 -30
- data/spec/vcr/Docker_Container/_stop/stops_the_container.yml +54 -83
- data/spec/vcr/Docker_Container/_streaming_logs/when_not_selecting_any_stream/raises_a_client_error.yml +84 -81
- data/spec/vcr/Docker_Container/_streaming_logs/when_selecting_stdout/returns_blank_logs.yml +46 -30
- data/spec/vcr/Docker_Container/_top/returns_the_top_commands_as_an_Array.yml +103 -40
- data/spec/vcr/Docker_Container/_unpause/unpauses_the_container.yml +81 -57
- data/spec/vcr/Docker_Container/_wait/waits_for_the_command_to_finish.yml +39 -22
- data/spec/vcr/Docker_Container/_wait/when_an_argument_is_given/sets_the_read_timeout_to_that_amount_of_time.yml +39 -22
- data/spec/vcr/Docker_Exec/_create/when_the_HTTP_request_returns_a_201/sets_the_id.yml +128 -0
- data/spec/vcr/Docker_Exec/_resize/when_exec_instance_has_TTY_enabled/returns_a_200.yml +155 -0
- data/spec/vcr/Docker_Exec/_start_/when_detach_is_set_to_false/block_is_passed/attaches_to_the_stream.yml +152 -0
- data/spec/vcr/Docker_Exec/_start_/when_detach_is_set_to_false/returns_the_stdout_and_stderr_messages.yml +152 -0
- data/spec/vcr/Docker_Exec/_start_/when_detach_is_set_to_true/returns_empty_stdout_and_stderr_messages.yml +151 -0
- data/spec/vcr/Docker_Exec/_start_/when_the_HTTP_request_returns_a_201/starts_the_exec_instance.yml +151 -0
- data/spec/vcr/Docker_Exec/_start_/when_the_command_has_already_run/raises_an_error.yml +151 -0
- data/spec/vcr/Docker_Image/_all/materializes_each_Image_into_a_Docker_Image.yml +86 -200
- data/spec/vcr/Docker_Image/_build/with_a_valid_Dockerfile/with_a_block_capturing_build_output/calls_the_block_and_passes_build_output.yml +10 -14
- data/spec/vcr/Docker_Image/_build/with_a_valid_Dockerfile/with_specifying_a_repo_in_the_query_parameters/builds_an_image_and_tags_it.yml +147 -39
- data/spec/vcr/Docker_Image/_build/with_a_valid_Dockerfile/without_query_parameters/builds_an_image.yml +10 -14
- data/spec/vcr/Docker_Image/_build/with_an_invalid_Dockerfile/throws_a_UnexpectedResponseError.yml +12 -14
- data/spec/vcr/Docker_Image/_build_from_dir/with_a_valid_Dockerfile/with_a_block_capturing_build_output/calls_the_block_and_passes_build_output.yml +118 -16
- data/spec/vcr/Docker_Image/_build_from_dir/with_a_valid_Dockerfile/with_credentials_passed/sends_X-Registry-Config_header.yml +118 -14
- data/spec/vcr/Docker_Image/_build_from_dir/with_a_valid_Dockerfile/with_no_query_parameters/builds_the_image.yml +109 -37
- data/spec/vcr/Docker_Image/_build_from_dir/with_a_valid_Dockerfile/with_specifying_a_repo_in_the_query_parameters/builds_the_image_and_tags_it.yml +214 -60
- data/spec/vcr/Docker_Image/_create/when_the_Image_does_not_yet_exist_and_the_body_is_a_Hash/sets_the_id_and_sends_Docker_creds.yml +41 -2631
- data/spec/vcr/Docker_Image/_exist_/when_the_image_does_exist/returns_true.yml +12 -19
- data/spec/vcr/Docker_Image/_get/when_the_image_does_exist/returns_the_new_image.yml +7 -9
- data/spec/vcr/Docker_Image/_history/returns_the_history_of_the_Image.yml +17 -198
- data/spec/vcr/Docker_Image/_import/when_the_argument_is_a_URI/when_the_URI_is_invalid/raises_an_error.yml +26 -30
- data/spec/vcr/Docker_Image/_import/when_the_argument_is_a_URI/when_the_URI_is_valid/returns_an_Image.yml +246 -22
- data/spec/vcr/Docker_Image/_import/when_the_file_does_exist/creates_the_Image.yml +35 -10
- data/spec/vcr/Docker_Image/_insert_local/when_a_direcory_is_passed/inserts_the_directory.yml +1249 -74
- data/spec/vcr/Docker_Image/_insert_local/when_removing_intermediate_containers/creates_a_new_image.yml +84 -94
- data/spec/vcr/Docker_Image/_insert_local/when_removing_intermediate_containers/leave_no_intermediate_containers.yml +70 -92
- data/spec/vcr/Docker_Image/_insert_local/when_the_local_file_does_exist/creates_a_new_Image_that_has_that_file.yml +125 -98
- data/spec/vcr/Docker_Image/_insert_local/when_the_local_file_does_not_exist/raises_an_error.yml +13 -60
- data/spec/vcr/Docker_Image/_insert_local/when_there_are_multiple_files_passed/creates_a_new_Image_that_has_each_file.yml +190 -135
- data/spec/vcr/Docker_Image/_json/returns_additional_information_about_image_image.yml +15 -198
- data/spec/vcr/Docker_Image/_push/pushes_the_Image.yml +169 -264
- data/spec/vcr/Docker_Image/_push/when_there_are_no_credentials/still_pushes.yml +175 -4543
- data/spec/vcr/Docker_Image/_refresh_/updates_the_info_hash.yml +90 -206
- data/spec/vcr/Docker_Image/_remove/when_no_name_is_given/removes_the_Image.yml +300 -0
- data/spec/vcr/Docker_Image/_run/when_the_argument_is_a_String/splits_the_String_by_spaces_and_creates_a_new_Container.yml +77 -207
- data/spec/vcr/Docker_Image/_run/when_the_argument_is_an_Array/creates_a_new_Container.yml +77 -207
- data/spec/vcr/Docker_Image/_run/when_the_argument_is_nil/command_configured_in_image/should_normally_show_result_if_image_has_Cmd_configured.yml +160 -0
- data/spec/vcr/Docker_Image/_run/when_the_argument_is_nil/no_command_configured_in_image/should_raise_an_error_if_no_command_is_specified.yml +16 -197
- data/spec/vcr/Docker_Image/_search/materializes_each_Image_into_a_Docker_Image.yml +151 -73
- data/spec/vcr/Docker_Image/_tag/tags_the_image_with_the_repo_name.yml +42 -196
- metadata +67 -41
- data/spec/vcr/Docker_Container/_commit/if_run_is_passed_it_saves_the_command_in_the_image/saves_the_command.yml +0 -58
- data/spec/vcr/Docker_Container/_streaming_logs/when_not_selecting_any_stream/returns_the_error_message.yml +0 -163
- data/spec/vcr/Docker_Container/_wait/when_an_argument_is_given/and_a_command_runs_for_too_long/raises_a_ServerError.yml +0 -58
- data/spec/vcr/Docker_Image/_build_from_dir/with_a_valid_Dockerfile/with_credentials_passed/sends_Docker_creds.yml +0 -41
- data/spec/vcr/Docker_Image/_remove/removes_the_Image.yml +0 -276
data/spec/docker/event_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Docker::Event do
|
|
6
6
|
|
7
7
|
let(:status) { "start" }
|
8
8
|
let(:id) { "398c9f77b5d2" }
|
9
|
-
let(:from) { "
|
9
|
+
let(:from) { "debian:wheezy" }
|
10
10
|
let(:time) { 1381956164 }
|
11
11
|
|
12
12
|
let(:expected_string) {
|
@@ -26,7 +26,7 @@ describe Docker::Event do
|
|
26
26
|
.and_call_original
|
27
27
|
fork do
|
28
28
|
sleep 1
|
29
|
-
Docker::Image.create('fromImage' => '
|
29
|
+
Docker::Image.create('fromImage' => 'debian:wheezy').run('bash')
|
30
30
|
end
|
31
31
|
Docker::Event.stream do |event|
|
32
32
|
puts "#{event}"
|
@@ -46,7 +46,7 @@ describe Docker::Event do
|
|
46
46
|
.and_call_original
|
47
47
|
fork do
|
48
48
|
sleep 1
|
49
|
-
Docker::Image.create('fromImage' => '
|
49
|
+
Docker::Image.create('fromImage' => 'debian:wheezy').run('bash')
|
50
50
|
end
|
51
51
|
Docker::Event.since(time) do |event|
|
52
52
|
puts "#{event}"
|
@@ -61,7 +61,7 @@ describe Docker::Event do
|
|
61
61
|
subject { Docker::Event.new_event(response_body, nil, nil) }
|
62
62
|
let(:status) { "start" }
|
63
63
|
let(:id) { "398c9f77b5d2" }
|
64
|
-
let(:from) { "
|
64
|
+
let(:from) { "debian:wheezy" }
|
65
65
|
let(:time) { 1381956164 }
|
66
66
|
let(:response_body) {
|
67
67
|
"{\"status\":\"#{status}\",\"id\":\"#{id}\""\
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Docker::Exec do
|
4
|
+
|
5
|
+
describe '#to_s' do
|
6
|
+
subject {
|
7
|
+
described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:id) { 'bf119e2' }
|
11
|
+
let(:connection) { Docker.connection }
|
12
|
+
let(:expected_string) {
|
13
|
+
"Docker::Exec { :id => #{id}, :connection => #{connection} }"
|
14
|
+
}
|
15
|
+
before do
|
16
|
+
{
|
17
|
+
:@id => id,
|
18
|
+
:@connection => connection
|
19
|
+
}.each { |k, v| subject.instance_variable_set(k, v) }
|
20
|
+
end
|
21
|
+
|
22
|
+
its(:to_s) { should == expected_string }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.create' do
|
26
|
+
subject { described_class }
|
27
|
+
|
28
|
+
context 'when the HTTP request returns a 201' do
|
29
|
+
let(:container) {
|
30
|
+
Docker::Container.create(
|
31
|
+
'Cmd' => %w[sleep 5],
|
32
|
+
'Image' => 'debian:wheezy'
|
33
|
+
).start!
|
34
|
+
}
|
35
|
+
let(:options) do
|
36
|
+
{
|
37
|
+
'AttachStdin' => false,
|
38
|
+
'AttachStdout' => false,
|
39
|
+
'AttachStderr' => false,
|
40
|
+
'Tty' => false,
|
41
|
+
'Cmd' => [
|
42
|
+
'date'
|
43
|
+
],
|
44
|
+
'Container' => container.id
|
45
|
+
}
|
46
|
+
end
|
47
|
+
let(:process) { subject.create(options) }
|
48
|
+
after { container.kill!.remove }
|
49
|
+
|
50
|
+
it 'sets the id', :vcr do
|
51
|
+
expect(process).to be_a Docker::Exec
|
52
|
+
expect(process.id).to_not be_nil
|
53
|
+
expect(process.connection).to_not be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the parent container does not exist' do
|
58
|
+
before do
|
59
|
+
Docker.options = { :mock => true }
|
60
|
+
Excon.stub({ :method => :post }, { :status => 404 })
|
61
|
+
end
|
62
|
+
after do
|
63
|
+
Excon.stubs.shift
|
64
|
+
Docker.options = {}
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'raises an error' do
|
68
|
+
expect { subject.create }.to raise_error(Docker::Error::NotFoundError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#start!' do
|
74
|
+
let(:container) {
|
75
|
+
Docker::Container.create(
|
76
|
+
'Cmd' => %w[sleep 10],
|
77
|
+
'Image' => 'debian:wheezy'
|
78
|
+
).start!
|
79
|
+
}
|
80
|
+
|
81
|
+
context 'when the exec instance does not exist' do
|
82
|
+
subject do
|
83
|
+
described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'raises an error', :vcr do
|
87
|
+
skip 'The Docker API returns a 200 (docker/docker#9341)'
|
88
|
+
expect { subject.start! }.to raise_error(Docker::Error::NotFoundError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when :detach is set to false' do
|
93
|
+
subject {
|
94
|
+
described_class.create(
|
95
|
+
'Container' => container.id,
|
96
|
+
'AttachStdout' => true,
|
97
|
+
'Cmd' => ['bash','-c','sleep 2; echo hello']
|
98
|
+
)
|
99
|
+
}
|
100
|
+
after { container.kill!.remove }
|
101
|
+
|
102
|
+
it 'returns the stdout and stderr messages', :vcr do
|
103
|
+
expect(subject.start!).to eq([["hello\n"],[]])
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'block is passed' do
|
107
|
+
it 'attaches to the stream', :vcr do
|
108
|
+
chunk = nil
|
109
|
+
subject.start! do |stream, c|
|
110
|
+
chunk ||= c
|
111
|
+
end
|
112
|
+
expect(chunk).to eq("hello\n")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when :detach is set to true' do
|
118
|
+
subject {
|
119
|
+
described_class.create('Container' => container.id, 'Cmd' => %w[date])
|
120
|
+
}
|
121
|
+
after { container.kill!.remove }
|
122
|
+
|
123
|
+
it 'returns empty stdout and stderr messages', :vcr do
|
124
|
+
expect(subject.start!(:detach => true)).to eq([[],[]])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when the command has already run' do
|
129
|
+
subject {
|
130
|
+
described_class.create('Container' => container.id, 'Cmd' => ['date'])
|
131
|
+
}
|
132
|
+
before { subject.start! }
|
133
|
+
after { container.kill!.remove }
|
134
|
+
|
135
|
+
it 'raises an error', :vcr do
|
136
|
+
skip 'The Docker API returns a 200 (docker/docker#9341)'
|
137
|
+
expect { subject.start! }.to raise_error(Docker::Error::NotFoundError)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'when the HTTP request returns a 201' do
|
142
|
+
subject {
|
143
|
+
described_class.create('Container' => container.id, 'Cmd' => ['date'])
|
144
|
+
}
|
145
|
+
after { container.kill!.remove }
|
146
|
+
|
147
|
+
it 'starts the exec instance', :vcr do
|
148
|
+
expect { subject.start! }.not_to raise_error
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#resize' do
|
154
|
+
let(:container) {
|
155
|
+
Docker::Container.create(
|
156
|
+
'Cmd' => %w[sleep 20],
|
157
|
+
'Image' => 'debian:wheezy'
|
158
|
+
).start!
|
159
|
+
}
|
160
|
+
|
161
|
+
context 'when exec instance has TTY enabled' do
|
162
|
+
let(:instance) do
|
163
|
+
described_class.create(
|
164
|
+
'Container' => container.id,
|
165
|
+
'AttachStdin' => true,
|
166
|
+
'Tty' => true,
|
167
|
+
'Cmd' => %w[/bin/bash]
|
168
|
+
)
|
169
|
+
end
|
170
|
+
after do
|
171
|
+
container.kill!
|
172
|
+
sleep 1
|
173
|
+
container.remove
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns a 200', :vcr do
|
177
|
+
t = Thread.new do
|
178
|
+
instance.start!(:tty => true)
|
179
|
+
end
|
180
|
+
sleep 1
|
181
|
+
expect { instance.resize(:h => 10, :w => 30) }.not_to raise_error
|
182
|
+
t.kill
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'when the exec instance does not exist' do
|
187
|
+
subject do
|
188
|
+
described_class.send(:new, Docker.connection, 'id' => rand(10000).to_s)
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'raises an error', :vcr do
|
192
|
+
skip 'The Docker API returns a 200 (docker/docker#9341)'
|
193
|
+
expect { subject.resize }.to raise_error(Docker::Error::NotFoundError)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
data/spec/docker/image_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Docker::Image do
|
|
8
8
|
let(:connection) { Docker.connection }
|
9
9
|
|
10
10
|
let(:info) do
|
11
|
-
{"id" => "bf119e2", "Repository" => "
|
11
|
+
{"id" => "bf119e2", "Repository" => "debian", "Tag" => "wheezy",
|
12
12
|
"Created" => 1364102658, "Size" => 24653, "VirtualSize" => 180116135}
|
13
13
|
end
|
14
14
|
|
@@ -21,17 +21,30 @@ describe Docker::Image do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe '#remove' do
|
24
|
-
let(:id) { subject.id }
|
25
|
-
subject { described_class.create('fromImage' => 'base') }
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
context 'when no name is given' do
|
26
|
+
let(:id) { subject.id }
|
27
|
+
subject { described_class.create('fromImage' => 'busybox') }
|
28
|
+
|
29
|
+
it 'removes the Image', :vcr do
|
30
|
+
subject.remove(:force => true)
|
31
|
+
expect(Docker::Image.all.map(&:id)).to_not include(id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when a valid tag is given' do
|
36
|
+
it 'untags the Image'
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when an invalid tag is given' do
|
40
|
+
it 'raises an error'
|
30
41
|
end
|
31
42
|
end
|
32
43
|
|
33
44
|
describe '#insert_local' do
|
34
|
-
|
45
|
+
include_context "local paths"
|
46
|
+
|
47
|
+
subject { described_class.create('fromImage' => 'debian:wheezy') }
|
35
48
|
|
36
49
|
let(:rm) { false }
|
37
50
|
let(:new_image) {
|
@@ -49,23 +62,33 @@ describe Docker::Image do
|
|
49
62
|
end
|
50
63
|
|
51
64
|
context 'when the local file does exist' do
|
52
|
-
let(:file) { '
|
65
|
+
let(:file) { File.join(project_dir, 'Gemfile') }
|
53
66
|
let(:gemfile) { File.read('Gemfile') }
|
67
|
+
let(:container) { new_image.run('cat /Gemfile') }
|
68
|
+
after do
|
69
|
+
container.tap(&:wait).remove
|
70
|
+
new_image.remove
|
71
|
+
end
|
54
72
|
|
55
73
|
it 'creates a new Image that has that file', :vcr do
|
56
|
-
|
57
|
-
|
58
|
-
chunk ||= c
|
59
|
-
}
|
60
|
-
expect(chunk).to eq(gemfile)
|
74
|
+
output = container.streaming_logs(stdout: true)
|
75
|
+
expect(output).to eq(gemfile)
|
61
76
|
end
|
62
77
|
end
|
63
78
|
|
64
79
|
context 'when a direcory is passed' do
|
65
80
|
let(:new_image) {
|
66
|
-
subject.insert_local(
|
81
|
+
subject.insert_local(
|
82
|
+
'localPath' => File.join(project_dir, 'lib'),
|
83
|
+
'outputPath' => '/lib'
|
84
|
+
)
|
67
85
|
}
|
68
|
-
let(:
|
86
|
+
let(:container) { new_image.run('ls -a /lib/docker') }
|
87
|
+
let(:response) { container.streaming_logs(stdout: true) }
|
88
|
+
after do
|
89
|
+
container.tap(&:wait).remove
|
90
|
+
new_image.remove
|
91
|
+
end
|
69
92
|
|
70
93
|
it 'inserts the directory', :vcr do
|
71
94
|
expect(response.split("\n").sort).to eq(Dir.entries('lib/docker').sort)
|
@@ -73,21 +96,29 @@ describe Docker::Image do
|
|
73
96
|
end
|
74
97
|
|
75
98
|
context 'when there are multiple files passed' do
|
76
|
-
let(:file) {
|
99
|
+
let(:file) {
|
100
|
+
[File.join(project_dir, 'Gemfile'), File.join(project_dir, 'LICENSE')]
|
101
|
+
}
|
77
102
|
let(:gemfile) { File.read('Gemfile') }
|
78
|
-
let(:
|
103
|
+
let(:license) { File.read('LICENSE') }
|
104
|
+
let(:container) { new_image.run('cat /Gemfile /LICENSE') }
|
79
105
|
let(:response) {
|
80
|
-
|
106
|
+
container.streaming_logs(stdout: true)
|
81
107
|
}
|
108
|
+
after do
|
109
|
+
container.tap(&:wait).remove
|
110
|
+
new_image.remove
|
111
|
+
end
|
82
112
|
|
83
113
|
it 'creates a new Image that has each file', :vcr do
|
84
|
-
expect(response).to eq(
|
114
|
+
expect(response).to eq("#{gemfile}#{license}")
|
85
115
|
end
|
86
116
|
end
|
87
117
|
|
88
118
|
context 'when removing intermediate containers' do
|
89
119
|
let(:rm) { true }
|
90
|
-
let(:file) { '
|
120
|
+
let(:file) { File.join(project_dir, 'Gemfile') }
|
121
|
+
after(:each) { new_image.remove }
|
91
122
|
|
92
123
|
it 'leave no intermediate containers', :vcr do
|
93
124
|
expect { new_image }.to change {
|
@@ -104,47 +135,29 @@ describe Docker::Image do
|
|
104
135
|
describe '#push' do
|
105
136
|
let(:credentials) {
|
106
137
|
{
|
107
|
-
'username' => '
|
108
|
-
'password' => '
|
138
|
+
'username' => ENV['DOCKER_API_USER'],
|
139
|
+
'password' => ENV['DOCKER_API_PASS'],
|
109
140
|
'serveraddress' => 'https://index.docker.io/v1',
|
110
|
-
'email' => '
|
141
|
+
'email' => ENV['DOCKER_API_EMAIL']
|
111
142
|
}
|
112
143
|
}
|
113
|
-
let(:
|
114
|
-
|
115
|
-
|
116
|
-
let(:container) {
|
117
|
-
base_image.run('true')
|
118
|
-
}
|
119
|
-
let(:new_image) {
|
120
|
-
container.commit('repo' => 'nahiluhmot/base2')
|
121
|
-
Docker::Image.all(:all => true).select { |image|
|
122
|
-
image.info['RepoTags'].include?('nahiluhmot/base2:latest')
|
123
|
-
}.first
|
144
|
+
let(:repo_tag) { "#{ENV['DOCKER_API_USER']}/true" }
|
145
|
+
let(:image) {
|
146
|
+
described_class.build("FROM tianon/true\n", "t" => repo_tag).refresh!
|
124
147
|
}
|
148
|
+
after { image.remove(:name => repo_tag, :noprune => true) }
|
125
149
|
|
126
150
|
it 'pushes the Image', :vcr do
|
127
|
-
|
151
|
+
image.push(credentials)
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when a tag is specified' do
|
155
|
+
it 'pushes that specific tag'
|
128
156
|
end
|
129
157
|
|
130
158
|
context 'when there are no credentials' do
|
131
159
|
let(:credentials) { nil }
|
132
|
-
let(:
|
133
|
-
Docker::Image.create('fromImage' => 'registry', 'tag' => 'latest')
|
134
|
-
}
|
135
|
-
|
136
|
-
let(:container) { Docker::Container.create('Image' => image.id) }
|
137
|
-
|
138
|
-
before do
|
139
|
-
opts = {
|
140
|
-
"PortBindings" => {
|
141
|
-
"5000/tcp" => [{"HostPort" => "5000"}]
|
142
|
-
}
|
143
|
-
}
|
144
|
-
container.start!(opts)
|
145
|
-
sleep 10 # for some reason the registry isn't ready right away
|
146
|
-
image.tag('repo' => 'localhost:5000/registry', 'tag' => 'test')
|
147
|
-
end
|
160
|
+
let(:repo_tag) { "localhost:5000/true" }
|
148
161
|
|
149
162
|
it 'still pushes', :vcr do
|
150
163
|
expect { image.push }.to_not raise_error
|
@@ -153,16 +166,17 @@ describe Docker::Image do
|
|
153
166
|
end
|
154
167
|
|
155
168
|
describe '#tag' do
|
156
|
-
subject { described_class.create('fromImage' => '
|
169
|
+
subject { described_class.create('fromImage' => 'debian:wheezy') }
|
170
|
+
after { subject.remove(:name => 'teh:latest', :noprune => true) }
|
157
171
|
|
158
172
|
it 'tags the image with the repo name', :vcr do
|
159
|
-
subject.tag(:repo => :
|
160
|
-
expect(subject.info['RepoTags']).to include '
|
173
|
+
subject.tag(:repo => :teh, :force => true)
|
174
|
+
expect(subject.info['RepoTags']).to include 'teh:latest'
|
161
175
|
end
|
162
176
|
end
|
163
177
|
|
164
178
|
describe '#json' do
|
165
|
-
subject { described_class.create('fromImage' => '
|
179
|
+
subject { described_class.create('fromImage' => 'debian:wheezy') }
|
166
180
|
let(:json) { subject.json }
|
167
181
|
|
168
182
|
it 'returns additional information about image image', :vcr do
|
@@ -172,7 +186,7 @@ describe Docker::Image do
|
|
172
186
|
end
|
173
187
|
|
174
188
|
describe '#history' do
|
175
|
-
subject { described_class.create('fromImage' => '
|
189
|
+
subject { described_class.create('fromImage' => 'debian:wheezy') }
|
176
190
|
let(:history) { subject.history }
|
177
191
|
|
178
192
|
it 'returns the history of the Image', :vcr do
|
@@ -183,48 +197,51 @@ describe Docker::Image do
|
|
183
197
|
end
|
184
198
|
|
185
199
|
describe '#run' do
|
186
|
-
subject { described_class.create('fromImage' => '
|
187
|
-
let(:
|
200
|
+
subject { described_class.create('fromImage' => 'debian:wheezy') }
|
201
|
+
let(:container) { subject.run(cmd) }
|
202
|
+
let(:output) { container.streaming_logs(stdout: true) }
|
188
203
|
|
189
204
|
context 'when the argument is a String', :vcr do
|
190
205
|
let(:cmd) { 'ls /lib64/' }
|
206
|
+
after { container.tap(&:wait).remove }
|
207
|
+
|
191
208
|
it 'splits the String by spaces and creates a new Container' do
|
192
|
-
expect(output).to eq(
|
209
|
+
expect(output).to eq("ld-linux-x86-64.so.2\n")
|
193
210
|
end
|
194
211
|
end
|
195
212
|
|
196
213
|
context 'when the argument is an Array' do
|
197
214
|
let(:cmd) { %w[which pwd] }
|
215
|
+
after { container.tap(&:wait).remove }
|
198
216
|
|
199
217
|
it 'creates a new Container', :vcr do
|
200
|
-
expect(output).to eq(
|
218
|
+
expect(output).to eq("/bin/pwd\n")
|
201
219
|
end
|
202
220
|
end
|
203
221
|
|
204
222
|
context 'when the argument is nil', :vcr do
|
205
223
|
let(:cmd) { nil }
|
206
|
-
context 'no command configured in image'do
|
224
|
+
context 'no command configured in image' do
|
225
|
+
subject { described_class.create('fromImage' => 'scratch') }
|
207
226
|
it 'should raise an error if no command is specified' do
|
208
|
-
expect {
|
227
|
+
expect {container}.to raise_error(Docker::Error::ServerError,
|
209
228
|
"No command specified.")
|
210
229
|
end
|
211
230
|
end
|
212
231
|
|
213
232
|
context "command configured in image" do
|
214
|
-
let(:
|
215
|
-
|
216
|
-
subject { container.commit('run' => {"Cmd" => %w[pwd]}) }
|
233
|
+
let(:cmd) { 'pwd' }
|
234
|
+
after { container.tap(&:wait).remove }
|
217
235
|
|
218
236
|
it 'should normally show result if image has Cmd configured' do
|
219
|
-
|
220
|
-
expect(output).to eql [["/\n"],[]]
|
237
|
+
expect(output).to eql "/\n"
|
221
238
|
end
|
222
239
|
end
|
223
240
|
end
|
224
241
|
end
|
225
242
|
|
226
243
|
describe '#refresh!' do
|
227
|
-
let(:image) { Docker::Image.create('fromImage' => '
|
244
|
+
let(:image) { Docker::Image.create('fromImage' => 'debian:wheezy') }
|
228
245
|
|
229
246
|
it 'updates the @info hash', :vcr do
|
230
247
|
size = image.info.size
|
@@ -237,16 +254,17 @@ describe Docker::Image do
|
|
237
254
|
subject { described_class }
|
238
255
|
|
239
256
|
context 'when the Image does not yet exist and the body is a Hash' do
|
240
|
-
let(:image) { subject.create('fromImage' => '
|
257
|
+
let(:image) { subject.create('fromImage' => 'swipely/scratch') }
|
241
258
|
let(:creds) {
|
242
259
|
{
|
243
|
-
:username => '
|
244
|
-
:password => '
|
245
|
-
:email => '
|
260
|
+
:username => ENV['DOCKER_API_USER'],
|
261
|
+
:password => ENV['DOCKER_API_PASS'],
|
262
|
+
:email => ENV['DOCKER_API_EMAIL']
|
246
263
|
}
|
247
264
|
}
|
248
265
|
|
249
266
|
before { Docker.creds = creds }
|
267
|
+
after { image.remove(:name => 'swipely/scratch', :noprune => true) }
|
250
268
|
|
251
269
|
it 'sets the id and sends Docker.creds', :vcr do
|
252
270
|
expect(image).to be_a Docker::Image
|
@@ -264,7 +282,7 @@ describe Docker::Image do
|
|
264
282
|
let(:image) { subject.get(image_name) }
|
265
283
|
|
266
284
|
context 'when the image does exist' do
|
267
|
-
let(:image_name) { '
|
285
|
+
let(:image_name) { 'debian:wheezy' }
|
268
286
|
|
269
287
|
it 'returns the new image', :vcr do
|
270
288
|
expect(image).to be_a Docker::Image
|
@@ -295,7 +313,7 @@ describe Docker::Image do
|
|
295
313
|
let(:exists) { subject.exist?(image_name) }
|
296
314
|
|
297
315
|
context 'when the image does exist' do
|
298
|
-
let(:image_name) { '
|
316
|
+
let(:image_name) { 'debian:wheezy' }
|
299
317
|
|
300
318
|
it 'returns true', :vcr do
|
301
319
|
expect(exists).to eq(true)
|
@@ -322,6 +340,8 @@ describe Docker::Image do
|
|
322
340
|
end
|
323
341
|
|
324
342
|
describe '.import' do
|
343
|
+
include_context "local paths"
|
344
|
+
|
325
345
|
subject { described_class }
|
326
346
|
|
327
347
|
context 'when the file does not exist' do
|
@@ -334,15 +354,11 @@ describe Docker::Image do
|
|
334
354
|
end
|
335
355
|
|
336
356
|
context 'when the file does exist' do
|
337
|
-
let(:file) { 'spec
|
338
|
-
let(:
|
339
|
-
|
340
|
-
before do
|
341
|
-
allow(Docker::Image).to receive(:open).with(file).and_yield(body)
|
342
|
-
end
|
357
|
+
let(:file) { File.join(project_dir, 'spec', 'fixtures', 'export.tar') }
|
358
|
+
let(:import) { subject.import(file) }
|
359
|
+
after { import.remove(:noprune => true) }
|
343
360
|
|
344
361
|
it 'creates the Image', :vcr do
|
345
|
-
import = subject.import(file)
|
346
362
|
expect(import).to be_a Docker::Image
|
347
363
|
expect(import.id).to_not be_nil
|
348
364
|
end
|
@@ -357,12 +373,13 @@ describe Docker::Image do
|
|
357
373
|
end
|
358
374
|
|
359
375
|
context 'when the URI is valid' do
|
360
|
-
let(:uri) { 'http://swipely-pub.s3.amazonaws.com/
|
376
|
+
let(:uri) { 'http://swipely-pub.s3.amazonaws.com/tianon_true.tar' }
|
377
|
+
let(:import) { subject.import(uri) }
|
378
|
+
after { import.remove(:noprune => true) }
|
361
379
|
|
362
380
|
it 'returns an Image', :vcr do
|
363
|
-
|
364
|
-
expect(
|
365
|
-
expect(image.id).to_not be_nil
|
381
|
+
expect(import).to be_a Docker::Image
|
382
|
+
expect(import.id).to_not be_nil
|
366
383
|
end
|
367
384
|
end
|
368
385
|
end
|
@@ -372,7 +389,7 @@ describe Docker::Image do
|
|
372
389
|
subject { described_class }
|
373
390
|
|
374
391
|
let(:images) { subject.all(:all => true) }
|
375
|
-
before { subject.create('fromImage' => '
|
392
|
+
before { subject.create('fromImage' => 'debian:wheezy') }
|
376
393
|
|
377
394
|
it 'materializes each Image into a Docker::Image', :vcr do
|
378
395
|
images.each do |image|
|
@@ -412,7 +429,7 @@ describe Docker::Image do
|
|
412
429
|
|
413
430
|
context 'with a valid Dockerfile' do
|
414
431
|
context 'without query parameters' do
|
415
|
-
let(:image) { subject.build("
|
432
|
+
let(:image) { subject.build("FROM debian:wheezy\n") }
|
416
433
|
|
417
434
|
it 'builds an image', :vcr do
|
418
435
|
expect(image).to be_a Docker::Image
|
@@ -423,25 +440,31 @@ describe Docker::Image do
|
|
423
440
|
|
424
441
|
context 'with specifying a repo in the query parameters' do
|
425
442
|
let(:image) {
|
426
|
-
subject.build(
|
443
|
+
subject.build(
|
444
|
+
"FROM debian:wheezy\nRUN true\n",
|
445
|
+
"t" => "#{ENV['DOCKER_API_USER']}/debian:true"
|
446
|
+
)
|
427
447
|
}
|
428
|
-
|
448
|
+
after { image.remove(:noprune => true) }
|
429
449
|
|
430
450
|
it 'builds an image and tags it', :vcr do
|
431
451
|
expect(image).to be_a Docker::Image
|
432
452
|
expect(image.id).to_not be_nil
|
433
453
|
expect(image.connection).to be_a Docker::Connection
|
434
|
-
|
454
|
+
image.refresh!
|
455
|
+
expect(image.info["RepoTags"]).to eq(
|
456
|
+
["#{ENV['DOCKER_API_USER']}/debian:true"]
|
457
|
+
)
|
435
458
|
end
|
436
459
|
end
|
437
460
|
|
438
461
|
context 'with a block capturing build output' do
|
439
462
|
let(:build_output) { "" }
|
440
463
|
let(:block) { Proc.new { |chunk| build_output << chunk } }
|
441
|
-
let!(:image) { subject.build("FROM
|
464
|
+
let!(:image) { subject.build("FROM debian:wheezy\n", &block) }
|
442
465
|
|
443
466
|
it 'calls the block and passes build output', :vcr do
|
444
|
-
expect(build_output).to match(/Step 0 : FROM
|
467
|
+
expect(build_output).to match(/Step 0 : FROM debian:wheezy/)
|
445
468
|
end
|
446
469
|
end
|
447
470
|
end
|
@@ -463,20 +486,26 @@ describe Docker::Image do
|
|
463
486
|
'Cmd' => %w[cat /Dockerfile])
|
464
487
|
end
|
465
488
|
let(:output) { container.tap(&:start)
|
466
|
-
.
|
467
|
-
|
489
|
+
.streaming_logs(stdout: true) }
|
490
|
+
after(:each) do
|
491
|
+
container.tap(&:wait).remove
|
492
|
+
image.remove(:noprune => true)
|
493
|
+
end
|
468
494
|
|
469
495
|
context 'with no query parameters' do
|
470
496
|
it 'builds the image', :vcr do
|
471
|
-
expect(output).to eq(
|
497
|
+
expect(output).to eq(docker_file.read)
|
472
498
|
end
|
473
499
|
end
|
474
500
|
|
475
501
|
context 'with specifying a repo in the query parameters' do
|
476
|
-
let(:opts) { { "t" => "
|
502
|
+
let(:opts) { { "t" => "#{ENV['DOCKER_API_USER']}/debian:from_dir" } }
|
477
503
|
it 'builds the image and tags it', :vcr do
|
478
|
-
expect(output).to eq(
|
479
|
-
|
504
|
+
expect(output).to eq(docker_file.read)
|
505
|
+
image.refresh!
|
506
|
+
expect(image.info["RepoTags"]).to eq(
|
507
|
+
["#{ENV['DOCKER_API_USER']}/debian:from_dir"]
|
508
|
+
)
|
480
509
|
end
|
481
510
|
end
|
482
511
|
|
@@ -486,16 +515,16 @@ describe Docker::Image do
|
|
486
515
|
|
487
516
|
it 'calls the block and passes build output', :vcr do
|
488
517
|
image # Create the image variable, which is lazy-loaded by Rspec
|
489
|
-
expect(build_output).to match(/Step 0 :
|
518
|
+
expect(build_output).to match(/Step 0 : FROM debian:wheezy/)
|
490
519
|
end
|
491
520
|
end
|
492
521
|
|
493
522
|
context 'with credentials passed' do
|
494
523
|
let(:creds) {
|
495
524
|
{
|
496
|
-
:username => '
|
497
|
-
:password => '
|
498
|
-
:email => '
|
525
|
+
:username => ENV['DOCKER_API_USER'],
|
526
|
+
:password => ENV['DOCKER_API_PASS'],
|
527
|
+
:email => ENV['DOCKER_API_EMAIL'],
|
499
528
|
:serveraddress => 'https://index.docker.io/v1'
|
500
529
|
}
|
501
530
|
}
|