dockerspec 0.2.0 → 0.3.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/LICENSE +1 -1
  4. data/README.md +190 -24
  5. data/Rakefile +60 -6
  6. data/TODO.md +3 -2
  7. data/lib/dockerspec.rb +1 -2
  8. data/lib/dockerspec/builder.rb +13 -6
  9. data/lib/dockerspec/builder/config_helpers.rb +8 -3
  10. data/lib/dockerspec/builder/logger/ci.rb +2 -2
  11. data/lib/dockerspec/builder/matchers.rb +32 -51
  12. data/lib/dockerspec/configuration.rb +188 -0
  13. data/lib/dockerspec/docker_exception_parser.rb +2 -2
  14. data/lib/dockerspec/engine/base.rb +156 -0
  15. data/lib/dockerspec/engine/infrataster.rb +87 -0
  16. data/lib/dockerspec/engine/specinfra.rb +130 -0
  17. data/lib/dockerspec/engine/specinfra/backend.rb +163 -0
  18. data/lib/dockerspec/{serverspec/specinfra_hack.rb → engine/specinfra/backend_hack.rb} +17 -3
  19. data/lib/dockerspec/engine_list.rb +150 -0
  20. data/lib/dockerspec/exceptions.rb +13 -0
  21. data/lib/dockerspec/helper/multiple_sources_description.rb +3 -3
  22. data/lib/dockerspec/helper/rspec_example_helpers.rb +86 -6
  23. data/lib/dockerspec/infrataster.rb +26 -0
  24. data/lib/dockerspec/rspec.rb +21 -0
  25. data/lib/dockerspec/{rspec_configuration.rb → rspec/configuration.rb} +1 -1
  26. data/lib/dockerspec/rspec/resources.rb +602 -0
  27. data/lib/dockerspec/rspec/resources/its_container.rb +110 -0
  28. data/lib/dockerspec/{rspec_settings.rb → rspec/settings.rb} +5 -1
  29. data/lib/dockerspec/runner.rb +2 -357
  30. data/lib/dockerspec/runner/base.rb +367 -0
  31. data/lib/dockerspec/runner/compose.rb +322 -0
  32. data/lib/dockerspec/runner/docker.rb +302 -0
  33. data/lib/dockerspec/runner/serverspec.rb +21 -0
  34. data/lib/dockerspec/runner/serverspec/base.rb +185 -0
  35. data/lib/dockerspec/runner/serverspec/compose.rb +106 -0
  36. data/lib/dockerspec/runner/serverspec/docker.rb +116 -0
  37. data/lib/dockerspec/runner/serverspec/rspec.rb +20 -0
  38. data/lib/dockerspec/{serverspec/rspec_settings.rb → runner/serverspec/rspec/settings.rb} +1 -1
  39. data/lib/dockerspec/serverspec.rb +12 -2
  40. data/lib/dockerspec/version.rb +1 -1
  41. data/spec/spec_helper.rb +6 -2
  42. metadata +84 -15
  43. data/lib/dockerspec/rspec_assertions.rb +0 -54
  44. data/lib/dockerspec/rspec_resources.rb +0 -203
  45. data/lib/dockerspec/serverspec/rspec_resources.rb +0 -179
  46. data/lib/dockerspec/serverspec/runner.rb +0 -305
  47. data/lib/dockerspec/serverspec/specinfra_backend.rb +0 -128
@@ -18,5 +18,4 @@
18
18
  #
19
19
 
20
20
  require 'dockerspec/version'
21
- require 'dockerspec/rspec_resources'
22
- require 'dockerspec/rspec_configuration'
21
+ require 'dockerspec/rspec'
@@ -83,7 +83,7 @@ module Dockerspec
83
83
  # `:debug` or `3` (outputs all the provided information in its raw
84
84
  # original form).
85
85
  #
86
- # @see Dockerspec::RSpecResources#docker_build
86
+ # @see Dockerspec::RSpec::Resources#docker_build
87
87
  #
88
88
  # @api public
89
89
  #
@@ -117,6 +117,8 @@ module Dockerspec
117
117
  #
118
118
  # @return [String] Docker image ID.
119
119
  #
120
+ # @raise [Dockerspec::DockerError] For underlaying docker errors.
121
+ #
120
122
  # @api public
121
123
  #
122
124
  def build
@@ -173,7 +175,7 @@ module Dockerspec
173
175
  #
174
176
  # @api private
175
177
  #
176
- alias_method :description_from_template, :description_from_file
178
+ alias description_from_template description_from_file
177
179
 
178
180
  #
179
181
  # Sets or gets the Docker image.
@@ -201,7 +203,7 @@ module Dockerspec
201
203
  # @api private
202
204
  #
203
205
  def rspec_options
204
- config = RSpec.configuration
206
+ config = ::RSpec.configuration
205
207
  {}.tap do |opts|
206
208
  opts[:path] = config.dockerfile_path if config.dockerfile_path?
207
209
  opts[:rm] = config.rm_build if config.rm_build?
@@ -313,11 +315,13 @@ module Dockerspec
313
315
  #
314
316
  # @return void
315
317
  #
318
+ # @raise [Dockerspec::DockerError] For underlaying docker errors.
319
+ #
316
320
  # @api private
317
321
  #
318
322
  def build_from_dir(dir)
319
323
  image(::Docker::Image.build_from_dir(dir, &build_block))
320
- add_respository_tag
324
+ add_repository_tag
321
325
  rescue ::Docker::Error::DockerError => e
322
326
  DockerExceptionParser.new(e)
323
327
  end
@@ -370,13 +374,16 @@ module Dockerspec
370
374
  #
371
375
  # @return void
372
376
  #
377
+ # @raise [Dockerspec::DockerError] For underlaying docker errors.
378
+ #
373
379
  # @api private
374
380
  #
375
381
  def build_from_id(id)
376
382
  @image = ::Docker::Image.get(id)
377
- add_respository_tag
383
+ add_repository_tag
378
384
  rescue ::Docker::Error::NotFoundError
379
385
  @image = ::Docker::Image.create('fromImage' => id)
386
+ add_repository_tag
380
387
  rescue ::Docker::Error::DockerError => e
381
388
  DockerExceptionParser.new(e)
382
389
  end
@@ -388,7 +395,7 @@ module Dockerspec
388
395
  #
389
396
  # @api private
390
397
  #
391
- def add_respository_tag
398
+ def add_repository_tag
392
399
  return unless @options.key?(:tag)
393
400
  repo, repo_tag = @options[:tag].split(':', 2)
394
401
  @image.tag(repo: repo, tag: repo_tag, force: true)
@@ -24,7 +24,7 @@ module Dockerspec
24
24
  #
25
25
  # **Note:** Keep in mind that not all the available Dockerfile instructions
26
26
  # can be checked in the docker image. You should use
27
- # {Dockerspec::Serverspec::RSpecResources#docker_run} to check some
27
+ # {Dockerspec::Serverspec::RSpec::Resources#docker_run} to check some
28
28
  # instructions like `FROM`, `RUN`, `ADD` and `COPY` (see the examples
29
29
  # there).
30
30
  #
@@ -72,7 +72,7 @@ module Dockerspec
72
72
  @image.json['Architecture']
73
73
  end
74
74
 
75
- alias_method :arch, :architecture
75
+ alias arch architecture
76
76
 
77
77
  #
78
78
  # Returns the image Operating System.
@@ -194,6 +194,11 @@ module Dockerspec
194
194
  # it { should have_expose '80' }
195
195
  # end
196
196
  #
197
+ # @example RSpec Example Using *Have* Matchers with Integer Valuess
198
+ # describe docker_build(path: '.') do
199
+ # it { should have_expose 80 }
200
+ # end
201
+ #
197
202
  # @example RSpec Example Using Regular Expressions
198
203
  # describe docker_build(path: '.') do
199
204
  # it { should have_expose(/80$/) }
@@ -253,7 +258,7 @@ module Dockerspec
253
258
  end
254
259
  end
255
260
 
256
- alias_method :env, :envs
261
+ alias env envs
257
262
 
258
263
  #
259
264
  # Returns the image entrypoint (`ENTRYPOINT`).
@@ -52,12 +52,12 @@ module Dockerspec
52
52
  # @api private
53
53
  #
54
54
  def print_stream(stream)
55
- if stream.match(/^Step /)
55
+ if stream =~ /^Step /
56
56
  @buffer = stream
57
57
  @skip = true
58
58
  else
59
59
  @buffer += stream
60
- @skip = false if stream.match(/^ ---> (Running in|\[Warning\]) /)
60
+ @skip = false if stream =~ /^ ---> (Running in|\[Warning\]) /
61
61
  end
62
62
  return if @skip
63
63
  @output.puts @buffer
@@ -55,78 +55,59 @@ module Dockerspec
55
55
  workdir: :string,
56
56
  onbuild: :array,
57
57
  stopsignal: :string
58
- }
58
+ }.freeze
59
59
 
60
60
  PREDICATE_TYPES.each do |name, type|
61
61
  matcher_name = "have_#{name}".to_sym
62
62
 
63
- case type
64
- when :string
65
- matcher matcher_name do |expected|
66
- match { |actual| !expected.match(actual.send(name)).nil? }
63
+ value_method = name
64
+ verb = 'be'
65
+ matcher matcher_name do |expected|
66
+ case type
67
+ when :string
68
+ verb = 'match'
67
69
 
68
- failure_message do |actual|
69
- "expected `#{name.upcase}` to match `#{expected.inspect}`, "\
70
- "got `#{actual.send(name)}`"
71
- end
70
+ match { |actual| !expected.match(actual.send(value_method)).nil? }
71
+ when :json
72
+ verb = 'be'
72
73
 
73
- failure_message_when_negated do |actual|
74
- "expected `#{name.upcase}` not to match `#{expected.inspect}`, "\
75
- "got `#{actual.send(name)}`"
76
- end
77
- end
78
- when :json
79
- matcher matcher_name do |expected|
80
74
  include MatcherHelpers
81
75
 
82
- match { |actual| maybe_json?(actual.send(name), expected) }
76
+ match { |actual| maybe_json?(actual.send(value_method), expected) }
77
+ when :array
78
+ value_method = "#{name}s"
79
+ verb = 'include'
83
80
 
84
- failure_message do |actual|
85
- "expected `#{name.upcase}` to be `#{expected.inspect}`, "\
86
- "got `#{actual.send(name)}`"
81
+ # Allow ports to be passed as integer:
82
+ if matcher_name == :have_expose && expected.is_a?(Numeric)
83
+ expected = expected.to_s
87
84
  end
88
85
 
89
- failure_message_when_negated do |actual|
90
- "expected `#{name.upcase}` not to be `#{expected.inspect}`, "\
91
- "got `#{actual.send(name)}`"
92
- end
93
- end
94
- when :array
95
- matcher matcher_name do |expected|
96
- match { |actual| !actual.send("#{name}s").grep(expected).empty? }
97
-
98
- failure_message do |actual|
99
- "expected `#{name.upcase}` to include `#{expected.inspect}`, "\
100
- "got `#{actual.send("#{name}s").inspect}`"
101
- end
86
+ match { |actual| !actual.send(value_method).grep(expected).empty? }
87
+ when :hash
88
+ value_method = "#{name}s"
89
+ verb = 'contain'
102
90
 
103
- failure_message_when_negated do |actual|
104
- "expected `#{name.upcase}` not to include "\
105
- "`#{expected.inspect}`, got `#{actual.send("#{name}s").inspect}`"
106
- end
107
- end
108
- when :hash
109
- matcher matcher_name do |expected|
110
91
  include MatcherHelpers
111
92
 
112
93
  match do |actual|
113
- actual = actual.send("#{name}s")
94
+ actual = actual.send(value_method)
114
95
  break sub_hash?(actual, expected) if expected.is_a?(Hash)
115
96
  !actual.keys.grep(expected).empty?
116
97
  end
98
+ end # case type
117
99
 
118
- failure_message do |actual|
119
- "expected `#{name.upcase}` to contain `#{expected.inspect}`, "\
120
- "got `#{actual.send("#{name}s")}`"
121
- end
100
+ failure_message do |actual|
101
+ "expected `#{name.upcase}` to #{verb} `#{expected.inspect}`, "\
102
+ "got `#{actual.send(value_method).inspect}`"
103
+ end
122
104
 
123
- failure_message_when_negated do |actual|
124
- "expected `#{name.upcase}` not to contain "\
125
- "`#{expected.inspect}`, got `#{actual.send("#{name}s")}`"
126
- end
105
+ failure_message_when_negated do |actual|
106
+ "expected `#{name.upcase}` not to #{verb} "\
107
+ "`#{expected.inspect}`, got `#{actual.send(value_method).inspect}`"
127
108
  end
128
- end
129
- end
109
+ end # matcher
110
+ end # PREDICATE_TYPES each
130
111
  end
131
112
  end
132
113
  end
@@ -0,0 +1,188 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Xabier de Zuazo (<xabier@zuazo.org>)
4
+ # Copyright:: Copyright (c) 2016 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 'dockerspec/runner/docker'
21
+ require 'dockerspec/runner/compose'
22
+
23
+ module Dockerspec
24
+ #
25
+ # Saves internal configuration for {Dockerspec}.
26
+ #
27
+ # - The test engines to Run: Specinfra, ...
28
+ # - The internal library used to run Docker.
29
+ #
30
+ class Configuration
31
+ #
32
+ # The {Dockerspec::Runner} class used to run Docker.
33
+ #
34
+ # @return [Class] The {Dockerspec::Runner::Base} class.
35
+ #
36
+ attr_accessor :docker_runner
37
+
38
+ #
39
+ # The {Dockerspec::Runner::Compose} class used to run Docker Compose.
40
+ #
41
+ # @return [Class] The {Dockerspec::Runner::Compose} class.
42
+ #
43
+ attr_accessor :compose_runner
44
+
45
+ #
46
+ # A list of test engines used to run the tests.
47
+ #
48
+ # @return [Array<Class>] A list of {Dockerspec::Engine::Base} classes.
49
+ #
50
+ attr_reader :engines
51
+
52
+ class << self
53
+ #
54
+ # Adds a class to use as engine to run the tests.
55
+ #
56
+ # @example
57
+ # Dockerspec.Configuration.add_engine Dockerspec::Engine::Specinfra
58
+ #
59
+ # @param engine [Class] A {Dockerspec::Engine::Base} subclass.
60
+ #
61
+ # @return void
62
+ #
63
+ # @api public
64
+ #
65
+ def add_engine(engine)
66
+ instance.add_engine(engine)
67
+ end
68
+
69
+ #
70
+ # Gets the engine classes used to run the tests.
71
+ #
72
+ # @return [Array<Class>] A list of {Dockerspec::Engine::Base} subclasses.
73
+ #
74
+ # @api public
75
+ #
76
+ def engines
77
+ instance.engines
78
+ end
79
+
80
+ #
81
+ # Sets the class used to create and start Docker Containers.
82
+ #
83
+ # @example
84
+ # Dockerspec.Configuration.docker_runner = Dockerspec::Runner::Docker
85
+ #
86
+ # @param runner [Class] A {Dockerspec::Runner::Base} subclass.
87
+ #
88
+ # @return void
89
+ #
90
+ # @api public
91
+ #
92
+ def docker_runner=(runner)
93
+ instance.docker_runner = runner
94
+ end
95
+
96
+ #
97
+ # Gets the class used to create and start Docker Containers.
98
+ #
99
+ # @return [Class] A {Dockerspec::Runner::Base} subclass.
100
+ #
101
+ # @api public
102
+ #
103
+ def docker_runner
104
+ instance.docker_runner
105
+ end
106
+
107
+ #
108
+ # Sets the class used to start Docker Compose.
109
+ #
110
+ # @example
111
+ # Dockerspec.Configuration.compose_runner = Dockerspec::Runner::Compose
112
+ #
113
+ # @param runner [Class] A {Dockerspec::Runner::Compose::Base} subclass.
114
+ #
115
+ # @return void
116
+ #
117
+ # @api public
118
+ #
119
+ def compose_runner=(runner)
120
+ instance.compose_runner = runner
121
+ end
122
+
123
+ #
124
+ # Gets the class used to start Docker Compose.
125
+ #
126
+ # @return [Class] A {Dockerspec::Runner::Compose::Base} subclass.
127
+ #
128
+ # @api public
129
+ #
130
+ def compose_runner
131
+ instance.compose_runner
132
+ end
133
+
134
+ #
135
+ # Resets the internal Configuration singleton object.
136
+ #
137
+ # @return void
138
+ #
139
+ # @api public
140
+ #
141
+ def reset
142
+ @instance = nil
143
+ end
144
+
145
+ protected
146
+
147
+ #
148
+ # Creates the Configuration singleton instance.
149
+ #
150
+ # @return void
151
+ #
152
+ # @api private
153
+ #
154
+ def instance
155
+ @instance ||= new
156
+ end
157
+ end
158
+
159
+ #
160
+ # Adds a class to use as engine to run the tests.
161
+ #
162
+ # @param engine [Class] A {Dockerspec::Engine::Base} subclass.
163
+ #
164
+ # @return void
165
+ #
166
+ # @api private
167
+ #
168
+ def add_engine(engine)
169
+ @engines << engine
170
+ @engines.uniq!
171
+ end
172
+
173
+ protected
174
+
175
+ #
176
+ # Constructs a configuration object.
177
+ #
178
+ # @return [Dockerspec::Configuretion] The configuration object.
179
+ #
180
+ # @api private
181
+ #
182
+ def initialize
183
+ @docker_runner = Runner::Docker
184
+ @compose_runner = Runner::Compose
185
+ @engines = []
186
+ end
187
+ end
188
+ end
@@ -45,7 +45,7 @@ module Dockerspec
45
45
  def initialize(e)
46
46
  e_ary = parse_exception(e)
47
47
  raise_docker_error_exception(e_ary)
48
- fail e
48
+ raise e
49
49
  end
50
50
 
51
51
  protected
@@ -153,7 +153,7 @@ module Dockerspec
153
153
  output = parse_streams(e_ary)
154
154
  error_msg = parse_error_detail(e_ary)
155
155
  return if error_msg.nil?
156
- fail DockerError, generate_error_message(error_msg, output)
156
+ raise DockerError, generate_error_message(error_msg, output)
157
157
  end
158
158
  end
159
159
  end