chef-provisioning-fog 0.13.2 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/chef/provisioning/fog_driver/driver.rb +66 -55
- data/lib/chef/provisioning/fog_driver/providers/aws.rb +3 -3
- data/lib/chef/provisioning/fog_driver/providers/digitalocean.rb +1 -1
- data/lib/chef/provisioning/fog_driver/providers/google.rb +84 -0
- data/lib/chef/provisioning/fog_driver/providers/vcair.rb +376 -0
- data/lib/chef/provisioning/fog_driver/recipe_dsl.rb +4 -0
- data/lib/chef/provisioning/fog_driver/version.rb +1 -1
- data/spec/unit/providers/rackspace_spec.rb +1 -1
- metadata +22 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52b659938865f82a47d2bd233d5f9e4d62d4b708
|
4
|
+
data.tar.gz: ee9dc1faac3c6e1a2527fcd64079fd7b0521ae73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 469dcadcf9ca2ad0e608de694abdc3a85b3e1dd9bb677330191ef0e86c2d3041c1197ad89a678718d17980c1ea983f4987805a3593d190760972d418ab865394
|
7
|
+
data.tar.gz: 28fc5d4cce8c2c1b77306d32fc5592bf83eeab2d1b18c82b433c2a272e345c9c7f4b0141296d22052b85dbb82d5cc5e8a3c04c9754777b8fd4f294a28ca37bca
|
data/README.md
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
# chef-provisioning-fog
|
2
2
|
|
3
|
-
This is the Fog driver for Chef Provisioning. It provides EC2, Rackspace, DigitalOcean, SoftLayer, and
|
3
|
+
This is the Fog driver for Chef Provisioning. It provides Amazon EC2, Rackspace, DigitalOcean, SoftLayer, OpenStack, and vCloud Air functionality.
|
@@ -19,6 +19,7 @@ require 'fog/compute'
|
|
19
19
|
require 'socket'
|
20
20
|
require 'etc'
|
21
21
|
require 'time'
|
22
|
+
require 'retryable'
|
22
23
|
require 'cheffish/merged_config'
|
23
24
|
require 'chef/provisioning/fog_driver/recipe_dsl'
|
24
25
|
|
@@ -51,15 +52,15 @@ module FogDriver
|
|
51
52
|
#
|
52
53
|
# To add a new supported Fog provider, pick an appropriate identifier, go to
|
53
54
|
# from_provider and compute_options_for, and add the new provider in the case
|
54
|
-
# statements so that URLs for your
|
55
|
+
# statements so that URLs for your Fog provider can be generated. If your
|
55
56
|
# cloud provider has environment variables or standard config files (like
|
56
57
|
# ~/.aws/credentials or ~/.aws/config), you can read those and merge that information
|
57
58
|
# in the compute_options_for function.
|
58
59
|
#
|
59
|
-
# ##
|
60
|
+
# ## Reference format
|
60
61
|
#
|
61
|
-
# All machines have a
|
62
|
-
# the
|
62
|
+
# All machines have a reference hash to find them. These are the keys used by
|
63
|
+
# the Fog provisioner:
|
63
64
|
#
|
64
65
|
# - driver_url: fog:<driver>:<unique_account_info>
|
65
66
|
# - server_id: the ID of the server so it can be found again
|
@@ -102,6 +103,9 @@ module FogDriver
|
|
102
103
|
:ssh_timeout => 20
|
103
104
|
}
|
104
105
|
|
106
|
+
RETRYABLE_ERRORS = [Fog::Compute::AWS::Error]
|
107
|
+
RETRYABLE_OPTIONS = { tries: 12, sleep: 5, on: RETRYABLE_ERRORS }
|
108
|
+
|
105
109
|
class << self
|
106
110
|
alias :__new__ :new
|
107
111
|
|
@@ -149,7 +153,7 @@ module FogDriver
|
|
149
153
|
Provisioning.driver_for_url(driver_url, config)
|
150
154
|
end
|
151
155
|
|
152
|
-
# Create a new
|
156
|
+
# Create a new Fog driver.
|
153
157
|
#
|
154
158
|
# ## Parameters
|
155
159
|
# driver_url - URL of driver. "fog:<provider>:<provider_id>"
|
@@ -211,7 +215,7 @@ module FogDriver
|
|
211
215
|
wait_for_transport(action_handler, machine_spec, machine_options, server)
|
212
216
|
rescue Fog::Errors::TimeoutError
|
213
217
|
# Only ever reboot once, and only if it's been less than 10 minutes since we stopped waiting
|
214
|
-
if machine_spec.
|
218
|
+
if machine_spec.reference['started_at'] || remaining_wait_time(machine_spec, machine_options) < -(10*60)
|
215
219
|
raise
|
216
220
|
else
|
217
221
|
# Sometimes (on EC2) the machine comes up but gets stuck or has
|
@@ -235,9 +239,9 @@ module FogDriver
|
|
235
239
|
def destroy_machine(action_handler, machine_spec, machine_options)
|
236
240
|
server = server_for(machine_spec)
|
237
241
|
if server
|
238
|
-
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.
|
242
|
+
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.reference['server_id']} at #{driver_url})" do
|
239
243
|
server.destroy
|
240
|
-
machine_spec.
|
244
|
+
machine_spec.reference = nil
|
241
245
|
end
|
242
246
|
end
|
243
247
|
strategy = convergence_strategy_for(machine_spec, machine_options)
|
@@ -254,7 +258,7 @@ module FogDriver
|
|
254
258
|
end
|
255
259
|
|
256
260
|
def image_for(image_spec)
|
257
|
-
compute.images.get(image_spec.
|
261
|
+
compute.images.get(image_spec.reference['image_id'])
|
258
262
|
end
|
259
263
|
|
260
264
|
def compute
|
@@ -263,7 +267,7 @@ module FogDriver
|
|
263
267
|
|
264
268
|
# Not meant to be part of public interface
|
265
269
|
def transport_for(machine_spec, machine_options, server, action_handler = nil)
|
266
|
-
if machine_spec.
|
270
|
+
if machine_spec.reference['is_windows']
|
267
271
|
action_handler.report_progress "Waiting for admin password on #{machine_spec.name} to be ready (may take up to 15 minutes)..." if action_handler
|
268
272
|
transport = create_winrm_transport(machine_spec, machine_options, server)
|
269
273
|
action_handler.report_progress 'Admin password available ...' if action_handler
|
@@ -280,7 +284,7 @@ module FogDriver
|
|
280
284
|
end
|
281
285
|
|
282
286
|
def creator
|
283
|
-
raise "unsupported
|
287
|
+
raise "unsupported Fog provider #{provider} (please implement #creator)"
|
284
288
|
end
|
285
289
|
|
286
290
|
def create_servers(action_handler, specs_and_options, parallelizer, &block)
|
@@ -299,8 +303,8 @@ module FogDriver
|
|
299
303
|
yield machine_spec, server if block_given?
|
300
304
|
next
|
301
305
|
end
|
302
|
-
elsif machine_spec.
|
303
|
-
Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.
|
306
|
+
elsif machine_spec.reference
|
307
|
+
Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.reference['server_id']} on #{driver_url}) no longer exists. Recreating ..."
|
304
308
|
end
|
305
309
|
|
306
310
|
bootstrap_options = bootstrap_options_for(action_handler, machine_spec, machine_options)
|
@@ -325,16 +329,16 @@ module FogDriver
|
|
325
329
|
# Assign each one to a machine spec
|
326
330
|
machine_spec = machine_specs.pop
|
327
331
|
machine_options = specs_and_options[machine_spec]
|
328
|
-
machine_spec.
|
332
|
+
machine_spec.reference = {
|
329
333
|
'driver_url' => driver_url,
|
330
334
|
'driver_version' => FogDriver::VERSION,
|
331
335
|
'server_id' => server.id,
|
332
336
|
'creator' => creator,
|
333
337
|
'allocated_at' => Time.now.to_i
|
334
338
|
}
|
335
|
-
machine_spec.
|
339
|
+
machine_spec.reference['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
|
336
340
|
%w(is_windows ssh_username sudo use_private_ip_for_ssh ssh_gateway).each do |key|
|
337
|
-
machine_spec.
|
341
|
+
machine_spec.reference[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
|
338
342
|
end
|
339
343
|
action_handler.performed_action "machine #{machine_spec.name} created as #{server.id} on #{driver_url}"
|
340
344
|
|
@@ -368,7 +372,7 @@ module FogDriver
|
|
368
372
|
if server.state == 'stopped'
|
369
373
|
action_handler.perform_action "start machine #{machine_spec.name} (#{server.id} on #{driver_url})" do
|
370
374
|
server.start
|
371
|
-
machine_spec.
|
375
|
+
machine_spec.reference['started_at'] = Time.now.to_i
|
372
376
|
end
|
373
377
|
machine_spec.save(action_handler)
|
374
378
|
end
|
@@ -377,16 +381,16 @@ module FogDriver
|
|
377
381
|
def restart_server(action_handler, machine_spec, server)
|
378
382
|
action_handler.perform_action "restart machine #{machine_spec.name} (#{server.id} on #{driver_url})" do
|
379
383
|
server.reboot
|
380
|
-
machine_spec.
|
384
|
+
machine_spec.reference['started_at'] = Time.now.to_i
|
381
385
|
end
|
382
386
|
machine_spec.save(action_handler)
|
383
387
|
end
|
384
388
|
|
385
389
|
def remaining_wait_time(machine_spec, machine_options)
|
386
|
-
if machine_spec.
|
387
|
-
timeout = option_for(machine_options, :start_timeout) - (Time.now.utc - parse_time(machine_spec.
|
390
|
+
if machine_spec.reference['started_at']
|
391
|
+
timeout = option_for(machine_options, :start_timeout) - (Time.now.utc - parse_time(machine_spec.reference['started_at']))
|
388
392
|
else
|
389
|
-
timeout = option_for(machine_options, :create_timeout) - (Time.now.utc - parse_time(machine_spec.
|
393
|
+
timeout = option_for(machine_options, :create_timeout) - (Time.now.utc - parse_time(machine_spec.reference['allocated_at']))
|
390
394
|
end
|
391
395
|
timeout > 0 ? timeout : 0.01
|
392
396
|
end
|
@@ -402,8 +406,10 @@ module FogDriver
|
|
402
406
|
def wait_until_ready(action_handler, machine_spec, machine_options, server)
|
403
407
|
if !server.ready?
|
404
408
|
if action_handler.should_perform_actions
|
405
|
-
|
406
|
-
|
409
|
+
Retryable.retryable(RETRYABLE_OPTIONS) do |retries,exception|
|
410
|
+
action_handler.report_progress "waiting for #{machine_spec.name} (#{server.id} on #{driver_url}) to be ready, API attempt #{retries+1}/#{RETRYABLE_OPTIONS[:tries]} ..."
|
411
|
+
server.wait_for(remaining_wait_time(machine_spec, machine_options)) { ready? }
|
412
|
+
end
|
407
413
|
action_handler.report_progress "#{machine_spec.name} is now ready"
|
408
414
|
end
|
409
415
|
end
|
@@ -414,12 +420,14 @@ module FogDriver
|
|
414
420
|
transport = transport_for(machine_spec, machine_options, server, action_handler)
|
415
421
|
if !transport.available?
|
416
422
|
if action_handler.should_perform_actions
|
417
|
-
|
423
|
+
Retryable.retryable(RETRYABLE_OPTIONS) do |retries,exception|
|
424
|
+
action_handler.report_progress "waiting for #{machine_spec.name} (#{server.id} on #{driver_url}) to be connectable (transport up and running), API attempt #{retries+1}/#{RETRYABLE_OPTIONS[:tries]} ..."
|
418
425
|
|
419
|
-
|
426
|
+
_self = self
|
420
427
|
|
421
|
-
|
422
|
-
|
428
|
+
server.wait_for(remaining_wait_time(machine_spec, machine_options)) do
|
429
|
+
transport.available?
|
430
|
+
end
|
423
431
|
end
|
424
432
|
action_handler.report_progress "#{machine_spec.name} is now connectable"
|
425
433
|
end
|
@@ -429,7 +437,7 @@ module FogDriver
|
|
429
437
|
def converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
430
438
|
pool = option_for(machine_options, :floating_ip_pool)
|
431
439
|
floating_ip = option_for(machine_options, :floating_ip)
|
432
|
-
attached_floating_ips = find_floating_ips(server)
|
440
|
+
attached_floating_ips = find_floating_ips(server, action_handler)
|
433
441
|
if pool
|
434
442
|
|
435
443
|
Chef::Log.debug "Attaching IP from pool #{pool}"
|
@@ -467,12 +475,15 @@ module FogDriver
|
|
467
475
|
end
|
468
476
|
|
469
477
|
# Find all attached floating IPs from all networks
|
470
|
-
def find_floating_ips(server)
|
478
|
+
def find_floating_ips(server, action_handler)
|
471
479
|
floating_ips = []
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
480
|
+
Retryable.retryable(RETRYABLE_OPTIONS) do |retries,exception|
|
481
|
+
action_handler.report_progress "Querying for floating IPs attached to server #{server.id}, API attempt #{retries+1}/#{RETRYABLE_OPTIONS[:tries]} ..."
|
482
|
+
server.addresses.each do |network, addrs|
|
483
|
+
addrs.each do | full_addr |
|
484
|
+
if full_addr['OS-EXT-IPS:type'] == 'floating'
|
485
|
+
floating_ips << full_addr['addr']
|
486
|
+
end
|
476
487
|
end
|
477
488
|
end
|
478
489
|
end
|
@@ -512,8 +523,8 @@ module FogDriver
|
|
512
523
|
end
|
513
524
|
|
514
525
|
def server_for(machine_spec)
|
515
|
-
if machine_spec.
|
516
|
-
compute.servers.get(machine_spec.
|
526
|
+
if machine_spec.reference
|
527
|
+
compute.servers.get(machine_spec.reference['server_id'])
|
517
528
|
else
|
518
529
|
nil
|
519
530
|
end
|
@@ -522,11 +533,11 @@ module FogDriver
|
|
522
533
|
def servers_for(machine_specs)
|
523
534
|
result = {}
|
524
535
|
machine_specs.each do |machine_spec|
|
525
|
-
if machine_spec.
|
526
|
-
if machine_spec.
|
527
|
-
raise "Switching a machine's driver from #{machine_spec.
|
536
|
+
if machine_spec.reference
|
537
|
+
if machine_spec.reference['driver_url'] != driver_url
|
538
|
+
raise "Switching a machine's driver from #{machine_spec.reference['driver_url']} to #{driver_url} for is not currently supported! Use machine :destroy and then re-create the machine on the new driver."
|
528
539
|
end
|
529
|
-
result[machine_spec] = compute.servers.get(machine_spec.
|
540
|
+
result[machine_spec] = compute.servers.get(machine_spec.reference['server_id'])
|
530
541
|
else
|
531
542
|
result[machine_spec] = nil
|
532
543
|
end
|
@@ -537,8 +548,8 @@ module FogDriver
|
|
537
548
|
@@chef_default_lock = Mutex.new
|
538
549
|
|
539
550
|
def overwrite_default_key_willy_nilly(action_handler, machine_spec)
|
540
|
-
if machine_spec.
|
541
|
-
Gem::Version.new(machine_spec.
|
551
|
+
if machine_spec.reference &&
|
552
|
+
Gem::Version.new(machine_spec.reference['driver_version']) < Gem::Version.new('0.10')
|
542
553
|
return 'metal_default'
|
543
554
|
end
|
544
555
|
|
@@ -585,7 +596,7 @@ module FogDriver
|
|
585
596
|
raise "Server for node #{machine_spec.name} has not been created!"
|
586
597
|
end
|
587
598
|
|
588
|
-
if machine_spec.
|
599
|
+
if machine_spec.reference['is_windows']
|
589
600
|
Machine::WindowsMachine.new(machine_spec, transport_for(machine_spec, machine_options, server), convergence_strategy_for(machine_spec, machine_options))
|
590
601
|
else
|
591
602
|
Machine::UnixMachine.new(machine_spec, transport_for(machine_spec, machine_options, server), convergence_strategy_for(machine_spec, machine_options))
|
@@ -594,11 +605,11 @@ module FogDriver
|
|
594
605
|
|
595
606
|
def convergence_strategy_for(machine_spec, machine_options)
|
596
607
|
# Defaults
|
597
|
-
if !machine_spec.
|
608
|
+
if !machine_spec.reference
|
598
609
|
return ConvergenceStrategy::NoConverge.new(machine_options[:convergence_options], config)
|
599
610
|
end
|
600
611
|
|
601
|
-
if machine_spec.
|
612
|
+
if machine_spec.reference['is_windows']
|
602
613
|
ConvergenceStrategy::InstallMsi.new(machine_options[:convergence_options], config)
|
603
614
|
elsif machine_options[:cached_installer] == true
|
604
615
|
ConvergenceStrategy::InstallCached.new(machine_options[:convergence_options], config)
|
@@ -622,10 +633,10 @@ module FogDriver
|
|
622
633
|
raise "Server has key name '#{server.key_name}', but the corresponding private key was not found locally. Check if the key is in Chef::Config.private_key_paths: #{Chef::Config.private_key_paths.join(', ')}"
|
623
634
|
end
|
624
635
|
key
|
625
|
-
elsif machine_spec.
|
626
|
-
key = get_private_key(machine_spec.
|
636
|
+
elsif machine_spec.reference['key_name']
|
637
|
+
key = get_private_key(machine_spec.reference['key_name'])
|
627
638
|
if !key
|
628
|
-
raise "Server was created with key name '#{machine_spec.
|
639
|
+
raise "Server was created with key name '#{machine_spec.reference['key_name']}', but the corresponding private key was not found locally. Check if the key is in Chef::Config.private_key_paths: #{Chef::Config.private_key_paths.join(', ')}"
|
629
640
|
end
|
630
641
|
key
|
631
642
|
elsif machine_options[:bootstrap_options][:key_path]
|
@@ -634,7 +645,7 @@ module FogDriver
|
|
634
645
|
get_private_key(machine_options[:bootstrap_options][:key_name])
|
635
646
|
else
|
636
647
|
# TODO make a way to suggest other keys to try ...
|
637
|
-
raise "No key found to connect to #{machine_spec.name} (#{machine_spec.
|
648
|
+
raise "No key found to connect to #{machine_spec.name} (#{machine_spec.reference.inspect})!"
|
638
649
|
end
|
639
650
|
end
|
640
651
|
|
@@ -661,17 +672,17 @@ module FogDriver
|
|
661
672
|
|
662
673
|
def create_ssh_transport(machine_spec, machine_options, server)
|
663
674
|
ssh_options = ssh_options_for(machine_spec, machine_options, server)
|
664
|
-
username = machine_spec.
|
665
|
-
if machine_options.has_key?(:ssh_username) && machine_options[:ssh_username] != machine_spec.
|
666
|
-
Chef::Log.warn("Server #{machine_spec.name} was created with SSH username #{machine_spec.
|
675
|
+
username = machine_spec.reference['ssh_username'] || default_ssh_username
|
676
|
+
if machine_options.has_key?(:ssh_username) && machine_options[:ssh_username] != machine_spec.reference['ssh_username']
|
677
|
+
Chef::Log.warn("Server #{machine_spec.name} was created with SSH username #{machine_spec.reference['ssh_username']} and machine_options specifies username #{machine_options[:ssh_username]}. Using #{machine_spec.reference['ssh_username']}. Please edit the node and change the chef_provisioning.reference.ssh_username attribute if you want to change it.")
|
667
678
|
end
|
668
679
|
options = {}
|
669
|
-
if machine_spec.
|
680
|
+
if machine_spec.reference[:sudo] || (!machine_spec.reference.has_key?(:sudo) && username != 'root')
|
670
681
|
options[:prefix] = 'sudo '
|
671
682
|
end
|
672
683
|
|
673
684
|
remote_host = nil
|
674
|
-
if machine_spec.
|
685
|
+
if machine_spec.reference['use_private_ip_for_ssh']
|
675
686
|
remote_host = server.private_ip_address
|
676
687
|
elsif !server.public_ip_address
|
677
688
|
Chef::Log.warn("Server #{machine_spec.name} has no public floating_ip address. Using private floating_ip '#{server.private_ip_address}'. Set driver option 'use_private_ip_for_ssh' => true if this will always be the case ...")
|
@@ -684,13 +695,13 @@ module FogDriver
|
|
684
695
|
|
685
696
|
#Enable pty by default
|
686
697
|
options[:ssh_pty_enable] = true
|
687
|
-
options[:ssh_gateway] = machine_spec.
|
698
|
+
options[:ssh_gateway] = machine_spec.reference['ssh_gateway'] if machine_spec.reference.has_key?('ssh_gateway')
|
688
699
|
|
689
700
|
Transport::SSH.new(remote_host, username, ssh_options, options, config)
|
690
701
|
end
|
691
702
|
|
692
703
|
def self.compute_options_for(provider, id, config)
|
693
|
-
raise "unsupported
|
704
|
+
raise "unsupported Fog provider #{provider}"
|
694
705
|
end
|
695
706
|
end
|
696
707
|
end
|
@@ -36,7 +36,7 @@ module FogDriver
|
|
36
36
|
remote_host = if machine_spec.location['use_private_ip_for_ssh']
|
37
37
|
server.private_ip_address
|
38
38
|
elsif !server.public_ip_address
|
39
|
-
Chef::Log.warn("Server #{machine_spec.name} has no public
|
39
|
+
Chef::Log.warn("Server #{machine_spec.name} has no public IP address. Using private IP '#{server.private_ip_address}'. Set driver option 'use_private_ip_for_ssh' => true if this will always be the case ...")
|
40
40
|
server.private_ip_address
|
41
41
|
elsif server.public_ip_address
|
42
42
|
server.public_ip_address
|
@@ -349,7 +349,7 @@ module FogDriver
|
|
349
349
|
id = $1
|
350
350
|
new_compute_options[:region] = $3
|
351
351
|
else
|
352
|
-
Chef::Log.warn("Old-style AWS URL #{id} from an early beta of chef-
|
352
|
+
Chef::Log.warn("Old-style AWS URL #{id} from an early beta of chef-provisioning (before chef-metal 0.11-final) found. If you have servers in multiple regions on this account, you may see odd behavior like servers being recreated. To fix, edit any nodes with attribute chef_provisioning.location.driver_url to include the region like so: fog:AWS:#{id}:<region> (e.g. us-east-1)")
|
353
353
|
end
|
354
354
|
else
|
355
355
|
# Assume it is a profile name, and set that.
|
@@ -384,7 +384,7 @@ module FogDriver
|
|
384
384
|
end
|
385
385
|
|
386
386
|
def create_many_servers(num_servers, bootstrap_options, parallelizer)
|
387
|
-
# Create all the servers in one request if we have a version of
|
387
|
+
# Create all the servers in one request if we have a version of Fog that can do that
|
388
388
|
if compute.servers.respond_to?(:create_many)
|
389
389
|
servers = compute.servers.create_many(num_servers, num_servers, bootstrap_options)
|
390
390
|
if block_given?
|
@@ -11,7 +11,7 @@ module FogDriver
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
14
|
-
#
|
14
|
+
# DigitalOcean does not have floating IPs
|
15
15
|
end
|
16
16
|
|
17
17
|
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class Chef
|
2
|
+
module Provisioning
|
3
|
+
module FogDriver
|
4
|
+
module Providers
|
5
|
+
class Google < FogDriver::Driver
|
6
|
+
Driver.register_provider_class('Google', FogDriver::Providers::Google)
|
7
|
+
|
8
|
+
def creator
|
9
|
+
''
|
10
|
+
end
|
11
|
+
|
12
|
+
def converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
13
|
+
end
|
14
|
+
|
15
|
+
def server_for(machine_spec)
|
16
|
+
if machine_spec.name
|
17
|
+
compute.servers.get(machine_spec.name)
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def servers_for(machine_specs)
|
24
|
+
result = {}
|
25
|
+
machine_specs.each do |machine_spec|
|
26
|
+
result[machine_spec] = server_for(machine_spec)
|
27
|
+
end
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
32
|
+
bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
|
33
|
+
bootstrap_options[:image_name] = 'debian-7-wheezy-v20150325'
|
34
|
+
bootstrap_options[:machine_type] = 'n1-standard-1'
|
35
|
+
bootstrap_options[:zone_name] = 'europe-west1-b'
|
36
|
+
bootstrap_options[:name] = machine_spec.name
|
37
|
+
|
38
|
+
if bootstrap_options[:disks].nil?
|
39
|
+
# create the persistent boot disk
|
40
|
+
disk_defaults = {
|
41
|
+
:name => machine_spec.name,
|
42
|
+
:size_gb => 10,
|
43
|
+
:zone_name => bootstrap_options[:zone_name],
|
44
|
+
:source_image => bootstrap_options[:image_name],
|
45
|
+
}
|
46
|
+
|
47
|
+
disk = compute.disks.create(disk_defaults)
|
48
|
+
disk.wait_for { disk.ready? }
|
49
|
+
bootstrap_options[:disks] = [disk]
|
50
|
+
end
|
51
|
+
|
52
|
+
bootstrap_options
|
53
|
+
end
|
54
|
+
|
55
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
56
|
+
server = server_for(machine_spec)
|
57
|
+
if server && server.state != 'archive'
|
58
|
+
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
|
59
|
+
server.destroy
|
60
|
+
end
|
61
|
+
end
|
62
|
+
machine_spec.location = nil
|
63
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
64
|
+
strategy.cleanup_convergence(action_handler, machine_spec)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.compute_options_for(provider, id, config)
|
68
|
+
new_compute_options = {}
|
69
|
+
new_compute_options[:provider] = provider
|
70
|
+
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
71
|
+
new_defaults = {
|
72
|
+
:driver_options => { :compute_options => {} },
|
73
|
+
:machine_options => { :bootstrap_options => {}, :ssh_options => {} }
|
74
|
+
}
|
75
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
76
|
+
|
77
|
+
[result, '']
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,376 @@
|
|
1
|
+
# fog:Vcair:<client id>
|
2
|
+
class Chef
|
3
|
+
module Provisioning
|
4
|
+
module FogDriver
|
5
|
+
module Providers
|
6
|
+
class Vcair < FogDriver::Driver
|
7
|
+
Driver.register_provider_class('Vcair', FogDriver::Providers::Vcair)
|
8
|
+
|
9
|
+
def creator
|
10
|
+
Chef::Config[:knife][:vcair_username]
|
11
|
+
end
|
12
|
+
|
13
|
+
def compute
|
14
|
+
@compute ||= begin
|
15
|
+
Chef::Log.debug("vcair_username #{Chef::Config[:knife][:vcair_username]}")
|
16
|
+
Chef::Log.debug("vcair_org #{Chef::Config[:knife][:vcair_org]}")
|
17
|
+
Chef::Log.debug("vcair_api_host #{Chef::Config[:knife][:vcair_api_host]}")
|
18
|
+
#Chef::Log.debug("vcair_api_version #{Chef::Config[:knife][:vcair_api_version]}")
|
19
|
+
Chef::Log.debug("vcair_show_progress #{Chef::Config[:knife][:vcair_show_progress]}")
|
20
|
+
|
21
|
+
username = [
|
22
|
+
Chef::Config[:knife][:vcair_username],
|
23
|
+
Chef::Config[:knife][:vcair_org]
|
24
|
+
].join('@')
|
25
|
+
|
26
|
+
@auth_params = {
|
27
|
+
:provider => 'vclouddirector', #TODO: see compute_options_for, and grab else where
|
28
|
+
:vcloud_director_username => username,
|
29
|
+
:vcloud_director_password => Chef::Config[:knife][:vcair_password],
|
30
|
+
:vcloud_director_host => Chef::Config[:knife][:vcair_api_host],
|
31
|
+
#:vcair_api_host => Chef::Config[:knife][:vcair_api_host],
|
32
|
+
:vcloud_director_api_version => Chef::Config[:knife][:vcair_api_version],
|
33
|
+
:vcloud_director_show_progress => false
|
34
|
+
}
|
35
|
+
|
36
|
+
Fog::Compute.new(@auth_params)
|
37
|
+
rescue Excon::Errors::Unauthorized => e
|
38
|
+
error_message = "Connection failure, please check your username and password."
|
39
|
+
Chef::Log.error(error_message)
|
40
|
+
raise "#{e.message}. #{error_message}"
|
41
|
+
rescue Excon::Errors::SocketError => e
|
42
|
+
error_message = "Connection failure, please check your authentication URL."
|
43
|
+
Chef::Log.error(error_message)
|
44
|
+
raise "#{e.message}. #{error_message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def create_many_servers(num_servers, bootstrap_options, parallelizer)
|
50
|
+
parallelizer.parallelize(1.upto(num_servers)) do |i|
|
51
|
+
clean_bootstrap_options = Marshal.load(Marshal.dump(bootstrap_options)) # Prevent destructive operations on bootstrap_options.
|
52
|
+
vm=nil
|
53
|
+
begin
|
54
|
+
instantiate(clean_bootstrap_options)
|
55
|
+
|
56
|
+
vapp = vdc.vapps.get_by_name(bootstrap_options[:name])
|
57
|
+
vm = vapp.vms.find {|v| v.vapp_name == bootstrap_options[:name]}
|
58
|
+
|
59
|
+
update_customization(clean_bootstrap_options, vm)
|
60
|
+
|
61
|
+
if bootstrap_options[:cpus]
|
62
|
+
vm.cpu = bootstrap_options[:cpus]
|
63
|
+
end
|
64
|
+
if bootstrap_options[:memory]
|
65
|
+
vm.memory = bootstrap_options[:memory]
|
66
|
+
end
|
67
|
+
update_network(bootstrap_options, vapp, vm)
|
68
|
+
|
69
|
+
rescue Excon::Errors::BadRequest => e
|
70
|
+
response = Chef::JSONCompat.from_json(e.response.body)
|
71
|
+
if response['badRequest']['code'] == 400
|
72
|
+
message = "Bad request (400): #{response['badRequest']['message']}"
|
73
|
+
Chef::Log.error(message)
|
74
|
+
else
|
75
|
+
message = "Unknown server error (#{response['badRequest']['code']}): #{response['badRequest']['message']}"
|
76
|
+
Chef::Log.error(message)
|
77
|
+
end
|
78
|
+
raise message
|
79
|
+
rescue Fog::Errors::Error => e
|
80
|
+
raise e.message
|
81
|
+
end
|
82
|
+
|
83
|
+
yield vm if block_given?
|
84
|
+
vm
|
85
|
+
|
86
|
+
end.to_a
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def start_server(action_handler, machine_spec, server)
|
91
|
+
|
92
|
+
# If it is stopping, wait for it to get out of "stopping" transition state before starting
|
93
|
+
if server.status == 'stopping'
|
94
|
+
action_handler.report_progress "wait for #{machine_spec.name} (#{server.id} on #{driver_url}) to finish stopping ..."
|
95
|
+
# vCloud Air
|
96
|
+
# NOTE: vCloud Air Fog does not get server.status via http every time
|
97
|
+
server.wait_for { server.reload ; server.status != 'stopping' }
|
98
|
+
action_handler.report_progress "#{machine_spec.name} is now stopped"
|
99
|
+
end
|
100
|
+
|
101
|
+
# NOTE: vCloud Air Fog does not get server.status via http every time
|
102
|
+
server.reload
|
103
|
+
|
104
|
+
if server.status == 'off' or server.status != 'on'
|
105
|
+
action_handler.perform_action "start machine #{machine_spec.name} (#{server.id} on #{driver_url})" do
|
106
|
+
server.power_on
|
107
|
+
machine_spec.location['started_at'] = Time.now.to_i
|
108
|
+
end
|
109
|
+
machine_spec.save(action_handler)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def server_for(machine_spec)
|
115
|
+
if machine_spec.location
|
116
|
+
vapp = vdc.vapps.get_by_name(machine_spec.name)
|
117
|
+
|
118
|
+
server = unless vapp.nil?
|
119
|
+
unless vapp.vms.first.nil?
|
120
|
+
vapp.vms.find{|vm| vm.id == machine_spec.location['server_id'] }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
else
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def servers_for(machine_specs)
|
129
|
+
result = {}
|
130
|
+
machine_specs.each do |machine_spec|
|
131
|
+
server_for(machine_spec)
|
132
|
+
end
|
133
|
+
result
|
134
|
+
end
|
135
|
+
|
136
|
+
def ssh_options_for(machine_spec, machine_options, server)
|
137
|
+
{ auth_methods: [ 'password' ],
|
138
|
+
timeout: (machine_options[:ssh_timeout] || 600),
|
139
|
+
password: machine_options[:ssh_password]
|
140
|
+
}.merge(machine_options[:ssh_options] || {})
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_ssh_transport(machine_spec, machine_options, server)
|
144
|
+
ssh_options = ssh_options_for(machine_spec, machine_options, server)
|
145
|
+
username = machine_spec.location['ssh_username'] || default_ssh_username
|
146
|
+
options = {}
|
147
|
+
if machine_spec.location[:sudo] || (!machine_spec.location.has_key?(:sudo) && username != 'root')
|
148
|
+
options[:prefix] = 'sudo '
|
149
|
+
end
|
150
|
+
|
151
|
+
remote_host = nil
|
152
|
+
# vCloud Air networking is funky
|
153
|
+
#if machine_options[:use_private_ip_for_ssh] # vCloud Air probably needs private ip for now
|
154
|
+
if server.ip_address
|
155
|
+
remote_host = server.ip_address
|
156
|
+
else
|
157
|
+
raise "Server #{server.id} has no private or public IP address!"
|
158
|
+
end
|
159
|
+
|
160
|
+
#Enable pty by default
|
161
|
+
options[:ssh_pty_enable] = true
|
162
|
+
options[:ssh_gateway] = machine_spec.location['ssh_gateway'] if machine_spec.location.has_key?('ssh_gateway')
|
163
|
+
|
164
|
+
Transport::SSH.new(remote_host, username, ssh_options, options, config)
|
165
|
+
end
|
166
|
+
|
167
|
+
def ready_machine(action_handler, machine_spec, machine_options)
|
168
|
+
server = server_for(machine_spec)
|
169
|
+
if server.nil?
|
170
|
+
raise "Machine #{machine_spec.name} does not have a server associated with it, or server does not exist."
|
171
|
+
end
|
172
|
+
|
173
|
+
# Start the server if needed, and wait for it to start
|
174
|
+
start_server(action_handler, machine_spec, server)
|
175
|
+
wait_until_ready(action_handler, machine_spec, machine_options, server)
|
176
|
+
|
177
|
+
# Attach/detach floating IPs if necessary
|
178
|
+
# vCloud Air is funky for network. VM has to be powered off or you get this error:
|
179
|
+
# Primary NIC cannot be changed when the VM is not in Powered-off state
|
180
|
+
# See code in update_network()
|
181
|
+
#DISABLED: converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
182
|
+
|
183
|
+
begin
|
184
|
+
wait_for_transport(action_handler, machine_spec, machine_options, server)
|
185
|
+
rescue Fog::Errors::TimeoutError
|
186
|
+
# Only ever reboot once, and only if it's been less than 10 minutes since we stopped waiting
|
187
|
+
if machine_spec.location['started_at'] || remaining_wait_time(machine_spec, machine_options) < -(10*60)
|
188
|
+
raise
|
189
|
+
else
|
190
|
+
# Sometimes (on EC2) the machine comes up but gets stuck or has
|
191
|
+
# some other problem. If this is the case, we restart the server
|
192
|
+
# to unstick it. Reboot covers a multitude of sins.
|
193
|
+
Chef::Log.warn "Machine #{machine_spec.name} (#{server.id} on #{driver_url}) was started but SSH did not come up. Rebooting machine in an attempt to unstick it ..."
|
194
|
+
restart_server(action_handler, machine_spec, server)
|
195
|
+
wait_until_ready(action_handler, machine_spec, machine_options, server)
|
196
|
+
wait_for_transport(action_handler, machine_spec, machine_options, server)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
machine_for(machine_spec, machine_options, server)
|
201
|
+
end
|
202
|
+
|
203
|
+
def org
|
204
|
+
@org ||= compute.organizations.get_by_name(Chef::Config[:knife][:vcair_org])
|
205
|
+
end
|
206
|
+
|
207
|
+
def vdc
|
208
|
+
if Chef::Config[:knife][:vcair_vdc]
|
209
|
+
@vdc ||= org.vdcs.get_by_name(Chef::Config[:knife][:vcair_vdc])
|
210
|
+
else
|
211
|
+
@vdc ||= org.vdcs.first
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def net
|
216
|
+
if Chef::Config[:knife][:vcair_net]
|
217
|
+
@net ||= org.networks.get_by_name(Chef::Config[:knife][:vcair_net])
|
218
|
+
else
|
219
|
+
# Grab first non-isolated (bridged, natRouted) network
|
220
|
+
@net ||= org.networks.find { |n| n if !n.fence_mode.match("isolated") }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def template(bootstrap_options)
|
225
|
+
# TODO: find by catalog item ID and/or NAME
|
226
|
+
# TODO: add option to search just public and/or private catalogs
|
227
|
+
|
228
|
+
#TODO: maybe make a hash for caching
|
229
|
+
org.catalogs.map do |cat|
|
230
|
+
#cat.catalog_items.get_by_name(config_value(:image))
|
231
|
+
cat.catalog_items.get_by_name(bootstrap_options[:image_name])
|
232
|
+
end.compact.first
|
233
|
+
end
|
234
|
+
|
235
|
+
def instantiate(bootstrap_options)
|
236
|
+
begin
|
237
|
+
#node_name = config_value(:chef_node_name)
|
238
|
+
node_name = bootstrap_options[:name]
|
239
|
+
template(bootstrap_options).instantiate(
|
240
|
+
node_name,
|
241
|
+
vdc_id: vdc.id,
|
242
|
+
network_id: net.id,
|
243
|
+
description: "id:#{node_name}")
|
244
|
+
#rescue CloudExceptions::ServerCreateError => e
|
245
|
+
rescue => e
|
246
|
+
raise e
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def update_customization(bootstrap_options, server)
|
251
|
+
## Initialization before first power on.
|
252
|
+
c=server.customization
|
253
|
+
|
254
|
+
if bootstrap_options[:customization_script]
|
255
|
+
c.script = open(bootstrap_options[:customization_script]).read
|
256
|
+
end
|
257
|
+
|
258
|
+
# TODO: check machine type and pick accordingly for Chef provisioning
|
259
|
+
# password = case config_value(:bootstrap_protocol)
|
260
|
+
# when 'winrm'
|
261
|
+
# config_value(:winrm_password)
|
262
|
+
# when 'ssh'
|
263
|
+
# config_value(:ssh_password)
|
264
|
+
# end
|
265
|
+
|
266
|
+
password = bootstrap_options[:ssh_options][:password]
|
267
|
+
if password
|
268
|
+
c.admin_password = password
|
269
|
+
c.admin_password_auto = false
|
270
|
+
c.reset_password_required = false
|
271
|
+
else
|
272
|
+
# Password will be autogenerated
|
273
|
+
c.admin_password_auto=true
|
274
|
+
# API will force password resets when auto is enabled
|
275
|
+
c.reset_password_required = true
|
276
|
+
end
|
277
|
+
|
278
|
+
# TODO: Add support for admin_auto_logon to Fog
|
279
|
+
# c.admin_auto_logon_count = 100
|
280
|
+
# c.admin_auto_logon_enabled = true
|
281
|
+
|
282
|
+
# DNS and Windows want AlphaNumeric and dashes for hostnames
|
283
|
+
# Windows can only handle 15 character hostnames
|
284
|
+
# TODO: only change name for Windows!
|
285
|
+
#c.computer_name = config_value(:chef_node_name).gsub(/\W/,"-").slice(0..14)
|
286
|
+
c.computer_name = bootstrap_options[:name].gsub(/\W/,"-").slice(0..14)
|
287
|
+
c.enabled = true
|
288
|
+
c.save
|
289
|
+
end
|
290
|
+
|
291
|
+
## vCloud Air
|
292
|
+
## TODO: make work with floating_ip junk currently used
|
293
|
+
## NOTE: current vCloud Air networking changes require VM to be powered off
|
294
|
+
def update_network(bootstrap_options, vapp, vm)
|
295
|
+
## TODO: allow user to specify network to connect to (see above net used)
|
296
|
+
# Define network connection for vm based on existing routed network
|
297
|
+
|
298
|
+
# vCloud Air inlining vapp() and vm()
|
299
|
+
#vapp = vdc.vapps.get_by_name(bootstrap_options[:name])
|
300
|
+
#vm = vapp.vms.find {|v| v.vapp_name == bootstrap_options[:name]}
|
301
|
+
nc = vapp.network_config.find { |n| n if n[:networkName].match(net.name) }
|
302
|
+
networks_config = [nc]
|
303
|
+
section = {PrimaryNetworkConnectionIndex: 0}
|
304
|
+
section[:NetworkConnection] = networks_config.compact.each_with_index.map do |network, i|
|
305
|
+
connection = {
|
306
|
+
network: network[:networkName],
|
307
|
+
needsCustomization: true,
|
308
|
+
NetworkConnectionIndex: i,
|
309
|
+
IsConnected: true
|
310
|
+
}
|
311
|
+
ip_address = network[:ip_address]
|
312
|
+
## TODO: support config options for allocation mode
|
313
|
+
#allocation_mode = network[:allocation_mode]
|
314
|
+
#allocation_mode = 'manual' if ip_address
|
315
|
+
#allocation_mode = 'dhcp' unless %w{dhcp manual pool}.include?(allocation_mode)
|
316
|
+
#allocation_mode = 'POOL'
|
317
|
+
#connection[:Dns1] = dns1 if dns1
|
318
|
+
allocation_mode = 'pool'
|
319
|
+
connection[:IpAddressAllocationMode] = allocation_mode.upcase
|
320
|
+
connection[:IpAddress] = ip_address if ip_address
|
321
|
+
connection
|
322
|
+
end
|
323
|
+
|
324
|
+
## attach the network to the vm
|
325
|
+
nc_task = compute.put_network_connection_system_section_vapp(
|
326
|
+
vm.id,section).body
|
327
|
+
compute.process_task(nc_task)
|
328
|
+
end
|
329
|
+
|
330
|
+
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
331
|
+
bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
|
332
|
+
|
333
|
+
bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
|
334
|
+
bootstrap_options[:name] ||= machine_spec.name
|
335
|
+
|
336
|
+
bootstrap_options = bootstrap_options.merge(machine_options.configs[1])
|
337
|
+
bootstrap_options
|
338
|
+
end
|
339
|
+
|
340
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
341
|
+
server = server_for(machine_spec)
|
342
|
+
if server && server.status != 'archive' # TODO: does vCloud Air do archive?
|
343
|
+
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
|
344
|
+
#NOTE: currently doing 1 vm for 1 vapp
|
345
|
+
vapp = vdc.vapps.get_by_name(machine_spec.name)
|
346
|
+
if vapp
|
347
|
+
vapp.power_off
|
348
|
+
vapp.undeploy
|
349
|
+
vapp.destroy
|
350
|
+
else
|
351
|
+
Chef::Log.warn "No VApp named '#{server_name}' was found."
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
machine_spec.location = nil
|
356
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
357
|
+
strategy.cleanup_convergence(action_handler, machine_spec)
|
358
|
+
end
|
359
|
+
|
360
|
+
def self.compute_options_for(provider, id, config)
|
361
|
+
new_compute_options = {}
|
362
|
+
new_compute_options[:provider] = 'vclouddirector'
|
363
|
+
new_config = { :driver_options => { :compute_options => new_compute_options }}
|
364
|
+
new_defaults = {
|
365
|
+
:driver_options => { :compute_options => {} },
|
366
|
+
:machine_options => { :bootstrap_options => {}, :ssh_options => {} }
|
367
|
+
}
|
368
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
369
|
+
|
370
|
+
[result, id]
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
@@ -8,7 +8,7 @@ describe Chef::Provisioning::FogDriver::Providers::Rackspace do
|
|
8
8
|
expect(subject).to be_an_instance_of Chef::Provisioning::FogDriver::Providers::Rackspace
|
9
9
|
end
|
10
10
|
|
11
|
-
it "has a
|
11
|
+
it "has a Fog backend" do
|
12
12
|
pending unless Fog.mock?
|
13
13
|
expect(subject.compute).to be_an_instance_of Fog::Compute::RackspaceV2::Mock
|
14
14
|
end
|
metadata
CHANGED
@@ -1,59 +1,48 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-fog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
8
|
+
- Chris McClimans
|
9
|
+
- Taylor Carpenter
|
10
|
+
- Wavell Watson
|
8
11
|
autorequire:
|
9
12
|
bindir: bin
|
10
13
|
cert_chain: []
|
11
|
-
date: 2015-
|
14
|
+
date: 2015-08-12 00:00:00.000000000 Z
|
12
15
|
dependencies:
|
13
16
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: chef
|
17
|
+
name: chef-provisioning
|
15
18
|
requirement: !ruby/object:Gem::Requirement
|
16
19
|
requirements:
|
17
|
-
- - "
|
20
|
+
- - "~>"
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
22
|
+
version: '1.0'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
29
|
+
version: '1.0'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
31
|
+
name: fog
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
30
33
|
requirements:
|
31
34
|
- - ">="
|
32
35
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
36
|
+
version: '0'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: chef-provisioning
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.0'
|
43
|
+
version: '0'
|
55
44
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
45
|
+
name: retryable
|
57
46
|
requirement: !ruby/object:Gem::Requirement
|
58
47
|
requirements:
|
59
48
|
- - ">="
|
@@ -95,7 +84,11 @@ dependencies:
|
|
95
84
|
- !ruby/object:Gem::Version
|
96
85
|
version: '0'
|
97
86
|
description: Driver for creating Fog instances in Chef Provisioning.
|
98
|
-
email:
|
87
|
+
email:
|
88
|
+
- jkeiser@getchef.com
|
89
|
+
- hh@vulk.co
|
90
|
+
- t@vulk.co
|
91
|
+
- w@vulk.co
|
99
92
|
executables: []
|
100
93
|
extensions: []
|
101
94
|
extra_rdoc_files:
|
@@ -112,10 +105,12 @@ files:
|
|
112
105
|
- lib/chef/provisioning/fog_driver/providers/aws/credentials.rb
|
113
106
|
- lib/chef/provisioning/fog_driver/providers/cloudstack.rb
|
114
107
|
- lib/chef/provisioning/fog_driver/providers/digitalocean.rb
|
108
|
+
- lib/chef/provisioning/fog_driver/providers/google.rb
|
115
109
|
- lib/chef/provisioning/fog_driver/providers/joyent.rb
|
116
110
|
- lib/chef/provisioning/fog_driver/providers/openstack.rb
|
117
111
|
- lib/chef/provisioning/fog_driver/providers/rackspace.rb
|
118
112
|
- lib/chef/provisioning/fog_driver/providers/softlayer.rb
|
113
|
+
- lib/chef/provisioning/fog_driver/providers/vcair.rb
|
119
114
|
- lib/chef/provisioning/fog_driver/recipe_dsl.rb
|
120
115
|
- lib/chef/provisioning/fog_driver/version.rb
|
121
116
|
- lib/chef/resource/fog_key_pair.rb
|
@@ -145,9 +140,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
140
|
version: '0'
|
146
141
|
requirements: []
|
147
142
|
rubyforge_project:
|
148
|
-
rubygems_version: 2.4.
|
143
|
+
rubygems_version: 2.4.7
|
149
144
|
signing_key:
|
150
145
|
specification_version: 4
|
151
146
|
summary: Driver for creating Fog instances in Chef Provisioning.
|
152
147
|
test_files: []
|
153
|
-
has_rdoc:
|