chef-metal-docker 0.1.1 → 0.2

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: a106532b6fa395835377aed7d7e8952db0f78552
4
- data.tar.gz: 3f8998e4a21485428004f1d93273eff5639d1cb3
3
+ metadata.gz: 9f6ac421bc65fa8a3497942dbd04d15efb23badc
4
+ data.tar.gz: 1b23d70778b4bbece79836bb419cb3ecd462fc19
5
5
  SHA512:
6
- metadata.gz: f1d1150a775d7b98c59004b3f365c35aa08a31cbb3241cd5640e1cd14002ce4390f9f90ab21a2a8743e668bd8b0d48384ac22dc5a17457ddd5a0cc64c6972e0b
7
- data.tar.gz: 45407348ba54a5d1ebefc101bd490581261a6e2f7b9957cf01a36bf3af7c8d3f5ea643c8625a79e1cc54b7ff7eaad1f521047ee681e4bcf27da687ed0afc8554
6
+ metadata.gz: ec3d7947e1e67187603842051249713a662ee9f800a8d4abd72fd10334a4e692c0005fd1f25c34a7121b01a5f6a5c3e5aea8f3f18416a2e8d5ccb882c943e3ce
7
+ data.tar.gz: a2df491bf80e944a349f256e333d6e759f2b4e2f46aab7a3ed6e7727507338a9c93dda64331ae516f50761a35b29464e70637891bb43f3dd44f8d47bb7629a72
@@ -3,8 +3,8 @@ require 'chef_metal/convergence_strategy/no_converge'
3
3
  require 'chef_metal/convergence_strategy/install_cached'
4
4
  require 'chef_metal_docker/helpers/container'
5
5
  require 'chef_metal_docker/docker_transport'
6
- require 'chef_metal_docker/docker_convergence_strategy'
7
6
  require 'chef_metal_docker/docker_unix_machine'
7
+ require 'chef_metal/transport/ssh'
8
8
  require 'docker'
9
9
 
10
10
  module ChefMetalDocker
@@ -50,10 +50,12 @@ module ChefMetalDocker
50
50
  #
51
51
  # -- provisioner_url: docker:<URL of Docker API endpoint>
52
52
  # -- base_image: Base image name to use, or repository_name:tag_name to use a specific tagged revision of that image
53
- # -- command: command to run (if unspecified or nil, will spin up the container. If false, will not run anything and will just leave the image alone.)
54
- # -- container_options: options for container create (see http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.10/#create-a-container)
55
- # -- host_options: options for container start (see http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.10/#start-a-container)
56
- # -- convergence_strategy: :no_converge or :install_cached (former will not converge, latter will set up chef-client and converge)
53
+ # -- create_container: hash of a container to create. If present, no image will be created, just a container.
54
+ # Hash options:
55
+ # - command: command to run (if unspecified or nil, will spin up the container. If false, will not run anything and will just leave the image alone.)
56
+ # - container_options: options for container create (see http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.10/#create-a-container)
57
+ # - host_options: options for container start (see http://docs.docker.io/en/latest/reference/api/docker_remote_api_v1.10/#start-a-container)
58
+ # - ssh_options: hash of ssh options. Presence of hash indicates sshd is running in the container. Net::SSH.new(ssh_options['username'], ssh_options) will be called. Set 'sudo' to true to sudo all commands (will be detected if username != root)
57
59
  #
58
60
  # node['normal']['provisioner_output'] will be populated with information
59
61
  # about the created machine. For lxc, it is a hash with this
@@ -77,29 +79,45 @@ module ChefMetalDocker
77
79
  base_image_name = provisioner_options['base_image']
78
80
  raise "base_image not specified in provisioner options!" if !base_image_name
79
81
 
80
- # Tag the initial image. We aren't going to actually DO anything yet.
81
- # We will start up after we converge!
82
- base_image = Docker::Image.get(base_image_name)
83
- begin
84
- repository_image = Docker::Image.get("#{repository_name}:latest")
85
- # If the current image does NOT have the base_image as an ancestor,
86
- # we are going to have to re-tag it and rebuild.
87
- if repository_image.history.any? { |entry| entry['Id'] == base_image.id }
88
- tag_base_image = false
89
- else
82
+ if provisioner_options['create_container']
83
+ create_container(action_handler, provisioner_options, provisioner_output)
84
+ # We don't bother waiting ... our only job is to bring it up.
85
+ else # We are in image build mode. Get prepped.
86
+ # Tag the initial image. We aren't going to actually DO anything yet.
87
+ # We will start up after we converge!
88
+ base_image = Docker::Image.get(base_image_name)
89
+ begin
90
+ repository_image = Docker::Image.get("#{repository_name}:latest")
91
+ # If the current image does NOT have the base_image as an ancestor,
92
+ # we are going to have to re-tag it and rebuild.
93
+ if repository_image.history.any? { |entry| entry['Id'] == base_image.id }
94
+ tag_base_image = false
95
+ else
96
+ tag_base_image = true
97
+ end
98
+ rescue Docker::Error::NotFoundError
90
99
  tag_base_image = true
91
100
  end
92
- rescue Docker::Error::NotFoundError
93
- tag_base_image = true
94
- end
95
- if tag_base_image
96
- action_handler.perform_action "Tag base image #{base_image_name} as #{repository_name}" do
97
- base_image.tag('repo' => repository_name, 'force' => true)
101
+ if tag_base_image
102
+ action_handler.perform_action "Tag base image #{base_image_name} as #{repository_name}" do
103
+ base_image.tag('repo' => repository_name, 'force' => true)
104
+ end
98
105
  end
99
106
  end
100
107
 
101
108
  node['normal']['provisioner_output'] = provisioner_output
102
109
 
110
+ if provisioner_options['create_container'] && provisioner_options['create_container']['ssh_options']
111
+ action_handler.perform_action "wait for node to start ssh" do
112
+ transport = transport_for(node)
113
+ Timeout::timeout(5*60) do
114
+ while !transport.available?
115
+ sleep(0.5)
116
+ end
117
+ end
118
+ end
119
+ end
120
+
103
121
  # Nothing else needs to happen until converge. We already have the image we need!
104
122
  machine_for(node)
105
123
  end
@@ -168,48 +186,87 @@ module ChefMetalDocker
168
186
  private
169
187
 
170
188
  def machine_for(node)
189
+ strategy = convergence_strategy_for(node)
171
190
  ChefMetalDocker::DockerUnixMachine.new(node, transport_for(node), convergence_strategy_for(node))
172
191
  end
173
192
 
174
193
  def convergence_strategy_for(node)
175
194
  provisioner_output = node['normal']['provisioner_output']
176
195
  provisioner_options = node['normal']['provisioner_options']
177
- strategy = case provisioner_options['convergence_strategy']
178
- when 'no_converge'
179
- ChefMetal::ConvergenceStrategy::NoConverge.new
180
- else
181
- options = {}
182
- provisioner_options = node['normal']['provisioner_options'] || {}
183
- options[:chef_client_timeout] = provisioner_options['chef_client_timeout'] if provisioner_options.has_key?('chef_client_timeout')
184
- ChefMetal::ConvergenceStrategy::InstallCached.new(options)
185
- end
186
- container_configuration = provisioner_options['container_configuration'] || {}
187
- if provisioner_options['command']
188
- command = provisioner_options['command']
189
- command = command.split(/\s+/) if command.is_a?(String)
190
- container_configuration['Cmd'] = command
191
- elsif provisioner_options['command'] == false
192
- container_configuration = nil
193
- else
194
- # TODO how do we get things started? runit? cron? wassup here.
195
- container_configuration['Cmd'] = %w(while 1; sleep 1000; end)
196
+ strategy = begin
197
+ options = {}
198
+ provisioner_options = node['normal']['provisioner_options'] || {}
199
+ options[:chef_client_timeout] = provisioner_options['chef_client_timeout'] if provisioner_options.has_key?('chef_client_timeout')
200
+ ChefMetal::ConvergenceStrategy::InstallCached.new(options)
196
201
  end
197
- ChefMetalDocker::DockerConvergenceStrategy.new(strategy,
198
- provisioner_output['repository_name'],
199
- provisioner_output['container_name'],
200
- container_configuration,
201
- provisioner_options['host_configuration'] || {},
202
- credentials,
203
- connection)
204
202
  end
205
203
 
206
204
  def transport_for(node)
205
+ provisioner_options = node['normal']['provisioner_options']
207
206
  provisioner_output = node['normal']['provisioner_output']
208
- ChefMetalDocker::DockerTransport.new(
209
- provisioner_output['repository_name'],
210
- provisioner_output['container_name'],
211
- credentials,
212
- connection)
207
+ if provisioner_options['create_container'] && provisioner_options['create_container']['ssh_options']
208
+ container = Docker::Container.get(provisioner_output['container_name'])
209
+ ssh_options = {
210
+ # TODO create a user known hosts file
211
+ # :user_known_hosts_file => vagrant_ssh_config['UserKnownHostsFile'],
212
+ # :paranoid => true,
213
+ :host_key_alias => "#{container.id}.docker"
214
+ }.merge(provisioner_options['create_container']['ssh_options'])
215
+ username = ssh_options.delete(:username)
216
+ options = {}
217
+ if ssh_options[:sudo] || (!ssh_options.has_key?(:sudo) && username != 'root')
218
+ if ssh_options[:password]
219
+ options[:prefix] = "echo #{ssh_options[:password]} | sudo -S -p '' "
220
+ else
221
+ options[:prefix] = 'sudo '
222
+ end
223
+ end
224
+ ssh_options.delete(:sudo)
225
+ ip_address = container.info['NetworkSettings']['IPAddress']
226
+ Chef::Log.debug("Container #{provisioner_output['container_name']} address is #{ip_address}")
227
+ ChefMetal::Transport::SSH.new(ip_address, username, ssh_options, options)
228
+ else
229
+ ChefMetalDocker::DockerTransport.new(
230
+ provisioner_output['repository_name'],
231
+ provisioner_output['container_name'],
232
+ credentials,
233
+ connection)
234
+ end
235
+ end
236
+
237
+ def create_container(action_handler, provisioner_options, provisioner_output)
238
+ container_name = provisioner_output['container_name']
239
+
240
+ container_configuration = provisioner_options['create_container']['container_configuration'] || {}
241
+ host_configuration = provisioner_options['create_container']['host_configuration'] || {}
242
+ command = provisioner_options['create_container']['command']
243
+ raise "Must pass create_container.command if creating a container" if !command
244
+ command = command.split(/\s+/) if command.is_a?(String)
245
+ container_configuration['Cmd'] = command
246
+ need_to_create = false
247
+ begin
248
+ # Try to get the container; if that fails, it doesn't exist and we start it.
249
+ container = Docker::Container.get(container_name)
250
+ if !container.info['State']['Running']
251
+ action_handler.perform_action "Delete old, non-running container" do
252
+ container.delete
253
+ end
254
+ need_to_create = true
255
+ end
256
+
257
+ rescue Docker::Error::NotFoundError
258
+ need_to_create = true
259
+ end
260
+
261
+ if need_to_create
262
+ action_handler.perform_action "Create new container and run container_configuration['Cmd']" do
263
+ container = Docker::Container.create({
264
+ 'name' => container_name,
265
+ 'Image' => provisioner_options['base_image']
266
+ }.merge(container_configuration), connection)
267
+ container.start!(host_configuration)
268
+ end
269
+ end
213
270
  end
214
271
  end
215
272
  end
@@ -1,3 +1,3 @@
1
1
  module ChefMetalDocker
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-metal-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Duffield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-12 00:00:00.000000000 Z
11
+ date: 2014-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -108,7 +108,6 @@ files:
108
108
  - lib/chef/provider/docker_container.rb
109
109
  - lib/chef/resource/docker_container.rb
110
110
  - lib/chef_metal/provisioner_init/docker_init.rb
111
- - lib/chef_metal_docker/docker_convergence_strategy.rb
112
111
  - lib/chef_metal_docker/docker_provisioner.rb
113
112
  - lib/chef_metal_docker/docker_transport.rb
114
113
  - lib/chef_metal_docker/docker_unix_machine.rb
@@ -1,55 +0,0 @@
1
- require 'chef_metal/convergence_strategy'
2
- require 'docker'
3
-
4
- module ChefMetalDocker
5
- class DockerConvergenceStrategy < ChefMetal::ConvergenceStrategy
6
- def initialize(real_convergence_strategy, repository_name, container_name, container_configuration, host_configuration, credentials, connection)
7
- @real_convergence_strategy = real_convergence_strategy
8
- @repository_name = repository_name
9
- @container_name = container_name
10
- @container_configuration = container_configuration
11
- @host_configuration = host_configuration
12
- @credentials = credentials
13
- @connection = connection
14
- end
15
-
16
- attr_reader :real_convergence_strategy
17
- attr_reader :repository_name
18
- attr_reader :container_name
19
- attr_reader :container_configuration
20
- attr_reader :host_configuration
21
- attr_reader :credentials
22
- attr_reader :connection
23
-
24
- def setup_convergence(action_handler, machine, machine_resource)
25
- real_convergence_strategy.setup_convergence(action_handler, machine, machine_resource)
26
- end
27
-
28
- def converge(action_handler, machine, chef_server)
29
- real_convergence_strategy.converge(action_handler, machine, chef_server)
30
-
31
- # After converge, we bring up the container command
32
- if container_configuration
33
- begin
34
- container = Docker::Container.get(container_name)
35
- action_handler.perform_action "Delete existing container" do
36
- container.delete
37
- end
38
- rescue Docker::Error::NotFoundError
39
- end
40
- action_handler.perform_action "Create new container and run container_configuration['Cmd']" do
41
- container = Docker::Container.create({
42
- 'name' => container_name,
43
- 'Image' => "#{repository_name}:latest"
44
- }.merge(container_configuration), connection)
45
- container.start!(host_configuration)
46
- end
47
- # We don't bother waiting ... our only job is to bring it up.
48
- end
49
- end
50
-
51
- def cleanup_convergence(action_handler, node)
52
- real_convergence_strategy.cleanup_convergence(action_handler, node)
53
- end
54
- end
55
- end