chef-provisioning-docker 0.11.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,10 +28,6 @@ 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
-
35
31
  def initialize(driver_url, config)
36
32
  super
37
33
  url = Driver.connection_url(driver_url)
@@ -41,14 +37,10 @@ module DockerDriver
41
37
  # to be set for command-line utilities
42
38
  ENV['DOCKER_HOST'] = url
43
39
  Chef::Log.debug("Setting Docker URL to #{url}")
40
+ Docker.url = url
44
41
  end
45
42
 
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)
43
+ @connection = Docker.connection
52
44
  end
53
45
 
54
46
  def self.canonicalize_url(driver_url, config)
@@ -83,8 +75,6 @@ module DockerDriver
83
75
  action_handler,
84
76
  machine_spec
85
77
  )
86
-
87
- # Grab options from existing machine (TODO seems wrong) and set the machine_spec to that
88
78
  docker_options = machine_options[:docker_options]
89
79
  container_id = nil
90
80
  image_id = machine_options[:image_id]
@@ -94,6 +84,7 @@ module DockerDriver
94
84
  image_id ||= machine_spec.reference['image_id']
95
85
  docker_options ||= machine_spec.reference['docker_options']
96
86
  end
87
+
97
88
  container_name ||= machine_spec.name
98
89
  machine_spec.reference = {
99
90
  'driver_url' => driver_url,
@@ -105,66 +96,125 @@ module DockerDriver
105
96
  'docker_options' => stringize_keys(docker_options),
106
97
  'container_id' => container_id
107
98
  }
99
+ build_container(machine_spec, docker_options)
108
100
  end
109
101
 
110
102
  def ready_machine(action_handler, machine_spec, machine_options)
103
+ start_machine(action_handler, machine_spec, machine_options)
111
104
  machine_for(machine_spec, machine_options)
112
105
  end
113
106
 
114
- def start_machine(action_handler, machine_spec, machine_options)
107
+ def build_container(machine_spec, docker_options)
115
108
  container = container_for(machine_spec)
116
- if container && !container.info['State']['Running']
117
- action_handler.perform_action "start container #{machine_spec.name}" do
118
- container.start!
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
+ # We create the initial container with --net host so it can access things
127
+ # while it converges. When the final container starts, it will have its
128
+ # normal network.
129
+ args << '--net'
130
+ args << 'host'
131
+
132
+ if docker_options[:env]
133
+ docker_options[:env].each do |key, value|
134
+ args << '-e'
135
+ args << "#{key}=#{value}"
119
136
  end
120
137
  end
121
- end
122
138
 
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
139
+ if docker_options[:ports]
140
+ docker_options[:ports].each do |portnum|
141
+ args << '-p'
142
+ args << "#{portnum}"
143
+ end
144
+ end
128
145
 
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
146
+ if docker_options[:volumes]
147
+ docker_options[:volumes].each do |volume|
148
+ args << '-v'
149
+ args << "#{volume}"
136
150
  end
137
151
  end
138
- end
139
152
 
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!
153
+ if docker_options[:dns]
154
+ docker_options[:dns].each do |entry|
155
+ args << '--dns'
156
+ args << "#{entry}"
145
157
  end
146
158
  end
159
+
160
+ if docker_options[:dns_search]
161
+ args << '--dns-search'
162
+ args << "#{docker_options[:dns_search]}"
163
+ end
164
+
165
+ args << image.id
166
+ args += Shellwords.split("/bin/sh -c 'while true;do sleep 1000; done'")
167
+
168
+ cmdstr = Shellwords.join(args)
169
+ Chef::Log.debug("Executing #{cmdstr}")
170
+
171
+ cmd = Mixlib::ShellOut.new(cmdstr)
172
+ cmd.run_command
173
+
174
+ container = Docker::Container.get(machine_spec.reference['container_name'])
175
+
176
+ Chef::Log.debug("Container id: #{container.id}")
177
+ machine_spec.reference['container_id'] = container.id
178
+ container
147
179
  end
148
180
 
149
- #
150
- # Images
151
- #
181
+ def build_image(machine_spec, docker_options)
182
+ base_image = docker_options[:base_image] || base_image_for(machine_spec)
183
+ source_name = base_image[:name]
184
+ source_repository = base_image[:repository]
185
+ source_tag = base_image[:tag]
152
186
 
153
- def allocate_image(action_handler, image_spec, image_options, machine_spec, machine_options)
154
- tag_container_image(action_handler, machine_spec, image_spec)
187
+ target_tag = machine_spec.reference['container_name']
188
+
189
+ image = Docker::Image.create(
190
+ 'fromImage' => source_name,
191
+ 'repo' => source_repository,
192
+ 'tag' => source_tag
193
+ )
194
+
195
+ Chef::Log.debug("Allocated #{image}")
196
+ image.tag('repo' => 'chef', 'tag' => target_tag)
197
+ Chef::Log.debug("Tagged image #{image}")
198
+
199
+ machine_spec.reference['image_id'] = image.id
200
+ image
201
+ end
155
202
 
203
+ def allocate_image(action_handler, image_spec, image_options, machine_spec, machine_options)
156
204
  # Set machine options on the image to match our newly created image
157
205
  image_spec.reference = {
158
206
  'driver_url' => driver_url,
159
207
  'driver_version' => Chef::Provisioning::DockerDriver::VERSION,
160
208
  'allocated_at' => Time.now.to_i,
161
- 'docker_options' => {
162
- 'base_image' => {
163
- 'name' => image_spec.name
164
- }
209
+ :docker_options => {
210
+ :base_image => {
211
+ :name => "chef_#{image_spec.name}",
212
+ :repository => 'chef',
213
+ :tag => image_spec.name
214
+ },
215
+ :from_image => true
165
216
  }
166
217
  }
167
-
168
218
  # Workaround for chef/chef-provisioning-docker#37
169
219
  machine_spec.attrs[:keep_image] = true
170
220
  end
@@ -175,33 +225,66 @@ module DockerDriver
175
225
 
176
226
  # workaround for https://github.com/chef/chef-provisioning/issues/358.
177
227
  def destroy_image(action_handler, image_spec, image_options, machine_options={})
178
- image = image_for(image_spec)
228
+ image = Docker::Image.get("chef:#{image_spec.name}")
179
229
  image.delete unless image.nil?
180
230
  end
181
231
 
182
- private
232
+ # Connect to machine without acquiring it
233
+ def connect_to_machine(machine_spec, machine_options)
234
+ Chef::Log.debug('Connect to machine')
235
+ machine_for(machine_spec, machine_options)
236
+ end
183
237
 
184
- def tag_container_image(action_handler, machine_spec, image_spec)
238
+ def destroy_machine(action_handler, machine_spec, machine_options)
185
239
  container = container_for(machine_spec)
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
240
+ if container
241
+ Chef::Log.debug("Destroying container: #{container.id}")
242
+ container.delete(:force => true)
243
+ end
244
+
245
+ if !machine_spec.attrs[:keep_image] && !machine_options[:keep_image]
246
+ image = find_image(machine_spec)
247
+ Chef::Log.debug("Destroying image: chef:#{image.id}")
248
+ image.delete
192
249
  end
193
250
  end
194
251
 
195
- def to_camel_case(name)
196
- name.split('_').map { |x| x.capitalize }.join("")
252
+ def stop_machine(action_handler, machine_spec, machine_options)
253
+ container = container_for(machine_spec)
254
+ return if container.nil?
255
+
256
+ container.stop if container.info['State']['Running']
197
257
  end
198
258
 
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
259
+ def find_image(machine_spec)
260
+ image = nil
261
+
262
+ if machine_spec.reference['image_id']
263
+ begin
264
+ image = Docker::Image.get(machine_spec.reference['image_id'])
265
+ rescue Docker::Error::NotFoundError
266
+ end
267
+ end
268
+
269
+ if image.nil?
270
+ image_name = "chef:#{machine_spec.reference['container_name']}"
271
+ if machine_spec.from_image
272
+ base_image = base_image_for(machine_spec)
273
+ image_name = "#{base_image[:repository]}:#{base_image[:tag]}"
274
+ end
275
+
276
+ image = Docker::Image.all.select {
277
+ |i| i.info['RepoTags'].include? image_name
278
+ }.first
279
+
280
+ if machine_spec.from_image && image.nil?
281
+ raise "Unable to locate machine_image for #{image_name}"
282
+ end
283
+ end
284
+
285
+ machine_spec.reference['image_id'] = image.id if image
286
+
287
+ image
205
288
  end
206
289
 
207
290
  def from_image_from_action_handler(action_handler, machine_spec)
@@ -215,11 +298,22 @@ module DockerDriver
215
298
  end
216
299
  end
217
300
 
301
+ def driver_url
302
+ "docker:#{Docker.url}"
303
+ end
304
+
305
+ def start_machine(action_handler, machine_spec, machine_options)
306
+ container = container_for(machine_spec)
307
+ if container && !container.info['State']['Running']
308
+ container.start
309
+ end
310
+ end
311
+
218
312
  def machine_for(machine_spec, machine_options)
219
313
  Chef::Log.debug('machine_for...')
220
- docker_options = machine_options[:docker_options] || Mash.from_hash(machine_spec.reference['docker_options'] || {})
314
+ docker_options = machine_options[:docker_options] || Mash.from_hash(machine_spec.reference['docker_options'])
221
315
 
222
- container = container_for(machine_spec)
316
+ container = Docker::Container.get(machine_spec.reference['container_id'], @connection)
223
317
 
224
318
  if machine_spec.from_image
225
319
  convergence_strategy = Chef::Provisioning::ConvergenceStrategy::NoConverge.new({}, config)
@@ -234,31 +328,28 @@ module DockerDriver
234
328
  machine_spec,
235
329
  transport,
236
330
  convergence_strategy,
237
- @connection,
238
331
  docker_options[:command]
239
332
  )
240
333
  end
241
334
 
242
335
  def container_for(machine_spec)
336
+ container_id = machine_spec.reference['container_id']
243
337
  begin
244
- Docker::Container.get(machine_spec.name, {}, @connection)
338
+ container = Docker::Container.get(container_id, @connection) if container_id
245
339
  rescue Docker::Error::NotFoundError
246
340
  end
247
341
  end
248
342
 
249
- def image_for(image_spec)
250
- begin
251
- Docker::Image.get(image_spec.name, {}, @connection)
252
- rescue Docker::Error::NotFoundError
253
- end
343
+ def base_image_for(machine_spec)
344
+ Chef::Log.debug("Looking for image #{machine_spec.from_image}")
345
+ image_spec = machine_spec.managed_entry_store.get!(:machine_image, machine_spec.from_image)
346
+ Mash.new(image_spec.reference)[:docker_options][:base_image]
254
347
  end
255
348
 
256
349
  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
350
+ hash.each_with_object({}) do |(k,v),hash|
351
+ v = stringize_keys(v) if v.is_a?(Hash)
352
+ hash[k.to_s] = v
262
353
  end
263
354
  end
264
355
  end
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module DockerDriver
4
- VERSION = '0.11.0'
4
+ VERSION = '1.0.0.beta.1'
5
5
  end
6
6
  end
7
7
  end
@@ -1,3 +1,3 @@
1
1
  require 'chef/provisioning/docker_driver/driver'
2
2
 
3
- Chef::Provisioning.register_driver_class('docker', Chef::Provisioning::DockerDriver::Driver)
3
+ ChefMetal.register_driver_class('docker', Chef::Provisioning::DockerDriver::Driver)
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: 0.11.0
4
+ version: 1.0.0.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Duffield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-12 00:00:00.000000000 Z
11
+ date: 2016-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -28,42 +28,30 @@ dependencies:
28
28
  name: chef-provisioning
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- - - "<"
31
+ - - "~>"
35
32
  - !ruby/object:Gem::Version
36
- version: '3.0'
33
+ version: '1.0'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: '2.0'
44
- - - "<"
38
+ - - "~>"
45
39
  - !ruby/object:Gem::Version
46
- version: '3.0'
40
+ version: '1.0'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: docker-api
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
45
  - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: '1.26'
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: 1.26.2
47
+ version: '1.25'
57
48
  type: :runtime
58
49
  prerelease: false
59
50
  version_requirements: !ruby/object:Gem::Requirement
60
51
  requirements:
61
52
  - - "~>"
62
53
  - !ruby/object:Gem::Version
63
- version: '1.26'
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 1.26.2
54
+ version: '1.25'
67
55
  - !ruby/object:Gem::Dependency
68
56
  name: minitar
69
57
  requirement: !ruby/object:Gem::Requirement
@@ -135,7 +123,7 @@ dependencies:
135
123
  - !ruby/object:Gem::Version
136
124
  version: '0'
137
125
  description: Provisioner for creating Docker containers in Chef Provisioning.
138
- email: tom@chef.io
126
+ email: tom@getchef.com
139
127
  executables: []
140
128
  extensions: []
141
129
  extra_rdoc_files:
@@ -148,9 +136,7 @@ files:
148
136
  - Rakefile
149
137
  - chef-provisioning-docker.gemspec
150
138
  - lib/chef/provisioning/docker_driver.rb
151
- - lib/chef/provisioning/docker_driver/chef_zero_http_proxy.rb
152
139
  - lib/chef/provisioning/docker_driver/docker_container_machine.rb
153
- - lib/chef/provisioning/docker_driver/docker_run_options.rb
154
140
  - lib/chef/provisioning/docker_driver/docker_transport.rb
155
141
  - lib/chef/provisioning/docker_driver/driver.rb
156
142
  - lib/chef/provisioning/docker_driver/version.rb
@@ -158,7 +144,7 @@ files:
158
144
  - spec/docker_support.rb
159
145
  - spec/integration/primitives_spec.rb
160
146
  - spec/spec_helper.rb
161
- homepage: https://github.com/chef/chef-provisioning-docker
147
+ homepage: https://github.com/opscode/chef-provisioning-docker
162
148
  licenses: []
163
149
  metadata: {}
164
150
  post_install_message:
@@ -172,13 +158,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
172
158
  version: '0'
173
159
  required_rubygems_version: !ruby/object:Gem::Requirement
174
160
  requirements:
175
- - - ">="
161
+ - - ">"
176
162
  - !ruby/object:Gem::Version
177
- version: '0'
163
+ version: 1.3.1
178
164
  requirements: []
179
165
  rubyforge_project:
180
- rubygems_version: 2.7.5
166
+ rubygems_version: 2.6.1
181
167
  signing_key:
182
168
  specification_version: 4
183
169
  summary: Provisioner for creating Docker containers in Chef Provisioning.
184
170
  test_files: []
171
+ has_rdoc: