dockistrano 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,296 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockistrano::Cli do
|
4
|
+
|
5
|
+
let(:service) { double(registry: "registry.provider.tld", image_name: "application", tag: "develop", volumes: [], backing_services: { "postgresql" => backing_service }, environment_variables: {}, newer_version_available?: false, stop: nil) }
|
6
|
+
let(:backing_service) { double(full_image_name: "registry.provider.tld/postgresql:develop", image_name: "postgresql", running?: false, newer_version_available?: false, start: nil, stop: nil) }
|
7
|
+
let(:hipache) { double }
|
8
|
+
let(:output) { capture(:stdout) { described_class.start(command) } }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(Dockistrano::Service).to receive(:factory).and_return(service)
|
12
|
+
end
|
13
|
+
|
14
|
+
context "doc status" do
|
15
|
+
let(:command) { ["status"] }
|
16
|
+
|
17
|
+
it "prints the DOCKISTRANO_ENVIRONMENT" do
|
18
|
+
expect(output).to include("DOCKISTRANO_ENVIRONMENT: default")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "prints the DOCKER_HOST_IP" do
|
22
|
+
expect(output).to include("DOCKER_HOST_IP: 127.0.0.1")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "prints the DOCKER_BINARY" do
|
26
|
+
expect(output).to include("DOCKER_BINARY:")
|
27
|
+
expect(output).to include("bin/docker")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "prints the registry" do
|
31
|
+
expect(output).to include("registry: #{service.registry}")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "prints the name of the image" do
|
35
|
+
expect(output).to include("image name: #{service.image_name}")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "prints the tag" do
|
39
|
+
expect(output).to include("tag: #{service.tag}")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "lists all dependencies" do
|
43
|
+
expect(output).to include(backing_service.full_image_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "lists environment variables" do
|
47
|
+
allow(service).to receive(:environment_variables).and_return({ "VARIABLE" => "value"} )
|
48
|
+
expect(output).to include("VARIABLE=value")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "lists the Hipache configuration" do
|
52
|
+
allow(Dockistrano::Hipache).to receive(:new).with("127.0.0.1").and_return(hipache)
|
53
|
+
allow(hipache).to receive(:status).and_return({ "somehostname.dev" => ["127.0.0.1:1000", "23.45.56.75:1234"] })
|
54
|
+
expect(output).to include("somehostname.dev: 127.0.0.1:1000, 23.45.56.75:1234")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "doc build" do
|
59
|
+
let(:command) { ["build"] }
|
60
|
+
|
61
|
+
it "builds a container" do
|
62
|
+
expect(service).to receive(:build).and_return(true)
|
63
|
+
expect(service).to receive(:test).and_return(true)
|
64
|
+
expect(service).to receive(:push).and_return(true)
|
65
|
+
expect(output).to include("built")
|
66
|
+
expect(output).to include("tests")
|
67
|
+
expect(output).to include("pushed")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "doesn't run the tests and push when building failed" do
|
71
|
+
expect(service).to receive(:build).and_return(false)
|
72
|
+
expect(service).to_not receive(:test)
|
73
|
+
expect(service).to_not receive(:push)
|
74
|
+
expect { output }.to raise_error(SystemExit)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "doesn't push when tests failed" do
|
78
|
+
expect(service).to receive(:build).and_return(true)
|
79
|
+
expect(service).to receive(:test).and_return(false)
|
80
|
+
expect(service).to_not receive(:push)
|
81
|
+
expect { output }.to raise_error(SystemExit)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "doc pull" do
|
86
|
+
let(:command) { ["pull"] }
|
87
|
+
|
88
|
+
it "pulls a backing service when newer versions are available" do
|
89
|
+
expect(backing_service).to receive(:newer_version_available?).and_return(true)
|
90
|
+
expect(backing_service).to receive(:pull)
|
91
|
+
expect(output).to include("Pulled")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "doesn't pull a service when no new versions are available" do
|
95
|
+
expect(backing_service).to receive(:newer_version_available?).and_return(false)
|
96
|
+
expect(backing_service).to_not receive(:pull)
|
97
|
+
expect(output).to include("Uptodate")
|
98
|
+
end
|
99
|
+
|
100
|
+
it "pulls the application container when newer versions are available" do
|
101
|
+
expect(service).to receive(:newer_version_available?).and_return(true)
|
102
|
+
expect(service).to receive(:pull)
|
103
|
+
expect(output).to include("Pulled")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "doesn't pull the application container when no newer versions are available" do
|
107
|
+
expect(service).to receive(:newer_version_available?).and_return(false)
|
108
|
+
expect(service).to_not receive(:pull)
|
109
|
+
expect(output).to include("Uptodate")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "doc push" do
|
114
|
+
it "pushes the current container" do
|
115
|
+
expect(service).to receive(:push)
|
116
|
+
described_class.start(["push"])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "doc start-services" do
|
121
|
+
let(:command) { ["start-services"] }
|
122
|
+
|
123
|
+
it "starts a backing service when it is not running" do
|
124
|
+
expect(backing_service).to receive(:running?).and_return(false)
|
125
|
+
expect(backing_service).to receive(:start)
|
126
|
+
expect(output).to include("Started")
|
127
|
+
end
|
128
|
+
|
129
|
+
it "does nothing when a backing services is already running" do
|
130
|
+
expect(backing_service).to receive(:running?).and_return(true)
|
131
|
+
expect(backing_service).to_not receive(:start)
|
132
|
+
expect(output).to include("Running")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "doc stop-all" do
|
137
|
+
let(:command) { ["stop-all"] }
|
138
|
+
|
139
|
+
it "stops the current container" do
|
140
|
+
expect(service).to receive(:stop)
|
141
|
+
expect(output).to include("Stopped")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "stops all backing services" do
|
145
|
+
expect(backing_service).to receive(:running?).and_return(true)
|
146
|
+
expect(backing_service).to receive(:stop)
|
147
|
+
expect(output).to include("Stopped")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "doc start" do
|
152
|
+
let(:command) { ["start"] }
|
153
|
+
|
154
|
+
it "starts the services when not running" do
|
155
|
+
expect(service).to receive(:running?).and_return(false)
|
156
|
+
expect(service).to receive(:start)
|
157
|
+
expect(output).to include("Started")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "doesn't start the services when already running" do
|
161
|
+
expect(service).to receive(:running?).and_return(true)
|
162
|
+
expect(service).to_not receive(:start)
|
163
|
+
expect(output).to include("Running")
|
164
|
+
end
|
165
|
+
|
166
|
+
it "prints an error when environment variables are missing" do
|
167
|
+
expect(service).to receive(:running?).and_return(false)
|
168
|
+
expect(service).to receive(:start).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
|
169
|
+
expect(output).to include("error message")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context "doc stop" do
|
174
|
+
let(:command) { ["stop"] }
|
175
|
+
|
176
|
+
it "stops the current container" do
|
177
|
+
expect(service).to receive(:stop)
|
178
|
+
expect(output).to include("Stopped")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "doc stop ID" do
|
183
|
+
let(:command) { ["stop", "123456789"] }
|
184
|
+
|
185
|
+
it "stops the container with the id" do
|
186
|
+
expect(Dockistrano::Docker).to receive(:stop).with("123456789")
|
187
|
+
expect(output).to include("Stopped")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "doc restart" do
|
192
|
+
let(:command) { ["restart"] }
|
193
|
+
|
194
|
+
it "restarts the current container" do
|
195
|
+
expect(service).to receive(:stop)
|
196
|
+
expect(service).to receive(:start)
|
197
|
+
expect(output).to include("Stopped")
|
198
|
+
expect(output).to include("Started")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "doc exec COMMAND" do
|
203
|
+
let(:command) { ["exec", "bin/rspec", "-t", "spec/models/my_model_spec.rb"] }
|
204
|
+
|
205
|
+
it "executes the command in the container" do
|
206
|
+
expect(service).to receive(:exec).with("bin/rspec -t spec/models/my_model_spec.rb", { "environment" => "default" })
|
207
|
+
output
|
208
|
+
end
|
209
|
+
|
210
|
+
it "prints an error when environment variables are missing" do
|
211
|
+
expect(service).to receive(:exec).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
|
212
|
+
expect(output).to include("error message")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "doc console" do
|
217
|
+
let(:command) { ["console"] }
|
218
|
+
|
219
|
+
it "starts a bash console in the container" do
|
220
|
+
expect(service).to receive(:console).with("/bin/bash", { "environment" => "default" })
|
221
|
+
output
|
222
|
+
end
|
223
|
+
|
224
|
+
it "prints an error when environment variables are missing" do
|
225
|
+
expect(service).to receive(:console).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
|
226
|
+
expect(output).to include("error message")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context "doc console COMMAND" do
|
231
|
+
let(:command) { ["console", "bin/rails console"] }
|
232
|
+
|
233
|
+
it "starts a console in the container" do
|
234
|
+
expect(service).to receive(:console).with("bin/rails console", { "environment" => "default" })
|
235
|
+
output
|
236
|
+
end
|
237
|
+
|
238
|
+
it "prints an error when environment variables are missing" do
|
239
|
+
expect(service).to receive(:console).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
|
240
|
+
expect(output).to include("error message")
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "doc clean" do
|
245
|
+
let(:command) { ["clean"] }
|
246
|
+
|
247
|
+
it "cleans the Docker instance and service dependency cache" do
|
248
|
+
expect(Dockistrano::Docker).to receive(:clean)
|
249
|
+
expect(Dockistrano::ServiceDependency).to receive(:clear_cache)
|
250
|
+
output
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context "doc logs" do
|
255
|
+
let(:command) { ["logs"] }
|
256
|
+
|
257
|
+
it "attaches to the containers output when the container is running" do
|
258
|
+
expect(service).to receive(:running?).and_return(true)
|
259
|
+
expect(service).to receive(:attach)
|
260
|
+
expect(output).to include("Container application running, attaching to output")
|
261
|
+
end
|
262
|
+
|
263
|
+
it "prints the logs of the last run" do
|
264
|
+
expect(service).to receive(:running?).and_return(false)
|
265
|
+
expect(service).to receive(:logs)
|
266
|
+
expect(output).to include("Container application stopped, printing logs of last run")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context "doc logs NAME" do
|
271
|
+
let(:command) { ["logs", "postgresql"] }
|
272
|
+
|
273
|
+
it "attaches to the containers output when the container is running" do
|
274
|
+
expect(backing_service).to receive(:running?).and_return(true)
|
275
|
+
expect(backing_service).to receive(:attach)
|
276
|
+
expect(output).to include("Container postgresql running, attaching to output")
|
277
|
+
end
|
278
|
+
|
279
|
+
it "prints the logs of the last run" do
|
280
|
+
expect(backing_service).to receive(:running?).and_return(false)
|
281
|
+
expect(backing_service).to receive(:logs)
|
282
|
+
expect(output).to include("Container postgresql stopped, printing logs of last run")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context "doc ALIAS ARGUMENTS" do
|
287
|
+
let(:command) { ["rspec", "spec/models/my_model_spec.rb"] }
|
288
|
+
|
289
|
+
it "executes aliases that are defined in the configuration" do
|
290
|
+
allow(service).to receive(:config).and_return({ "aliases" => { "rspec" => "exec -e test bin/rspec" } })
|
291
|
+
expect(Kernel).to receive(:exec).with("doc exec -e test bin/rspec spec/models/my_model_spec.rb")
|
292
|
+
output
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockistrano::CommandLine do
|
4
|
+
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
context ".command_with_result" do
|
8
|
+
it "executes the command and returns a string with the result" do
|
9
|
+
expect(described_class.command_with_result("date")).to eq(`date`)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context ".command_with_stream" do
|
14
|
+
it "executes the command and returns a stream of output" do
|
15
|
+
expect(Kernel).to receive(:system).with("date").and_return(true)
|
16
|
+
expect(described_class.command_with_stream("date")).to be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context ".command_with_interaction" do
|
21
|
+
it "executes the command and returns a stream of output" do
|
22
|
+
expect(Kernel).to receive(:exec).with("date").and_return(true)
|
23
|
+
expect(described_class.command_with_interaction("date")).to be_true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockistrano::Docker do
|
4
|
+
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
before do
|
8
|
+
ENV["DOCKER_BINARY"] = "docker"
|
9
|
+
ENV["DOCKER_HOST_IP"] = "127.0.0.1"
|
10
|
+
end
|
11
|
+
|
12
|
+
context ".docker_command" do
|
13
|
+
it "returns a string that allows us to call docker" do
|
14
|
+
ENV["DOCKER_BINARY"] = "/bin/docker"
|
15
|
+
ENV["DOCKER_HOST_IP"] = "127.0.0.1"
|
16
|
+
expect(subject.docker_command).to eq("/bin/docker -H 127.0.0.1")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises an error when DOCKER_BINARY is not set" do
|
20
|
+
ENV["DOCKER_BINARY"] = nil
|
21
|
+
ENV["DOCKER_HOST_IP"] = "127.0.0.1"
|
22
|
+
expect { subject.docker_command }.to raise_error(Dockistrano::Docker::EnvironmentVariableMissing, /DOCKER_BINARY/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises an error when DOCKER_BINARY is not set" do
|
26
|
+
ENV["DOCKER_BINARY"] = "/bin/docker"
|
27
|
+
ENV["DOCKER_HOST_IP"] = nil
|
28
|
+
expect { subject.docker_command }.to raise_error(Dockistrano::Docker::EnvironmentVariableMissing, /DOCKER_HOST_IP/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context ".ps" do
|
33
|
+
it "calls docker with the ps command" do
|
34
|
+
expect(subject).to receive(:execute).with(["ps", {}])
|
35
|
+
subject.ps
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context ".stop" do
|
40
|
+
it "stops the container" do
|
41
|
+
expect(subject).to receive(:execute).with(["stop", "123456789"])
|
42
|
+
subject.stop("123456789")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context ".run" do
|
47
|
+
it "runs the default command when no command is given" do
|
48
|
+
expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag"])
|
49
|
+
subject.run("registry/image:tag", e: "VAR=value")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "runs the default command when no command is given" do
|
53
|
+
expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag", "echo 'foobar'"])
|
54
|
+
subject.run("registry/image:tag", e: "VAR=value", command: "echo 'foobar'")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context ".exec" do
|
59
|
+
it "runs the default command when no command is given" do
|
60
|
+
expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag"], :stream)
|
61
|
+
subject.exec("registry/image:tag", e: "VAR=value")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "runs the default command when no command is given" do
|
65
|
+
expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag", "echo 'foobar'"], :stream)
|
66
|
+
subject.exec("registry/image:tag", e: "VAR=value", command: "echo 'foobar'")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context ".console" do
|
71
|
+
it "runs the default command when no command is given" do
|
72
|
+
expect(subject).to receive(:execute).with(["run", { "e" => "VAR=value", "t" => true, "i" => true }, "registry/image:tag"], :interaction)
|
73
|
+
subject.console("registry/image:tag", "e" => "VAR=value")
|
74
|
+
end
|
75
|
+
|
76
|
+
it "runs the default command when no command is given" do
|
77
|
+
expect(subject).to receive(:execute).with(["run", { "e" => "VAR=value", "t" => true, "i" => true}, "registry/image:tag", "echo 'foobar'"], :interaction)
|
78
|
+
subject.console("registry/image:tag", "e" => "VAR=value", command: "echo 'foobar'")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context ".execute" do
|
83
|
+
it "calls docker and returns the result" do
|
84
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version")
|
85
|
+
subject.execute(["version"])
|
86
|
+
end
|
87
|
+
|
88
|
+
it "adds options to the command" do
|
89
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version -a")
|
90
|
+
subject.execute(["version", { a: true }])
|
91
|
+
end
|
92
|
+
|
93
|
+
it "adds array options to the command" do
|
94
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version -a b -a c")
|
95
|
+
subject.execute(["version", { a: ["b", "c"] }])
|
96
|
+
end
|
97
|
+
|
98
|
+
it "calls docker and stream to stdout" do
|
99
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker -H 127.0.0.1 version")
|
100
|
+
subject.execute(["version"], :stream)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "calls docker and takes over the console" do
|
104
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_interaction).with("docker -H 127.0.0.1 version")
|
105
|
+
subject.execute(["version"], :interaction)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context ".running_container_id" do
|
110
|
+
it "returns the first id of a running container matching with the image name" do
|
111
|
+
stub_request(:get, "http://127.0.0.1:4243/containers/json").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider webserver","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
112
|
+
{"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
113
|
+
{"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
|
114
|
+
|
115
|
+
expect(subject.running_container_id("registry.dev.provider.net/provider-app-2.0:develop")).to eq("8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context ".last_run_container_id" do
|
120
|
+
it "returns the id of the previous run of the container" do
|
121
|
+
stub_request(:get, "http://127.0.0.1:4243/containers/json?all=1").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"cat /dockistrano.yml","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
122
|
+
{"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
123
|
+
{"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
|
124
|
+
|
125
|
+
expect(subject.last_run_container_id("registry.dev.provider.net/provider-app-2.0:develop")).to eq("107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context ".image_id" do
|
130
|
+
it "returns the id of the image with the given name" do
|
131
|
+
expect(subject).to receive(:inspect_image).and_return({ "id" => "123456789" })
|
132
|
+
expect(subject.image_id("registry.dev/application:tag")).to eq("123456789")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context ".inspect_image" do
|
137
|
+
it "returns information about the image" do
|
138
|
+
stub_request(:get, "http://127.0.0.1:4243/images/123456789/json").to_return({
|
139
|
+
status: 200,
|
140
|
+
body: '{"id":"49f387cc90f2d5b82ded91c239b6e583f8b955cb532912cc959b1d1289b3f8f1","parent":"7735e8f30a47f02aa46732e864879fad0fb0b74230f7695b6235d6faf766dcb2","created":"2013-10-21T16:03:17.191097983+02:00","container":"5c2c523d3561d205f5459925325890bbf8054010cd908f61feed3e76520dcf54","container_config":{},"docker_version":"0.6.3","config":{},"architecture":"x86_64","Size":12288}'
|
141
|
+
})
|
142
|
+
expect(subject.inspect_image("123456789")).to include('id')
|
143
|
+
end
|
144
|
+
|
145
|
+
it "raises an error when the image is not found" do
|
146
|
+
stub_request(:get, "http://127.0.0.1:4243/images/123456789/json").to_return({
|
147
|
+
status: 404,
|
148
|
+
body: 'No such image: 123456789'
|
149
|
+
})
|
150
|
+
|
151
|
+
expect { subject.inspect_image("123456789") }.to raise_error(Dockistrano::Docker::ImageNotFound, /No such image: 123456789/)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context ".build" do
|
156
|
+
it "builds the container" do
|
157
|
+
expect(subject).to receive(:execute).with(["build", {t: "full_image_name"}, "."], :stream)
|
158
|
+
subject.build("full_image_name")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context ".pull" do
|
163
|
+
it "pulls the container with Docker" do
|
164
|
+
expect(subject).to receive(:execute).with(["pull", { t: "tag" }, "full_image_name"])
|
165
|
+
subject.pull("full_image_name", "tag")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context ".push" do
|
170
|
+
it "pushes the container with Docker" do
|
171
|
+
expect(subject).to receive(:execute).with(["push", "full_image_name", "tag"], :stream)
|
172
|
+
subject.push("full_image_name", "tag")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context ".logs" do
|
177
|
+
it "returns the logs for the container" do
|
178
|
+
expect(subject).to receive(:execute).with(["logs", "72819312"], :stream)
|
179
|
+
subject.logs("72819312")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context ".attach" do
|
184
|
+
it "attaches to the containers output" do
|
185
|
+
expect(subject).to receive(:execute).with(["attach", "72819312"], :stream)
|
186
|
+
subject.attach("72819312")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context ".inspect_container" do
|
191
|
+
it "returns information about the container" do
|
192
|
+
stub_request(:get, 'http://127.0.0.1:4243/containers/123456789/json').to_return({
|
193
|
+
status: 200,
|
194
|
+
body: '{"ID":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Created":"2013-10-22T15:43:00.213138644+02:00"}'
|
195
|
+
})
|
196
|
+
|
197
|
+
expect(subject.inspect_container("123456789")).to include("ID")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context ".clean" do
|
202
|
+
before do
|
203
|
+
allow(Dockistrano::CommandLine).to receive(:command_with_stream)
|
204
|
+
allow(subject).to receive(:docker_command).and_return("docker")
|
205
|
+
end
|
206
|
+
|
207
|
+
it "cleans images from the docker instance" do
|
208
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker rmi $(docker images -a | grep \"^<none>\" | awk '{print $3}')")
|
209
|
+
subject.clean
|
210
|
+
end
|
211
|
+
|
212
|
+
it "cleans containers from the docker instance" do
|
213
|
+
expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker rm $(docker ps -a -q)")
|
214
|
+
subject.clean
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context ".stop_all_containers_from_image" do
|
219
|
+
it "stops all containers from an image" do
|
220
|
+
stub_request(:get, "http://127.0.0.1:4243/containers/json").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider webserver","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
221
|
+
{"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
|
222
|
+
{"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
|
223
|
+
|
224
|
+
expect(subject).to receive(:execute).with(["stop", "8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36"])
|
225
|
+
expect(subject).to receive(:execute).with(["stop", "107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a"])
|
226
|
+
|
227
|
+
subject.stop_all_containers_from_image("registry.dev.provider.net/provider-app-2.0:develop")
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context ".tags_for_image" do
|
232
|
+
it "returns a list of tags for an image" do
|
233
|
+
stub_request(:get, "http://127.0.0.1:4243/images/json").to_return({
|
234
|
+
status: 200,
|
235
|
+
body: '[{"Repository":"registry.provider.net/application","Tag":"develop"},{"Repository":"registry.provider.net/application","Tag":"latest"},{"Repository":"registry.provider.net/memcached","Tag":"develop"}]'
|
236
|
+
})
|
237
|
+
|
238
|
+
expect(subject.tags_for_image("registry.provider.net/application")).to eq(["develop", "latest"])
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dockistrano::Git do
|
4
|
+
|
5
|
+
context ".repository_name" do
|
6
|
+
let(:command) { double }
|
7
|
+
|
8
|
+
it "returns the name from a ssh remote" do
|
9
|
+
expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
|
10
|
+
expect(command).to receive(:run).and_return("git@github.com:username/reponame-with-2.0.git")
|
11
|
+
|
12
|
+
expect(described_class.repository_name).to eq("reponame-with-2.0")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns the name from a ssh remote ending without .git" do
|
16
|
+
expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
|
17
|
+
expect(command).to receive(:run).and_return("git@github.com:username/reponame-with-2.0")
|
18
|
+
|
19
|
+
expect(described_class.repository_name).to eq("reponame-with-2.0")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the name from a https remote" do
|
23
|
+
expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
|
24
|
+
expect(command).to receive(:run).and_return("https://github.com/username/reponame-with-2.0")
|
25
|
+
|
26
|
+
expect(described_class.repository_name).to eq("reponame-with-2.0")
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
context ".branch" do
|
32
|
+
let(:command) { double }
|
33
|
+
it "returns the name of the branch" do
|
34
|
+
expect(Cocaine::CommandLine).to receive(:new).with("git rev-parse --abbrev-ref HEAD").and_return(command)
|
35
|
+
expect(command).to receive(:run).and_return("branch_name\n")
|
36
|
+
|
37
|
+
expect(described_class.branch).to eq("branch_name")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the JANKY_BRANCH env variable when available" do
|
41
|
+
ENV["JANKY_BRANCH"] = "feature/foobar"
|
42
|
+
expect(described_class.branch).to eq("feature-foobar")
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|