dockerspec 0.1.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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGELOG.md +7 -0
  4. data/CONTRIBUTING.md +13 -0
  5. data/LICENSE +190 -0
  6. data/README.md +202 -0
  7. data/Rakefile +57 -0
  8. data/TESTING.md +30 -0
  9. data/TODO.md +6 -0
  10. data/lib/dockerspec.rb +21 -0
  11. data/lib/dockerspec/builder.rb +408 -0
  12. data/lib/dockerspec/builder/config_helpers.rb +425 -0
  13. data/lib/dockerspec/builder/image_gc.rb +71 -0
  14. data/lib/dockerspec/builder/logger.rb +56 -0
  15. data/lib/dockerspec/builder/logger/ci.rb +69 -0
  16. data/lib/dockerspec/builder/logger/debug.rb +47 -0
  17. data/lib/dockerspec/builder/logger/info.rb +111 -0
  18. data/lib/dockerspec/builder/logger/silent.rb +51 -0
  19. data/lib/dockerspec/builder/matchers.rb +134 -0
  20. data/lib/dockerspec/builder/matchers/helpers.rb +88 -0
  21. data/lib/dockerspec/docker_gem.rb +25 -0
  22. data/lib/dockerspec/exceptions.rb +26 -0
  23. data/lib/dockerspec/helper/ci.rb +61 -0
  24. data/lib/dockerspec/helper/docker.rb +44 -0
  25. data/lib/dockerspec/helper/multiple_sources_description.rb +142 -0
  26. data/lib/dockerspec/helper/rspec_example_helpers.rb +48 -0
  27. data/lib/dockerspec/rspec_assertions.rb +54 -0
  28. data/lib/dockerspec/rspec_resources.rb +198 -0
  29. data/lib/dockerspec/rspec_settings.rb +29 -0
  30. data/lib/dockerspec/runner.rb +374 -0
  31. data/lib/dockerspec/serverspec.rb +20 -0
  32. data/lib/dockerspec/serverspec/rspec_resources.rb +174 -0
  33. data/lib/dockerspec/serverspec/rspec_settings.rb +27 -0
  34. data/lib/dockerspec/serverspec/runner.rb +302 -0
  35. data/lib/dockerspec/serverspec/specinfra_backend.rb +128 -0
  36. data/lib/dockerspec/serverspec/specinfra_hack.rb +43 -0
  37. data/lib/dockerspec/version.rb +29 -0
  38. data/spec/spec_helper.rb +44 -0
  39. metadata +293 -0
@@ -0,0 +1,425 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Xabier de Zuazo (<xabier@zuazo.org>)
4
+ # Copyright:: Copyright (c) 2015 Xabier de Zuazo
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Dockerspec
21
+ class Builder
22
+ #
23
+ # Some helpers to get container image information from its JSON data.
24
+ #
25
+ # **Note:** Keep in mind that not all the available Dockerfile instructions
26
+ # can be checked in the docker image. You should use
27
+ # {Dockerspec::Serverspec::RSpecResources#docker_run} to check some
28
+ # instructions like `FROM`, `RUN`, `ADD` and `COPY` (see the examples
29
+ # there).
30
+ #
31
+ module ConfigHelpers
32
+ #
33
+ # Returns the image configuration.
34
+ #
35
+ # @return [Hash] The image configuration.
36
+ #
37
+ # @api public
38
+ #
39
+ def image_config
40
+ @image.json['Config']
41
+ end
42
+
43
+ #
44
+ # Returns the image size in bytes.
45
+ #
46
+ # @example RSpec Example
47
+ # describe docker_build(path: '.') do
48
+ # its(:size) { should be < 20 * 2**20 } # 20M
49
+ # end
50
+ #
51
+ # @return [Fixnum] The image size in bytes.
52
+ #
53
+ # @api public
54
+ #
55
+ def size
56
+ @image.json['VirtualSize']
57
+ end
58
+
59
+ #
60
+ # Returns the image architecture.
61
+ #
62
+ # @example RSpec Example
63
+ # describe docker_build(path: '.') do
64
+ # its(:arch) { should eq 'amd64' }
65
+ # end
66
+ #
67
+ # @return [String] The architecture name.
68
+ #
69
+ # @api public
70
+ #
71
+ def architecture
72
+ @image.json['Architecture']
73
+ end
74
+
75
+ alias_method :arch, :architecture
76
+
77
+ #
78
+ # Returns the image Operating System.
79
+ #
80
+ # @example RSpec Example
81
+ # describe docker_build(path: '.') do
82
+ # its(:os) { should eq 'linux' }
83
+ # end
84
+ #
85
+ # @return [String] The OS name.
86
+ #
87
+ # @api public
88
+ #
89
+ def os
90
+ @image.json['Os']
91
+ end
92
+
93
+ #
94
+ # Returns the image maintainer or author (`MAINTAINER`).
95
+ #
96
+ # @example Basic RSpec Example
97
+ # describe docker_build(path: '.') do
98
+ # its(:maintainer) { should eq 'John Doe "john.doe@example.com"' }
99
+ # end
100
+ #
101
+ # @example RSpec Example Using *Have* Matchers
102
+ # describe docker_build(path: '.') do
103
+ # it { should have_maintainer 'John Doe "john.doe@example.com"' }
104
+ # end
105
+ #
106
+ # @example RSpec Example Using a Regular Expression
107
+ # describe docker_build(path: '.') do
108
+ # it { should have_maintainer(/John Doe/) }
109
+ # end
110
+ #
111
+ # @return [String] The maintainer.
112
+ #
113
+ # @api public
114
+ #
115
+ def maintainer
116
+ @image.json['Author']
117
+ end
118
+
119
+ #
120
+ # Returns the image command (`CMD`).
121
+ #
122
+ # @example Basic RSpec Example
123
+ # describe docker_build(path: '.') do
124
+ # its(:cmd) { should eq ['/usr/bin/supervisord'] }
125
+ # end
126
+ #
127
+ # @example RSpec Example Using *Have* Matchers
128
+ # describe docker_build(path: '.') do
129
+ # it { should have_cmd ['/usr/bin/supervisord'] }
130
+ # end
131
+ #
132
+ # @return [Array] The image command.
133
+ #
134
+ # @api public
135
+ #
136
+ def cmd
137
+ image_config['Cmd']
138
+ end
139
+
140
+ #
141
+ # Returns the image labels (`LABEL`).
142
+ #
143
+ # @example Basic RSpec Example
144
+ # describe docker_build(path: '.') do
145
+ # its(:labels) { should include 'description' => 'My Container' }
146
+ # end
147
+ #
148
+ # @example RSpec Example Using *Have* Matchers
149
+ # describe docker_build(path: '.') do
150
+ # it { should have_label 'description' => 'My Container' }
151
+ # end
152
+ #
153
+ # @example RSpec Example Checking Only the Existence of the label
154
+ # describe docker_build(path: '.') do
155
+ # it { should have_label 'description' }
156
+ # end
157
+ #
158
+ # @return [Hash] The labels list.
159
+ #
160
+ # @api public
161
+ #
162
+ def labels
163
+ image_config['Labels']
164
+ end
165
+
166
+ #
167
+ # Returns **the first** label as a string (`LABEL`).
168
+ #
169
+ # @example Basic RSpec Example
170
+ # describe docker_build(path: '.') do
171
+ # its(:label) { should eq 'description=My Container' }
172
+ # end
173
+ #
174
+ # @return [String] The first label.
175
+ #
176
+ # @api public
177
+ #
178
+ def label
179
+ labels.first.join('=')
180
+ end
181
+
182
+ #
183
+ # Returns the image exposed ports (`EXPOSE`).
184
+ #
185
+ # @example Basic RSpec Example
186
+ # describe docker_build(path: '.') do
187
+ # its(:exposes) { should include '80' }
188
+ # end
189
+ #
190
+ # @example RSpec Example Using *Have* Matchers
191
+ # describe docker_build(path: '.') do
192
+ # it { should have_expose '80' }
193
+ # end
194
+ #
195
+ # @example RSpec Example Using Regular Expressions
196
+ # describe docker_build(path: '.') do
197
+ # it { should have_expose(/80$/) }
198
+ # end
199
+ #
200
+ # @return [Array] The exposed ports list.
201
+ #
202
+ # @api public
203
+ #
204
+ def exposes
205
+ image_config['ExposedPorts'].keys.map { |x| x.delete('/tcp') }
206
+ end
207
+
208
+ #
209
+ # Returns **the first** exposed port (`EXPOSE`).
210
+ #
211
+ # @example Basic RSpec Example
212
+ # describe docker_build(path: '.') do
213
+ # its(:expose) { should eq '80' }
214
+ # end
215
+ #
216
+ # @return [String] The exposed port.
217
+ #
218
+ # @api public
219
+ #
220
+ def expose
221
+ exposes.first
222
+ end
223
+
224
+ #
225
+ # Returns the image environment (`ENV`).
226
+ #
227
+ # @example Basic RSpec Example
228
+ # describe docker_build(path: '.') do
229
+ # its(:env) { should include 'container' => 'docker' }
230
+ # end
231
+ #
232
+ # @example RSpec Example Using *Have* Matchers
233
+ # describe docker_build(path: '.') do
234
+ # it { should have_env 'container' => 'docker' }
235
+ # end
236
+ #
237
+ # @example RSpec Example Checking Only the Existence of the Env Variable
238
+ # describe docker_build(path: '.') do
239
+ # it { should have_env 'container' }
240
+ # end
241
+ #
242
+ # @return [Hash] The environment.
243
+ #
244
+ # @api public
245
+ #
246
+ def envs
247
+ @env ||=
248
+ image_config['Env'].each_with_object({}) do |var, memo|
249
+ key, value = var.split('=', 2)
250
+ memo[key] = value
251
+ end
252
+ end
253
+
254
+ alias_method :env, :envs
255
+
256
+ #
257
+ # Returns the image entrypoint (`ENTRYPOINT`).
258
+ #
259
+ # @example Basic RSpec Example
260
+ # describe docker_build(path: '.') do
261
+ # its(:entrypoint) { should eq ['/entrypoint.sh'] }
262
+ # end
263
+ #
264
+ # @example RSpec Example Using *Have* Matchers
265
+ # describe docker_build(path: '.') do
266
+ # it { should have_entrypoint ['/entrypoint.sh'] }
267
+ # end
268
+ #
269
+ # @return [Array] The image entrypoint.
270
+ #
271
+ # @api public
272
+ #
273
+ def entrypoint
274
+ image_config['Entrypoint']
275
+ end
276
+
277
+ #
278
+ # Returns the image volumes (`VOLUME`).
279
+ #
280
+ # @example Basic RSpec Example
281
+ # describe docker_build(path: '.') do
282
+ # its(:volumes) { should include '/data1' }
283
+ # end
284
+ #
285
+ # @example RSpec Example Using *Have* Matchers
286
+ # describe docker_build(path: '.') do
287
+ # it { should have_volume '/data1' }
288
+ # end
289
+ #
290
+ # @example RSpec Example Using Regular Expressions
291
+ # describe docker_build(path: '.') do
292
+ # it { should have_volume %r{^/data[0-9]+$} }
293
+ # end
294
+ #
295
+ # @return [Array] The image volume list.
296
+ #
297
+ # @api public
298
+ #
299
+ def volumes
300
+ image_config['Volumes'].keys
301
+ end
302
+
303
+ #
304
+ # Returns **the first** volume (`VOLUME`).
305
+ #
306
+ # @example Basic RSpec Example
307
+ # describe docker_build(path: '.') do
308
+ # its(:volume) { should eq '/data1' }
309
+ # end
310
+ #
311
+ # @return [String] The first volume.
312
+ #
313
+ # @api public
314
+ #
315
+ def volume
316
+ volumes.first
317
+ end
318
+
319
+ #
320
+ # Returns the image user (`USER`).
321
+ #
322
+ # @example Basic RSpec Example
323
+ # describe docker_build(path: '.') do
324
+ # its(:user) { should eq 'nobody' }
325
+ # end
326
+ #
327
+ # @example RSpec Example Using *Have* Matchers
328
+ # describe docker_build(path: '.') do
329
+ # it { should have_user 'nobody' }
330
+ # end
331
+ #
332
+ # @return [String] The username.
333
+ #
334
+ # @api public
335
+ #
336
+ def user
337
+ image_config['User']
338
+ end
339
+
340
+ #
341
+ # Returns the image workdir (`WORKDIR`).
342
+ #
343
+ # @example Basic RSpec Example
344
+ # describe docker_build(path: '.') do
345
+ # its(:workdir) { should eq '/opt/myapp' }
346
+ # end
347
+ #
348
+ # @example RSpec Example Using *Have* Matchers
349
+ # describe docker_build(path: '.') do
350
+ # it { should have_workdir '/opt/myapp' }
351
+ # end
352
+ #
353
+ # @example RSpec Example Using Regular Expressions
354
+ # describe docker_build(path: '.') do
355
+ # it { should have_workdir %r{^/opt/myapp} }
356
+ # end
357
+ #
358
+ # @return [String] The workdir.
359
+ #
360
+ # @api public
361
+ #
362
+ def workdir
363
+ image_config['WorkingDir']
364
+ end
365
+
366
+ #
367
+ # Returns the onbuild instructions (`ONBUILD`).
368
+ #
369
+ # @example Basic RSpec Example
370
+ # describe docker_build(path: '.') do
371
+ # its(:onbuilds) { should include 'RUN echo onbuild' }
372
+ # end
373
+ #
374
+ # @example RSpec Example Using *Have* Matchers
375
+ # describe docker_build(path: '.') do
376
+ # it { should have_onbuild 'RUN echo onbuild' }
377
+ # end
378
+ #
379
+ # @return [Array] The onbuild instructions.
380
+ #
381
+ # @api public
382
+ #
383
+ def onbuilds
384
+ image_config['OnBuild']
385
+ end
386
+
387
+ #
388
+ # Returns **the first** onbuild instruction (`ONBUILD`).
389
+ #
390
+ # @example Basic RSpec Example
391
+ # describe docker_build(path: '.') do
392
+ # its(:onbuild) { should eq 'RUN echo onbuild' }
393
+ # end
394
+ #
395
+ # @return [String] The onbuild instruction.
396
+ #
397
+ # @api public
398
+ #
399
+ def onbuild
400
+ onbuilds.first
401
+ end
402
+
403
+ #
404
+ # Returns the stop signal (`STOPSIGNAL`).
405
+ #
406
+ # @example Basic RSpec Example
407
+ # describe docker_build(path: '.') do
408
+ # its(:stopsignal) { should eq 'SIGTERM' }
409
+ # end
410
+ #
411
+ # @example RSpec Example Using *Have* Matchers
412
+ # describe docker_build(path: '.') do
413
+ # it { should have_stopsignal 'SIGTERM' }
414
+ # end
415
+ #
416
+ # @return [String] The stop signal name.
417
+ #
418
+ # @api public
419
+ #
420
+ def stopsignal
421
+ image_config['StopSignal']
422
+ end
423
+ end
424
+ end
425
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Xabier de Zuazo (<xabier@zuazo.org>)
4
+ # Copyright:: Copyright (c) 2015 Xabier de Zuazo
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'singleton'
21
+ require 'dockerspec/docker_gem'
22
+
23
+ module Dockerspec
24
+ class Builder
25
+ #
26
+ # A class to manage docker image deletion. The class stores the images
27
+ # created by {Dockerspec::Builder} objects and deletes them at the end of
28
+ # the Ruby/RSpec run.
29
+ #
30
+ class ImageGC
31
+ include Singleton
32
+
33
+ #
34
+ # The Image Garbage Collector constructor.
35
+ #
36
+ # @api public
37
+ #
38
+ def initialize
39
+ @images = []
40
+ ObjectSpace.define_finalizer(self, proc { finalize })
41
+ end
42
+
43
+ #
44
+ # Adds a Docker image to be garbage deleted at the end.
45
+ #
46
+ # @param image [String] Docker image ID.
47
+ #
48
+ # @return void
49
+ #
50
+ # @api public
51
+ #
52
+ def add(image)
53
+ @images << image
54
+ end
55
+
56
+ #
57
+ # Removes all the Docker images.
58
+ #
59
+ # Automatically called at the end of the RSpec/Ruby run.
60
+ #
61
+ # @return void
62
+ #
63
+ # @api public
64
+ #
65
+ def finalize
66
+ @images.each { |i| ::Docker::Image.remove(i, force: true) }
67
+ @images = []
68
+ end
69
+ end
70
+ end
71
+ end