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 +4 -4
- data/lib/chef/provider/fog_key_pair.rb +2 -0
- data/lib/chef_metal_fog/fog_driver.rb +90 -30
- data/lib/chef_metal_fog/providers/aws.rb +55 -3
- data/lib/chef_metal_fog/providers/aws/credentials.rb +21 -9
- data/lib/chef_metal_fog/providers/cloudstack.rb +4 -0
- data/lib/chef_metal_fog/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df1eb39ee54fce02bce795f16bcffb150a5a457b
|
4
|
+
data.tar.gz: 1c33c93f06ec8858fbd1f84c82850d351065936e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
70
|
-
# - start_timeout: the time to wait for the instance to start (defaults to
|
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
|
-
|
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
|
255
|
-
|
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
|
-
|
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
|
-
|
280
|
+
yield machine_spec, server if block_given?
|
281
|
+
next
|
266
282
|
end
|
267
|
-
|
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
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
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
|
-
|
293
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
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
|
-
|
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
|
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.
|
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-
|
11
|
+
date: 2014-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|