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,88 @@
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
+
22
+ module Dockerspec
23
+ class Builder
24
+ module Matchers
25
+ #
26
+ # Some helpers methods for the Docker build RSpec matchers.
27
+ #
28
+ module MatcherHelpers
29
+ #
30
+ # Checks whether a hash is a subhash of another.
31
+ #
32
+ # @example
33
+ # self.sub_hash?({ a: 1, b: 2, c: 3 }, { a: 1 }) #=> true
34
+ # self.sub_hash?({ a: 1, b: 2, c: 3 }, { b: 2, c: 3 }) #=> true
35
+ # self.sub_hash?({ a: 1, b: 2, c: 3 }, { a: 2, b: 2 }) #=> false
36
+ # self.sub_hash?({ a: 'Hello', b: 'World' }, { a: /H/, b: /Wor/ }
37
+ # #=> true
38
+ # self.sub_hash?({ a: 'Hello', b: 'World' }, { a: /Bye/ } #=> false
39
+ #
40
+ # @param hash [Hash] The hash in which to search.
41
+ # @param sub_hash [Hash] The subhash.
42
+ #
43
+ # @return [Boolean] Whether it's a subhash.
44
+ #
45
+ # @api public
46
+ #
47
+ def sub_hash?(hash, sub_hash)
48
+ sub_hash.all? do |sub_hash_key, sub_hash_value|
49
+ next false unless hash.key?(sub_hash_key)
50
+ if sub_hash_value.respond_to?(:match)
51
+ !sub_hash_value.match(hash[sub_hash_key]).nil?
52
+ else
53
+ sub_hash_value == hash[sub_hash_key]
54
+ end
55
+ end
56
+ end
57
+
58
+ #
59
+ # A matcher to check JSON values like `CMD` and `ENTRYPOINT`.
60
+ #
61
+ # The expected value can be in JSON (a Ruby array) or in String format
62
+ # just like in the *Dockerfile*.
63
+ #
64
+ # The real (*got*) value will always be in array format.
65
+ #
66
+ # @example
67
+ # self.maybe_json?([0, 1, 3, 4], [0, 1, 3, 4]) #=> true
68
+ # self.maybe_json?([0, 1, 3, 4], [0, 1, 3, 5]) #=> false
69
+ # self.maybe_json?(%w(hello world), 'hello world') #=> true
70
+ # self.maybe_json?(%w(hello world), 'bye') #=> false
71
+ # self.maybe_json?(%w(hello world), /llo wor/) #=> true
72
+ # self.maybe_json?(%w(hello world), /bye/) #=> false
73
+ #
74
+ # @param got [Array] The received value.
75
+ # @param expected [Array, String, Regexp] The expected value.
76
+ #
77
+ # @return [Boolean] Whether the expected value matches the real value.
78
+ #
79
+ # @api public
80
+ #
81
+ def maybe_json?(got, expected)
82
+ return expected == got if expected.is_a?(Array)
83
+ !expected.match(got.join(' ')).nil?
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,25 @@
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 'docker'
21
+
22
+ #
23
+ # We tweak the timeout to get along better with CI environments.
24
+ #
25
+ ::Docker.options[:read_timeout] = 50 * 60 # 50 mins
@@ -0,0 +1,26 @@
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
+ #
22
+ # An exception message raised when the arguments passed to `docker_run` are
23
+ # wrong.
24
+ #
25
+ class DockerRunArgumentError < ArgumentError; end
26
+ end
@@ -0,0 +1,61 @@
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
+ module Helper
22
+ #
23
+ # Some helper methods for detecting Continuous Integration environments.
24
+ #
25
+ module CI
26
+ #
27
+ # Returns whether we are running on a [Continuous Integration]
28
+ # (https://en.wikipedia.org/wiki/Continuous_integration) machine.
29
+ #
30
+ # @return [Boolean] `true` if we are inside a CI.
31
+ #
32
+ # @api public
33
+ #
34
+ def ci?
35
+ ENV['CI'] == 'true'
36
+ end
37
+
38
+ #
39
+ # Returns whether we are running on [Travis CI](https://travis-ci.org/).
40
+ #
41
+ # @return [Boolean] `true` if we are inside Travis CI.
42
+ #
43
+ # @api public
44
+ #
45
+ def travis_ci?
46
+ ENV['TRAVIS'] == 'true'
47
+ end
48
+
49
+ #
50
+ # Returns whether we are running on [CircleCI](https://circleci.com/).
51
+ #
52
+ # @return [Boolean] `true` if we are inside CircleCI.
53
+ #
54
+ # @api public
55
+ #
56
+ def circle_ci?
57
+ ENV['CIRCLECI'] == 'true'
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,44 @@
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/docker_gem'
21
+
22
+ module Dockerspec
23
+ #
24
+ # Some generic helpers for {Dockerspec} classes.
25
+ #
26
+ module Helper
27
+ #
28
+ # Some helper methods to get information of the Docker environment in the
29
+ # system.
30
+ #
31
+ module Docker
32
+ #
33
+ # Detects if we are using the Docker LXC execution driver.
34
+ #
35
+ # @return [Boolean] `true` if we are using the LXC driver.
36
+ #
37
+ # @api public
38
+ #
39
+ def self.lxc_execution_driver?
40
+ ::Docker.info['ExecutionDriver'].start_with?('lxc')
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,142 @@
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'
21
+ require 'rspec/its'
22
+ require 'erubis'
23
+ require 'dockerspec/docker_gem'
24
+ require 'dockerspec/builder/config_helpers'
25
+ require 'dockerspec/builder/matchers'
26
+ require 'dockerspec/builder/logger'
27
+ require 'dockerspec/builder/image_gc'
28
+ require 'dockerspec/helper/ci'
29
+
30
+ module Dockerspec
31
+ module Helper
32
+ #
33
+ # Methods to generate the correct object description for objects that
34
+ # has a source attribute.
35
+ #
36
+ # Shortens the docker IDs automatically.
37
+ #
38
+ # Requirements:
39
+ #
40
+ # - `source` method: Returns the source you are using to generating your
41
+ # object.
42
+ # - `:@options` attribute: The options array with the configuration
43
+ # options, including the source.
44
+ #
45
+ # Used by the {Dockerspec::Builder} and {Dockerspec::Runner} classes.
46
+ #
47
+ module MultipleSourcesDescription
48
+ #
49
+ # Generates a description of the object.
50
+ #
51
+ # @example
52
+ # self.description('Docker Build from')
53
+ # #=> "Docker Build from path: \".\""
54
+ #
55
+ # @param prefix [String] The prefix to add to the description.
56
+ #
57
+ # @return [String] The object description.
58
+ #
59
+ # @api private
60
+ #
61
+ def description(prefix)
62
+ value = @options[source]
63
+ desc = send("description_from_#{source}", value)
64
+ "#{prefix} #{source.to_s.tr('_', ' ')}: \"#{desc}\""
65
+ end
66
+
67
+ protected
68
+
69
+ #
70
+ # Generates an adequate description of a Docker object description.
71
+ #
72
+ # Essentially it shortens the docker identifiers.
73
+ #
74
+ # @example
75
+ # self.description_from_docker_object('debian') #=> "debian"
76
+ # self.description_from_docker_object('92cc98ab560a92cc98ab560[...]')
77
+ # #=> "92cc98ab560a"
78
+ #
79
+ # @param str [String] The description.
80
+ #
81
+ # @return [String] The description, shortened if necessary.
82
+ #
83
+ # @api private
84
+ #
85
+ def description_from_docker(str)
86
+ return str unless str.match(/^[0-9a-f]+$/)
87
+ str[0..11]
88
+ end
89
+
90
+ #
91
+ # Generates a description from Docker ID.
92
+ #
93
+ alias_method :description_from_id, :description_from_docker
94
+
95
+ #
96
+ # Generates a description from string.
97
+ #
98
+ # shortens the string.
99
+ #
100
+ # @example
101
+ # self.description_from_string #=> "FROM nginx:1..."
102
+ #
103
+ # @return [String] A description.
104
+ #
105
+ # @api private
106
+ #
107
+ def description_from_string(str)
108
+ len = 12
109
+ return str unless str.length > len
110
+ "#{str[0..len - 1]}..." # Is this length correct?
111
+ end
112
+
113
+ #
114
+ # Generates a description of a file.
115
+ #
116
+ # Basically expands the path.
117
+ #
118
+ # @example
119
+ # self.description_from_file("mydir") #=> "mydir"
120
+ #
121
+ # @return [String] A description.
122
+ #
123
+ # @api private
124
+ #
125
+ def description_from_file(str)
126
+ File.expand_path(str)
127
+ end
128
+
129
+ #
130
+ # Generates a description of a file.
131
+ #
132
+ # @example
133
+ # self.description_from_template("mydir") #=> "mydir"
134
+ #
135
+ # @return [String] A description.
136
+ #
137
+ # @api private
138
+ #
139
+ alias_method :description_from_path, :description_from_file
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,48 @@
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
+ module Helper
22
+ #
23
+ # Some Helper methods to work with RSpec Examples.
24
+ #
25
+ module RSpecExampleHelpers
26
+ #
27
+ # Searches for an object in the description of the parent RSpec examples.
28
+ #
29
+ # @param metadata [Hash] RSpec metadata.
30
+ # @param klass [Class] Type of object to search.
31
+ #
32
+ # @return [Object] Returns the object if found. `nil` if not found.
33
+ #
34
+ # @api public
35
+ #
36
+ def self.search_object(metadata, klass)
37
+ return metadata if metadata.nil?
38
+ if metadata[:described_class].is_a?(klass)
39
+ metadata[:described_class]
40
+ elsif metadata.key?(:parent_example_group)
41
+ search_object(metadata[:parent_example_group], klass)
42
+ elsif metadata.key?(:example_group)
43
+ search_object(metadata[:example_group], klass)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,54 @@
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/exceptions'
21
+
22
+ module Dockerspec
23
+ #
24
+ # Some helper methods to check {Dockerspec::RSpecResources#docker_run}`
25
+ # arguments and output understandable error messages.
26
+ #
27
+ module RSpecAssertions
28
+ #
29
+ # A message with description on how to avoid the error in
30
+ # {Dockerspec::Serverspec::Runner#docker_run}
31
+ #
32
+ DOCKER_RUN_ALWAYS_MESSAGE = <<-EOE
33
+
34
+ Remember to include the Serverspec library:
35
+
36
+ require 'dockerspec'
37
+ require 'dockerspec/serverspec'
38
+
39
+ EOE
40
+
41
+ #
42
+ # Raises and exception with instructions on how to fix it.
43
+ #
44
+ # @raise [Dockerspec::DockerRunArgumentError] Raises this exception always.
45
+ #
46
+ # @return void
47
+ #
48
+ # @api private
49
+ #
50
+ def self.assert_docker_run!(_opts)
51
+ fail DockerRunArgumentError, DOCKER_RUN_ALWAYS_MESSAGE
52
+ end
53
+ end
54
+ end