bigrig 0.0.0 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +84 -0
- data/LICENSE +28 -0
- data/README.md +191 -0
- data/Rakefile +10 -0
- data/bigrig.gemspec +29 -0
- data/bin/bigrig +113 -0
- data/lib/bigrig/actions/destroy_action.rb +21 -0
- data/lib/bigrig/actions/dev_action.rb +19 -0
- data/lib/bigrig/actions/log_action.rb +45 -0
- data/lib/bigrig/actions/run_action.rb +14 -0
- data/lib/bigrig/actions/ship_action.rb +51 -0
- data/lib/bigrig/actions.rb +5 -0
- data/lib/bigrig/dependency_graph.rb +21 -0
- data/lib/bigrig/descriptor.rb +43 -0
- data/lib/bigrig/docker_adapter.rb +129 -0
- data/lib/bigrig/models/application.rb +22 -0
- data/lib/bigrig/models/base_model.rb +7 -0
- data/lib/bigrig/models/container.rb +40 -0
- data/lib/bigrig/models.rb +3 -0
- data/lib/bigrig/output_parser.rb +52 -0
- data/lib/bigrig/runner.rb +94 -0
- data/lib/bigrig/version.rb +3 -0
- data/lib/bigrig.rb +8 -0
- data/spec/bigrig/actions/destroy_action_spec.rb +55 -0
- data/spec/bigrig/actions/dev_action_spec.rb +17 -0
- data/spec/bigrig/actions/log_action_spec.rb +33 -0
- data/spec/bigrig/actions/run_action_spec.rb +270 -0
- data/spec/bigrig/actions/ship_action_spec.rb +82 -0
- data/spec/bigrig/dependency_graph_spec.rb +19 -0
- data/spec/bigrig/descriptor_spec.rb +56 -0
- data/spec/bigrig/docker_adapter_spec.rb +409 -0
- data/spec/bigrig/models/application_spec.rb +32 -0
- data/spec/bigrig/models/container_spec.rb +115 -0
- data/spec/bigrig/output_parser_spec.rb +71 -0
- data/spec/bigrig_spec.rb +249 -0
- data/spec/data/addscontainer.json +24 -0
- data/spec/data/build/Dockerfile +2 -0
- data/spec/data/build/test +0 -0
- data/spec/data/dev.json +26 -0
- data/spec/data/duplicate.json +13 -0
- data/spec/data/env.json +12 -0
- data/spec/data/hosts_ip.json +12 -0
- data/spec/data/hosts_name.json +11 -0
- data/spec/data/links.json +13 -0
- data/spec/data/log.json +8 -0
- data/spec/data/multiple.json +13 -0
- data/spec/data/path.json +5 -0
- data/spec/data/ports.json +9 -0
- data/spec/data/profiles.json +24 -0
- data/spec/data/ship.json +5 -0
- data/spec/data/single.json +8 -0
- data/spec/data/tagandpath.json +24 -0
- data/spec/data/tiny-image.tar +0 -0
- data/spec/data/volumes.json +13 -0
- data/spec/spec_helper.rb +104 -0
- data/spec/support/bigrig_vcr +8 -0
- data/spec/support/vcr.rb +15 -0
- data/spec/vcr/Bigrig_DestroyAction/_perform/given_json_with_a_single_container/and_the_container_has_exited/should_remove_the_container.yml +392 -0
- data/spec/vcr/Bigrig_DestroyAction/_perform/given_json_with_a_single_container/and_the_container_is_running/kills_and_removes_the_container.yml +418 -0
- data/spec/vcr/Bigrig_DockerAdapter/_build/builds_the_given_directory.yml +63 -0
- data/spec/vcr/Bigrig_DockerAdapter/_build/passes_build_input_to_a_block.yml +35 -0
- data/spec/vcr/Bigrig_DockerAdapter/_container_exists_/when_the_container_does_not_exist/is_false.yml +115 -0
- data/spec/vcr/Bigrig_DockerAdapter/_container_exists_/when_the_container_exists/is_true.yml +82 -0
- data/spec/vcr/Bigrig_DockerAdapter/_image_id_by_tag/when_the_image_does_not_exist/raise_a_ImageNotFoundError.yml +172 -0
- data/spec/vcr/Bigrig_DockerAdapter/_image_id_by_tag/when_the_image_exists/returns_the_image_id.yml +148 -0
- data/spec/vcr/Bigrig_DockerAdapter/_kill/given_the_container_does_not_exist/should_raise_an_error.yml +115 -0
- data/spec/vcr/Bigrig_DockerAdapter/_kill/given_the_container_is_running/should_kill_the_container.yml +200 -0
- data/spec/vcr/Bigrig_DockerAdapter/_logs/streams_logs_to_a_block.yml +163 -0
- data/spec/vcr/Bigrig_DockerAdapter/_pull/given_a_block_to_capture_output/should_capture_output.yml +64 -0
- data/spec/vcr/Bigrig_DockerAdapter/_pull/given_the_repo_does_not_exist/raises_a_RepoNotFoundError.yml +30 -0
- data/spec/vcr/Bigrig_DockerAdapter/_pull/given_the_repo_exists/returns_the_image_id.yml +92 -0
- data/spec/vcr/Bigrig_DockerAdapter/_push/given_credentials/will_pass_login_and_password.yml +254 -0
- data/spec/vcr/Bigrig_DockerAdapter/_push/should_push_the_image.yml +482 -0
- data/spec/vcr/Bigrig_DockerAdapter/_remove_container/when_the_container_does_not_exist/raises_a_ContainerNotFoundError.yml +227 -0
- data/spec/vcr/Bigrig_DockerAdapter/_remove_container/when_the_container_exists/should_remove_the_container.yml +222 -0
- data/spec/vcr/Bigrig_DockerAdapter/_remove_container/when_the_container_is_running/raises_a_ContainerRunningError.yml +80 -0
- data/spec/vcr/Bigrig_DockerAdapter/_remove_image/when_the_image_doesnt_exist/raises_an_error.yml +115 -0
- data/spec/vcr/Bigrig_DockerAdapter/_remove_image/when_the_image_exists/removes_the_image.yml +199 -0
- data/spec/vcr/Bigrig_DockerAdapter/_run/given_an_image_id_that_exists/and_a_name/starts_the_container_with_the_right_name.yml +204 -0
- data/spec/vcr/Bigrig_DockerAdapter/_run/given_an_image_id_that_exists/and_a_name_and_env_variables/starts_the_container_with_env_set.yml +204 -0
- data/spec/vcr/Bigrig_DockerAdapter/_run/given_an_image_id_that_exists/and_a_name_and_ports/starts_the_container_with_ports_exposed.yml +230 -0
- data/spec/vcr/Bigrig_DockerAdapter/_running_/when_the_container_does_not_exist/returns_false.yml +115 -0
- data/spec/vcr/Bigrig_DockerAdapter/_running_/when_the_container_is_not_running/returns_false.yml +82 -0
- data/spec/vcr/Bigrig_DockerAdapter/_running_/when_the_container_is_running/returns_true.yml +103 -0
- data/spec/vcr/Bigrig_DockerAdapter/_tag/should_tag_the_image.yml +290 -0
- data/spec/vcr/Bigrig_LogAction/_perform/follows_the_log.yml +163 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_a_path/builds_the_image_before_starting_it.yml +310 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_hosts_by_ip/should_pass_hosts_to_container.yml +430 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_hosts_by_name/should_lookup_ips_for_hosts_with_a_hostname.yml +430 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_links/should_pass_links_to_the_right_container.yml +805 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_multiple_containers/launches_both_containers_in_parallel.yml +731 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_multiple_containers/spins_up_multiple_containers.yml +805 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_one_container/should_spin_up_a_single_container.yml +404 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_one_container/when_a_dead_container_exists/should_remove_existing_containers.yml +329 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_volumes_from/should_pass_volumes_from_to_the_right_container.yml +805 -0
- data/spec/vcr/Bigrig_RunAction/_perform/given_a_file_with_volumes_from/starts_the_dependant_container_last.yml +731 -0
- data/spec/vcr/Bigrig_RunAction/_perform/when_activating_profiles_that_do_not_exist/ignores_the_missing_profile.yml +409 -0
- data/spec/vcr/Bigrig_RunAction/_perform/with_a_file_with_active_profiles/uses_the_overridden_image.yml +432 -0
- data/spec/vcr/bigrig/destroy/spec/data/single_json/kills_the_container.yml +166 -0
- data/spec/vcr/bigrig/dev/spec/data/dev_json/activates_the_dev_profile.yml +37 -0
- data/spec/vcr/bigrig/dev/spec/data/dev_json/destroys_containers_on_exit.yml +227 -0
- data/spec/vcr/bigrig/dev/spec/data/dev_json/starts_the_containers.yml +107 -0
- data/spec/vcr/bigrig/logs/spec/data/log_json/tails_the_logs.yml +163 -0
- data/spec/vcr/bigrig/run/spec/data/profiles_json_-p_qa/leaves_existing_env_values_alone.yml +110 -0
- data/spec/vcr/bigrig/run/spec/data/profiles_json_-p_qa/overrides_the_env.yml +110 -0
- data/spec/vcr/bigrig/run/spec/data/profiles_json_-p_qa/overrides_the_tag.yml +103 -0
- data/spec/vcr/bigrig/run/spec/data/single_json/sends_the_name_of_the_container_to_stdout.yml +75 -0
- data/spec/vcr/bigrig/run/spec/data/single_json/starts_the_container.yml +101 -0
- data/spec/vcr/bigrig/ship/spec/data/ship_json/with_a_version/-c/cleans_the_image_when_its_done.yml +212 -0
- data/spec/vcr/bigrig/ship/spec/data/ship_json/with_a_version/builds_and_pushes_the_image.yml +128 -0
- data/spec/vcr/bigrig_bin_bigrig_destroy_spec/data/single_json_kills_the_container.yml +179 -0
- data/spec/vcr/bigrig_bin_bigrig_dev_spec/data/dev_json_activates_the_dev_profile.yml +1068 -0
- data/spec/vcr/bigrig_bin_bigrig_dev_spec/data/dev_json_destroys_containers_on_exit.yml +1070 -0
- data/spec/vcr/bigrig_bin_bigrig_dev_spec/data/dev_json_starts_the_containers.yml +1068 -0
- data/spec/vcr/bigrig_bin_bigrig_dev_spec/data/dev_json_tails_the_logs.yml +1075 -0
- data/spec/vcr/bigrig_bin_bigrig_logs_spec/data/log_json_tails_the_logs.yml +69 -0
- data/spec/vcr/bigrig_bin_bigrig_run_spec/data/profiles_json_-p_qa_leaves_existing_env_values_alone.yml +306 -0
- data/spec/vcr/bigrig_bin_bigrig_run_spec/data/profiles_json_-p_qa_overrides_the_env.yml +306 -0
- data/spec/vcr/bigrig_bin_bigrig_run_spec/data/profiles_json_-p_qa_overrides_the_tag.yml +306 -0
- data/spec/vcr/bigrig_bin_bigrig_run_spec/data/single_json_sends_the_name_of_the_container_to_stdout.yml +306 -0
- data/spec/vcr/bigrig_bin_bigrig_run_spec/data/single_json_starts_the_container.yml +306 -0
- data/spec/vcr/bigrig_bin_bigrig_ship_spec/data/ship_json_with_a_version_-c_cleans_the_image_when_its_done.yml +335 -0
- data/spec/vcr/bigrig_bin_bigrig_ship_spec/data/ship_json_with_a_version_builds_and_pushes_the_image.yml +285 -0
- data/test/dev/shipper.json +24 -0
- data/test/logs/bigrig.json +6 -0
- data/test/logs/container1/Dockerfile +4 -0
- data/test/logs/container1/run.sh +7 -0
- data/test/logs/container2/Dockerfile +4 -0
- data/test/logs/container2/run.sh +7 -0
- data/test/ship/bigrig-1.2.3.json +1 -0
- data/test/ship/bigrig.json +5 -0
- data/test/ship/registry.json +11 -0
- data/test/ship/ship/Dockerfile +4 -0
- data/test/ship/ship/run.sh +6 -0
- data/test/volumes_from/exports_volumes/Dockerfile +8 -0
- data/test/volumes_from/exports_volumes/index.html +8 -0
- data/test/volumes_from/exports_volumes/run.sh +7 -0
- data/test/volumes_from/shipper.json +14 -0
- metadata +278 -8
data/spec/bigrig_spec.rb
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'docker'
|
2
|
+
require 'colorize'
|
3
|
+
require 'open4'
|
4
|
+
|
5
|
+
describe 'bigrig' do
|
6
|
+
subject { `#{here}spec/support/bigrig_vcr "#{casette_name}" -f #{file} #{args.join ' '}` }
|
7
|
+
let(:here) { '' }
|
8
|
+
let(:output) { subject }
|
9
|
+
let(:casette_name) do |example|
|
10
|
+
"bigrig bin #{example.metadata[:full_description].gsub('"', '\\"')}"
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'dev' do
|
14
|
+
context 'spec/data/dev.json' do
|
15
|
+
let(:args) { ['-f', 'spec/data/dev.json', 'dev'] }
|
16
|
+
let(:env) do
|
17
|
+
url = URI.parse Docker.connection.url
|
18
|
+
text = Net::HTTP.get URI.parse("http://#{url.host}:4568")
|
19
|
+
text.split("\n").each_with_object({}) { |e, o| o.store(*e.split('=')) }
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'starts the containers', :vcr do
|
23
|
+
command = %(spec/support/bigrig_vcr "#{casette_name}" #{args.join ' '})
|
24
|
+
pid = Open4.popen4(command).first
|
25
|
+
sleep 2
|
26
|
+
dev_test = Docker::Container.get('dev-test')
|
27
|
+
dev_logs = Docker::Container.get('dev-logs')
|
28
|
+
begin
|
29
|
+
expect(dev_test.json['State']['Running']).to be true
|
30
|
+
expect(dev_logs.json['State']['Running']).to be true
|
31
|
+
ensure
|
32
|
+
Process.kill :SIGINT, pid
|
33
|
+
Process.wait pid
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'destroys containers on exit', :vcr do
|
38
|
+
command = %(spec/support/bigrig_vcr "#{casette_name}" #{args.join ' '})
|
39
|
+
pid = Open4.popen4(command).first
|
40
|
+
sleep 2
|
41
|
+
Process.kill :SIGINT, pid
|
42
|
+
Process.wait pid
|
43
|
+
begin
|
44
|
+
Docker::Container.get('dev-test')
|
45
|
+
fail 'dev-test is still running'
|
46
|
+
rescue Docker::Error::NotFoundError # rubocop:disable Lint/HandleExceptions
|
47
|
+
end
|
48
|
+
begin
|
49
|
+
Docker::Container.get('dev-logs')
|
50
|
+
fail 'dev-logs is still running'
|
51
|
+
rescue Docker::Error::NotFoundError # rubocop:disable Lint/HandleExceptions
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'activates the dev profile', :vcr do
|
56
|
+
command = %(spec/support/bigrig_vcr "#{casette_name}" #{args.join ' '})
|
57
|
+
pid = Open4.popen4(command).first
|
58
|
+
sleep 2
|
59
|
+
begin
|
60
|
+
expect(env).to include 'PROFILE' => 'dev'
|
61
|
+
ensure
|
62
|
+
Process.kill :SIGINT, pid
|
63
|
+
Process.wait pid
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'tails the logs', :vcr do
|
68
|
+
command = %(spec/support/bigrig_vcr "#{casette_name}" #{args.join ' '})
|
69
|
+
pid, output = capture_stdout command
|
70
|
+
Process.kill :SIGINT, pid
|
71
|
+
Process.wait pid
|
72
|
+
expect(output).to match(/container 1 stdout/)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'logs' do
|
78
|
+
context 'spec/data/log.json' do
|
79
|
+
let(:args) { ['-f spec/data/log.json', 'log'] }
|
80
|
+
let(:container) { Docker::Container.get 'log-test' }
|
81
|
+
let(:image) { Docker::Image.create 'fromImage' => 'hawknewton/log-test:0.0.1' }
|
82
|
+
|
83
|
+
before do
|
84
|
+
container = Docker::Container.create 'name' => 'log-test', 'Image' => image.id
|
85
|
+
container.start
|
86
|
+
end
|
87
|
+
|
88
|
+
# Killing the container will cause bigrig to exit naturally
|
89
|
+
after { container.kill.delete }
|
90
|
+
|
91
|
+
it 'tails the logs', :vcr do
|
92
|
+
command = %(spec/support/bigrig_vcr "#{casette_name}" #{args.join ' '})
|
93
|
+
_pid, output = capture_stdout command
|
94
|
+
|
95
|
+
expect(output).to match(/^\e\[0;32;49mlog-test\e\[0m: .+ container 1 stdout/)
|
96
|
+
expect(output).to match(/^\e\[0;32;49mlog-test\e\[0m: .+ container 1 stderr/)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'run' do
|
102
|
+
context 'spec/data/single.json' do
|
103
|
+
let(:args) { ['run'] }
|
104
|
+
let(:output) { subject }
|
105
|
+
let(:container) { Docker::Container.get 'single-test' }
|
106
|
+
let(:running?) { container.json['State']['Running'] }
|
107
|
+
let(:file) { 'spec/data/single.json' }
|
108
|
+
|
109
|
+
after { container.kill.delete }
|
110
|
+
|
111
|
+
it 'starts the container', :vcr do
|
112
|
+
subject
|
113
|
+
expect(running?).to be true
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'sends the name of the container to stdout', :vcr do
|
117
|
+
expect(output).to match(/^Starting single-test/)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'spec/data/profiles.json -p qa' do
|
122
|
+
let(:args) { ['run', '-p qa'] }
|
123
|
+
let(:container) { Docker::Container.get('profiles') }
|
124
|
+
let(:image) { Docker::Image.get 'hawknewton/show-env' }
|
125
|
+
let(:file) { 'spec/data/profiles.json' }
|
126
|
+
let(:env) do
|
127
|
+
url = URI.parse Docker.connection.url
|
128
|
+
text = Net::HTTP.get URI.parse("http://#{url.host}:4567")
|
129
|
+
text.split("\n").each_with_object({}) { |e, o| o.store(*e.split('=')) }
|
130
|
+
end
|
131
|
+
|
132
|
+
after { container.kill.delete }
|
133
|
+
|
134
|
+
it 'overrides the tag', :vcr do
|
135
|
+
subject
|
136
|
+
expect(container.info['Image']).to eq image.id
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'overrides the env', :vcr do
|
140
|
+
subject
|
141
|
+
sleep 1
|
142
|
+
expect(env).to include 'NAME1' => 'VALUE1A'
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'leaves existing env values alone', :vcr do
|
146
|
+
subject
|
147
|
+
sleep 1
|
148
|
+
expect(env).to include 'NAME2' => 'VALUE2'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'destroy' do
|
154
|
+
context 'spec/data/single.json' do
|
155
|
+
let(:args) { ['destroy'] }
|
156
|
+
let(:file) { 'spec/data/single.json' }
|
157
|
+
before do
|
158
|
+
c = Docker::Container.create 'name' => 'single-test', 'Image' => 'hawknewton/show-env'
|
159
|
+
c.start
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'kills the container', :vcr do
|
163
|
+
subject
|
164
|
+
begin
|
165
|
+
Docker::Container.get 'single-test'
|
166
|
+
fail 'Container still exists!'
|
167
|
+
rescue Docker::Error::NotFoundError # rubocop:disable Lint/HandleExceptions
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'ship' do
|
174
|
+
context 'spec/data/ship.json' do
|
175
|
+
context 'with a version' do
|
176
|
+
let(:args) { ['ship', version] }
|
177
|
+
let(:dir) { Dir.mktmpdir }
|
178
|
+
let(:file) do
|
179
|
+
descriptor = {
|
180
|
+
containers: {
|
181
|
+
'ship-me' => {
|
182
|
+
repo: "#{repo}:5000/test/ship-me",
|
183
|
+
path: 'build'
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
file = Tempfile.new('bigrig').path
|
188
|
+
File.write file, JSON.dump(descriptor)
|
189
|
+
file
|
190
|
+
end
|
191
|
+
let(:here) { "#{File.expand_path '../..', __FILE__}/" }
|
192
|
+
let(:registry) do
|
193
|
+
Docker::Container.create(
|
194
|
+
'name' => 'registry',
|
195
|
+
'Image' => 'registry',
|
196
|
+
'Env' => ['GUNICORN_OPTS=[--preload]'],
|
197
|
+
'ExposedPorts' => {
|
198
|
+
'5000/tcp' => {}
|
199
|
+
},
|
200
|
+
'HostConfig' => {
|
201
|
+
'PortBindings' => { '5000/tcp' => [{ 'HostPort' => '5000' }] }
|
202
|
+
}
|
203
|
+
)
|
204
|
+
end
|
205
|
+
let(:version) { '1.2.3' }
|
206
|
+
let(:repo) { URI.parse(Docker.connection.url).host }
|
207
|
+
|
208
|
+
before do
|
209
|
+
registry.start
|
210
|
+
end
|
211
|
+
|
212
|
+
after do
|
213
|
+
registry.kill.delete
|
214
|
+
end
|
215
|
+
|
216
|
+
around do |example|
|
217
|
+
FileUtils.copy_file file, File.join(dir, 'bigrig.json')
|
218
|
+
FileUtils.cp_r "#{test_file('.')}/build", dir
|
219
|
+
Dir.chdir dir do
|
220
|
+
example.run
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'builds and pushes the image', :vcr do
|
225
|
+
subject
|
226
|
+
expect { Docker::Image.get "#{repo}:5000/test/ship-me:#{version}" }.to_not raise_error
|
227
|
+
end
|
228
|
+
|
229
|
+
context '-c' do
|
230
|
+
let(:args) { ['ship', '-c', version] }
|
231
|
+
|
232
|
+
it 'cleans the image when it''s done', :vcr do
|
233
|
+
subject
|
234
|
+
expect { Docker::Image.get "#{repo}:5000/test/ship-me:#{version}" }.
|
235
|
+
to raise_error(Docker::Error::NotFoundError)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
context 'with no version' do
|
240
|
+
let(:args) { ['ship'] }
|
241
|
+
let(:file) { test_file 'ship.json' }
|
242
|
+
|
243
|
+
it 'raises an error' do
|
244
|
+
expect(output).to match(/version is required/)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"containers": {
|
3
|
+
"profiles": {
|
4
|
+
"repo": "hawknewton/true",
|
5
|
+
"tag": "0.0.1",
|
6
|
+
"env": {
|
7
|
+
"NAME1": "VALUE1",
|
8
|
+
"NAME2": "VALUE2"
|
9
|
+
},
|
10
|
+
"ports": ["4567:80"]
|
11
|
+
}
|
12
|
+
},
|
13
|
+
|
14
|
+
"profiles": {
|
15
|
+
"new": {
|
16
|
+
"new": {
|
17
|
+
"repo": "hawknewton/show-env",
|
18
|
+
"env": {
|
19
|
+
"NAME1": "VALUE1A"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
File without changes
|
data/spec/data/dev.json
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"containers": {
|
3
|
+
"dev-test": {
|
4
|
+
"repo": "hawknewton/show-env",
|
5
|
+
"tag": "0.0.1",
|
6
|
+
"env": {
|
7
|
+
"PROFILE": "default"
|
8
|
+
},
|
9
|
+
"ports": ["4568:80"]
|
10
|
+
},
|
11
|
+
"dev-logs": {
|
12
|
+
"repo": "hawknewton/log-test",
|
13
|
+
"tag": "0.0.1"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
|
17
|
+
"profiles": {
|
18
|
+
"dev": {
|
19
|
+
"dev-test": {
|
20
|
+
"env": {
|
21
|
+
"PROFILE": "dev"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
data/spec/data/env.json
ADDED
data/spec/data/log.json
ADDED
data/spec/data/path.json
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"containers": {
|
3
|
+
"profiles": {
|
4
|
+
"repo": "hawknewton/true",
|
5
|
+
"tag": "0.0.1",
|
6
|
+
"env": {
|
7
|
+
"NAME1": "VALUE1",
|
8
|
+
"NAME2": "VALUE2"
|
9
|
+
},
|
10
|
+
"ports": ["4567:80"]
|
11
|
+
}
|
12
|
+
},
|
13
|
+
|
14
|
+
"profiles": {
|
15
|
+
"qa": {
|
16
|
+
"profiles": {
|
17
|
+
"repo": "hawknewton/show-env",
|
18
|
+
"env": {
|
19
|
+
"NAME1": "VALUE1A"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
data/spec/data/ship.json
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"containers": {
|
3
|
+
"profiles": {
|
4
|
+
"repo": "hawknewton/true",
|
5
|
+
"tag": "0.0.1",
|
6
|
+
"env": {
|
7
|
+
"NAME1": "VALUE1",
|
8
|
+
"NAME2": "VALUE2"
|
9
|
+
},
|
10
|
+
"ports": ["4567:80"]
|
11
|
+
}
|
12
|
+
},
|
13
|
+
|
14
|
+
"profiles": {
|
15
|
+
"qa": {
|
16
|
+
"profiles": {
|
17
|
+
"repo": "hawknewton/show-env",
|
18
|
+
"env": {
|
19
|
+
"NAME1": "VALUE1A"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'bigrig'
|
2
|
+
require 'rspec/its'
|
3
|
+
|
4
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
# Suppress stdout if we're not focused on asingle file
|
8
|
+
unless config.files_to_run.one?
|
9
|
+
config.before { allow($stdout).to receive(:puts) }
|
10
|
+
end
|
11
|
+
|
12
|
+
# rspec-expectations config goes here. You can use an alternate
|
13
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
14
|
+
# assertions if you prefer.
|
15
|
+
config.expect_with :rspec do |expectations|
|
16
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
17
|
+
# and `failure_message` of custom matchers include text for helper methods
|
18
|
+
# defined using `chain`, e.g.:
|
19
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
20
|
+
# # => "be bigger than 2 and smaller than 4"
|
21
|
+
# ...rather than:
|
22
|
+
# # => "be bigger than 2"
|
23
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
24
|
+
end
|
25
|
+
|
26
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
27
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
28
|
+
config.mock_with :rspec do |mocks|
|
29
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
30
|
+
# a real object. This is generally recommended, and will default to
|
31
|
+
# `true` in RSpec 4.
|
32
|
+
mocks.verify_partial_doubles = true
|
33
|
+
end
|
34
|
+
|
35
|
+
# The settings below are suggested to provide a good initial experience
|
36
|
+
# with RSpec, but feel free to customize to your heart's content.
|
37
|
+
# # These two settings work together to allow you to limit a spec run
|
38
|
+
# # to individual examples or groups you care about by tagging them with
|
39
|
+
# # `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
40
|
+
# # get run.
|
41
|
+
# config.filter_run :focus
|
42
|
+
# config.run_all_when_everything_filtered = true
|
43
|
+
#
|
44
|
+
# # Limits the available syntax to the non-monkey patched syntax that is recommended.
|
45
|
+
# # For more details, see:
|
46
|
+
# # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
47
|
+
# # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
48
|
+
# # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
49
|
+
# config.disable_monkey_patching!
|
50
|
+
#
|
51
|
+
# # This setting enables warnings. It's recommended, but in some cases may
|
52
|
+
# # be too noisy due to issues in dependencies.
|
53
|
+
# config.warnings = true
|
54
|
+
#
|
55
|
+
# # Many RSpec users commonly either run the entire suite or an individual
|
56
|
+
# # file, and it's useful to allow more verbose output when running an
|
57
|
+
# # individual spec file.
|
58
|
+
# if config.files_to_run.one?
|
59
|
+
# # Use the documentation formatter for detailed output,
|
60
|
+
# # unless a formatter has already been configured
|
61
|
+
# # (e.g. via a command-line flag).
|
62
|
+
# config.default_formatter = 'doc'
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# # Print the 10 slowest examples and example groups at the
|
66
|
+
# # end of the spec run, to help surface which specs are running
|
67
|
+
# # particularly slow.
|
68
|
+
# config.profile_examples = 10
|
69
|
+
#
|
70
|
+
# # Run specs in random order to surface order dependencies. If you find an
|
71
|
+
# # order dependency and want to debug it, you can fix the order by providing
|
72
|
+
# # the seed, which is printed after each run.
|
73
|
+
# # --seed 1234
|
74
|
+
# config.order = :random
|
75
|
+
#
|
76
|
+
# # Seed global randomization in this process using the `--seed` CLI option.
|
77
|
+
# # Setting this allows you to use `--seed` to deterministically reproduce
|
78
|
+
# # test failures related to randomization by passing the same `--seed` value
|
79
|
+
# # as the one that triggered the failure.
|
80
|
+
# Kernel.srand config.seed
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_file(name)
|
84
|
+
File.expand_path "../data/#{name}", __FILE__
|
85
|
+
end
|
86
|
+
|
87
|
+
def capture_stdout(command)
|
88
|
+
pid, _stdin, stdout, _stderr = Open4.popen4 command
|
89
|
+
output = read_stdout stdout
|
90
|
+
[pid, output]
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_stdout(stdout)
|
94
|
+
output = ''
|
95
|
+
5.times do
|
96
|
+
begin
|
97
|
+
output << stdout.read_nonblock(512_000)
|
98
|
+
rescue => e
|
99
|
+
e.is_a?(EOFError) && break # The things I do for method length...
|
100
|
+
end
|
101
|
+
sleep 1
|
102
|
+
end
|
103
|
+
output
|
104
|
+
end
|
data/spec/support/vcr.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'vcr'
|
2
|
+
require 'webmock'
|
3
|
+
require 'docker'
|
4
|
+
|
5
|
+
VCR.configure do |c|
|
6
|
+
c.allow_http_connections_when_no_cassette = false
|
7
|
+
c.filter_sensitive_data('<DOCKER_HOST>') { Docker.url.sub(/tcp\:/, 'https:') }
|
8
|
+
c.filter_sensitive_data('<DOCKER_HTTP>') { "http:#{Docker.url.split(':')[1]}:4567" }
|
9
|
+
c.filter_sensitive_data('<USERNAME>') { ENV['DOCKER_API_USER'] }
|
10
|
+
c.filter_sensitive_data('<PASSWORD>') { ENV['DOCKER_API_PASS'] }
|
11
|
+
c.filter_sensitive_data('<EMAIL>') { ENV['DOCKER_API_EMAIL'] }
|
12
|
+
c.hook_into :excon, :webmock
|
13
|
+
c.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'vcr')
|
14
|
+
defined?(RSpec) && c.configure_rspec_metadata!
|
15
|
+
end
|