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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/LICENSE +1 -1
- data/README.md +190 -24
- data/Rakefile +60 -6
- data/TODO.md +3 -2
- data/lib/dockerspec.rb +1 -2
- data/lib/dockerspec/builder.rb +13 -6
- data/lib/dockerspec/builder/config_helpers.rb +8 -3
- data/lib/dockerspec/builder/logger/ci.rb +2 -2
- data/lib/dockerspec/builder/matchers.rb +32 -51
- data/lib/dockerspec/configuration.rb +188 -0
- data/lib/dockerspec/docker_exception_parser.rb +2 -2
- data/lib/dockerspec/engine/base.rb +156 -0
- data/lib/dockerspec/engine/infrataster.rb +87 -0
- data/lib/dockerspec/engine/specinfra.rb +130 -0
- data/lib/dockerspec/engine/specinfra/backend.rb +163 -0
- data/lib/dockerspec/{serverspec/specinfra_hack.rb → engine/specinfra/backend_hack.rb} +17 -3
- data/lib/dockerspec/engine_list.rb +150 -0
- data/lib/dockerspec/exceptions.rb +13 -0
- data/lib/dockerspec/helper/multiple_sources_description.rb +3 -3
- data/lib/dockerspec/helper/rspec_example_helpers.rb +86 -6
- data/lib/dockerspec/infrataster.rb +26 -0
- data/lib/dockerspec/rspec.rb +21 -0
- data/lib/dockerspec/{rspec_configuration.rb → rspec/configuration.rb} +1 -1
- data/lib/dockerspec/rspec/resources.rb +602 -0
- data/lib/dockerspec/rspec/resources/its_container.rb +110 -0
- data/lib/dockerspec/{rspec_settings.rb → rspec/settings.rb} +5 -1
- data/lib/dockerspec/runner.rb +2 -357
- data/lib/dockerspec/runner/base.rb +367 -0
- data/lib/dockerspec/runner/compose.rb +322 -0
- data/lib/dockerspec/runner/docker.rb +302 -0
- data/lib/dockerspec/runner/serverspec.rb +21 -0
- data/lib/dockerspec/runner/serverspec/base.rb +185 -0
- data/lib/dockerspec/runner/serverspec/compose.rb +106 -0
- data/lib/dockerspec/runner/serverspec/docker.rb +116 -0
- data/lib/dockerspec/runner/serverspec/rspec.rb +20 -0
- data/lib/dockerspec/{serverspec/rspec_settings.rb → runner/serverspec/rspec/settings.rb} +1 -1
- data/lib/dockerspec/serverspec.rb +12 -2
- data/lib/dockerspec/version.rb +1 -1
- data/spec/spec_helper.rb +6 -2
- metadata +84 -15
- data/lib/dockerspec/rspec_assertions.rb +0 -54
- data/lib/dockerspec/rspec_resources.rb +0 -203
- data/lib/dockerspec/serverspec/rspec_resources.rb +0 -179
- data/lib/dockerspec/serverspec/runner.rb +0 -305
- data/lib/dockerspec/serverspec/specinfra_backend.rb +0 -128
data/lib/dockerspec.rb
CHANGED
data/lib/dockerspec/builder.rb
CHANGED
@@ -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::
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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::
|
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
|
-
|
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
|
-
|
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
|
55
|
+
if stream =~ /^Step /
|
56
56
|
@buffer = stream
|
57
57
|
@skip = true
|
58
58
|
else
|
59
59
|
@buffer += stream
|
60
|
-
@skip = false if stream
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
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(
|
76
|
+
match { |actual| maybe_json?(actual.send(value_method), expected) }
|
77
|
+
when :array
|
78
|
+
value_method = "#{name}s"
|
79
|
+
verb = 'include'
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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(
|
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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
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
|
-
|
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
|
-
|
156
|
+
raise DockerError, generate_error_message(error_msg, output)
|
157
157
|
end
|
158
158
|
end
|
159
159
|
end
|