chef-provisioning-docker 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -8
- data/chef-provisioning-docker.gemspec +1 -1
- data/lib/chef/provisioning/docker_driver/docker_container_machine.rb +199 -13
- data/lib/chef/provisioning/docker_driver/docker_run_options.rb +593 -0
- data/lib/chef/provisioning/docker_driver/docker_transport.rb +120 -57
- data/lib/chef/provisioning/docker_driver/driver.rb +82 -148
- data/lib/chef/provisioning/docker_driver/version.rb +1 -1
- metadata +12 -5
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'chef/provisioning/transport'
|
2
|
+
require 'chef/provisioning/transport/ssh'
|
3
|
+
require 'chef/provisioning/docker_driver/chef_zero_http_proxy'
|
2
4
|
require 'docker'
|
3
5
|
require 'archive/tar/minitar'
|
4
6
|
require 'shellwords'
|
@@ -6,7 +8,7 @@ require 'uri'
|
|
6
8
|
require 'socket'
|
7
9
|
require 'mixlib/shellout'
|
8
10
|
require 'sys/proctable'
|
9
|
-
require '
|
11
|
+
require 'tempfile'
|
10
12
|
|
11
13
|
class Chef
|
12
14
|
module Provisioning
|
@@ -20,15 +22,15 @@ module DockerDriver
|
|
20
22
|
attr_reader :config
|
21
23
|
attr_accessor :container
|
22
24
|
|
23
|
-
def execute(command, options
|
24
|
-
Chef::Log.debug("execute '#{command}' with options #{options}")
|
25
|
-
|
25
|
+
def execute(command, timeout: nil, keep_stdin_open: nil, tty: nil, detached: nil, **options)
|
26
26
|
opts = {}
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
opts[:tty] = tty unless tty.nil?
|
28
|
+
opts[:detached] = detached unless detached.nil?
|
29
|
+
opts[:stdin] = keep_stdin_open unless keep_stdin_open.nil?
|
30
|
+
opts[:wait] = timeout unless timeout.nil?
|
30
31
|
|
31
32
|
command = Shellwords.split(command) if command.is_a?(String)
|
33
|
+
Chef::Log.debug("execute #{command.inspect} on container #{container.id} with options #{opts}'")
|
32
34
|
response = container.exec(command, opts) do |stream, chunk|
|
33
35
|
case stream
|
34
36
|
when :stdout
|
@@ -47,9 +49,11 @@ module DockerDriver
|
|
47
49
|
begin
|
48
50
|
tarfile = ''
|
49
51
|
# NOTE: this would be more efficient if we made it a stream and passed that to Minitar
|
50
|
-
container.
|
52
|
+
container.archive_out(path) do |block|
|
51
53
|
tarfile << block
|
52
54
|
end
|
55
|
+
rescue Docker::Error::NotFoundError
|
56
|
+
return nil
|
53
57
|
rescue Docker::Error::ServerError
|
54
58
|
if $!.message =~ /500/ || $!.message =~ /Could not find the file/
|
55
59
|
return nil
|
@@ -72,12 +76,12 @@ module DockerDriver
|
|
72
76
|
end
|
73
77
|
|
74
78
|
def write_file(path, content)
|
75
|
-
|
79
|
+
tar = StringIO.new(Docker::Util.create_tar(path => content))
|
80
|
+
container.archive_in_stream('/') { tar.read }
|
76
81
|
end
|
77
82
|
|
78
83
|
def download_file(path, local_path)
|
79
|
-
|
80
|
-
file = File.open(local_path, 'w')
|
84
|
+
file = File.open(local_path, 'wb')
|
81
85
|
begin
|
82
86
|
file.write(read_file(path))
|
83
87
|
file.close
|
@@ -87,71 +91,130 @@ module DockerDriver
|
|
87
91
|
end
|
88
92
|
|
89
93
|
def upload_file(local_path, path)
|
90
|
-
|
94
|
+
write_file(path, IO.read(local_path, mode: "rb"))
|
91
95
|
end
|
92
96
|
|
93
|
-
def make_url_available_to_remote(
|
94
|
-
|
95
|
-
|
96
|
-
uri.scheme
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
$1
|
113
|
-
end
|
114
|
-
|
115
|
-
if !@proxy_thread
|
116
|
-
# Listen to docker instances only, and forward to localhost
|
117
|
-
@proxy_thread = Thread.new do
|
118
|
-
Chef::Log.debug("Starting proxy thread: #{uri.host}:#{uri.port} <--> #{host}:#{uri.port}")
|
119
|
-
ChefZeroHttpProxy.new(uri.host, uri.port, host, uri.port).run
|
97
|
+
def make_url_available_to_remote(local_url)
|
98
|
+
uri = URI(local_url)
|
99
|
+
|
100
|
+
if uri.scheme == "chefzero" || is_local_machine(uri.host)
|
101
|
+
# chefzero: URLs are just http URLs with a shortcut if you are in-process.
|
102
|
+
# The remote machine is definitely not in-process.
|
103
|
+
uri.scheme = "http" if uri.scheme == "chefzero"
|
104
|
+
|
105
|
+
if docker_toolkit_transport
|
106
|
+
# Forward localhost on docker_machine -> chef-zero. The container will
|
107
|
+
# be able to access this because it was started with --net=host.
|
108
|
+
uri = docker_toolkit_transport.make_url_available_to_remote(uri.to_s)
|
109
|
+
uri = URI(uri)
|
110
|
+
@docker_toolkit_transport_thread ||= Thread.new do
|
111
|
+
begin
|
112
|
+
docker_toolkit_transport.send(:session).loop { true }
|
113
|
+
rescue
|
114
|
+
Chef::Log.error("SSH forwarding loop failed: #{$!}")
|
115
|
+
raise
|
120
116
|
end
|
117
|
+
Chef::Log.debug("Session loop completed normally")
|
121
118
|
end
|
122
|
-
Chef::Log.debug("Using Chef server URL: #{uri.to_s}")
|
123
|
-
|
124
|
-
return uri.to_s
|
125
119
|
else
|
126
|
-
|
120
|
+
# We are the host. Find the docker machine's gateway (us) and talk to that;
|
121
|
+
# and set up a little proxy that will forward the container's requests to
|
122
|
+
# chef-zero
|
123
|
+
result = execute('ip route list', :read_only => true)
|
124
|
+
|
125
|
+
Chef::Log.debug("IP route: #{result.stdout}")
|
126
|
+
|
127
|
+
if result.stdout =~ /default via (\S+)/
|
128
|
+
|
129
|
+
old_uri = uri.dup
|
130
|
+
|
131
|
+
uri.host = $1
|
132
|
+
|
133
|
+
if !@proxy_thread
|
134
|
+
# Listen to docker instances only, and forward to localhost
|
135
|
+
@proxy_thread = Thread.new do
|
136
|
+
begin
|
137
|
+
Chef::Log.debug("Starting proxy thread: #{old_uri.host}:#{old_uri.port} <--> #{uri.host}:#{uri.port}")
|
138
|
+
ChefZeroHttpProxy.new(uri.host, uri.port, old_uri.host, old_uri.port).run
|
139
|
+
rescue
|
140
|
+
Chef::Log.error("Proxy thread unable to start: #{$!}")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
else
|
145
|
+
raise "Cannot forward port: ip route ls did not show default in expected format.\nSTDOUT: #{result.stdout}"
|
146
|
+
end
|
147
|
+
|
127
148
|
end
|
128
149
|
end
|
129
|
-
|
150
|
+
|
151
|
+
uri.to_s
|
130
152
|
end
|
131
153
|
|
132
154
|
def disconnect
|
133
|
-
|
155
|
+
if @docker_toolkit_transport_thread
|
156
|
+
@docker_toolkit_transport_thread.kill
|
157
|
+
@docker_toolkit_transport_thread = nil
|
158
|
+
end
|
134
159
|
end
|
135
160
|
|
136
161
|
def available?
|
137
162
|
end
|
138
163
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
if proc.respond_to?(:cmdline)
|
146
|
-
if proc.send(:cmdline).to_s =~ /.*--comment boot2docker.*/
|
147
|
-
return true
|
148
|
-
end
|
164
|
+
def is_local_machine(host)
|
165
|
+
local_addrs = Socket.ip_address_list
|
166
|
+
host_addrs = Addrinfo.getaddrinfo(host, nil)
|
167
|
+
local_addrs.any? do |local_addr|
|
168
|
+
host_addrs.any? do |host_addr|
|
169
|
+
local_addr.ip_address == host_addr.ip_address
|
149
170
|
end
|
150
171
|
end
|
151
172
|
end
|
152
173
|
|
153
|
-
def
|
154
|
-
|
174
|
+
def docker_toolkit_transport(connection_url=nil)
|
175
|
+
if !defined?(@docker_toolkit_transport)
|
176
|
+
# Figure out which docker-machine this container is in
|
177
|
+
begin
|
178
|
+
docker_machines = `docker-machine ls --format "{{.Name}},{{.URL}}"`
|
179
|
+
rescue Errno::ENOENT
|
180
|
+
Chef::Log.debug("docker-machine ls returned ENOENT: Docker Toolkit is presumably not installed.")
|
181
|
+
@docker_toolkit_transport = nil
|
182
|
+
return
|
183
|
+
end
|
184
|
+
|
185
|
+
connection_url ||= container.connection.url
|
186
|
+
|
187
|
+
Chef::Log.debug("Found docker machines:")
|
188
|
+
docker_machine = nil
|
189
|
+
docker_machines.lines.each do |line|
|
190
|
+
machine_name, machine_url = line.chomp.split(',', 2)
|
191
|
+
Chef::Log.debug("- #{machine_name} at URL #{machine_url.inspect}")
|
192
|
+
if machine_url == connection_url
|
193
|
+
Chef::Log.debug("Docker machine #{machine_name} at URL #{machine_url} matches the container's URL #{connection_url}! Will use it for port forwarding.")
|
194
|
+
docker_machine = machine_name
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if !docker_machine
|
198
|
+
Chef::Log.debug("Docker Toolkit is installed, but no Docker machine's URL matches #{connection_url.inspect}. Assuming docker must be installed as well ...")
|
199
|
+
@docker_toolkit_transport = nil
|
200
|
+
return
|
201
|
+
end
|
202
|
+
|
203
|
+
# Get the SSH information for the docker-machine
|
204
|
+
docker_toolkit_json = `docker-machine inspect #{docker_machine}`
|
205
|
+
machine_info = JSON.parse(docker_toolkit_json, create_additions: false)["Driver"]
|
206
|
+
ssh_host = machine_info["IPAddress"]
|
207
|
+
ssh_username = machine_info["SSHUser"]
|
208
|
+
ssh_options = {
|
209
|
+
# port: machine_info["SSHPort"], seems to be bad information (44930???)
|
210
|
+
keys: [ machine_info["SSHKeyPath"] ],
|
211
|
+
keys_only: true
|
212
|
+
}
|
213
|
+
|
214
|
+
Chef::Log.debug("Docker Toolkit is installed. Will use SSH transport with docker-machine #{docker_machine.inspect} to perform port forwarding.")
|
215
|
+
@docker_toolkit_transport = Chef::Provisioning::Transport::SSH.new(ssh_host, ssh_username, ssh_options, {}, Chef::Config)
|
216
|
+
end
|
217
|
+
@docker_toolkit_transport
|
155
218
|
end
|
156
219
|
|
157
220
|
class DockerResult
|
@@ -28,6 +28,10 @@ module DockerDriver
|
|
28
28
|
Driver.new(driver_url, config)
|
29
29
|
end
|
30
30
|
|
31
|
+
def driver_url
|
32
|
+
"docker:#{Docker.url}"
|
33
|
+
end
|
34
|
+
|
31
35
|
def initialize(driver_url, config)
|
32
36
|
super
|
33
37
|
url = Driver.connection_url(driver_url)
|
@@ -37,10 +41,14 @@ module DockerDriver
|
|
37
41
|
# to be set for command-line utilities
|
38
42
|
ENV['DOCKER_HOST'] = url
|
39
43
|
Chef::Log.debug("Setting Docker URL to #{url}")
|
40
|
-
Docker.url = url
|
41
44
|
end
|
42
45
|
|
43
|
-
|
46
|
+
ENV['DOCKER_HOST'] ||= url if url
|
47
|
+
Docker.logger = Chef::Log
|
48
|
+
options = Docker.options.dup || {}
|
49
|
+
options.merge!(read_timeout: 600)
|
50
|
+
options.merge!(config[:docker_connection].hash_dup) if config && config[:docker_connection]
|
51
|
+
@connection = Docker::Connection.new(url || Docker.url, options)
|
44
52
|
end
|
45
53
|
|
46
54
|
def self.canonicalize_url(driver_url, config)
|
@@ -75,6 +83,8 @@ module DockerDriver
|
|
75
83
|
action_handler,
|
76
84
|
machine_spec
|
77
85
|
)
|
86
|
+
|
87
|
+
# Grab options from existing machine (TODO seems wrong) and set the machine_spec to that
|
78
88
|
docker_options = machine_options[:docker_options]
|
79
89
|
container_id = nil
|
80
90
|
image_id = machine_options[:image_id]
|
@@ -84,7 +94,6 @@ module DockerDriver
|
|
84
94
|
image_id ||= machine_spec.reference['image_id']
|
85
95
|
docker_options ||= machine_spec.reference['docker_options']
|
86
96
|
end
|
87
|
-
|
88
97
|
container_name ||= machine_spec.name
|
89
98
|
machine_spec.reference = {
|
90
99
|
'driver_url' => driver_url,
|
@@ -93,110 +102,69 @@ module DockerDriver
|
|
93
102
|
'host_node' => action_handler.host_node,
|
94
103
|
'container_name' => container_name,
|
95
104
|
'image_id' => image_id,
|
96
|
-
'docker_options' => docker_options,
|
105
|
+
'docker_options' => stringize_keys(docker_options),
|
97
106
|
'container_id' => container_id
|
98
107
|
}
|
99
|
-
build_container(machine_spec, docker_options)
|
100
108
|
end
|
101
109
|
|
102
110
|
def ready_machine(action_handler, machine_spec, machine_options)
|
103
|
-
start_machine(action_handler, machine_spec, machine_options)
|
104
111
|
machine_for(machine_spec, machine_options)
|
105
112
|
end
|
106
113
|
|
107
|
-
def
|
114
|
+
def start_machine(action_handler, machine_spec, machine_options)
|
108
115
|
container = container_for(machine_spec)
|
109
|
-
|
110
|
-
|
111
|
-
|
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}"
|
116
|
+
if container && !container.info['State']['Running']
|
117
|
+
action_handler.perform_action "start container #{machine_spec.name}" do
|
118
|
+
container.start!
|
130
119
|
end
|
131
120
|
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Connect to machine without acquiring it
|
124
|
+
def connect_to_machine(machine_spec, machine_options)
|
125
|
+
Chef::Log.debug('Connect to machine')
|
126
|
+
machine_for(machine_spec, machine_options)
|
127
|
+
end
|
132
128
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
129
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
130
|
+
container = container_for(machine_spec)
|
131
|
+
if container
|
132
|
+
image_id = container.info['Image']
|
133
|
+
action_handler.perform_action "stop and destroy container #{machine_spec.name}" do
|
134
|
+
container.stop
|
135
|
+
container.delete
|
137
136
|
end
|
138
137
|
end
|
138
|
+
end
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
140
|
+
def stop_machine(action_handler, machine_spec, machine_options)
|
141
|
+
container = container_for(machine_spec)
|
142
|
+
if container.info['State']['Running']
|
143
|
+
action_handler.perform_action "stop container #{machine_spec.name}" do
|
144
|
+
container.stop!
|
144
145
|
end
|
145
146
|
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
147
|
end
|
162
148
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
source_repository = base_image[:repository]
|
167
|
-
source_tag = base_image[:tag]
|
168
|
-
|
169
|
-
target_tag = machine_spec.reference['container_name']
|
170
|
-
|
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
|
183
|
-
end
|
149
|
+
#
|
150
|
+
# Images
|
151
|
+
#
|
184
152
|
|
185
153
|
def allocate_image(action_handler, image_spec, image_options, machine_spec, machine_options)
|
154
|
+
tag_container_image(action_handler, machine_spec, image_spec)
|
155
|
+
|
186
156
|
# Set machine options on the image to match our newly created image
|
187
157
|
image_spec.reference = {
|
188
158
|
'driver_url' => driver_url,
|
189
159
|
'driver_version' => Chef::Provisioning::DockerDriver::VERSION,
|
190
160
|
'allocated_at' => Time.now.to_i,
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
:tag => image_spec.name
|
196
|
-
},
|
197
|
-
:from_image => true
|
161
|
+
'docker_options' => {
|
162
|
+
'base_image' => {
|
163
|
+
'name' => image_spec.name
|
164
|
+
}
|
198
165
|
}
|
199
166
|
}
|
167
|
+
|
200
168
|
# Workaround for chef/chef-provisioning-docker#37
|
201
169
|
machine_spec.attrs[:keep_image] = true
|
202
170
|
end
|
@@ -207,66 +175,33 @@ module DockerDriver
|
|
207
175
|
|
208
176
|
# workaround for https://github.com/chef/chef-provisioning/issues/358.
|
209
177
|
def destroy_image(action_handler, image_spec, image_options, machine_options={})
|
210
|
-
image =
|
178
|
+
image = image_for(image_spec)
|
211
179
|
image.delete unless image.nil?
|
212
180
|
end
|
213
181
|
|
214
|
-
|
215
|
-
def connect_to_machine(machine_spec, machine_options)
|
216
|
-
Chef::Log.debug('Connect to machine')
|
217
|
-
machine_for(machine_spec, machine_options)
|
218
|
-
end
|
182
|
+
private
|
219
183
|
|
220
|
-
def
|
184
|
+
def tag_container_image(action_handler, machine_spec, image_spec)
|
221
185
|
container = container_for(machine_spec)
|
222
|
-
|
223
|
-
|
224
|
-
container.
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
image = find_image(machine_spec)
|
229
|
-
Chef::Log.debug("Destroying image: chef:#{image.id}")
|
230
|
-
image.delete
|
186
|
+
existing_image = image_for(image_spec)
|
187
|
+
unless existing_image && existing_image.id == container.info['Image']
|
188
|
+
image = Docker::Image.get(container.info['Image'], {}, @connection)
|
189
|
+
action_handler.perform_action "tag image #{container.info['Image']} as chef-images/#{image_spec.name}" do
|
190
|
+
image.tag('repo' => image_spec.name, 'force' => true)
|
191
|
+
end
|
231
192
|
end
|
232
193
|
end
|
233
194
|
|
234
|
-
def
|
235
|
-
|
236
|
-
return if container.nil?
|
237
|
-
|
238
|
-
container.stop if container.info['State']['Running']
|
195
|
+
def to_camel_case(name)
|
196
|
+
name.split('_').map { |x| x.capitalize }.join("")
|
239
197
|
end
|
240
198
|
|
241
|
-
def
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
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
|
199
|
+
def to_snake_case(name)
|
200
|
+
# ExposedPorts -> _exposed_ports
|
201
|
+
name = name.gsub(/[A-Z]/) { |x| "_#{x.downcase}" }
|
202
|
+
# _exposed_ports -> exposed_ports
|
203
|
+
name = name[1..-1] if name.start_with?('_')
|
204
|
+
name
|
270
205
|
end
|
271
206
|
|
272
207
|
def from_image_from_action_handler(action_handler, machine_spec)
|
@@ -280,22 +215,11 @@ module DockerDriver
|
|
280
215
|
end
|
281
216
|
end
|
282
217
|
|
283
|
-
def driver_url
|
284
|
-
"docker:#{Docker.url}"
|
285
|
-
end
|
286
|
-
|
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
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
218
|
def machine_for(machine_spec, machine_options)
|
295
219
|
Chef::Log.debug('machine_for...')
|
296
|
-
docker_options = machine_options[:docker_options] || Mash.from_hash(machine_spec.reference['docker_options'])
|
220
|
+
docker_options = machine_options[:docker_options] || Mash.from_hash(machine_spec.reference['docker_options'] || {})
|
297
221
|
|
298
|
-
container =
|
222
|
+
container = container_for(machine_spec)
|
299
223
|
|
300
224
|
if machine_spec.from_image
|
301
225
|
convergence_strategy = Chef::Provisioning::ConvergenceStrategy::NoConverge.new({}, config)
|
@@ -310,22 +234,32 @@ module DockerDriver
|
|
310
234
|
machine_spec,
|
311
235
|
transport,
|
312
236
|
convergence_strategy,
|
237
|
+
@connection,
|
313
238
|
docker_options[:command]
|
314
239
|
)
|
315
240
|
end
|
316
241
|
|
317
242
|
def container_for(machine_spec)
|
318
|
-
container_id = machine_spec.reference['container_id']
|
319
243
|
begin
|
320
|
-
|
244
|
+
Docker::Container.get(machine_spec.name, {}, @connection)
|
245
|
+
rescue Docker::Error::NotFoundError
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def image_for(image_spec)
|
250
|
+
begin
|
251
|
+
Docker::Image.get(image_spec.name, {}, @connection)
|
321
252
|
rescue Docker::Error::NotFoundError
|
322
253
|
end
|
323
254
|
end
|
324
255
|
|
325
|
-
def
|
326
|
-
|
327
|
-
|
328
|
-
|
256
|
+
def stringize_keys(hash)
|
257
|
+
if hash
|
258
|
+
hash.each_with_object({}) do |(k,v),hash|
|
259
|
+
v = stringize_keys(v) if v.is_a?(Hash)
|
260
|
+
hash[k.to_s] = v
|
261
|
+
end
|
262
|
+
end
|
329
263
|
end
|
330
264
|
end
|
331
265
|
end
|