chef-provisioning-fog 0.13.2 → 0.14.0
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 +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:
|