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 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: