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,198 @@
|
|
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'
|
21
|
+
require 'dockerspec/runner' # Not really necessary (currently unused)
|
22
|
+
require 'dockerspec/rspec_settings'
|
23
|
+
require 'dockerspec/rspec_assertions'
|
24
|
+
|
25
|
+
module Dockerspec
|
26
|
+
#
|
27
|
+
# Some resources included inside {RSpec::Core::ExampleGroup} to build and run
|
28
|
+
# Docker containers.
|
29
|
+
#
|
30
|
+
# ## RSpec Settings
|
31
|
+
#
|
32
|
+
# * `dockerfile_path`: The dockerfile path.
|
33
|
+
# * `rm_build`: Whether to remove the build after the run.
|
34
|
+
# * `log_level`: Log level to use by default.
|
35
|
+
#
|
36
|
+
# All the RSpec settings are optional.
|
37
|
+
#
|
38
|
+
# @example RSpec Settings
|
39
|
+
# RSpec.configure do |config|
|
40
|
+
# config.log_level = :silent
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
module RSpecResources
|
44
|
+
#
|
45
|
+
# Builds a Docker image.
|
46
|
+
#
|
47
|
+
# The image can be build from a path or from a string.
|
48
|
+
#
|
49
|
+
# See the {Dockerspec::Builder::ConfigHelpers} documentation for more
|
50
|
+
# information about the available RSpec resource helpers.
|
51
|
+
#
|
52
|
+
# @example A Simple Example
|
53
|
+
# describe 'My Dockerfile' do
|
54
|
+
# describe docker_build('.') do
|
55
|
+
# it { should have_maintainer /John Doe/ }
|
56
|
+
# it { should have_cmd ['/bin/dash'] }
|
57
|
+
# it { should have_expose '80' }
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# @example A Complete Example
|
62
|
+
# describe docker_build(path: '.') do
|
63
|
+
# it { should have_maintainer 'John Doe "john.doe@example.com"' }
|
64
|
+
# it { should have_maintainer(/John Doe/) }
|
65
|
+
# it { should have_cmd %w(2 2000) }
|
66
|
+
# it { should have_label 'description' }
|
67
|
+
# it { should have_label 'description' => 'My Container' }
|
68
|
+
# it { should have_expose '80' }
|
69
|
+
# it { should have_expose(/80$/) }
|
70
|
+
# it { should have_env 'container' }
|
71
|
+
# it { should have_env 'container' => 'docker' }
|
72
|
+
# it { should have_env 'CRACKER' => 'RANDOM;PATH=/tmp/bin:/sbin:/bin' }
|
73
|
+
# it { should have_entrypoint ['sleep'] }
|
74
|
+
# it { should have_volume '/volume1' }
|
75
|
+
# it { should have_volume %r{/vol.*2} }
|
76
|
+
# it { should have_user 'nobody' }
|
77
|
+
# it { should have_workdir '/opt' }
|
78
|
+
# it { should have_workdir %r{^/op} }
|
79
|
+
# it { should have_onbuild 'RUN echo onbuild' }
|
80
|
+
# it { should have_stopsignal 'SIGTERM' }
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# @example Checking the Attribute Values Using the `its` Method
|
84
|
+
# describe docker_build(path: '.') do
|
85
|
+
# its(:maintainer) { should eq 'John Doe "john.doe@example.com"' }
|
86
|
+
# its(:cmd) { should eq %w(2 2000) }
|
87
|
+
# its(:labels) { should include 'description' }
|
88
|
+
# its(:labels) { should include 'description' => 'My Container' }
|
89
|
+
# its(:exposes) { should include '80' }
|
90
|
+
# its(:env) { should include 'container' }
|
91
|
+
# its(:env) { should include 'container' => 'docker' }
|
92
|
+
# its(:entrypoint) { should eq ['sleep'] }
|
93
|
+
# its(:volumes) { should include '/volume1' }
|
94
|
+
# its(:user) { should eq 'nobody' }
|
95
|
+
# its(:workdir) { should eq '/opt' }
|
96
|
+
# its(:onbuilds) { should include 'RUN echo onbuild' }
|
97
|
+
# its(:stopsignal) { should eq 'SIGTERM' }
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# @example Checking Its Size and OS
|
101
|
+
# describe docker_build(path: '.') do
|
102
|
+
# its(:size) { should be < 20 * 2**20 } # 20M
|
103
|
+
# its(:arch) { should eq 'amd64' }
|
104
|
+
# its(:os) { should eq 'linux' }
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# @example Building from a File
|
108
|
+
# describe docker_build(path: '../dockerfiles/Dockerfile-nginx') do
|
109
|
+
# # [...]
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# @example Building from a Template
|
113
|
+
# describe docker_build(template: 'Dockerfile1.erb') do
|
114
|
+
# # [...]
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# @example Building from a Template with a Context
|
118
|
+
# describe docker_build(
|
119
|
+
# template: 'Dockerfile1.erb', context: {version: '8'}
|
120
|
+
# ) do
|
121
|
+
# it { should have_maintainer(/John Doe/) }
|
122
|
+
# it { should have_cmd %w(/bin/sh) }
|
123
|
+
# # [...]
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# @example Building from a String
|
127
|
+
# describe docker_build(string: "FROM nginx:1.9\n [...]") do
|
128
|
+
# # [...]
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# @example Building from a Docker Image ID
|
132
|
+
# describe docker_build(id: '07d362aea98d') do
|
133
|
+
# # [...]
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# @example Building from a Docker Image name
|
137
|
+
# describe docker_build(id: 'nginx:1.9') do
|
138
|
+
# # [...]
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# @param opts [String, Hash] The `:path` or a list of options.
|
142
|
+
#
|
143
|
+
# @option opts [String] :path ('.') The directory or file that contains the
|
144
|
+
# *Dockerfile*. By default tries to read it from the `DOCKERFILE_PATH`
|
145
|
+
# environment variable and uses `'.'` if it is not set.
|
146
|
+
# @option opts [String] :string Use this string as *Dockerfile* instead of
|
147
|
+
# `:path`. Not set by default.
|
148
|
+
# @option opts [String] :template Use this [Erubis]
|
149
|
+
# (http://www.kuwata-lab.com/erubis/users-guide.html) template file as
|
150
|
+
# *Dockerfile*.
|
151
|
+
# @option opts [String] :id Use this Docker image ID instead of a
|
152
|
+
# *Dockerfile*.
|
153
|
+
# @option opts [Boolean] :rm Whether to remove the generated docker images
|
154
|
+
# after running the tests. By default only removes them if it is running
|
155
|
+
# on a CI machine.
|
156
|
+
# @option opts [Hash, Erubis::Context] :context ({}) Template *context*
|
157
|
+
# used when the `:template` source is used.
|
158
|
+
# @option opts [String] :tag Repository tag to be applied to the resulting
|
159
|
+
# image.
|
160
|
+
# @option opts [Fixnum, Symbol] :log_level Sets the docker library
|
161
|
+
# verbosity level. Possible values:
|
162
|
+
# `:silent` or `0` (no output),
|
163
|
+
# `:ci` or `1` (enables some outputs recommended for CI environments),
|
164
|
+
# `:info` or `2` (gives information about main build steps),
|
165
|
+
# `:debug` or `3` (outputs all the provided information in its raw
|
166
|
+
# original form).
|
167
|
+
#
|
168
|
+
# @return [Dockerspec::Builder] Builder object.
|
169
|
+
#
|
170
|
+
# @see Dockerspec::Builder::ConfigHelpers
|
171
|
+
#
|
172
|
+
# @api public
|
173
|
+
#
|
174
|
+
def docker_build(*opts)
|
175
|
+
builder = Dockerspec::Builder.new(*opts)
|
176
|
+
builder.build
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Runs a docker image.
|
181
|
+
#
|
182
|
+
# @param opts [Hash] List of options.
|
183
|
+
#
|
184
|
+
# @see Dockerspec::Serverspec::RSpecResources#docker_run
|
185
|
+
#
|
186
|
+
def docker_run(*opts)
|
187
|
+
RSpecAssertions.assert_docker_run!(opts)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
#
|
193
|
+
# Add the Dockerspec resources to RSpec core.
|
194
|
+
#
|
195
|
+
RSpec::Core::ExampleGroup.class_eval do
|
196
|
+
extend Dockerspec::RSpecResources
|
197
|
+
include Dockerspec::RSpecResources
|
198
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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
|
+
|
22
|
+
#
|
23
|
+
# Add some RSpec custom settings for {Dockerspec}.
|
24
|
+
#
|
25
|
+
RSpec.configure do |c|
|
26
|
+
c.add_setting :dockerfile_path
|
27
|
+
c.add_setting :rm_build
|
28
|
+
c.add_setting :log_level
|
29
|
+
end
|
@@ -0,0 +1,374 @@
|
|
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
|
+
require 'dockerspec/docker_gem'
|
22
|
+
require 'dockerspec/exceptions'
|
23
|
+
require 'dockerspec/helper/multiple_sources_description'
|
24
|
+
|
25
|
+
module Dockerspec
|
26
|
+
#
|
27
|
+
# This class runs a docker image (without using Serverspec for that).
|
28
|
+
#
|
29
|
+
# This class is not used much, only inherited by
|
30
|
+
# {Dockerspec::Serverspec::Runner}, which uses Serverspec to run the images.
|
31
|
+
# Some of the methods here are used there, others not.
|
32
|
+
#
|
33
|
+
class Runner
|
34
|
+
include Dockerspec::Helper::MultipleSourcesDescription
|
35
|
+
|
36
|
+
#
|
37
|
+
# Constructs a Docker runner class to run Docker images.
|
38
|
+
#
|
39
|
+
# @example From a Running Docker Image
|
40
|
+
# Dockerspec::Runner.new('debian:8') #=> #<Dockerspec::Runner:0x0124>
|
41
|
+
#
|
42
|
+
# @example From a Running Docker Container ID
|
43
|
+
# # This does not start any new container
|
44
|
+
# Dockerspec::Runner.new(id: 'c51f86c28340')
|
45
|
+
# #=> #<Dockerspec::Runner:0x0124>
|
46
|
+
#
|
47
|
+
# @example From a Running Docker Container Image Name
|
48
|
+
# Dockerspec::Runner.new('my-debian') #=> #<Dockerspec::Runner:0x0125>
|
49
|
+
#
|
50
|
+
# @param opts [String, Hash] The `:tag` or a list of options.
|
51
|
+
#
|
52
|
+
# @option opts [String] :tag The Docker image tag name to run.
|
53
|
+
# @option opts [String] :id The Docker container ID to use instead of
|
54
|
+
# starting a new container.
|
55
|
+
# @option opts [Boolean] :rm (calculated) Whether to remove the Docker
|
56
|
+
# container afterwards.
|
57
|
+
# @option opts [String] :path The environment `PATH` value of the
|
58
|
+
# container.
|
59
|
+
# @option opts [Hash, Array] :env Some `ENV` instructions to add to the
|
60
|
+
# container.
|
61
|
+
#
|
62
|
+
# @return [Dockerspec::Runner] Runner object.
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
#
|
66
|
+
def initialize(*opts)
|
67
|
+
@options = parse_options(opts)
|
68
|
+
send("setup_from_#{source}", @options[source])
|
69
|
+
ObjectSpace.define_finalizer(self, proc { finalize })
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Runs the Docker Container.
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# builder = Dockerspec::Builder.new('.')
|
77
|
+
# builder.build
|
78
|
+
# runner = Dockerspec::Runner.new(builder)
|
79
|
+
# runner.run #=> #<Dockerspec::Runner:0x0123>
|
80
|
+
#
|
81
|
+
# @return [Dockerspec::Runner] Runner object.
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
#
|
85
|
+
def run
|
86
|
+
create_container
|
87
|
+
run_container
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Gets the Docker container ID.
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# builder = Dockerspec::Builder.new('.').build
|
96
|
+
# runner = Dockerspec::Runner.new(builder).run
|
97
|
+
# runner.id #=> "b8ba0befc716[...]"
|
98
|
+
#
|
99
|
+
# @return [String] Container ID.
|
100
|
+
#
|
101
|
+
# @api public
|
102
|
+
#
|
103
|
+
def id
|
104
|
+
return nil unless @container.respond_to?(:id)
|
105
|
+
@container.id
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Gets the Docker image ID.
|
110
|
+
#
|
111
|
+
# @example
|
112
|
+
# builder = Dockerspec::Builder.new('.').build
|
113
|
+
# runner = Dockerspec::Runner.new(builder)
|
114
|
+
# runner.image_id #=> "c51f86c28340[...]"
|
115
|
+
#
|
116
|
+
# @return [String] Image ID.
|
117
|
+
#
|
118
|
+
# @api public
|
119
|
+
#
|
120
|
+
def image_id
|
121
|
+
return @build.id unless @build.nil?
|
122
|
+
@container.json['Image']
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Stops and deletes the Docker Container.
|
127
|
+
#
|
128
|
+
# Automatically called when `:rm` option is enabled.
|
129
|
+
#
|
130
|
+
# @return void
|
131
|
+
#
|
132
|
+
# @api public
|
133
|
+
#
|
134
|
+
def finalize
|
135
|
+
return unless @options[:rm] && !@container.nil?
|
136
|
+
@container.stop
|
137
|
+
@container.delete
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# Gets a descriptions of the object.
|
142
|
+
#
|
143
|
+
# @example Running from a Container Image ID
|
144
|
+
# r = Dockerspec::Runner.new('debian')
|
145
|
+
# r.to_s #=> "Docker Run from tag: \"debian\""
|
146
|
+
#
|
147
|
+
# @example Attaching to a Running Container ID
|
148
|
+
# r = Dockerspec::Runner.new(id: '92cc98ab560a')
|
149
|
+
# r.to_s #=> "Docker Run from id: \"92cc98ab560a\""
|
150
|
+
#
|
151
|
+
# @return [String] The object description.
|
152
|
+
#
|
153
|
+
# @api public
|
154
|
+
#
|
155
|
+
def to_s
|
156
|
+
description('Docker Run from')
|
157
|
+
end
|
158
|
+
|
159
|
+
protected
|
160
|
+
|
161
|
+
#
|
162
|
+
# Gets the source to start the container from.
|
163
|
+
#
|
164
|
+
# Possible values: `:tag`, `:id`.
|
165
|
+
#
|
166
|
+
# @example Start the Container from an Image Tag
|
167
|
+
# self.source #=> :tag
|
168
|
+
#
|
169
|
+
# @example Attach to a Running Container ID
|
170
|
+
# self.source #=> :id
|
171
|
+
#
|
172
|
+
# @return [Symbol] The source.
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
#
|
176
|
+
def source
|
177
|
+
return @source unless @source.nil?
|
178
|
+
%i(tag id).any? do |from|
|
179
|
+
next false unless @options.key?(from)
|
180
|
+
@source = from # Used for description
|
181
|
+
end
|
182
|
+
@source
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Generates a description from Docker tag name.
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# self.description_from_tag('debian') #=> "debian"
|
190
|
+
# self.description_from_tag('92cc98ab560a92cc98ab560[...]')
|
191
|
+
# #=> "92cc98ab560a"
|
192
|
+
#
|
193
|
+
# @return [String] The description, shortened if necessary.
|
194
|
+
#
|
195
|
+
# @see Dockerspec::Helper::MultipleSourceDescription#description_from_docker
|
196
|
+
#
|
197
|
+
# @api private
|
198
|
+
#
|
199
|
+
alias_method :description_from_tag, :description_from_docker
|
200
|
+
|
201
|
+
#
|
202
|
+
# Gets the default options configured using `RSpec.configuration`.
|
203
|
+
#
|
204
|
+
# @example
|
205
|
+
# self.rspec_options #=> {}
|
206
|
+
#
|
207
|
+
# @return [Hash] The configuration options.
|
208
|
+
#
|
209
|
+
# @api private
|
210
|
+
#
|
211
|
+
def rspec_options
|
212
|
+
{}
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# Gets the default configuration options after merging them with RSpec
|
217
|
+
# configuration options.
|
218
|
+
#
|
219
|
+
# @example
|
220
|
+
# self.default_options #=> {}
|
221
|
+
#
|
222
|
+
# @return [Hash] The configuration options.
|
223
|
+
#
|
224
|
+
# @api private
|
225
|
+
#
|
226
|
+
def default_options
|
227
|
+
{}.merge(rspec_options)
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
# Ensures that the passed options are correct.
|
232
|
+
#
|
233
|
+
# Currently this only checks that you passed the `:tag` or the `:id`
|
234
|
+
# argument.
|
235
|
+
#
|
236
|
+
# @return void
|
237
|
+
#
|
238
|
+
# @raise [Dockerspec::DockerRunArgumentError] Raises this exception when
|
239
|
+
# the required fields are missing.
|
240
|
+
#
|
241
|
+
# @api private
|
242
|
+
#
|
243
|
+
def assert_options!(opts)
|
244
|
+
return if opts[:tag].is_a?(String) || opts[:id].is_a?(String)
|
245
|
+
fail DockerRunArgumentError, 'You need to pass the `:tag` or the `:id` '\
|
246
|
+
'option to the #docker_run method.'
|
247
|
+
end
|
248
|
+
|
249
|
+
#
|
250
|
+
# Parses the configuration options passed to the constructor.
|
251
|
+
#
|
252
|
+
# @example
|
253
|
+
# self.parse_options #=> {:rm=>true}
|
254
|
+
#
|
255
|
+
# @param opts [Array<String, Hash>] The list of options. The strings will
|
256
|
+
# be interpreted as `:tag`, others will be merged.
|
257
|
+
#
|
258
|
+
# @return [Hash] The configuration options.
|
259
|
+
#
|
260
|
+
# @raise [Dockerspec::DockerRunArgumentError] Raises this exception when
|
261
|
+
# some required fields are missing.
|
262
|
+
#
|
263
|
+
# @see #initialize
|
264
|
+
#
|
265
|
+
# @api private
|
266
|
+
#
|
267
|
+
def parse_options(opts)
|
268
|
+
opts_hs_ary = opts.map { |x| x.is_a?(Hash) ? x : { tag: x } }
|
269
|
+
result = opts_hs_ary.reduce(default_options) { |a, e| a.merge(e) }
|
270
|
+
assert_options!(result)
|
271
|
+
result
|
272
|
+
end
|
273
|
+
|
274
|
+
#
|
275
|
+
# Generates the build object from the Docker image tag.
|
276
|
+
#
|
277
|
+
# Saves the build internally.
|
278
|
+
#
|
279
|
+
# @param tag [String] The image name or ID.
|
280
|
+
#
|
281
|
+
# @return void
|
282
|
+
#
|
283
|
+
# @api private
|
284
|
+
#
|
285
|
+
def setup_from_tag(tag)
|
286
|
+
@build = Builder.new(id: tag).build
|
287
|
+
end
|
288
|
+
|
289
|
+
#
|
290
|
+
# Generates the container object from a running Docker container.
|
291
|
+
#
|
292
|
+
# Saves the container internally.
|
293
|
+
#
|
294
|
+
# @param id [String] The container ID or name.
|
295
|
+
#
|
296
|
+
# @return void
|
297
|
+
#
|
298
|
+
# @api private
|
299
|
+
#
|
300
|
+
def setup_from_id(id)
|
301
|
+
@container = ::Docker::Container.get(id)
|
302
|
+
end
|
303
|
+
|
304
|
+
#
|
305
|
+
# Ensures that the Docker container has a correct `CMD`.
|
306
|
+
#
|
307
|
+
# @param opts [Hash] {Docker::Container} options.
|
308
|
+
#
|
309
|
+
# @return [Hash] {Docker::Container} options.
|
310
|
+
#
|
311
|
+
# @api private
|
312
|
+
#
|
313
|
+
def add_container_cmd_option(opts)
|
314
|
+
opts['Cmd'] = %w(/bin/sh) if @build.cmd.nil?
|
315
|
+
opts
|
316
|
+
end
|
317
|
+
|
318
|
+
#
|
319
|
+
# Adds some `ENV` options to the Docker container.
|
320
|
+
#
|
321
|
+
# @param opts [Hash] {Docker::Container} options.
|
322
|
+
#
|
323
|
+
# @return [Hash] {Docker::Container} options.
|
324
|
+
#
|
325
|
+
# @api private
|
326
|
+
#
|
327
|
+
def add_container_env_options(opts)
|
328
|
+
opts['Env'] = opts['Env'].to_a << "PATH=#{path}" if @options.key?(:path)
|
329
|
+
env = @options[:env].to_a.map { |v| v.join('=') }
|
330
|
+
opts['Env'] = opts['Env'].to_a.concat(env)
|
331
|
+
opts
|
332
|
+
end
|
333
|
+
|
334
|
+
#
|
335
|
+
# Generates the Docker container options for {Docker::Container}.
|
336
|
+
#
|
337
|
+
# @return [Hash] The container options.
|
338
|
+
#
|
339
|
+
# @api private
|
340
|
+
#
|
341
|
+
def container_options
|
342
|
+
opts = { 'Image' => image_id, 'OpenStdin' => true }
|
343
|
+
|
344
|
+
add_container_cmd_option(opts)
|
345
|
+
add_container_env_options(opts)
|
346
|
+
opts
|
347
|
+
end
|
348
|
+
|
349
|
+
#
|
350
|
+
# Creates the Docker container.
|
351
|
+
#
|
352
|
+
# *Note: Based on Specinfra `:docker` backend code.*
|
353
|
+
#
|
354
|
+
# @return void
|
355
|
+
#
|
356
|
+
# @api private
|
357
|
+
#
|
358
|
+
def create_container
|
359
|
+
return @container unless @container.nil?
|
360
|
+
@container = ::Docker::Container.create(container_options)
|
361
|
+
end
|
362
|
+
|
363
|
+
#
|
364
|
+
# Runs the Docker container.
|
365
|
+
#
|
366
|
+
# @return void
|
367
|
+
#
|
368
|
+
# @api private
|
369
|
+
#
|
370
|
+
def run_container
|
371
|
+
@container.start
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|