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.
- checksums.yaml +7 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +7 -0
- data/CONTRIBUTING.md +13 -0
- data/LICENSE +190 -0
- data/README.md +202 -0
- data/Rakefile +57 -0
- data/TESTING.md +30 -0
- data/TODO.md +6 -0
- data/lib/dockerspec.rb +21 -0
- data/lib/dockerspec/builder.rb +408 -0
- data/lib/dockerspec/builder/config_helpers.rb +425 -0
- data/lib/dockerspec/builder/image_gc.rb +71 -0
- data/lib/dockerspec/builder/logger.rb +56 -0
- data/lib/dockerspec/builder/logger/ci.rb +69 -0
- data/lib/dockerspec/builder/logger/debug.rb +47 -0
- data/lib/dockerspec/builder/logger/info.rb +111 -0
- data/lib/dockerspec/builder/logger/silent.rb +51 -0
- data/lib/dockerspec/builder/matchers.rb +134 -0
- data/lib/dockerspec/builder/matchers/helpers.rb +88 -0
- data/lib/dockerspec/docker_gem.rb +25 -0
- data/lib/dockerspec/exceptions.rb +26 -0
- data/lib/dockerspec/helper/ci.rb +61 -0
- data/lib/dockerspec/helper/docker.rb +44 -0
- data/lib/dockerspec/helper/multiple_sources_description.rb +142 -0
- data/lib/dockerspec/helper/rspec_example_helpers.rb +48 -0
- data/lib/dockerspec/rspec_assertions.rb +54 -0
- data/lib/dockerspec/rspec_resources.rb +198 -0
- data/lib/dockerspec/rspec_settings.rb +29 -0
- data/lib/dockerspec/runner.rb +374 -0
- data/lib/dockerspec/serverspec.rb +20 -0
- data/lib/dockerspec/serverspec/rspec_resources.rb +174 -0
- data/lib/dockerspec/serverspec/rspec_settings.rb +27 -0
- data/lib/dockerspec/serverspec/runner.rb +302 -0
- data/lib/dockerspec/serverspec/specinfra_backend.rb +128 -0
- data/lib/dockerspec/serverspec/specinfra_hack.rb +43 -0
- data/lib/dockerspec/version.rb +29 -0
- data/spec/spec_helper.rb +44 -0
- metadata +293 -0
@@ -0,0 +1,56 @@
|
|
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 'dockerspec/builder/logger/silent'
|
21
|
+
require 'dockerspec/builder/logger/ci'
|
22
|
+
require 'dockerspec/builder/logger/info'
|
23
|
+
require 'dockerspec/builder/logger/debug'
|
24
|
+
|
25
|
+
module Dockerspec
|
26
|
+
class Builder
|
27
|
+
#
|
28
|
+
# Creates an output logger for the {Dockerspec::Builder}.
|
29
|
+
#
|
30
|
+
class Logger
|
31
|
+
#
|
32
|
+
# Creates a logger object.
|
33
|
+
#
|
34
|
+
# @param type [Fixnum, Symbol] The logger to create. Possible values:
|
35
|
+
# `:silent` or `0` (no output),
|
36
|
+
# `:ci` or `1` (enables some outputs recommended for CI environments),
|
37
|
+
# `:info` or `2` (gives information about main build steps),
|
38
|
+
# `:debug` or `3` (outputs all the provided information in its raw
|
39
|
+
# original form).
|
40
|
+
#
|
41
|
+
# @return [Dockerspec::Builder::Logger] The logger.
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
#
|
45
|
+
def self.instance(type)
|
46
|
+
case type.to_s.downcase
|
47
|
+
when '0', 'silent' then Silent.new
|
48
|
+
when '1', 'ci' then CI.new
|
49
|
+
when '2', 'info' then Info.new
|
50
|
+
else
|
51
|
+
Debug.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,69 @@
|
|
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 'dockerspec/builder/logger/info'
|
21
|
+
|
22
|
+
module Dockerspec
|
23
|
+
class Builder
|
24
|
+
class Logger
|
25
|
+
#
|
26
|
+
# A {Dockerspec::Builder} logger recommended for CI environments with
|
27
|
+
# output timeouts.
|
28
|
+
#
|
29
|
+
class CI < Info
|
30
|
+
#
|
31
|
+
# Creates a CI logger instance.
|
32
|
+
#
|
33
|
+
# @param output [IO] the output stream.
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
#
|
37
|
+
def initialize(output = STDOUT)
|
38
|
+
super
|
39
|
+
@buffer = ''
|
40
|
+
@skip = false
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
#
|
46
|
+
# Print a Docker build stream in the proper format.
|
47
|
+
#
|
48
|
+
# @param stream [String] The stream in raw.
|
49
|
+
#
|
50
|
+
# @return void
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
#
|
54
|
+
def print_stream(stream)
|
55
|
+
if stream.match(/^Step /)
|
56
|
+
@buffer = stream
|
57
|
+
@skip = true
|
58
|
+
else
|
59
|
+
@buffer += stream
|
60
|
+
@skip = false if stream.match(/^ ---> (Running in|\[Warning\]) /)
|
61
|
+
end
|
62
|
+
return if @skip
|
63
|
+
@output.puts @buffer
|
64
|
+
@buffer = ''
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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 'dockerspec/builder/logger/info'
|
21
|
+
|
22
|
+
module Dockerspec
|
23
|
+
class Builder
|
24
|
+
class Logger
|
25
|
+
#
|
26
|
+
# A {Dockerspec::Builder} logger to output all the provided information in
|
27
|
+
# its raw original form.
|
28
|
+
#
|
29
|
+
class Debug < Info
|
30
|
+
#
|
31
|
+
# Prints the docker build chunk in raw.
|
32
|
+
#
|
33
|
+
# @param chunk [Hash] The docker build chunk.
|
34
|
+
#
|
35
|
+
# @return void
|
36
|
+
#
|
37
|
+
# @api public
|
38
|
+
#
|
39
|
+
def print_chunk(chunk)
|
40
|
+
chunk_json = parse_chunk(chunk)
|
41
|
+
print_status(chunk_json.delete('status'))
|
42
|
+
@output.puts chunk_json.inspect
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,111 @@
|
|
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
|
+
class Logger
|
23
|
+
#
|
24
|
+
# A {Dockerspec::Builder} logger that gives information about main build
|
25
|
+
# steps.
|
26
|
+
#
|
27
|
+
class Info
|
28
|
+
#
|
29
|
+
# Creates a Info logger instance.
|
30
|
+
#
|
31
|
+
# @param output [IO] the output stream.
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
#
|
35
|
+
def initialize(output = STDOUT)
|
36
|
+
@output = output
|
37
|
+
@status = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Prints the Docker build chunk.
|
42
|
+
#
|
43
|
+
# @param chunk [Hash] The docker build chunk.
|
44
|
+
#
|
45
|
+
# @return void
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
#
|
49
|
+
def print_chunk(chunk)
|
50
|
+
chunk_json = parse_chunk(chunk)
|
51
|
+
print_status(chunk_json['status'])
|
52
|
+
return unless chunk_json.key?('stream')
|
53
|
+
print_stream(chunk_json['stream'])
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
#
|
59
|
+
# Parses the Docker build process chunk.
|
60
|
+
#
|
61
|
+
# @param chunk [String] The chunk in JSON.
|
62
|
+
#
|
63
|
+
# @return [Hash] The chunk parsed as a Hash.
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
def parse_chunk(chunk)
|
68
|
+
return chunk if chunk.is_a?(Hash)
|
69
|
+
JSON.parse(chunk)
|
70
|
+
rescue JSON::ParserError
|
71
|
+
{ 'stream' => chunk }
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Prints progress status in a shorter format.
|
76
|
+
#
|
77
|
+
# For example: `'Downloading.....\nExtracting..`'.
|
78
|
+
#
|
79
|
+
# @param status [String] The name of the current status.
|
80
|
+
#
|
81
|
+
# @return void
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
#
|
85
|
+
def print_status(status)
|
86
|
+
if status != @status
|
87
|
+
@output.puts
|
88
|
+
@status = status
|
89
|
+
@output.print "#{status}." unless status.nil?
|
90
|
+
elsif !status.nil?
|
91
|
+
@output.print '.'
|
92
|
+
end
|
93
|
+
@output.flush
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Prints the stream.
|
98
|
+
#
|
99
|
+
# @param stream [String] The text to print.
|
100
|
+
#
|
101
|
+
# @return void
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
#
|
105
|
+
def print_stream(stream)
|
106
|
+
@output.puts stream
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,51 @@
|
|
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
|
+
class Logger
|
23
|
+
#
|
24
|
+
# A {Dockerspec::Builder} logger that outputs nothing.
|
25
|
+
#
|
26
|
+
class Silent
|
27
|
+
#
|
28
|
+
# Creates a Silent logger instance.
|
29
|
+
#
|
30
|
+
# @param _args [Mixed] ignored.
|
31
|
+
#
|
32
|
+
# @return void
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
#
|
36
|
+
def initialize(*_args); end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Prints nothing.
|
40
|
+
#
|
41
|
+
# @param _chunk [Mixed] ignored.
|
42
|
+
#
|
43
|
+
# @return void
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
#
|
47
|
+
def print_chunk(_chunk); end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,134 @@
|
|
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 'rspec/expectations'
|
21
|
+
require 'dockerspec/builder/matchers/helpers'
|
22
|
+
|
23
|
+
module Dockerspec
|
24
|
+
class Builder
|
25
|
+
#
|
26
|
+
# Creates some RSpec *have_* matchers for Docker builds.
|
27
|
+
#
|
28
|
+
module Matchers
|
29
|
+
extend RSpec::Matchers::DSL
|
30
|
+
|
31
|
+
#
|
32
|
+
# The matcher list with the type it belongs to.
|
33
|
+
#
|
34
|
+
# This is based on [the official *Dockerfile* parser code]
|
35
|
+
# (https://github.com/docker/docker/tree/master/builder/dockerfile/parser)
|
36
|
+
# .
|
37
|
+
#
|
38
|
+
# The possible types are:
|
39
|
+
#
|
40
|
+
# - `:string`: A simple string. For example the `MAINTAINER` instruction.
|
41
|
+
# - `:json`: Can in JSON (a Ruby array) or in string format. For example
|
42
|
+
# the `CMD` or the `ENTRYPOINT` instructions.
|
43
|
+
# - `:hash`: A hash. For example the `ENV` or the `LABEL` instructions.
|
44
|
+
# - `:array`: A array of values. For example the `EXPOSE` instruction.
|
45
|
+
#
|
46
|
+
PREDICATE_TYPES = {
|
47
|
+
maintainer: :string,
|
48
|
+
cmd: :json,
|
49
|
+
label: :hash,
|
50
|
+
expose: :array,
|
51
|
+
env: :hash,
|
52
|
+
entrypoint: :json,
|
53
|
+
volume: :array,
|
54
|
+
user: :string,
|
55
|
+
workdir: :string,
|
56
|
+
onbuild: :array,
|
57
|
+
stopsignal: :string
|
58
|
+
}
|
59
|
+
|
60
|
+
PREDICATE_TYPES.each do |name, type|
|
61
|
+
matcher_name = "have_#{name}".to_sym
|
62
|
+
|
63
|
+
case type
|
64
|
+
when :string
|
65
|
+
matcher matcher_name do |expected|
|
66
|
+
match { |actual| !expected.match(actual.send(name)).nil? }
|
67
|
+
|
68
|
+
failure_message do |actual|
|
69
|
+
"expected `#{name.upcase}` to match `#{expected.inspect}`, "\
|
70
|
+
"got `#{actual.send(name)}`"
|
71
|
+
end
|
72
|
+
|
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
|
+
include MatcherHelpers
|
81
|
+
|
82
|
+
match { |actual| maybe_json?(actual.send(name), expected) }
|
83
|
+
|
84
|
+
failure_message do |actual|
|
85
|
+
"expected `#{name.upcase}` to be `#{expected.inspect}`, "\
|
86
|
+
"got `#{actual.send(name)}`"
|
87
|
+
end
|
88
|
+
|
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
|
102
|
+
|
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
|
+
include MatcherHelpers
|
111
|
+
|
112
|
+
match do |actual|
|
113
|
+
actual = actual.send("#{name}s")
|
114
|
+
break sub_hash?(actual, expected) if expected.is_a?(Hash)
|
115
|
+
!actual.keys.grep(expected).empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
failure_message do |actual|
|
119
|
+
"expected `#{name.upcase}` to contain `#{expected.inspect}`, "\
|
120
|
+
"got `#{actual.send("#{name}s")}`"
|
121
|
+
end
|
122
|
+
|
123
|
+
failure_message_when_negated do |actual|
|
124
|
+
"expected `#{name.upcase}` not to contain "\
|
125
|
+
"`#{expected.inspect}`, got `#{actual.send("#{name}s")}`"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
RSpec.configure { |c| c.include(Dockerspec::Builder::Matchers) }
|