chef-metal-fog 0.6.1 → 0.7

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: b5883afe070478a843245ccc9844ea0f355e9596
4
- data.tar.gz: f3ea03361d9501d0860e32eadfbad2a0408164dc
3
+ metadata.gz: df1eb39ee54fce02bce795f16bcffb150a5a457b
4
+ data.tar.gz: 1c33c93f06ec8858fbd1f84c82850d351065936e
5
5
  SHA512:
6
- metadata.gz: 580d1fc60224a67c4962f76c208ffa1691fb0b82b882e01769d624a066237fb2f4a413afb0591ca9562883373fe22dde212ebfd861374b772d63f031e7b12d3d
7
- data.tar.gz: 83f6827b9ead2253391d5a409c32a869e40e2d4d31ab36cba8880f338e6ccac5149a14cd8732bd3129f08de1006d15ee4850b76d9a027f0ac9244a7e059b797c
6
+ metadata.gz: f669a9e485c513128afc5498932311c944d82eb185ccaba96c4fd5479be8c85c1cbefa2fd28432c2a69cb6045fea2e10c7cc0924973ce99548287921726001f4
7
+ data.tar.gz: 6660dc13199041cf38389da3820bff2b4572a0ba081b7531aff915e7cc464fea193c73662d75caf382a898b606011c45c07c38935ac70f567350c68717cf4406
@@ -32,6 +32,8 @@ class Chef::Provider::FogKeyPair < Chef::Provider::LWRPBase
32
32
  "#{new_resource.name} on #{new_driver.driver_url}"
33
33
  end
34
34
 
35
+ @@use_pkcs8 = nil # For Ruby 1.9 and below, PKCS can be run
36
+
35
37
  def create_key(action)
36
38
  if @should_create_directory
37
39
  Cheffish.inline_resource(self, action) do
@@ -66,8 +66,8 @@ module ChefMetalFog
66
66
  #
67
67
  # - bootstrap_options: hash of options to pass to compute.servers.create
68
68
  # - is_windows: true if windows. TODO detect this from ami?
69
- # - create_timeout: the time to wait for the instance to boot to ssh (defaults to 600)
70
- # - start_timeout: the time to wait for the instance to start (defaults to 600)
69
+ # - create_timeout: the time to wait for the instance to boot to ssh (defaults to 180)
70
+ # - start_timeout: the time to wait for the instance to start (defaults to 180)
71
71
  # - ssh_timeout: the time to wait for ssh to be available if the instance is detected as up (defaults to 20)
72
72
  # - ssh_username: username to use for ssh
73
73
  # - sudo: true to prefix all commands with "sudo"
@@ -155,6 +155,11 @@ module ChefMetalFog
155
155
  # - log_level: :debug, :info, :warn, :error
156
156
  def initialize(driver_url, config)
157
157
  super(driver_url, config)
158
+ if config[:log_level] == :debug
159
+ Fog::Logger[:debug] = ::STDERR
160
+ Excon.defaults[:debug_request] = true
161
+ Excon.defaults[:debug_response] = true
162
+ end
158
163
  end
159
164
 
160
165
  def compute_options
@@ -170,7 +175,15 @@ module ChefMetalFog
170
175
  # converge, execute, file and directory.
171
176
  def allocate_machine(action_handler, machine_spec, machine_options)
172
177
  # If the server does not exist, create it
173
- create_server(action_handler, machine_spec, machine_options)
178
+ create_servers(action_handler, { machine_spec => machine_options }, Chef::ChefFS::Parallelizer.new(0))
179
+ machine_spec
180
+ end
181
+
182
+ def allocate_machines(action_handler, specs_and_options, parallelizer)
183
+ create_servers(action_handler, specs_and_options, parallelizer) do |machine_spec, server|
184
+ yield machine_spec
185
+ end
186
+ specs_and_options.keys
174
187
  end
175
188
 
176
189
  def ready_machine(action_handler, machine_spec, machine_options)
@@ -251,46 +264,78 @@ module ChefMetalFog
251
264
  raise "unsupported fog provider #{provider} (please implement #creator)"
252
265
  end
253
266
 
254
- def create_server(action_handler, machine_spec, machine_options)
255
- if machine_spec.location
256
- if machine_spec.location['driver_url'] != driver_url
257
- raise "Switching a machine's driver from #{machine_spec.location['driver_url']} to #{driver_url} for is not currently supported! Use machine :destroy and then re-create the machine on the new driver."
258
- end
267
+ def create_servers(action_handler, specs_and_options, parallelizer, &block)
268
+ specs_and_servers = servers_for(specs_and_options.keys)
259
269
 
260
- server = server_for(machine_spec)
270
+ # Get the list of servers which exist, segmented by their bootstrap options
271
+ # (we will try to create a set of servers for each set of bootstrap options
272
+ # with create_many)
273
+ by_bootstrap_options = {}
274
+ specs_and_options.each do |machine_spec, machine_options|
275
+ server = specs_and_servers[machine_spec]
261
276
  if server
262
277
  if %w(terminated archive).include?(server.state) # Can't come back from that
263
278
  Chef::Log.warn "Machine #{machine_spec.name} (#{server.id} on #{driver_url}) is terminated. Recreating ..."
264
279
  else
265
- return server
280
+ yield machine_spec, server if block_given?
281
+ next
266
282
  end
267
- else
283
+ elsif machine_spec.location
268
284
  Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.location['server_id']} on #{driver_url}) no longer exists. Recreating ..."
269
285
  end
286
+
287
+ bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
288
+ by_bootstrap_options[bootstrap_options] ||= []
289
+ by_bootstrap_options[bootstrap_options] << machine_spec
270
290
  end
271
291
 
272
- bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
292
+ # Create the servers in parallel
293
+ parallelizer.parallel_do(by_bootstrap_options) do |bootstrap_options, machine_specs|
294
+ machine_description = if machine_specs.size == 1
295
+ "machine #{machine_specs.first.name}"
296
+ else
297
+ "machines #{machine_specs.map { |s| s.name }.join(", ")}"
298
+ end
299
+ description = [ "creating #{machine_description} on #{driver_url}" ]
300
+ bootstrap_options.each_pair { |key,value| description << " #{key}: #{value.inspect}" }
301
+ action_handler.report_progress description
273
302
 
274
- description = [ "creating machine #{machine_spec.name} on #{driver_url}" ]
275
- bootstrap_options.each_pair { |key,value| description << " #{key}: #{value.inspect}" }
276
- server = nil
277
- action_handler.report_progress description
278
- if action_handler.should_perform_actions
279
- server = compute.servers.create(bootstrap_options)
280
- machine_spec.location = {
281
- 'driver_url' => driver_url,
282
- 'driver_version' => ChefMetalFog::VERSION,
283
- 'server_id' => server.id,
284
- 'creator' => creator,
285
- 'allocated_at' => Time.now.to_i
286
- }
287
- machine_spec.location['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
288
- %w(is_windows ssh_username sudo use_private_ip_for_ssh ssh_gateway).each do |key|
289
- machine_spec.location[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
303
+ if action_handler.should_perform_actions
304
+ # Actually create the servers
305
+ create_many_servers(machine_specs.size, bootstrap_options, parallelizer) do |server|
306
+
307
+ # Assign each one to a machine spec
308
+ machine_spec = machine_specs.pop
309
+ machine_options = specs_and_options[machine_spec]
310
+ machine_spec.location = {
311
+ 'driver_url' => driver_url,
312
+ 'driver_version' => ChefMetalFog::VERSION,
313
+ 'server_id' => server.id,
314
+ 'creator' => creator,
315
+ 'allocated_at' => Time.now.to_i
316
+ }
317
+ machine_spec.location['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
318
+ %w(is_windows ssh_username sudo use_private_ip_for_ssh ssh_gateway).each do |key|
319
+ machine_spec.location[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
320
+ end
321
+ action_handler.performed_action "machine #{machine_spec.name} created as #{server.id} on #{driver_url}"
322
+
323
+ yield machine_spec, server if block_given?
324
+ end
325
+
326
+ if machine_specs.size > 0
327
+ raise "Not all machines were created by create_many_machines!"
328
+ end
290
329
  end
291
330
  end
292
- action_handler.performed_action "machine #{machine_spec.name} created as #{server.id} on #{driver_url}"
293
- server
331
+ end
332
+
333
+ def create_many_servers(num_servers, bootstrap_options, parallelizer)
334
+ parallelizer.parallelize(1.upto(num_servers)) do |i|
335
+ server = compute.servers.create(bootstrap_options)
336
+ yield server if block_given?
337
+ server
338
+ end.to_a
294
339
  end
295
340
 
296
341
  def start_server(action_handler, machine_spec, server)
@@ -418,6 +463,21 @@ module ChefMetalFog
418
463
  end
419
464
  end
420
465
 
466
+ def servers_for(machine_specs)
467
+ result = {}
468
+ machine_specs.each do |machine_spec|
469
+ if machine_spec.location
470
+ if machine_spec.location['driver_url'] != driver_url
471
+ raise "Switching a machine's driver from #{machine_spec.location['driver_url']} to #{driver_url} for is not currently supported! Use machine :destroy and then re-create the machine on the new driver."
472
+ end
473
+ result[machine_spec] = compute.servers.get(machine_spec.location['server_id'])
474
+ else
475
+ result[machine_spec] = nil
476
+ end
477
+ end
478
+ result
479
+ end
480
+
421
481
  @@metal_default_lock = Mutex.new
422
482
 
423
483
  def overwrite_default_key_willy_nilly(action_handler)
@@ -26,12 +26,34 @@ module ChefMetalFog
26
26
  if !bootstrap_options[:key_name]
27
27
  bootstrap_options[:key_name] = overwrite_default_key_willy_nilly(action_handler)
28
28
  end
29
+ bootstrap_options.delete(:tags) # we handle these separately for performance reasons
30
+ bootstrap_options
31
+ end
29
32
 
30
- bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
33
+ def create_servers(action_handler, specs_and_options, parallelizer)
34
+ super(action_handler, specs_and_options, parallelizer) do |machine_spec, server|
35
+ yield machine_spec, server if block_given?
31
36
 
32
- bootstrap_options[:name] ||= machine_spec.name
37
+ machine_options = specs_and_options[machine_spec]
38
+ bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
39
+ tags = default_tags(machine_spec, bootstrap_options[:tags] || {})
33
40
 
34
- bootstrap_options
41
+ # Right now, not doing that in case manual tagging is going on
42
+ server_tags = server.tags || {}
43
+ extra_tags = tags.keys.select { |tag_name| !server_tags.has_key?(tag_name) }.to_a
44
+ different_tags = server_tags.select { |tag_name, tag_value| tags.has_key?(tag_name) && tags[tag_name] != tag_value }.to_a
45
+ if extra_tags.size > 0 || different_tags.size > 0
46
+ tags_description = [ "Update tags for #{machine_spec.name} on #{driver_url}" ]
47
+ tags_description += extra_tags.map { |tag| " Add #{tag} = #{tags[tag].inspect}" }
48
+ tags_description += different_tags.map { |tag| " Update #{tag.name} from #{tag.value.inspect} to #{tags[tag.name].inspect}"}
49
+ action_handler.perform_action tags_description do
50
+ # TODO should we narrow this down to just extra/different tags or
51
+ # is it OK to just pass 'em all? Certainly easier to do the
52
+ # latter, and I can't think of a consequence for doing so offhand.
53
+ compute.create_tags(server.identity, tags)
54
+ end
55
+ end
56
+ end
35
57
  end
36
58
 
37
59
  def self.get_aws_profile(driver_options, aws_account_id)
@@ -209,6 +231,36 @@ module ChefMetalFog
209
231
 
210
232
  [result, id]
211
233
  end
234
+
235
+ def create_many_servers(num_servers, bootstrap_options, parallelizer)
236
+ # Create all the servers in one request if we have a version of fog that can do that
237
+ if compute.servers.respond_to?(:create_many)
238
+ servers = compute.servers.create_many(num_servers, num_servers, bootstrap_options)
239
+ if block_given?
240
+ parallelizer.parallel_do(servers) do |server|
241
+ yield server
242
+ end
243
+ end
244
+ servers
245
+ else
246
+ super
247
+ end
248
+ end
249
+
250
+ def servers_for(machine_specs)
251
+ # Grab all the servers in one request
252
+ instance_ids = machine_specs.map { |machine_spec| (machine_spec.location || {})['server_id'] }.select { |id| !id.nil? }
253
+ servers = compute.servers.all('instance-id' => instance_ids)
254
+ result = {}
255
+ machine_specs.each do |machine_spec|
256
+ if machine_spec.location
257
+ result[machine_spec] = servers.select { |s| s.id == machine_spec.location['server_id'] }.first
258
+ else
259
+ result[machine_spec] = nil
260
+ end
261
+ end
262
+ result
263
+ end
212
264
  end
213
265
  end
214
266
  end
@@ -13,6 +13,9 @@ module ChefMetalFog
13
13
  include Enumerable
14
14
 
15
15
  def default
16
+ if @credentials.size == 0
17
+ raise "No credentials loaded! Do you have a ~/.aws/config?"
18
+ end
16
19
  @credentials[ENV['AWS_DEFAULT_PROFILE'] || 'default'] || @credentials.first[1]
17
20
  end
18
21
 
@@ -30,15 +33,21 @@ module ChefMetalFog
30
33
 
31
34
  def load_ini(credentials_ini_file)
32
35
  inifile = IniFile.load(File.expand_path(credentials_ini_file))
33
- inifile.each_section do |section|
34
- if section =~ /^\s*profile\s+(.+)$/ || section =~ /^\s*(default)\s*/
35
- profile_name = $1.strip
36
- profile = inifile[section].inject({}) do |result, pair|
37
- result[pair[0].to_sym] = pair[1]
38
- result
36
+ if inifile
37
+ inifile.each_section do |section|
38
+ if section =~ /^\s*profile\s+(.+)$/ || section =~ /^\s*(default)\s*/
39
+ profile_name = $1.strip
40
+ profile = inifile[section].inject({}) do |result, pair|
41
+ result[pair[0].to_sym] = pair[1]
42
+ result
43
+ end
44
+ profile[:name] = profile_name
45
+ @credentials[profile_name] = profile
39
46
  end
40
- profile[:name] = profile_name
41
- @credentials[profile_name] = profile
47
+ end
48
+ else
49
+ # Get it to throw an error
50
+ File.open(File.expand_path(credentials_ini_file)) do
42
51
  end
43
52
  end
44
53
  end
@@ -55,7 +64,10 @@ module ChefMetalFog
55
64
  end
56
65
 
57
66
  def load_default
58
- load_ini(ENV['AWS_CONFIG_FILE'] || File.expand_path('~/.aws/config'))
67
+ config_file = ENV['AWS_CONFIG_FILE'] || File.expand_path('~/.aws/config')
68
+ if File.file?(config_file)
69
+ load_ini(config_file)
70
+ end
59
71
  end
60
72
 
61
73
  def self.method_missing(name, *args, &block)
@@ -4,6 +4,10 @@ module ChefMetalFog
4
4
 
5
5
  ChefMetalFog::FogDriver.register_provider_class('CloudStack', ChefMetalFog::Providers::CloudStack)
6
6
 
7
+ def creator
8
+ ''
9
+ end
10
+
7
11
  def self.compute_options_for(provider, id, config)
8
12
  new_compute_options = {}
9
13
  new_compute_options[:provider] = provider
@@ -1,3 +1,3 @@
1
1
  module ChefMetalFog
2
- VERSION = '0.6.1'
2
+ VERSION = '0.7'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-metal-fog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: '0.7'
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-18 00:00:00.000000000 Z
11
+ date: 2014-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef