dockerspec 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|