chef-provisioning-docker 0.7 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e6789da274574121591c374a64e0d9da7b53092
4
- data.tar.gz: eaf4c266978efe1a32247ce4a21f25daf77e1a6d
3
+ metadata.gz: eb7082e943ebcd274d30997976c1049a8eda063c
4
+ data.tar.gz: e453939b728683c8d9c0a74a313413a83496ec08
5
5
  SHA512:
6
- metadata.gz: 0ae43fca9bbb00973288ae92d1386802fc97403ce5e8f85dd5002e421f01026a9509247232a345810e94bdb64e40aa0cd28628dee71eea00e93e1a5f2f73a133
7
- data.tar.gz: 2e4533eee5d21ab3c049be12494c279333906fc9c6364de16d965174c22b3f71f0295f5be0aa9ed027324ca2f944770ee1d3d69bbf346075b6a4173d4ef6e135
6
+ metadata.gz: f4852d7f066c734ecf52dc2cbe2b2121f40327d82078503c1ef98ac2ed3e2565a43c33e916fac11ac8fdaa5c726270b7c1bd805355ba8120d734e8e9d6282f40
7
+ data.tar.gz: c6c7f6e92b01b9451fafb5f46db02b28f92944394aab21cc08f556d694e481f874ad95692e31a84cba4d14d0dc4756dad52036288b2955c0b645191d3661454f
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+ gemfile
3
+ gemspec
4
+
5
+ gem 'chef-provisioning', :git => 'https://github.com/opscode/chef-provisioning.git', :branch => 'master'
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 'web_server' do
76
- recipe 'apache'
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 'web00' do
88
- from_image 'web_server'
87
+ machine 'ssh00' do
88
+ from_image 'ssh_server'
89
89
 
90
90
  machine_options :docker_options => {
91
- :command => '/usr/sbin/httpd'
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, opts = {})
12
+ def initialize(machine_spec, transport, convergence_strategy, command = nil)
13
13
  super(machine_spec, transport, convergence_strategy)
14
- @env = opts[:env]
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
- if @command
30
- Chef::Log.debug("DockerContainerMachine converge complete, executing #{@command} in #{@container_name}")
31
- @transport.execute(@command, :env => @env ,:detached => true, :read_only => true, :ports => @ports, :volumes => @volumes, :keep_stdin_open => @keep_stdin_open)
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(container_name, base_image_name, credentials, connection, tunnel_transport = nil)
16
- @repository_name = 'chef'
17
- @container_name = container_name
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
- include Chef::Mixin::ShellOut
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
- begin
43
- connection.post("/containers/#{container_name}/stop?t=0", '')
44
- Chef::Log.debug("stopped /containers/#{container_name}")
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
- # TODO shell_out has no way to live stream stderr???
60
- live_stream = nil
61
- live_stream = STDOUT if options[:stream]
62
- live_stream = options[:stream_stdout] if options[:stream_stdout]
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
- if options[:keep_stdin_open]
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
- cmdstr = Shellwords.join(args)
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
- # TODO hate tempfiles. Find an in memory way.
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
- @image = @image.insert_local('localPath' => local_path, 'outputPath' => path, 't' => "#{repository_name}:#{container_name}")
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
- # Copy of container.attach with timeout support and pipeline
240
- def attach_with_timeout(container, read_timeout, options = {}, &block)
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 = machine_spec.name
88
+ container_name ||= machine_spec.name
77
89
  machine_spec.reference = {
78
- 'driver_url' => driver_url,
79
- 'driver_version' => Chef::Provisioning::DockerDriver::VERSION,
80
- 'allocated_at' => Time.now.utc.to_s,
81
- 'host_node' => action_handler.host_node,
82
- 'container_name' => container_name,
83
- 'image_id' => machine_options[:image_id],
84
- 'docker_options' => machine_options[:docker_options]
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
- base_image_name = build_container(machine_spec, machine_options)
90
- start_machine(action_handler, machine_spec, machine_options, base_image_name)
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, machine_options)
95
- docker_options = machine_options[:docker_options]
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
- base_image = docker_options[:base_image]
98
- if !base_image
99
- Chef::Log.debug("No base images specified in docker options.")
100
- base_image = base_image_for(machine_spec)
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
- # Don't do this if we're loading from an image
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
- "#{target_repository}:#{target_tag}"
132
- end
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
- container_name = machine_spec.location['container_name']
171
- Chef::Log.debug("Destroying container: #{container_name}")
172
- container = Docker::Container.get(container_name, @connection)
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
- Chef::Log.debug("Destroying image: chef:#{container_name}")
187
- image = Docker::Image.get("chef:#{container_name}")
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, node)
193
- Chef::Log.debug("Stop machine: #{node.inspect}")
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 image_named(image_name)
197
- Docker::Image.all.select {
198
- |i| i.info['RepoTags'].include? image_name
199
- }.first
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 find_image(repository, tag)
203
- Docker::Image.all.select {
204
- |i| i.info['RepoTags'].include? "#{repository}:#{tag}"
205
- }.first
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, base_image_name)
213
- # Spin up a docker instance if needed, otherwise use the existing one
214
- container_name = machine_spec.location['container_name']
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, base_image_name)
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
- docker_options = machine_options[:docker_options]
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(machine_spec.location['container_name'],
235
- base_image_name,
236
- nil,
237
- Docker.connection)
238
-
239
- convergence_strategy = if docker_options[:from_image]
240
- Chef::Provisioning::ConvergenceStrategy::NoConverge.new({}, config)
241
- else
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 convergence_strategy_for(machine_spec, machine_options)
258
- @unix_convergence_strategy ||= begin
259
- Chef::Provisioning::ConvergenceStrategy::InstallCached.
260
- new(machine_options[:convergence_options], config)
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
 
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module DockerDriver
4
- VERSION = '0.7'
4
+ VERSION = '0.8.0'
5
5
  end
6
6
  end
7
7
  end
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.7'
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: 2015-06-22 00:00:00.000000000 Z
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.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: