chef-provisioning-fog 0.15.0 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +11 -0
  3. data/LICENSE +201 -201
  4. data/README.md +208 -3
  5. data/Rakefile +6 -6
  6. data/chef-provisioning-fog.gemspec +28 -0
  7. data/lib/chef/provider/fog_key_pair.rb +266 -266
  8. data/lib/chef/provisioning/driver_init/fog.rb +3 -3
  9. data/lib/chef/provisioning/fog_driver/driver.rb +736 -736
  10. data/lib/chef/provisioning/fog_driver/providers/aws.rb +492 -492
  11. data/lib/chef/provisioning/fog_driver/providers/aws/credentials.rb +115 -115
  12. data/lib/chef/provisioning/fog_driver/providers/cloudstack.rb +44 -44
  13. data/lib/chef/provisioning/fog_driver/providers/digitalocean.rb +136 -136
  14. data/lib/chef/provisioning/fog_driver/providers/google.rb +85 -85
  15. data/lib/chef/provisioning/fog_driver/providers/joyent.rb +63 -63
  16. data/lib/chef/provisioning/fog_driver/providers/openstack.rb +117 -117
  17. data/lib/chef/provisioning/fog_driver/providers/rackspace.rb +42 -42
  18. data/lib/chef/provisioning/fog_driver/providers/softlayer.rb +36 -36
  19. data/lib/chef/provisioning/fog_driver/providers/vcair.rb +409 -409
  20. data/lib/chef/provisioning/fog_driver/providers/xenserver.rb +210 -210
  21. data/lib/chef/provisioning/fog_driver/recipe_dsl.rb +32 -32
  22. data/lib/chef/provisioning/fog_driver/version.rb +7 -7
  23. data/lib/chef/resource/fog_key_pair.rb +34 -34
  24. data/spec/spec_helper.rb +18 -18
  25. data/spec/support/aws/config-file.csv +2 -2
  26. data/spec/support/aws/ini-file.ini +10 -10
  27. data/spec/support/chef_metal_fog/providers/testdriver.rb +16 -16
  28. data/spec/unit/chef/provisioning/fog_driver/driver_spec.rb +71 -71
  29. data/spec/unit/fog_driver_spec.rb +32 -32
  30. data/spec/unit/providers/aws/credentials_spec.rb +45 -45
  31. data/spec/unit/providers/rackspace_spec.rb +16 -16
  32. metadata +5 -3
@@ -1,115 +1,115 @@
1
- require 'inifile'
2
- require 'csv'
3
- require 'chef/mixin/deep_merge'
4
-
5
- class Chef
6
- module Provisioning
7
- module FogDriver
8
- module Providers
9
- class AWS
10
- # Reads in a credentials file in Amazon's download format and presents the credentials to you
11
- class Credentials
12
- def initialize
13
- @credentials = {}
14
- end
15
-
16
- include Enumerable
17
- include Chef::Mixin::DeepMerge
18
-
19
- def default
20
- if @credentials.size == 0
21
- raise "No credentials loaded! Do you have one of ~/.aws/credentials or ~/.aws/config?"
22
- end
23
- @credentials[ENV['AWS_DEFAULT_PROFILE'] || 'default'] || @credentials.first[1]
24
- end
25
-
26
- def keys
27
- @credentials.keys
28
- end
29
-
30
- def [](name)
31
- @credentials[name]
32
- end
33
-
34
- def each(&block)
35
- @credentials.each(&block)
36
- end
37
-
38
- def load_inis(config_ini_file, credentials_ini_file = nil)
39
- @credentials = load_config_ini(config_ini_file)
40
- @credentials = deep_merge!(@credentials,
41
- load_credentials_ini(credentials_ini_file)
42
- ) if credentials_ini_file
43
- end
44
-
45
- def load_config_ini(config_ini_file)
46
- inifile = IniFile.load(File.expand_path(config_ini_file))
47
- config = {}
48
- if inifile
49
- inifile.each_section do |section|
50
- if section =~ /^\s*profile\s+(.+)$/ || section =~ /^\s*(default)\s*/
51
- profile_name = $1.strip
52
- profile = inifile[section].inject({}) do |result, pair|
53
- result[pair[0].to_sym] = pair[1]
54
- result
55
- end
56
- profile[:name] = profile_name
57
- config[profile_name] = profile
58
- end
59
- end
60
- end
61
- config
62
- end
63
-
64
- def load_credentials_ini(credentials_ini_file)
65
- inifile = IniFile.load(File.expand_path(credentials_ini_file))
66
- config = {}
67
- if inifile
68
- inifile.each_section do |section|
69
- profile = inifile[section].inject({}) do |result, pair|
70
- result[pair[0].to_sym] = pair[1]
71
- result
72
- end
73
- profile[:name] = section
74
- config[section] = profile
75
- end
76
- end
77
- config
78
- end
79
-
80
- def load_csv(credentials_csv_file)
81
- CSV.new(File.open(credentials_csv_file), :headers => :first_row).each do |row|
82
- @credentials[row['User Name']] = {
83
- :name => row['User Name'],
84
- :user_name => row['User Name'],
85
- :aws_access_key_id => row['Access Key Id'],
86
- :aws_secret_access_key => row['Secret Access Key']
87
- }
88
- end
89
- end
90
-
91
- def load_default
92
- config_file = ENV['AWS_CONFIG_FILE'] || File.expand_path('~/.aws/config')
93
- credentials_file = ENV['AWS_CREDENTIAL_FILE'] || File.expand_path('~/.aws/credentials')
94
- if File.file?(config_file)
95
- if File.file?(credentials_file)
96
- load_inis(config_file, credentials_file)
97
- else
98
- load_inis(config_file)
99
- end
100
- end
101
- end
102
-
103
- def self.method_missing(name, *args, &block)
104
- singleton.send(name, *args, &block)
105
- end
106
-
107
- def self.singleton
108
- @aws_credentials ||= Credentials.new
109
- end
110
- end
111
- end
112
- end
113
- end
114
- end
115
- end
1
+ require 'inifile'
2
+ require 'csv'
3
+ require 'chef/mixin/deep_merge'
4
+
5
+ class Chef
6
+ module Provisioning
7
+ module FogDriver
8
+ module Providers
9
+ class AWS
10
+ # Reads in a credentials file in Amazon's download format and presents the credentials to you
11
+ class Credentials
12
+ def initialize
13
+ @credentials = {}
14
+ end
15
+
16
+ include Enumerable
17
+ include Chef::Mixin::DeepMerge
18
+
19
+ def default
20
+ if @credentials.size == 0
21
+ raise "No credentials loaded! Do you have one of ~/.aws/credentials or ~/.aws/config?"
22
+ end
23
+ @credentials[ENV['AWS_DEFAULT_PROFILE'] || 'default'] || @credentials.first[1]
24
+ end
25
+
26
+ def keys
27
+ @credentials.keys
28
+ end
29
+
30
+ def [](name)
31
+ @credentials[name]
32
+ end
33
+
34
+ def each(&block)
35
+ @credentials.each(&block)
36
+ end
37
+
38
+ def load_inis(config_ini_file, credentials_ini_file = nil)
39
+ @credentials = load_config_ini(config_ini_file)
40
+ @credentials = deep_merge!(@credentials,
41
+ load_credentials_ini(credentials_ini_file)
42
+ ) if credentials_ini_file
43
+ end
44
+
45
+ def load_config_ini(config_ini_file)
46
+ inifile = IniFile.load(File.expand_path(config_ini_file))
47
+ config = {}
48
+ if inifile
49
+ inifile.each_section do |section|
50
+ if section =~ /^\s*profile\s+(.+)$/ || section =~ /^\s*(default)\s*/
51
+ profile_name = $1.strip
52
+ profile = inifile[section].inject({}) do |result, pair|
53
+ result[pair[0].to_sym] = pair[1]
54
+ result
55
+ end
56
+ profile[:name] = profile_name
57
+ config[profile_name] = profile
58
+ end
59
+ end
60
+ end
61
+ config
62
+ end
63
+
64
+ def load_credentials_ini(credentials_ini_file)
65
+ inifile = IniFile.load(File.expand_path(credentials_ini_file))
66
+ config = {}
67
+ if inifile
68
+ inifile.each_section do |section|
69
+ profile = inifile[section].inject({}) do |result, pair|
70
+ result[pair[0].to_sym] = pair[1]
71
+ result
72
+ end
73
+ profile[:name] = section
74
+ config[section] = profile
75
+ end
76
+ end
77
+ config
78
+ end
79
+
80
+ def load_csv(credentials_csv_file)
81
+ CSV.new(File.open(credentials_csv_file), :headers => :first_row).each do |row|
82
+ @credentials[row['User Name']] = {
83
+ :name => row['User Name'],
84
+ :user_name => row['User Name'],
85
+ :aws_access_key_id => row['Access Key Id'],
86
+ :aws_secret_access_key => row['Secret Access Key']
87
+ }
88
+ end
89
+ end
90
+
91
+ def load_default
92
+ config_file = ENV['AWS_CONFIG_FILE'] || File.expand_path('~/.aws/config')
93
+ credentials_file = ENV['AWS_CREDENTIAL_FILE'] || File.expand_path('~/.aws/credentials')
94
+ if File.file?(config_file)
95
+ if File.file?(credentials_file)
96
+ load_inis(config_file, credentials_file)
97
+ else
98
+ load_inis(config_file)
99
+ end
100
+ end
101
+ end
102
+
103
+ def self.method_missing(name, *args, &block)
104
+ singleton.send(name, *args, &block)
105
+ end
106
+
107
+ def self.singleton
108
+ @aws_credentials ||= Credentials.new
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,44 +1,44 @@
1
- class Chef
2
- module Provisioning
3
- module FogDriver
4
- module Providers
5
- class CloudStack < FogDriver::Driver
6
-
7
- Driver.register_provider_class('CloudStack', FogDriver::Providers::CloudStack)
8
-
9
- def creator
10
- ''
11
- end
12
-
13
- def self.compute_options_for(provider, id, config)
14
- new_compute_options = {}
15
- new_compute_options[:provider] = provider
16
- new_config = { :driver_options => { :compute_options => new_compute_options }}
17
- new_defaults = {
18
- :driver_options => { :compute_options => {} },
19
- :machine_options => { :bootstrap_options => {} }
20
- }
21
- result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
22
-
23
- if id && id != ''
24
- cloudstack_uri = URI.parse(id)
25
- new_compute_options[:cloudstack_scheme] = cloudstack_uri.scheme
26
- new_compute_options[:cloudstack_host] = cloudstack_uri.host
27
- new_compute_options[:cloudstack_port] = cloudstack_uri.port
28
- new_compute_options[:cloudstack_path] = cloudstack_uri.path
29
- end
30
-
31
- host = result[:driver_options][:compute_options][:cloudstack_host]
32
- path = result[:driver_options][:compute_options][:cloudstack_path] || '/client/api'
33
- port = result[:driver_options][:compute_options][:cloudstack_port] || 443
34
- scheme = result[:driver_options][:compute_options][:cloudstack_scheme] || 'https'
35
- id = URI.scheme_list[scheme.upcase].build(:host => host, :port => port, :path => path).to_s
36
-
37
- [result, id]
38
- end
39
-
40
- end
41
- end
42
- end
43
- end
44
- end
1
+ class Chef
2
+ module Provisioning
3
+ module FogDriver
4
+ module Providers
5
+ class CloudStack < FogDriver::Driver
6
+
7
+ Driver.register_provider_class('CloudStack', FogDriver::Providers::CloudStack)
8
+
9
+ def creator
10
+ ''
11
+ end
12
+
13
+ def self.compute_options_for(provider, id, config)
14
+ new_compute_options = {}
15
+ new_compute_options[:provider] = provider
16
+ new_config = { :driver_options => { :compute_options => new_compute_options }}
17
+ new_defaults = {
18
+ :driver_options => { :compute_options => {} },
19
+ :machine_options => { :bootstrap_options => {} }
20
+ }
21
+ result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
22
+
23
+ if id && id != ''
24
+ cloudstack_uri = URI.parse(id)
25
+ new_compute_options[:cloudstack_scheme] = cloudstack_uri.scheme
26
+ new_compute_options[:cloudstack_host] = cloudstack_uri.host
27
+ new_compute_options[:cloudstack_port] = cloudstack_uri.port
28
+ new_compute_options[:cloudstack_path] = cloudstack_uri.path
29
+ end
30
+
31
+ host = result[:driver_options][:compute_options][:cloudstack_host]
32
+ path = result[:driver_options][:compute_options][:cloudstack_path] || '/client/api'
33
+ port = result[:driver_options][:compute_options][:cloudstack_port] || 443
34
+ scheme = result[:driver_options][:compute_options][:cloudstack_scheme] || 'https'
35
+ id = URI.scheme_list[scheme.upcase].build(:host => host, :port => port, :path => path).to_s
36
+
37
+ [result, id]
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,136 +1,136 @@
1
- # fog:DigitalOcean:<client id>
2
- class Chef
3
- module Provisioning
4
- module FogDriver
5
- module Providers
6
- class DigitalOcean < FogDriver::Driver
7
- Driver.register_provider_class('DigitalOcean', FogDriver::Providers::DigitalOcean)
8
-
9
- def creator
10
- ''
11
- end
12
-
13
- def converge_floating_ips(action_handler, machine_spec, machine_options, server)
14
- # DigitalOcean does not have floating IPs
15
- end
16
-
17
- def bootstrap_options_for(action_handler, machine_spec, machine_options)
18
- bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
19
- if bootstrap_options[:key_path]
20
- bootstrap_options[:key_name] ||= File.basename(bootstrap_options[:key_path])
21
- # Verify that the provided key name and path are in line (or create the key pair if not!)
22
- driver = self
23
- Provisioning.inline_resource(action_handler) do
24
- fog_key_pair bootstrap_options[:key_name] do
25
- private_key_path bootstrap_options[:key_path]
26
- driver driver
27
- end
28
- end
29
- else
30
- bootstrap_options[:key_name] = overwrite_default_key_willy_nilly(action_handler, machine_spec)
31
- end
32
-
33
- bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
34
-
35
- if !bootstrap_options[:image_id]
36
- if !bootstrap_options[:image_distribution] && !bootstrap_options[:image_name]
37
- bootstrap_options[:image_distribution] = 'CentOS'
38
- bootstrap_options[:image_name] = '6.5 x64'
39
- end
40
- distributions = compute.images.select { |image| image.distribution == bootstrap_options[:image_distribution] }
41
- if distributions.empty?
42
- raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect}"
43
- end
44
- images = distributions.select { |image| image.name == bootstrap_options[:image_name] } if bootstrap_options[:image_name]
45
- if images.empty?
46
- raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect} and name #{bootstrap_options[:image_name].inspect}"
47
- end
48
- bootstrap_options[:image_id] = images.first.id
49
- end
50
- if !bootstrap_options[:flavor_id]
51
- bootstrap_options[:flavor_name] ||= '512MB'
52
- flavors = compute.flavors.select do |f|
53
- f.name == bootstrap_options[:flavor_name]
54
- end
55
- if flavors.empty?
56
- raise "Could not find flavor named '#{bootstrap_options[:flavor_name]}' on #{driver_url}"
57
- end
58
- bootstrap_options[:flavor_id] = flavors.first.id
59
- end
60
- if !bootstrap_options[:region_id]
61
- bootstrap_options[:region_name] ||= 'San Francisco 1'
62
- regions = compute.regions.select { |region| region.name == bootstrap_options[:region_name] }
63
- if regions.empty?
64
- raise "Could not find region named '#{bootstrap_options[:region_name]}' on #{driver_url}"
65
- end
66
- bootstrap_options[:region_id] = regions.first.id
67
- end
68
- keys = compute.ssh_keys.select { |k| k.name == bootstrap_options[:key_name] }
69
- if keys.empty?
70
- raise "Could not find key named '#{bootstrap_options[:key_name]}' on #{driver_url}"
71
- end
72
- found_key = keys.first
73
- bootstrap_options[:ssh_key_ids] ||= [ found_key.id ]
74
-
75
- # You don't get to specify name yourself
76
- bootstrap_options[:name] = machine_spec.name
77
-
78
- bootstrap_options
79
- end
80
-
81
- def destroy_machine(action_handler, machine_spec, machine_options)
82
- server = server_for(machine_spec)
83
- if server && server.state != 'archive'
84
- action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
85
- server.destroy
86
- end
87
- end
88
- machine_spec.location = nil
89
- strategy = convergence_strategy_for(machine_spec, machine_options)
90
- strategy.cleanup_convergence(action_handler, machine_spec)
91
- end
92
-
93
- def self.compute_options_for(provider, id, config)
94
- new_compute_options = {}
95
- new_compute_options[:provider] = provider
96
- new_config = { :driver_options => { :compute_options => new_compute_options }}
97
- new_defaults = {
98
- :driver_options => { :compute_options => {} },
99
- :machine_options => { :bootstrap_options => {}, :ssh_options => {} }
100
- }
101
- result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
102
-
103
- new_compute_options[:digitalocean_client_id] = id if (id && id != '')
104
-
105
- # This uses ~/.tugboat, generated by "tugboat authorize" - see https://github.com/pearkes/tugboat
106
- tugboat_file = File.expand_path('~/.tugboat')
107
- if File.exist?(tugboat_file)
108
- tugboat_data = YAML.load(IO.read(tugboat_file))
109
-
110
- new_bootstrap_options = new_defaults[:machine_options][:bootstrap_options]
111
- if tugboat_data['authentication']
112
- new_compute_options[:digitalocean_client_id] = tugboat_data['authentication']['client_key'] if tugboat_data['authentication']['client_key'] && tugboat_data['authentication']['client_key'].size > 0
113
- new_compute_options[:digitalocean_api_key] = tugboat_data['authentication']['api_key'] if tugboat_data['authentication']['api_key'] && tugboat_data['authentication']['api_key'].size > 0
114
- end
115
- if tugboat_data['defaults']
116
- new_bootstrap_options[:region_id] = tugboat_data['defaults']['region'].to_i if tugboat_data['defaults']['region'] && tugboat_data['defaults']['region'].size > 0
117
- new_bootstrap_options[:image_id] = tugboat_data['defaults']['image'].to_i if tugboat_data['defaults']['image'] && tugboat_data['defaults']['image'].size > 0
118
- new_bootstrap_options[:size_id] = tugboat_data['defaults']['size'].to_i if tugboat_data['defaults']['size'] && tugboat_data['defaults']['size'].size > 0
119
- new_bootstrap_options[:private_networking] = (tugboat_data['defaults']['private_networking'] == 'true') if tugboat_data['defaults']['private_networking'] && tugboat_data['defaults']['private_networking'].size > 0
120
- new_bootstrap_options[:backups_enabled] = (tugboat_data['defaults']['backups_enabled'] == 'true') if tugboat_data['defaults']['backups_enabled'] && tugboat_data['defaults']['backups_enabled'].size > 0
121
- new_bootstrap_options[:key_name] = tugboat_data['defaults']['ssh_key'] if tugboat_data['defaults']['ssh_key'] && tugboat_data['defaults']['ssh_key'].size > 0
122
- end
123
- if tugboat_data['ssh']
124
- new_bootstrap_options[:key_path] = tugboat_data['ssh']['ssh_key_path'] if tugboat_data['ssh']['ssh_key_path'] && tugboat_data['ssh']['ssh_key_path'].size > 0
125
- new_defaults[:machine_options][:ssh_options][:port] = tugboat_data['ssh']['ssh_port'] if tugboat_data['ssh']['ssh_port'] if tugboat_data['ssh']['ssh_port'].size > 0
126
- end
127
- end
128
-
129
- [result, new_compute_options[:digitalocean_client_id]]
130
- end
131
-
132
- end
133
- end
134
- end
135
- end
136
- end
1
+ # fog:DigitalOcean:<client id>
2
+ class Chef
3
+ module Provisioning
4
+ module FogDriver
5
+ module Providers
6
+ class DigitalOcean < FogDriver::Driver
7
+ Driver.register_provider_class('DigitalOcean', FogDriver::Providers::DigitalOcean)
8
+
9
+ def creator
10
+ ''
11
+ end
12
+
13
+ def converge_floating_ips(action_handler, machine_spec, machine_options, server)
14
+ # DigitalOcean does not have floating IPs
15
+ end
16
+
17
+ def bootstrap_options_for(action_handler, machine_spec, machine_options)
18
+ bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
19
+ if bootstrap_options[:key_path]
20
+ bootstrap_options[:key_name] ||= File.basename(bootstrap_options[:key_path])
21
+ # Verify that the provided key name and path are in line (or create the key pair if not!)
22
+ driver = self
23
+ Provisioning.inline_resource(action_handler) do
24
+ fog_key_pair bootstrap_options[:key_name] do
25
+ private_key_path bootstrap_options[:key_path]
26
+ driver driver
27
+ end
28
+ end
29
+ else
30
+ bootstrap_options[:key_name] = overwrite_default_key_willy_nilly(action_handler, machine_spec)
31
+ end
32
+
33
+ bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
34
+
35
+ if !bootstrap_options[:image_id]
36
+ if !bootstrap_options[:image_distribution] && !bootstrap_options[:image_name]
37
+ bootstrap_options[:image_distribution] = 'CentOS'
38
+ bootstrap_options[:image_name] = '6.5 x64'
39
+ end
40
+ distributions = compute.images.select { |image| image.distribution == bootstrap_options[:image_distribution] }
41
+ if distributions.empty?
42
+ raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect}"
43
+ end
44
+ images = distributions.select { |image| image.name == bootstrap_options[:image_name] } if bootstrap_options[:image_name]
45
+ if images.empty?
46
+ raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect} and name #{bootstrap_options[:image_name].inspect}"
47
+ end
48
+ bootstrap_options[:image_id] = images.first.id
49
+ end
50
+ if !bootstrap_options[:flavor_id]
51
+ bootstrap_options[:flavor_name] ||= '512MB'
52
+ flavors = compute.flavors.select do |f|
53
+ f.name == bootstrap_options[:flavor_name]
54
+ end
55
+ if flavors.empty?
56
+ raise "Could not find flavor named '#{bootstrap_options[:flavor_name]}' on #{driver_url}"
57
+ end
58
+ bootstrap_options[:flavor_id] = flavors.first.id
59
+ end
60
+ if !bootstrap_options[:region_id]
61
+ bootstrap_options[:region_name] ||= 'San Francisco 1'
62
+ regions = compute.regions.select { |region| region.name == bootstrap_options[:region_name] }
63
+ if regions.empty?
64
+ raise "Could not find region named '#{bootstrap_options[:region_name]}' on #{driver_url}"
65
+ end
66
+ bootstrap_options[:region_id] = regions.first.id
67
+ end
68
+ keys = compute.ssh_keys.select { |k| k.name == bootstrap_options[:key_name] }
69
+ if keys.empty?
70
+ raise "Could not find key named '#{bootstrap_options[:key_name]}' on #{driver_url}"
71
+ end
72
+ found_key = keys.first
73
+ bootstrap_options[:ssh_key_ids] ||= [ found_key.id ]
74
+
75
+ # You don't get to specify name yourself
76
+ bootstrap_options[:name] = machine_spec.name
77
+
78
+ bootstrap_options
79
+ end
80
+
81
+ def destroy_machine(action_handler, machine_spec, machine_options)
82
+ server = server_for(machine_spec)
83
+ if server && server.state != 'archive'
84
+ action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
85
+ server.destroy
86
+ end
87
+ end
88
+ machine_spec.location = nil
89
+ strategy = convergence_strategy_for(machine_spec, machine_options)
90
+ strategy.cleanup_convergence(action_handler, machine_spec)
91
+ end
92
+
93
+ def self.compute_options_for(provider, id, config)
94
+ new_compute_options = {}
95
+ new_compute_options[:provider] = provider
96
+ new_config = { :driver_options => { :compute_options => new_compute_options }}
97
+ new_defaults = {
98
+ :driver_options => { :compute_options => {} },
99
+ :machine_options => { :bootstrap_options => {}, :ssh_options => {} }
100
+ }
101
+ result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
102
+
103
+ new_compute_options[:digitalocean_client_id] = id if (id && id != '')
104
+
105
+ # This uses ~/.tugboat, generated by "tugboat authorize" - see https://github.com/pearkes/tugboat
106
+ tugboat_file = File.expand_path('~/.tugboat')
107
+ if File.exist?(tugboat_file)
108
+ tugboat_data = YAML.load(IO.read(tugboat_file))
109
+
110
+ new_bootstrap_options = new_defaults[:machine_options][:bootstrap_options]
111
+ if tugboat_data['authentication']
112
+ new_compute_options[:digitalocean_client_id] = tugboat_data['authentication']['client_key'] if tugboat_data['authentication']['client_key'] && tugboat_data['authentication']['client_key'].size > 0
113
+ new_compute_options[:digitalocean_api_key] = tugboat_data['authentication']['api_key'] if tugboat_data['authentication']['api_key'] && tugboat_data['authentication']['api_key'].size > 0
114
+ end
115
+ if tugboat_data['defaults']
116
+ new_bootstrap_options[:region_id] = tugboat_data['defaults']['region'].to_i if tugboat_data['defaults']['region'] && tugboat_data['defaults']['region'].size > 0
117
+ new_bootstrap_options[:image_id] = tugboat_data['defaults']['image'].to_i if tugboat_data['defaults']['image'] && tugboat_data['defaults']['image'].size > 0
118
+ new_bootstrap_options[:size_id] = tugboat_data['defaults']['size'].to_i if tugboat_data['defaults']['size'] && tugboat_data['defaults']['size'].size > 0
119
+ new_bootstrap_options[:private_networking] = (tugboat_data['defaults']['private_networking'] == 'true') if tugboat_data['defaults']['private_networking'] && tugboat_data['defaults']['private_networking'].size > 0
120
+ new_bootstrap_options[:backups_enabled] = (tugboat_data['defaults']['backups_enabled'] == 'true') if tugboat_data['defaults']['backups_enabled'] && tugboat_data['defaults']['backups_enabled'].size > 0
121
+ new_bootstrap_options[:key_name] = tugboat_data['defaults']['ssh_key'] if tugboat_data['defaults']['ssh_key'] && tugboat_data['defaults']['ssh_key'].size > 0
122
+ end
123
+ if tugboat_data['ssh']
124
+ new_bootstrap_options[:key_path] = tugboat_data['ssh']['ssh_key_path'] if tugboat_data['ssh']['ssh_key_path'] && tugboat_data['ssh']['ssh_key_path'].size > 0
125
+ new_defaults[:machine_options][:ssh_options][:port] = tugboat_data['ssh']['ssh_port'] if tugboat_data['ssh']['ssh_port'] if tugboat_data['ssh']['ssh_port'].size > 0
126
+ end
127
+ end
128
+
129
+ [result, new_compute_options[:digitalocean_client_id]]
130
+ end
131
+
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end