chef-provisioning-docker 0.7 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/README.md +6 -5
- data/Rakefile +9 -0
- data/chef-provisioning-docker.gemspec +31 -0
- data/lib/chef/provisioning/docker_driver/docker_container_machine.rb +16 -15
- data/lib/chef/provisioning/docker_driver/docker_transport.rb +20 -161
- data/lib/chef/provisioning/docker_driver/driver.rb +172 -111
- data/lib/chef/provisioning/docker_driver/version.rb +1 -1
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb7082e943ebcd274d30997976c1049a8eda063c
|
4
|
+
data.tar.gz: e453939b728683c8d9c0a74a313413a83496ec08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4852d7f066c734ecf52dc2cbe2b2121f40327d82078503c1ef98ac2ed3e2565a43c33e916fac11ac8fdaa5c726270b7c1bd805355ba8120d734e8e9d6282f40
|
7
|
+
data.tar.gz: c6c7f6e92b01b9451fafb5f46db02b28f92944394aab21cc08f556d694e481f874ad95692e31a84cba4d14d0dc4756dad52036288b2955c0b645191d3661454f
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -72,8 +72,8 @@ This supports the new machine image paradigm; with Docker you can build a base
|
|
72
72
|
```ruby
|
73
73
|
require 'chef/provisioning/docker_driver'
|
74
74
|
|
75
|
-
machine_image '
|
76
|
-
recipe '
|
75
|
+
machine_image 'ssh_server' do
|
76
|
+
recipe 'openssh'
|
77
77
|
|
78
78
|
machine_options :docker_options => {
|
79
79
|
:base_image => {
|
@@ -84,11 +84,12 @@ machine_image 'web_server' do
|
|
84
84
|
}
|
85
85
|
end
|
86
86
|
|
87
|
-
machine '
|
88
|
-
from_image '
|
87
|
+
machine 'ssh00' do
|
88
|
+
from_image 'ssh_server'
|
89
89
|
|
90
90
|
machine_options :docker_options => {
|
91
|
-
:command => '/usr/sbin/
|
91
|
+
:command => '/usr/sbin/sshd -D -o UsePAM=no -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid',
|
92
|
+
:ports => [22]
|
92
93
|
}
|
93
94
|
end
|
94
95
|
```
|
data/Rakefile
CHANGED
@@ -4,3 +4,12 @@ require 'bundler/gem_tasks'
|
|
4
4
|
task :spec do
|
5
5
|
require File.expand_path('spec/run')
|
6
6
|
end
|
7
|
+
|
8
|
+
require "github_changelog_generator/task"
|
9
|
+
|
10
|
+
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
11
|
+
config.future_release = Chef::Provisioning::DockerDriver::VERSION
|
12
|
+
config.enhancement_labels = "enhancement,Enhancement,New Feature".split(",")
|
13
|
+
config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",")
|
14
|
+
config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question".split(",")
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/lib')
|
2
|
+
require 'chef/provisioning/docker_driver/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'chef-provisioning-docker'
|
6
|
+
s.version = Chef::Provisioning::DockerDriver::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.extra_rdoc_files = ['README.md', 'LICENSE' ]
|
9
|
+
s.summary = 'Provisioner for creating Docker containers in Chef Provisioning.'
|
10
|
+
s.description = s.summary
|
11
|
+
s.author = 'Tom Duffield'
|
12
|
+
s.email = 'tom@getchef.com'
|
13
|
+
s.homepage = 'https://github.com/opscode/chef-provisioning-docker'
|
14
|
+
|
15
|
+
s.add_dependency 'chef'
|
16
|
+
s.add_dependency 'chef-provisioning', '~> 1.0'
|
17
|
+
s.add_dependency 'docker-api'
|
18
|
+
s.add_dependency 'minitar'
|
19
|
+
s.add_dependency 'sys-proctable'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'rake'
|
23
|
+
s.add_development_dependency 'github_changelog_generator'
|
24
|
+
|
25
|
+
s.bindir = "bin"
|
26
|
+
s.executables = %w( )
|
27
|
+
|
28
|
+
s.require_path = 'lib'
|
29
|
+
s.files = %w(Gemfile Rakefile LICENSE README.md) + Dir.glob("*.gemspec") +
|
30
|
+
Dir.glob("{distro,lib,tasks,spec}/**/*", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
|
31
|
+
end
|
@@ -9,29 +9,30 @@ module DockerDriver
|
|
9
9
|
# Options is expected to contain the optional keys
|
10
10
|
# :command => the final command to execute
|
11
11
|
# :ports => a list of port numbers to listen on
|
12
|
-
def initialize(machine_spec, transport, convergence_strategy,
|
12
|
+
def initialize(machine_spec, transport, convergence_strategy, command = nil)
|
13
13
|
super(machine_spec, transport, convergence_strategy)
|
14
|
-
@
|
15
|
-
@command = opts[:command]
|
16
|
-
@ports = opts[:ports]
|
17
|
-
@volumes = opts[:volumes]
|
18
|
-
@keep_stdin_open = opts[:keep_stdin_open]
|
19
|
-
@container_name = machine_spec.location['container_name']
|
14
|
+
@command = command
|
20
15
|
@transport = transport
|
21
16
|
end
|
22
17
|
|
23
|
-
def execute_always(command, options = {})
|
24
|
-
transport.execute(command, { :read_only => true }.merge(options))
|
25
|
-
end
|
26
|
-
|
27
18
|
def converge(action_handler)
|
28
19
|
super action_handler
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
Chef::Log.debug("DockerContainerMachine converge complete, executing #{@command} in #{@container_name}")
|
21
|
+
image = transport.container.commit(
|
22
|
+
'repo' => 'chef',
|
23
|
+
'tag' => machine_spec.reference['container_name']
|
24
|
+
)
|
25
|
+
machine_spec.reference['image_id'] = image.id
|
26
|
+
|
27
|
+
if @command && transport.container.info['Config']['Cmd'].join(' ') != @command
|
28
|
+
transport.container.delete(:force => true)
|
29
|
+
container = image.run(Shellwords.split(@command))
|
30
|
+
container.rename(machine_spec.reference['container_name'])
|
31
|
+
machine_spec.reference['container_id'] = container.id
|
32
|
+
transport.container = container
|
32
33
|
end
|
34
|
+
machine_spec.save(action_handler)
|
33
35
|
end
|
34
|
-
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -12,117 +12,38 @@ class Chef
|
|
12
12
|
module Provisioning
|
13
13
|
module DockerDriver
|
14
14
|
class DockerTransport < Chef::Provisioning::Transport
|
15
|
-
def initialize(
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@image = Docker::Image.get(base_image_name, connection)
|
19
|
-
@credentials = credentials
|
20
|
-
@connection = connection
|
21
|
-
@tunnel_transport = tunnel_transport
|
15
|
+
def initialize(container, config)
|
16
|
+
@container = container
|
17
|
+
@config = config
|
22
18
|
end
|
23
19
|
|
24
|
-
|
20
|
+
attr_reader :config
|
21
|
+
attr_accessor :container
|
25
22
|
|
26
|
-
attr_reader :container_name
|
27
|
-
attr_reader :repository_name
|
28
|
-
attr_reader :image
|
29
|
-
attr_reader :credentials
|
30
|
-
attr_reader :connection
|
31
|
-
attr_reader :tunnel_transport
|
32
|
-
|
33
|
-
# Execute the specified command inside the container, returns a Mixlib::Shellout object
|
34
|
-
# Options contains the optional keys:
|
35
|
-
# :env => env vars
|
36
|
-
# :read_only => Do not commit this execute operation, just execute it
|
37
|
-
# :ports => ports to listen on (-p command-line options)
|
38
|
-
# :detached => true/false, execute this command in detached mode (for final program to run)
|
39
23
|
def execute(command, options={})
|
40
24
|
Chef::Log.debug("execute '#{command}' with options #{options}")
|
41
25
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
rescue Excon::Errors::NotModified
|
46
|
-
Chef::Log.debug("Already stopped #{container_name}")
|
47
|
-
rescue Docker::Error::NotFoundError
|
48
|
-
end
|
49
|
-
|
50
|
-
begin
|
51
|
-
# Delete the container if it exists and is dormant
|
52
|
-
connection.delete("/containers/#{container_name}?v=true&force=true")
|
53
|
-
Chef::Log.debug("deleted /containers/#{container_name}")
|
54
|
-
rescue Docker::Error::NotFoundError
|
26
|
+
opts = {}
|
27
|
+
if options[:keep_stdin_open]
|
28
|
+
opts[:stdin] = true
|
55
29
|
end
|
56
30
|
|
57
31
|
command = Shellwords.split(command) if command.is_a?(String)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
args = ['docker', 'run', '--name', container_name]
|
65
|
-
|
66
|
-
if options[:env]
|
67
|
-
options[:env].each do |key, value|
|
68
|
-
args << '-e'
|
69
|
-
args << "#{key}=#{value}"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
if options[:detached]
|
74
|
-
args << '--detach'
|
75
|
-
end
|
76
|
-
|
77
|
-
if options[:ports]
|
78
|
-
options[:ports].each do |portnum|
|
79
|
-
args << '-p'
|
80
|
-
args << "#{portnum}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
if options[:volumes]
|
85
|
-
options[:volumes].each do |volume|
|
86
|
-
args << '-v'
|
87
|
-
args << "#{volume}"
|
32
|
+
response = container.exec(command, opts) do |stream, chunk|
|
33
|
+
case stream
|
34
|
+
when :stdout
|
35
|
+
stream_chunk(options, chunk, nil)
|
36
|
+
when :stderr
|
37
|
+
stream_chunk(options, nil, chunk)
|
88
38
|
end
|
89
39
|
end
|
90
40
|
|
91
|
-
|
92
|
-
args << '-i'
|
93
|
-
end
|
94
|
-
|
95
|
-
args << @image.id
|
96
|
-
args += command
|
41
|
+
Chef::Log.debug("Execute complete: status #{response[2]}")
|
97
42
|
|
98
|
-
|
99
|
-
Chef::Log.debug("Executing #{cmdstr}")
|
100
|
-
|
101
|
-
# Remove this when https://github.com/opscode/chef/pull/2100 gets merged and released
|
102
|
-
# nullify live_stream because at the moment EventsOutputStream doesn't understand <<, which
|
103
|
-
# ShellOut uses
|
104
|
-
live_stream = nil unless live_stream.respond_to? :<<
|
105
|
-
|
106
|
-
cmd = Mixlib::ShellOut.new(cmdstr, :live_stream => live_stream, :timeout => execute_timeout(options))
|
107
|
-
|
108
|
-
cmd.run_command
|
109
|
-
|
110
|
-
unless options[:read_only]
|
111
|
-
Chef::Log.debug("Committing #{container_name} as #{repository_name}:#{container_name}")
|
112
|
-
container = Docker::Container.get(container_name)
|
113
|
-
@image = container.commit('repo' => repository_name, 'tag' => container_name)
|
114
|
-
end
|
115
|
-
|
116
|
-
Chef::Log.debug("Execute complete: status #{cmd.exitstatus}")
|
117
|
-
|
118
|
-
cmd
|
43
|
+
DockerResult.new(command.join(' '), options, response[0].join, response[1].join, response[2])
|
119
44
|
end
|
120
45
|
|
121
46
|
def read_file(path)
|
122
|
-
container = Docker::Container.create({
|
123
|
-
'Image' => @image.id,
|
124
|
-
'Cmd' => %w(echo true)
|
125
|
-
}, connection)
|
126
47
|
begin
|
127
48
|
tarfile = ''
|
128
49
|
# NOTE: this would be more efficient if we made it a stream and passed that to Minitar
|
@@ -135,8 +56,6 @@ module DockerDriver
|
|
135
56
|
else
|
136
57
|
raise
|
137
58
|
end
|
138
|
-
ensure
|
139
|
-
container.delete
|
140
59
|
end
|
141
60
|
|
142
61
|
output = ''
|
@@ -153,12 +72,7 @@ module DockerDriver
|
|
153
72
|
end
|
154
73
|
|
155
74
|
def write_file(path, content)
|
156
|
-
|
157
|
-
Tempfile.open('metal_docker_write_file') do |file|
|
158
|
-
file.write(content)
|
159
|
-
file.close
|
160
|
-
@image = @image.insert_local('localPath' => file.path, 'outputPath' => path, 't' => "#{repository_name}:#{container_name}")
|
161
|
-
end
|
75
|
+
File.open(container_path(path), 'w') { |file| file.write(content) }
|
162
76
|
end
|
163
77
|
|
164
78
|
def download_file(path, local_path)
|
@@ -173,7 +87,7 @@ module DockerDriver
|
|
173
87
|
end
|
174
88
|
|
175
89
|
def upload_file(local_path, path)
|
176
|
-
|
90
|
+
FileUtils.cp(local_path, container_path(path))
|
177
91
|
end
|
178
92
|
|
179
93
|
def make_url_available_to_remote(url)
|
@@ -236,40 +150,8 @@ module DockerDriver
|
|
236
150
|
end
|
237
151
|
end
|
238
152
|
|
239
|
-
|
240
|
-
|
241
|
-
opts = {
|
242
|
-
:stream => true, :stdout => true, :stderr => true
|
243
|
-
}.merge(options)
|
244
|
-
# Creates list to store stdout and stderr messages
|
245
|
-
msgs = Docker::Messages.new
|
246
|
-
connection.start_request(
|
247
|
-
:post,
|
248
|
-
"/containers/#{container.id}/attach",
|
249
|
-
opts,
|
250
|
-
:response_block => attach_for(block, msgs),
|
251
|
-
:read_timeout => read_timeout,
|
252
|
-
:pipeline => true,
|
253
|
-
:persistent => true
|
254
|
-
)
|
255
|
-
end
|
256
|
-
|
257
|
-
# Method that takes chunks and calls the attached block for each mux'd message
|
258
|
-
def attach_for(block, msg_stack)
|
259
|
-
messages = Docker::Messages.new
|
260
|
-
lambda do |c,r,t|
|
261
|
-
messages = messages.decipher_messages(c)
|
262
|
-
msg_stack.append(messages)
|
263
|
-
|
264
|
-
unless block.nil?
|
265
|
-
messages.stdout_messages.each do |msg|
|
266
|
-
block.call(:stdout, msg)
|
267
|
-
end
|
268
|
-
messages.stderr_messages.each do |msg|
|
269
|
-
block.call(:stderr, msg)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
153
|
+
def container_path(path)
|
154
|
+
File.join('proc', container.info['State']['Pid'].to_s, 'root', path)
|
273
155
|
end
|
274
156
|
|
275
157
|
class DockerResult
|
@@ -300,26 +182,3 @@ module DockerDriver
|
|
300
182
|
end
|
301
183
|
end
|
302
184
|
end
|
303
|
-
|
304
|
-
class Docker::Connection
|
305
|
-
def start_request(method, *args, &block)
|
306
|
-
request = compile_request_params(method, *args, &block)
|
307
|
-
if Docker.logger
|
308
|
-
Docker.logger.debug(
|
309
|
-
[request[:method], request[:path], request[:query], request[:body]]
|
310
|
-
)
|
311
|
-
end
|
312
|
-
excon = resource
|
313
|
-
[ excon, excon.request(request) ]
|
314
|
-
rescue Excon::Errors::BadRequest => ex
|
315
|
-
raise ClientError, ex.message
|
316
|
-
rescue Excon::Errors::Unauthorized => ex
|
317
|
-
raise UnauthorizedError, ex.message
|
318
|
-
rescue Excon::Errors::NotFound => ex
|
319
|
-
raise NotFoundError, ex.message
|
320
|
-
rescue Excon::Errors::InternalServerError => ex
|
321
|
-
raise ServerError, ex.message
|
322
|
-
rescue Excon::Errors::Timeout => ex
|
323
|
-
raise TimeoutError, ex.message
|
324
|
-
end
|
325
|
-
end
|
@@ -70,66 +70,116 @@ module DockerDriver
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
73
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
74
|
+
machine_spec.from_image = from_image_from_action_handler(
|
75
|
+
action_handler,
|
76
|
+
machine_spec
|
77
|
+
)
|
78
|
+
docker_options = machine_options[:docker_options]
|
79
|
+
container_id = nil
|
80
|
+
image_id = machine_options[:image_id]
|
81
|
+
if machine_spec.reference
|
82
|
+
container_name = machine_spec.reference['container_name']
|
83
|
+
container_id = machine_spec.reference['container_id']
|
84
|
+
image_id ||= machine_spec.reference['image_id']
|
85
|
+
docker_options ||= machine_spec.reference['docker_options']
|
86
|
+
end
|
75
87
|
|
76
|
-
container_name
|
88
|
+
container_name ||= machine_spec.name
|
77
89
|
machine_spec.reference = {
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
'driver_url' => driver_url,
|
91
|
+
'driver_version' => Chef::Provisioning::DockerDriver::VERSION,
|
92
|
+
'allocated_at' => Time.now.utc.to_s,
|
93
|
+
'host_node' => action_handler.host_node,
|
94
|
+
'container_name' => container_name,
|
95
|
+
'image_id' => image_id,
|
96
|
+
'docker_options' => docker_options,
|
97
|
+
'container_id' => container_id
|
85
98
|
}
|
99
|
+
build_container(machine_spec, docker_options)
|
86
100
|
end
|
87
101
|
|
88
102
|
def ready_machine(action_handler, machine_spec, machine_options)
|
89
|
-
|
90
|
-
|
91
|
-
machine_for(machine_spec, machine_options, base_image_name)
|
103
|
+
start_machine(action_handler, machine_spec, machine_options)
|
104
|
+
machine_for(machine_spec, machine_options)
|
92
105
|
end
|
93
106
|
|
94
|
-
def build_container(machine_spec,
|
95
|
-
|
107
|
+
def build_container(machine_spec, docker_options)
|
108
|
+
container = container_for(machine_spec)
|
109
|
+
return container unless container.nil?
|
110
|
+
|
111
|
+
image = find_image(machine_spec) ||
|
112
|
+
build_image(machine_spec, docker_options)
|
113
|
+
|
114
|
+
args = [
|
115
|
+
'docker',
|
116
|
+
'run',
|
117
|
+
'--name',
|
118
|
+
machine_spec.reference['container_name'],
|
119
|
+
'--detach'
|
120
|
+
]
|
121
|
+
|
122
|
+
if docker_options[:keep_stdin_open]
|
123
|
+
args << '-i'
|
124
|
+
end
|
125
|
+
|
126
|
+
if docker_options[:env]
|
127
|
+
docker_options[:env].each do |key, value|
|
128
|
+
args << '-e'
|
129
|
+
args << "#{key}=#{value}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
if docker_options[:ports]
|
134
|
+
docker_options[:ports].each do |portnum|
|
135
|
+
args << '-p'
|
136
|
+
args << "#{portnum}"
|
137
|
+
end
|
138
|
+
end
|
96
139
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
140
|
+
if docker_options[:volumes]
|
141
|
+
docker_options[:volumes].each do |volume|
|
142
|
+
args << '-v'
|
143
|
+
args << "#{volume}"
|
144
|
+
end
|
101
145
|
end
|
146
|
+
|
147
|
+
args << image.id
|
148
|
+
args += Shellwords.split("/bin/sh -c 'while true;do sleep 1; done'")
|
149
|
+
|
150
|
+
cmdstr = Shellwords.join(args)
|
151
|
+
Chef::Log.debug("Executing #{cmdstr}")
|
152
|
+
|
153
|
+
cmd = Mixlib::ShellOut.new(cmdstr)
|
154
|
+
cmd.run_command
|
155
|
+
|
156
|
+
container = Docker::Container.get(machine_spec.reference['container_name'])
|
157
|
+
|
158
|
+
Chef::Log.debug("Container id: #{container.id}")
|
159
|
+
machine_spec.reference['container_id'] = container.id
|
160
|
+
container
|
161
|
+
end
|
162
|
+
|
163
|
+
def build_image(machine_spec, docker_options)
|
164
|
+
base_image = docker_options[:base_image] || base_image_for(machine_spec)
|
102
165
|
source_name = base_image[:name]
|
103
166
|
source_repository = base_image[:repository]
|
104
167
|
source_tag = base_image[:tag]
|
105
168
|
|
106
|
-
|
107
|
-
if docker_options[:from_image]
|
108
|
-
"#{source_repository}:#{source_tag}"
|
109
|
-
else
|
110
|
-
target_repository = 'chef'
|
111
|
-
target_tag = machine_spec.name
|
112
|
-
|
113
|
-
# check if target image exists, if not try to look up for source image.
|
114
|
-
image = find_image(target_repository, target_tag) || find_image(source_repository, source_tag)
|
115
|
-
|
116
|
-
# kick off image creation
|
117
|
-
if image == nil
|
118
|
-
Chef::Log.debug("No matching images for #{target_repository}:#{target_tag}, creating!")
|
119
|
-
image = Docker::Image.create('fromImage' => source_name,
|
120
|
-
'repo' => source_repository ,
|
121
|
-
'tag' => source_tag)
|
122
|
-
Chef::Log.debug("Allocated #{image}")
|
123
|
-
image.tag('repo' => 'chef', 'tag' => target_tag)
|
124
|
-
Chef::Log.debug("Tagged image #{image}")
|
125
|
-
elsif not image.info['RepoTags'].include? "#{target_repository}:#{target_tag}"
|
126
|
-
# if `find_image(source_repository, source_tag)` returned result, assign target tag to it to be able
|
127
|
-
# find it in `start_machine`.
|
128
|
-
image.tag('repo' => target_repository, 'tag' => target_tag)
|
129
|
-
end
|
169
|
+
target_tag = machine_spec.reference['container_name']
|
130
170
|
|
131
|
-
|
132
|
-
|
171
|
+
image = Docker::Image.create(
|
172
|
+
'fromImage' => source_name,
|
173
|
+
'repo' => source_repository,
|
174
|
+
'tag' => source_tag
|
175
|
+
)
|
176
|
+
|
177
|
+
Chef::Log.debug("Allocated #{image}")
|
178
|
+
image.tag('repo' => 'chef', 'tag' => target_tag)
|
179
|
+
Chef::Log.debug("Tagged image #{image}")
|
180
|
+
|
181
|
+
machine_spec.reference['image_id'] = image.id
|
182
|
+
image
|
133
183
|
end
|
134
184
|
|
135
185
|
def allocate_image(action_handler, image_spec, image_options, machine_spec, machine_options)
|
@@ -163,101 +213,112 @@ module DockerDriver
|
|
163
213
|
|
164
214
|
# Connect to machine without acquiring it
|
165
215
|
def connect_to_machine(machine_spec, machine_options)
|
166
|
-
Chef::Log.debug('Connect to machine
|
216
|
+
Chef::Log.debug('Connect to machine')
|
217
|
+
machine_for(machine_spec, machine_options)
|
167
218
|
end
|
168
219
|
|
169
220
|
def destroy_machine(action_handler, machine_spec, machine_options)
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
begin
|
175
|
-
Chef::Log.debug("Stopping #{container_name}")
|
176
|
-
container.stop
|
177
|
-
rescue Excon::Errors::NotModified
|
178
|
-
# this is okay
|
179
|
-
Chef::Log.debug('Already stopped!')
|
221
|
+
container = container_for(machine_spec)
|
222
|
+
if container
|
223
|
+
Chef::Log.debug("Destroying container: #{container.id}")
|
224
|
+
container.delete(:force => true)
|
180
225
|
end
|
181
226
|
|
182
|
-
Chef::Log.debug("Removing #{container_name}")
|
183
|
-
container.delete
|
184
|
-
|
185
227
|
if !machine_spec.attrs[:keep_image] && !machine_options[:keep_image]
|
186
|
-
|
187
|
-
|
228
|
+
image = find_image(machine_spec)
|
229
|
+
Chef::Log.debug("Destroying image: chef:#{image.id}")
|
188
230
|
image.delete
|
189
231
|
end
|
190
232
|
end
|
191
233
|
|
192
|
-
def stop_machine(action_handler,
|
193
|
-
|
234
|
+
def stop_machine(action_handler, machine_spec, machine_options)
|
235
|
+
container = container_for(machine_spec)
|
236
|
+
return if container.nil?
|
237
|
+
|
238
|
+
container.stop if container.info['State']['Running']
|
194
239
|
end
|
195
240
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
241
|
+
def find_image(machine_spec)
|
242
|
+
image = nil
|
243
|
+
|
244
|
+
if machine_spec.reference['image_id']
|
245
|
+
begin
|
246
|
+
image = Docker::Image.get(machine_spec.reference['image_id'])
|
247
|
+
rescue Docker::Error::NotFoundError
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
if image.nil?
|
252
|
+
image_name = "chef:#{machine_spec.reference['container_name']}"
|
253
|
+
if machine_spec.from_image
|
254
|
+
base_image = base_image_for(machine_spec)
|
255
|
+
image_name = "#{base_image[:repository]}:#{base_image[:tag]}"
|
256
|
+
end
|
257
|
+
|
258
|
+
image = Docker::Image.all.select {
|
259
|
+
|i| i.info['RepoTags'].include? image_name
|
260
|
+
}.first
|
261
|
+
|
262
|
+
if machine_spec.from_image && image.nil?
|
263
|
+
raise "Unable to locate machine_image for #{image_name}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
machine_spec.reference['image_id'] = image.id if image
|
268
|
+
|
269
|
+
image
|
200
270
|
end
|
201
271
|
|
202
|
-
def
|
203
|
-
|
204
|
-
|
205
|
-
|
272
|
+
def from_image_from_action_handler(action_handler, machine_spec)
|
273
|
+
case action_handler
|
274
|
+
when Chef::Provisioning::AddPrefixActionHandler
|
275
|
+
machines = action_handler.action_handler.provider.new_resource.machines
|
276
|
+
this_machine = machines.select { |m| m.name == machine_spec.name}.first
|
277
|
+
this_machine.from_image
|
278
|
+
else
|
279
|
+
action_handler.provider.new_resource.from_image
|
280
|
+
end
|
206
281
|
end
|
207
282
|
|
208
283
|
def driver_url
|
209
284
|
"docker:#{Docker.url}"
|
210
285
|
end
|
211
286
|
|
212
|
-
def start_machine(action_handler, machine_spec, machine_options
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
begin
|
217
|
-
Docker::Container.get(container_name, @connection)
|
218
|
-
rescue Docker::Error::NotFoundError
|
219
|
-
docker_options = machine_options[:docker_options]
|
220
|
-
Chef::Log.debug("Start machine for container #{container_name} using base image #{base_image_name} with options #{docker_options.inspect}")
|
221
|
-
image = image_named(base_image_name)
|
222
|
-
container = Docker::Container.create('Image' => image.id, 'name' => container_name)
|
223
|
-
Chef::Log.debug("Container id: #{container.id}")
|
224
|
-
machine_spec.location['container_id'] = container.id
|
287
|
+
def start_machine(action_handler, machine_spec, machine_options)
|
288
|
+
container = container_for(machine_spec)
|
289
|
+
if container && !container.info['State']['Running']
|
290
|
+
container.start
|
225
291
|
end
|
226
|
-
|
227
292
|
end
|
228
293
|
|
229
|
-
def machine_for(machine_spec, machine_options
|
294
|
+
def machine_for(machine_spec, machine_options)
|
230
295
|
Chef::Log.debug('machine_for...')
|
296
|
+
docker_options = machine_options[:docker_options] || Mash.from_hash(machine_spec.reference['docker_options'])
|
231
297
|
|
232
|
-
|
298
|
+
container = Docker::Container.get(machine_spec.reference['container_id'], @connection)
|
299
|
+
|
300
|
+
if machine_spec.from_image
|
301
|
+
convergence_strategy = Chef::Provisioning::ConvergenceStrategy::NoConverge.new({}, config)
|
302
|
+
else
|
303
|
+
convergence_strategy = Chef::Provisioning::ConvergenceStrategy::InstallCached.
|
304
|
+
new(machine_options[:convergence_options], config)
|
305
|
+
end
|
233
306
|
|
234
|
-
transport = DockerTransport.new(
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
convergence_strategy_for(machine_spec, machine_options)
|
243
|
-
end
|
244
|
-
|
245
|
-
Chef::Provisioning::DockerDriver::DockerContainerMachine.new(
|
246
|
-
machine_spec,
|
247
|
-
transport,
|
248
|
-
convergence_strategy,
|
249
|
-
:command => docker_options[:command],
|
250
|
-
:env => docker_options[:env],
|
251
|
-
:ports => Array(docker_options[:ports]),
|
252
|
-
:volumes => Array(docker_options[:volumes]),
|
253
|
-
:keep_stdin_open => docker_options[:keep_stdin_open]
|
254
|
-
)
|
307
|
+
transport = DockerTransport.new(container, config)
|
308
|
+
|
309
|
+
Chef::Provisioning::DockerDriver::DockerContainerMachine.new(
|
310
|
+
machine_spec,
|
311
|
+
transport,
|
312
|
+
convergence_strategy,
|
313
|
+
docker_options[:command]
|
314
|
+
)
|
255
315
|
end
|
256
316
|
|
257
|
-
def
|
258
|
-
|
259
|
-
|
260
|
-
|
317
|
+
def container_for(machine_spec)
|
318
|
+
container_id = machine_spec.reference['container_id']
|
319
|
+
begin
|
320
|
+
container = Docker::Container.get(container_id, @connection) if container_id
|
321
|
+
rescue Docker::Error::NotFoundError
|
261
322
|
end
|
262
323
|
end
|
263
324
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-docker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Duffield
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: github_changelog_generator
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description: Provisioner for creating Docker containers in Chef Provisioning.
|
112
126
|
email: tom@getchef.com
|
113
127
|
executables: []
|
@@ -116,9 +130,11 @@ extra_rdoc_files:
|
|
116
130
|
- README.md
|
117
131
|
- LICENSE
|
118
132
|
files:
|
133
|
+
- Gemfile
|
119
134
|
- LICENSE
|
120
135
|
- README.md
|
121
136
|
- Rakefile
|
137
|
+
- chef-provisioning-docker.gemspec
|
122
138
|
- lib/chef/provisioning/docker_driver.rb
|
123
139
|
- lib/chef/provisioning/docker_driver/chef_zero_http_proxy.rb
|
124
140
|
- lib/chef/provisioning/docker_driver/docker_container_machine.rb
|
@@ -148,9 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
164
|
version: '0'
|
149
165
|
requirements: []
|
150
166
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.4.
|
167
|
+
rubygems_version: 2.4.5.1
|
152
168
|
signing_key:
|
153
169
|
specification_version: 4
|
154
170
|
summary: Provisioner for creating Docker containers in Chef Provisioning.
|
155
171
|
test_files: []
|
156
|
-
has_rdoc:
|