dockistrano 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +1 -0
- data/bin/doc +13 -0
- data/bin/docker +0 -0
- data/dockistrano.gemspec +32 -0
- data/lib/dockistrano/cli.rb +220 -0
- data/lib/dockistrano/command_line.rb +28 -0
- data/lib/dockistrano/docker.rb +188 -0
- data/lib/dockistrano/git.rb +27 -0
- data/lib/dockistrano/hipache.rb +62 -0
- data/lib/dockistrano/registry.rb +48 -0
- data/lib/dockistrano/service.rb +331 -0
- data/lib/dockistrano/service_dependency.rb +114 -0
- data/lib/dockistrano/version.rb +3 -0
- data/lib/dockistrano.rb +14 -0
- data/spec/dockistrano/cli_spec.rb +296 -0
- data/spec/dockistrano/command_line_spec.rb +27 -0
- data/spec/dockistrano/docker_spec.rb +242 -0
- data/spec/dockistrano/git_spec.rb +48 -0
- data/spec/dockistrano/hipache_spec.rb +81 -0
- data/spec/dockistrano/registry_spec.rb +56 -0
- data/spec/dockistrano/service_dependency_spec.rb +154 -0
- data/spec/dockistrano/service_spec.rb +536 -0
- data/spec/fixtures/project_1/Dockerfile +0 -0
- data/spec/fixtures/project_1/config/dockistrano.yml +8 -0
- data/spec/spec_helper.rb +21 -0
- metadata +242 -0
@@ -0,0 +1,536 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockistrano::Service do
|
4
|
+
|
5
|
+
subject { described_class.new(config, "default") }
|
6
|
+
let(:config) {{
|
7
|
+
"default" => {
|
8
|
+
"image_name" => "image",
|
9
|
+
"tag" => "tag",
|
10
|
+
"registry" => "index.provide.dev:5000"
|
11
|
+
}
|
12
|
+
}}
|
13
|
+
|
14
|
+
context ".factory" do
|
15
|
+
it "initializes a service for the current directory" do
|
16
|
+
service = described_class.factory("spec/fixtures/project_1")
|
17
|
+
expect(service.config).to eq({
|
18
|
+
"registry" => "my.registry.com:5000",
|
19
|
+
"image_name" => "project_1",
|
20
|
+
"dependencies" => {
|
21
|
+
"redis" => "git@github.com:username/redis.git",
|
22
|
+
"memcached" => "git@github.com:username/memcached.git"
|
23
|
+
},
|
24
|
+
"environment" => {}
|
25
|
+
})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#config=" do
|
30
|
+
subject { described_class.new({ "default" => {} }, "default") }
|
31
|
+
|
32
|
+
it "uses the name of the git repository as the name of the image" do
|
33
|
+
expect(Dockistrano::Git).to receive(:repository_name).and_return("repo_name")
|
34
|
+
subject.config = {}
|
35
|
+
expect(subject.image_name).to eq("repo_name")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "uses the git branch as the tag" do
|
39
|
+
expect(Dockistrano::Git).to receive(:branch).and_return("develop")
|
40
|
+
subject.config = {}
|
41
|
+
expect(subject.tag).to eq("develop")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "#environment=" do
|
46
|
+
let(:config) {{
|
47
|
+
"default" => { "test_command" => "default" },
|
48
|
+
"test" => { "test_command" => "test" }
|
49
|
+
}}
|
50
|
+
|
51
|
+
it "sets the config to the new environment" do
|
52
|
+
subject.environment = "test"
|
53
|
+
expect(subject.config).to eq({ "test_command" => "test", "environment" => {} })
|
54
|
+
end
|
55
|
+
|
56
|
+
it "raises an error when the environment is not found" do
|
57
|
+
expect {
|
58
|
+
subject.environment = "foobar"
|
59
|
+
}.to raise_error(Dockistrano::Service::EnvironmentNotFoundInConfiguration)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "#registry_instance" do
|
64
|
+
it "returns an instance of the registry" do
|
65
|
+
expect(Dockistrano::Registry).to receive(:new).and_return(instance = double)
|
66
|
+
expect(subject.registry_instance).to eq(instance)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "#image_id" do
|
71
|
+
it "returns the image id of the current container" do
|
72
|
+
expect(Dockistrano::Docker).to receive(:image_id).with(subject.full_image_name).and_return(123456789)
|
73
|
+
expect(subject.image_id).to eq(123456789)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns nil when the image is not found" do
|
77
|
+
expect(Dockistrano::Docker).to receive(:image_id).with(subject.full_image_name).and_raise(Dockistrano::Docker::ImageNotFound)
|
78
|
+
expect(subject.image_id).to be_nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "#full_image_name" do
|
83
|
+
let(:config) {{
|
84
|
+
"default" => {
|
85
|
+
"image_name" => "image",
|
86
|
+
"tag" => "tag",
|
87
|
+
"registry" => "index.provider.dev:5000"
|
88
|
+
}
|
89
|
+
}}
|
90
|
+
|
91
|
+
it "returns the name with registry and tag" do
|
92
|
+
expect(subject.full_image_name).to eq("index.provider.dev:5000/image:tag")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "#build" do
|
97
|
+
it "builds the container" do
|
98
|
+
allow(subject).to receive(:image_id).and_return(123, 456)
|
99
|
+
allow(subject).to receive(:full_image_name).and_return("full_image_name")
|
100
|
+
expect(Dockistrano::Docker).to receive(:build).with("full_image_name")
|
101
|
+
expect(subject.build).to be_true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "returns false when the build didn't change the image id" do
|
105
|
+
allow(subject).to receive(:image_id).and_return(123, 123)
|
106
|
+
allow(subject).to receive(:full_image_name).and_return("full_image_name")
|
107
|
+
expect(Dockistrano::Docker).to receive(:build).with("full_image_name")
|
108
|
+
expect(subject.build).to be_false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "#test" do
|
113
|
+
before do
|
114
|
+
allow(subject).to receive(:full_image_name).and_return("full_image_name")
|
115
|
+
allow(subject).to receive(:test_command).and_return("rake test")
|
116
|
+
allow(subject).to receive(:checked_environment_variables).and_return(environment_variables)
|
117
|
+
allow(subject).to receive(:volumes).and_return(volumes)
|
118
|
+
end
|
119
|
+
|
120
|
+
let(:environment_variables) { double }
|
121
|
+
let(:volumes) { double }
|
122
|
+
|
123
|
+
it "tests the container" do
|
124
|
+
expect(subject).to receive(:ensure_backing_services)
|
125
|
+
expect(Dockistrano::Docker).to receive(:exec).with("full_image_name", command: "rake test", e: environment_variables, v: volumes).and_return(true)
|
126
|
+
expect(subject.test).to be_true
|
127
|
+
end
|
128
|
+
|
129
|
+
it "returns true when no test command is provided" do
|
130
|
+
allow(subject).to receive(:test_command).and_return("")
|
131
|
+
expect(subject.test).to be_true
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "#ensure_backing_services" do
|
136
|
+
before do
|
137
|
+
allow(subject).to receive(:backing_services).and_return({ "service_1" => service_1, "service_2" => service_2 })
|
138
|
+
end
|
139
|
+
let(:service_1) { double }
|
140
|
+
let(:service_2) { double }
|
141
|
+
|
142
|
+
it "starts services that are not running" do
|
143
|
+
expect(service_1).to receive(:running?).and_return(true)
|
144
|
+
expect(service_2).to receive(:running?).and_return(false)
|
145
|
+
|
146
|
+
expect(service_2).to receive(:start)
|
147
|
+
subject.ensure_backing_services
|
148
|
+
end
|
149
|
+
|
150
|
+
it "doesn't start services that are already running" do
|
151
|
+
expect(service_1).to receive(:running?).and_return(true)
|
152
|
+
expect(service_2).to receive(:running?).and_return(true)
|
153
|
+
|
154
|
+
expect(service_1).to_not receive(:start)
|
155
|
+
expect(service_2).to_not receive(:start)
|
156
|
+
subject.ensure_backing_services
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "#stop" do
|
161
|
+
let(:hipache) { double }
|
162
|
+
|
163
|
+
before do
|
164
|
+
allow(Dockistrano::Docker).to receive(:stop_all_containers_from_image)
|
165
|
+
allow(Dockistrano::Hipache).to receive(:new).and_return(hipache)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "stops the container" do
|
169
|
+
expect(Dockistrano::Docker).to receive(:stop_all_containers_from_image).with(subject.full_image_name)
|
170
|
+
subject.stop
|
171
|
+
end
|
172
|
+
|
173
|
+
it "unregisters a host from Hipache" do
|
174
|
+
allow(subject).to receive(:host).and_return("hostname.dev")
|
175
|
+
expect(subject).to receive(:ip_address).and_return("33.33.33.33")
|
176
|
+
expect(subject).to receive(:port).and_return("3000")
|
177
|
+
expect(hipache).to receive(:unregister).with(subject.image_name, "hostname.dev", "33.33.33.33", "3000")
|
178
|
+
subject.stop
|
179
|
+
end
|
180
|
+
|
181
|
+
it "unregisters multiple hosts from Hipache" do
|
182
|
+
allow(subject).to receive(:host).and_return({ "hostname.dev" => "8000" })
|
183
|
+
expect(subject).to receive(:ip_address).and_return("33.33.33.33")
|
184
|
+
expect(hipache).to receive(:unregister).with(subject.image_name, "hostname.dev", "33.33.33.33", "8000")
|
185
|
+
subject.stop
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "#running?" do
|
190
|
+
before do
|
191
|
+
allow(subject).to receive(:full_image_name).and_return("image_name:tag")
|
192
|
+
end
|
193
|
+
|
194
|
+
it "returns true when the service is running" do
|
195
|
+
expect(Dockistrano::Docker).to receive(:running_container_id).with("image_name:tag").and_return("423c138040f1")
|
196
|
+
expect(subject.running?).to eq("423c138040f1")
|
197
|
+
end
|
198
|
+
|
199
|
+
it "returns false when the service is not running" do
|
200
|
+
expect(Dockistrano::Docker).to receive(:running_container_id).with("image_name:tag").and_return(nil)
|
201
|
+
expect(subject.running?).to eq(nil)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "#pull_backing_services" do
|
206
|
+
before do
|
207
|
+
allow(subject).to receive(:backing_services).and_return({ "service_1" => service_1, "service_2" => service_2 })
|
208
|
+
end
|
209
|
+
let(:service_1) { double }
|
210
|
+
let(:service_2) { double }
|
211
|
+
|
212
|
+
it "pulls each backing service" do
|
213
|
+
expect(service_1).to receive(:pull)
|
214
|
+
expect(service_2).to receive(:pull)
|
215
|
+
subject.pull_backing_services
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context "#pull" do
|
220
|
+
before do
|
221
|
+
allow(subject).to receive(:registry).and_return("registry.net:5000")
|
222
|
+
allow(subject).to receive(:image_name).and_return("image_name")
|
223
|
+
allow(subject).to receive(:tag_with_fallback).and_return("latest")
|
224
|
+
end
|
225
|
+
|
226
|
+
it "pulls the service's container" do
|
227
|
+
expect(Dockistrano::Docker).to receive(:pull).with("registry.net:5000/image_name", "latest")
|
228
|
+
subject.pull
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context "#push" do
|
233
|
+
it "pushes the current container to the registry" do
|
234
|
+
allow(subject).to receive(:registry).and_return("registry.net:5000")
|
235
|
+
allow(subject).to receive(:image_name).and_return("image_name")
|
236
|
+
allow(subject).to receive(:tag).and_return("tag")
|
237
|
+
expect(Dockistrano::Docker).to receive(:push).with("registry.net:5000/image_name", "tag")
|
238
|
+
subject.push
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context "#start" do
|
243
|
+
let(:environment) { double }
|
244
|
+
let(:volumes) { double }
|
245
|
+
let(:ports) { double }
|
246
|
+
let(:hipache) { double }
|
247
|
+
|
248
|
+
before do
|
249
|
+
allow(Dockistrano::Hipache).to receive(:new).and_return(hipache)
|
250
|
+
allow(subject).to receive(:ensure_backing_services)
|
251
|
+
allow(subject).to receive(:create_data_directories)
|
252
|
+
allow(subject).to receive(:checked_environment_variables).and_return(environment)
|
253
|
+
allow(subject).to receive(:volumes).and_return(volumes)
|
254
|
+
allow(subject).to receive(:ports).and_return(ports)
|
255
|
+
allow(Dockistrano::Docker).to receive(:run)
|
256
|
+
end
|
257
|
+
|
258
|
+
it "ensures backing services are running" do
|
259
|
+
expect(subject).to receive(:ensure_backing_services)
|
260
|
+
subject.start
|
261
|
+
end
|
262
|
+
|
263
|
+
it "creates data directories" do
|
264
|
+
expect(subject).to receive(:create_data_directories)
|
265
|
+
subject.start
|
266
|
+
end
|
267
|
+
|
268
|
+
it "starts additional container when additional commands are configured" do
|
269
|
+
allow(subject).to receive(:additional_commands).and_return({ "worker" => "sidekiq start" })
|
270
|
+
expect(Dockistrano::Docker).to receive(:run).with(subject.full_image_name, e: environment, v: volumes, p: ports, d: true, command: "sidekiq start")
|
271
|
+
subject.start
|
272
|
+
end
|
273
|
+
|
274
|
+
it "starts the container with the default command, providing env variables and volumes" do
|
275
|
+
expect(Dockistrano::Docker).to receive(:run).with(subject.full_image_name, e: environment, v: volumes, p: ports, d: true)
|
276
|
+
subject.start
|
277
|
+
end
|
278
|
+
|
279
|
+
it "registers a host with Hipache" do
|
280
|
+
allow(subject).to receive(:host).and_return("hostname.dev")
|
281
|
+
expect(subject).to receive(:ip_address).and_return("33.33.33.33")
|
282
|
+
expect(subject).to receive(:port).and_return("3000")
|
283
|
+
expect(hipache).to receive(:register).with(subject.image_name, "hostname.dev", "33.33.33.33", "3000")
|
284
|
+
subject.start
|
285
|
+
end
|
286
|
+
|
287
|
+
it "registers multiple hosts with Hipache" do
|
288
|
+
allow(subject).to receive(:host).and_return({ "hostname.dev" => "8000" })
|
289
|
+
expect(subject).to receive(:ip_address).and_return("33.33.33.33")
|
290
|
+
expect(hipache).to receive(:register).with(subject.image_name, "hostname.dev", "33.33.33.33", "8000")
|
291
|
+
subject.start
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context "#run" do
|
296
|
+
it "runs the command inside the container" do
|
297
|
+
allow(subject).to receive(:environment_variables).and_return(environment = double)
|
298
|
+
allow(subject).to receive(:volumes).and_return(volumes = double)
|
299
|
+
allow(subject).to receive(:ports).and_return(ports = double)
|
300
|
+
expect(Dockistrano::Docker).to receive(:run).with(subject.full_image_name, e: environment, v: volumes, p: ports, command: "foobar")
|
301
|
+
subject.run("foobar")
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "#exec" do
|
306
|
+
it "executes the command inside the container" do
|
307
|
+
allow(subject).to receive(:environment_variables).and_return(environment = double)
|
308
|
+
allow(subject).to receive(:volumes).and_return(volumes = double)
|
309
|
+
allow(subject).to receive(:ports).and_return(ports = double)
|
310
|
+
expect(subject).to receive(:create_data_directories)
|
311
|
+
expect(Dockistrano::Docker).to receive(:exec).with(subject.full_image_name, e: environment, v: volumes, p: ports, command: "foobar")
|
312
|
+
subject.exec("foobar")
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "#console" do
|
317
|
+
it "runs the command inside the container" do
|
318
|
+
allow(subject).to receive(:environment_variables).and_return(environment = double)
|
319
|
+
allow(subject).to receive(:volumes).and_return(volumes = double)
|
320
|
+
allow(subject).to receive(:ports).and_return(ports = double)
|
321
|
+
expect(subject).to receive(:create_data_directories)
|
322
|
+
expect(Dockistrano::Docker).to receive(:console).with(subject.full_image_name, e: environment, v: volumes, p: ports, command: "foobar")
|
323
|
+
subject.console("foobar")
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
context "#backing_services" do
|
328
|
+
let(:service) { double }
|
329
|
+
|
330
|
+
before do
|
331
|
+
allow(subject).to receive(:dependencies).and_return({"postgresql" => {}})
|
332
|
+
end
|
333
|
+
|
334
|
+
it "returns a hash with backing services" do
|
335
|
+
expect(Dockistrano::ServiceDependency).to receive(:factory).with(subject, "postgresql", {}).and_return(service)
|
336
|
+
expect(subject.backing_services).to eq({ "postgresql" => service })
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context "#environment_variables" do
|
341
|
+
let(:backing_service){
|
342
|
+
double(
|
343
|
+
ip_address: "172.0.0.1",
|
344
|
+
port: "1245",
|
345
|
+
backing_service_env: { database: "dockistrano_development" },
|
346
|
+
environment_variables: { "DATABASE_URL" => "postgres://postgres@$POSTGRESQL_IP/$POSTGRESQL_DATABASE"}
|
347
|
+
)
|
348
|
+
}
|
349
|
+
|
350
|
+
before do
|
351
|
+
allow(subject).to receive(:backing_services).and_return({ "postgresql" => backing_service })
|
352
|
+
end
|
353
|
+
|
354
|
+
it "includes environment variables from the current containers configuration" do
|
355
|
+
subject.config = { "environment" => { "rails_env" => "test" } }
|
356
|
+
expect(subject.environment_variables).to include("RAILS_ENV")
|
357
|
+
expect(subject.environment_variables["RAILS_ENV"]).to eq("test")
|
358
|
+
end
|
359
|
+
|
360
|
+
it "includes environment variables with the ip and port of each backing service" do
|
361
|
+
expect(subject.environment_variables).to include("POSTGRESQL_IP")
|
362
|
+
expect(subject.environment_variables).to include("POSTGRESQL_PORT")
|
363
|
+
end
|
364
|
+
|
365
|
+
it "includes variables for the backing service provided in the local configuration" do
|
366
|
+
expect(subject.environment_variables).to include("POSTGRESQL_DATABASE")
|
367
|
+
expect(subject.environment_variables["POSTGRESQL_DATABASE"]).to eq("dockistrano_development")
|
368
|
+
end
|
369
|
+
|
370
|
+
it "includes environment variables from each backing service" do
|
371
|
+
expect(backing_service).to receive(:environment_variables).and_return({ "SUB_ENV" => "some_value" })
|
372
|
+
expect(subject.environment_variables["SUB_ENV"]).to eq("some_value")
|
373
|
+
end
|
374
|
+
|
375
|
+
it "includes environment variables that are provided by the service" do
|
376
|
+
expect(subject).to receive(:provides_env).and_return({ "BUNDLE_PATH" => "/bundle" })
|
377
|
+
expect(subject.environment_variables["BUNDLE_PATH"]).to eq("/bundle")
|
378
|
+
end
|
379
|
+
|
380
|
+
it "interpolates environment variables with present values" do
|
381
|
+
expect(subject.environment_variables["DATABASE_URL"]).to eq("postgres://postgres@172.0.0.1/dockistrano_development")
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context "#volumes" do
|
386
|
+
it "includes a default data volume" do
|
387
|
+
expect(subject.volumes).to include("/dockistrano/image/data:/dockistrano/data")
|
388
|
+
end
|
389
|
+
|
390
|
+
it "includes a source mount when configured" do
|
391
|
+
allow(subject).to receive(:mount_src).and_return("/home/app")
|
392
|
+
expect(subject.volumes).to include("/dockistrano/image/src:/home/app")
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context "#directories_required_on_host"
|
397
|
+
|
398
|
+
context "#available_tags" do
|
399
|
+
it "returns a list of available tags for the current service" do
|
400
|
+
expect(subject).to receive(:registry_instance).and_return(registry = double)
|
401
|
+
expect(registry).to receive(:tags_for_image).with(subject.full_image_name).and_return(["develop", "master"])
|
402
|
+
expect(subject.available_tags).to eq(["develop", "master"])
|
403
|
+
end
|
404
|
+
|
405
|
+
it "returns an empty list when the repository is not found in the registry" do
|
406
|
+
expect(subject).to receive(:registry_instance).and_return(registry = double)
|
407
|
+
expect(registry).to receive(:tags_for_image).with(subject.full_image_name).and_raise(Dockistrano::Registry::RepositoryNotFoundInRegistry)
|
408
|
+
expect(subject.available_tags).to eq([])
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
context "#tag_with_fallback" do
|
413
|
+
it "uses the feature branch when available" do
|
414
|
+
allow(subject).to receive(:tag).and_return("feature_branch")
|
415
|
+
allow(subject).to receive(:available_tags).and_return(["develop", "master", "feature_branch"])
|
416
|
+
expect(subject.tag_with_fallback).to eq("feature_branch")
|
417
|
+
end
|
418
|
+
|
419
|
+
it "uses the develop branch when available" do
|
420
|
+
allow(subject).to receive(:tag).and_return("feature_branch")
|
421
|
+
allow(subject).to receive(:available_tags).and_return(["develop", "master", "latest"])
|
422
|
+
expect(subject.tag_with_fallback).to eq("develop")
|
423
|
+
end
|
424
|
+
|
425
|
+
it "uses the master branch when available" do
|
426
|
+
allow(subject).to receive(:tag).and_return("feature_branch")
|
427
|
+
allow(subject).to receive(:available_tags).and_return(["master", "latest"])
|
428
|
+
expect(subject.tag_with_fallback).to eq("master")
|
429
|
+
end
|
430
|
+
|
431
|
+
it "uses the latest branch when available" do
|
432
|
+
allow(subject).to receive(:tag).and_return("feature_branch")
|
433
|
+
allow(subject).to receive(:available_tags).and_return(["latest"])
|
434
|
+
expect(subject.tag_with_fallback).to eq("latest")
|
435
|
+
end
|
436
|
+
|
437
|
+
it "raises an error when no tags are found" do
|
438
|
+
allow(subject).to receive(:tag).and_return("feature_branch")
|
439
|
+
allow(subject).to receive(:available_tags).and_return(["foobar", "test"])
|
440
|
+
expect { subject.tag_with_fallback }.to raise_error(Dockistrano::Service::NoTagFoundForImage)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context "#ip_address" do
|
445
|
+
it "returns the ip address of the running container" do
|
446
|
+
allow(subject).to receive(:running?).and_return(true)
|
447
|
+
allow(subject).to receive(:container_settings).and_return({ "NetworkSettings" => { "IPAddress" => "33.33.33.10" }})
|
448
|
+
expect(subject.ip_address).to eq("33.33.33.10")
|
449
|
+
end
|
450
|
+
|
451
|
+
it "returns nil when the container is not running" do
|
452
|
+
allow(subject).to receive(:running?).and_return(false)
|
453
|
+
expect(subject.ip_address).to be_nil
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
context "#port" do
|
458
|
+
it "returns the ip address of the running container" do
|
459
|
+
allow(subject).to receive(:running?).and_return(true)
|
460
|
+
allow(subject).to receive(:container_settings).and_return({ "NetworkSettings" => { "PortMapping" => { "Tcp" => { "8000" => "80" } } } })
|
461
|
+
expect(subject.port).to eq("8000")
|
462
|
+
end
|
463
|
+
|
464
|
+
it "returns nil when the container is not running" do
|
465
|
+
allow(subject).to receive(:running?).and_return(false)
|
466
|
+
expect(subject.port).to be_nil
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
context "#ports" do
|
471
|
+
it "returns a string representation of the port mappings" do
|
472
|
+
subject.config = { "ports" => { "1234" => "5678" } }
|
473
|
+
expect(subject.ports).to eq(["1234:5678"])
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
context "#attach" do
|
478
|
+
it "attaches to the output of the container" do
|
479
|
+
expect(Dockistrano::Docker).to receive(:attach).with("123456")
|
480
|
+
expect(Dockistrano::Docker).to receive(:running_container_id).with(subject.full_image_name).and_return("123456")
|
481
|
+
subject.attach
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
context "#logs" do
|
486
|
+
it "returns the logs of the last run of the container" do
|
487
|
+
expect(Dockistrano::Docker).to receive(:logs).with("123456")
|
488
|
+
expect(Dockistrano::Docker).to receive(:last_run_container_id).with(subject.full_image_name).and_return("123456")
|
489
|
+
subject.logs
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
context "#create_data_directories" do
|
494
|
+
it "creates directories in the mounted data folder" do
|
495
|
+
allow(subject).to receive(:data_directories).and_return(["logs"])
|
496
|
+
allow(subject).to receive(:volumes).and_return(volumes = double)
|
497
|
+
allow(subject).to receive(:environment_variables).and_return(environment_variables = double)
|
498
|
+
allow(Dockistrano::Docker).to receive(:inspect_image).with(subject.full_image_name).and_return({ "container_config" => { "User" => "app" }})
|
499
|
+
|
500
|
+
expect(Dockistrano::Docker).to receive(:run).with(subject.full_image_name,
|
501
|
+
v: volumes,
|
502
|
+
e: environment_variables,
|
503
|
+
u: "root",
|
504
|
+
command: "/bin/bash -c 'mkdir -p /dockistrano/data/logs; chown app:app /dockistrano/data/logs'"
|
505
|
+
)
|
506
|
+
|
507
|
+
subject.create_data_directories
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
context "#newer_version_available?" do
|
512
|
+
let(:registry_instance) { double }
|
513
|
+
|
514
|
+
before do
|
515
|
+
allow(subject).to receive(:registry_instance).and_return(registry_instance)
|
516
|
+
end
|
517
|
+
|
518
|
+
it "returns true when a newer version of the image is available" do
|
519
|
+
expect(subject).to receive(:image_id).and_return("1")
|
520
|
+
expect(registry_instance).to receive(:latest_id_for_image).with(subject.image_name, subject.tag).and_return("2")
|
521
|
+
expect(subject.newer_version_available?).to be_true
|
522
|
+
end
|
523
|
+
|
524
|
+
it "returns false when no registry image id is found" do
|
525
|
+
expect(registry_instance).to receive(:latest_id_for_image).with(subject.image_name, subject.tag).and_return(nil)
|
526
|
+
expect(subject.newer_version_available?).to be_false
|
527
|
+
end
|
528
|
+
|
529
|
+
it "returns false when the registry image id is equal to the local id" do
|
530
|
+
expect(subject).to receive(:image_id).and_return("1")
|
531
|
+
expect(registry_instance).to receive(:latest_id_for_image).with(subject.image_name, subject.tag).and_return("1")
|
532
|
+
expect(subject.newer_version_available?).to be_false
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
end
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'dockistrano'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
|
5
|
+
RSpec.configure do
|
6
|
+
|
7
|
+
# Capture method from Thor's own spec_helper
|
8
|
+
def capture(stream)
|
9
|
+
begin
|
10
|
+
stream = stream.to_s
|
11
|
+
eval "$#{stream} = StringIO.new"
|
12
|
+
yield
|
13
|
+
result = eval("$#{stream}").string
|
14
|
+
ensure
|
15
|
+
eval("$#{stream} = #{stream.upcase}")
|
16
|
+
end
|
17
|
+
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|