chef-provisioning-fog 0.26.1 → 0.26.3
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/Gemfile +29 -8
- data/Rakefile +23 -12
- data/chef-provisioning-fog.gemspec +24 -27
- data/lib/chef/provider/fog_key_pair.rb +49 -53
- data/lib/chef/provider/scaleway_volume.rb +46 -48
- data/lib/chef/provisioning/driver_init/fog.rb +1 -1
- data/lib/chef/provisioning/fog_driver/driver.rb +646 -653
- data/lib/chef/provisioning/fog_driver/providers/aws.rb +411 -422
- data/lib/chef/provisioning/fog_driver/providers/aws/credentials.rb +88 -90
- data/lib/chef/provisioning/fog_driver/providers/cloudstack.rb +32 -34
- data/lib/chef/provisioning/fog_driver/providers/digitalocean.rb +98 -100
- data/lib/chef/provisioning/fog_driver/providers/google.rb +27 -34
- data/lib/chef/provisioning/fog_driver/providers/joyent.rb +53 -55
- data/lib/chef/provisioning/fog_driver/providers/openstack.rb +139 -146
- data/lib/chef/provisioning/fog_driver/providers/rackspace.rb +40 -44
- data/lib/chef/provisioning/fog_driver/providers/scaleway.rb +183 -189
- data/lib/chef/provisioning/fog_driver/providers/softlayer.rb +61 -64
- data/lib/chef/provisioning/fog_driver/providers/vcair.rb +72 -78
- data/lib/chef/provisioning/fog_driver/providers/xenserver.rb +56 -69
- data/lib/chef/provisioning/fog_driver/recipe_dsl.rb +11 -12
- data/lib/chef/provisioning/fog_driver/version.rb +1 -1
- data/lib/chef/resource/fog_key_pair.rb +8 -8
- data/lib/chef/resource/scaleway_volume.rb +8 -8
- data/spec/spec_helper.rb +7 -7
- data/spec/support/chef/provisioning/fog_driver/providers/testdriver.rb +3 -3
- data/spec/unit/chef/provisioning/fog_driver/driver_spec.rb +39 -38
- data/spec/unit/fog_driver_spec.rb +6 -8
- data/spec/unit/providers/aws/credentials_spec.rb +10 -10
- data/spec/unit/providers/rackspace_spec.rb +5 -6
- data/spec/unit/providers/scaleway_spec.rb +9 -9
- data/spec/unit/providers/softlayer.rb +7 -7
- metadata +6 -36
- data/README.md +0 -357
@@ -1,115 +1,113 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "inifile"
|
2
|
+
require "csv"
|
3
|
+
require "chef/mixin/deep_merge"
|
4
4
|
|
5
5
|
class Chef
|
6
|
-
module Provisioning
|
7
|
-
module FogDriver
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
15
|
|
16
|
-
|
17
|
-
|
16
|
+
include Enumerable
|
17
|
+
include Chef::Mixin::DeepMerge
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def default
|
20
|
+
if @credentials.empty?
|
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
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
def keys
|
27
|
+
@credentials.keys
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def [](name)
|
31
|
+
@credentials[name]
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
def each(&block)
|
35
|
+
@credentials.each(&block)
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
def load_inis(config_ini_file, credentials_ini_file = nil)
|
39
|
+
@credentials = load_config_ini(config_ini_file)
|
40
|
+
if credentials_ini_file
|
41
|
+
@credentials = deep_merge!(@credentials,
|
42
|
+
load_credentials_ini(credentials_ini_file))
|
43
|
+
end
|
44
|
+
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
46
|
+
def load_config_ini(config_ini_file)
|
47
|
+
inifile = IniFile.load(File.expand_path(config_ini_file))
|
48
|
+
config = {}
|
49
|
+
if inifile
|
50
|
+
inifile.each_section do |section|
|
51
|
+
next unless section =~ /^\s*profile\s+(.+)$/ || section =~ /^\s*(default)\s*/
|
52
|
+
profile_name = Regexp.last_match(1).strip
|
53
|
+
profile = inifile[section].each_with_object({}) do |pair, result|
|
54
|
+
result[pair[0].to_sym] = pair[1]
|
55
|
+
end
|
56
|
+
profile[:name] = profile_name
|
57
|
+
config[profile_name] = profile
|
55
58
|
end
|
56
|
-
profile[:name] = profile_name
|
57
|
-
config[profile_name] = profile
|
58
59
|
end
|
60
|
+
config
|
59
61
|
end
|
60
|
-
end
|
61
|
-
config
|
62
|
-
end
|
63
62
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
def load_credentials_ini(credentials_ini_file)
|
64
|
+
inifile = IniFile.load(File.expand_path(credentials_ini_file))
|
65
|
+
config = {}
|
66
|
+
if inifile
|
67
|
+
inifile.each_section do |section|
|
68
|
+
profile = inifile[section].each_with_object({}) do |pair, result|
|
69
|
+
result[pair[0].to_sym] = pair[1]
|
70
|
+
end
|
71
|
+
profile[:name] = section
|
72
|
+
config[section] = profile
|
73
|
+
end
|
72
74
|
end
|
73
|
-
|
74
|
-
config[section] = profile
|
75
|
+
config
|
75
76
|
end
|
76
|
-
end
|
77
|
-
config
|
78
|
-
end
|
79
77
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
78
|
+
def load_csv(credentials_csv_file)
|
79
|
+
CSV.new(File.open(credentials_csv_file), headers: :first_row).each do |row|
|
80
|
+
@credentials[row["User Name"]] = {
|
81
|
+
name: row["User Name"],
|
82
|
+
user_name: row["User Name"],
|
83
|
+
aws_access_key_id: row["Access Key Id"],
|
84
|
+
aws_secret_access_key: row["Secret Access Key"]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
89
|
+
def load_default
|
90
|
+
config_file = ENV["AWS_CONFIG_FILE"] || File.expand_path("~/.aws/config")
|
91
|
+
credentials_file = ENV["AWS_CREDENTIAL_FILE"] || File.expand_path("~/.aws/credentials")
|
92
|
+
if File.file?(config_file)
|
93
|
+
if File.file?(credentials_file)
|
94
|
+
load_inis(config_file, credentials_file)
|
95
|
+
else
|
96
|
+
load_inis(config_file)
|
97
|
+
end
|
98
|
+
end
|
99
99
|
end
|
100
|
-
end
|
101
|
-
end
|
102
100
|
|
103
|
-
|
104
|
-
|
105
|
-
|
101
|
+
def self.method_missing(name, *args, &block)
|
102
|
+
singleton.send(name, *args, &block)
|
103
|
+
end
|
106
104
|
|
107
|
-
|
108
|
-
|
105
|
+
def self.singleton
|
106
|
+
@aws_credentials ||= Credentials.new
|
107
|
+
end
|
108
|
+
end
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,44 +1,42 @@
|
|
1
1
|
class Chef
|
2
|
-
module Provisioning
|
3
|
-
module FogDriver
|
4
|
-
|
5
|
-
|
2
|
+
module Provisioning
|
3
|
+
module FogDriver
|
4
|
+
module Providers
|
5
|
+
class CloudStack < FogDriver::Driver
|
6
|
+
Driver.register_provider_class("CloudStack", FogDriver::Providers::CloudStack)
|
6
7
|
|
7
|
-
|
8
|
+
def creator
|
9
|
+
""
|
10
|
+
end
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
:driver_options => { :compute_options => {} },
|
19
|
-
:machine_options => { :bootstrap_options => {} }
|
20
|
-
}
|
21
|
-
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
12
|
+
def self.compute_options_for(provider, id, config)
|
13
|
+
new_compute_options = {}
|
14
|
+
new_compute_options[:provider] = provider
|
15
|
+
new_config = { driver_options: { compute_options: new_compute_options } }
|
16
|
+
new_defaults = {
|
17
|
+
driver_options: { compute_options: {} },
|
18
|
+
machine_options: { bootstrap_options: {} }
|
19
|
+
}
|
20
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
if id && id != ""
|
23
|
+
cloudstack_uri = URI.parse(id)
|
24
|
+
new_compute_options[:cloudstack_scheme] = cloudstack_uri.scheme
|
25
|
+
new_compute_options[:cloudstack_host] = cloudstack_uri.host
|
26
|
+
new_compute_options[:cloudstack_port] = cloudstack_uri.port
|
27
|
+
new_compute_options[:cloudstack_path] = cloudstack_uri.path
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
host = result[:driver_options][:compute_options][:cloudstack_host]
|
31
|
+
path = result[:driver_options][:compute_options][:cloudstack_path] || "/client/api"
|
32
|
+
port = result[:driver_options][:compute_options][:cloudstack_port] || 443
|
33
|
+
scheme = result[:driver_options][:compute_options][:cloudstack_scheme] || "https"
|
34
|
+
id = URI.scheme_list[scheme.upcase].build(host: host, port: port, path: path).to_s
|
36
35
|
|
37
|
-
|
36
|
+
[result, id]
|
37
|
+
end
|
38
|
+
end
|
38
39
|
end
|
39
|
-
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,119 +1,117 @@
|
|
1
1
|
# fog:DigitalOcean:<client id>
|
2
2
|
class Chef
|
3
|
-
module Provisioning
|
4
|
-
module FogDriver
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Provisioning
|
4
|
+
module FogDriver
|
5
|
+
module Providers
|
6
|
+
class DigitalOcean < FogDriver::Driver
|
7
|
+
Driver.register_provider_class("DigitalOcean", FogDriver::Providers::DigitalOcean)
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def creator
|
10
|
+
""
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
13
|
+
def convergence_strategy_for(machine_spec, machine_options)
|
14
|
+
machine_options = Cheffish::MergedConfig.new(machine_options,
|
15
|
+
convergence_options: { ohai_hints: { "digital_ocean" => {} } })
|
16
|
+
super(machine_spec, machine_options)
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def converge_floating_ips(action_handler, machine_spec, machine_options, server)
|
20
|
+
# DigitalOcean does not have floating IPs
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
23
|
+
def bootstrap_options_for(action_handler, machine_spec, machine_options)
|
24
|
+
bootstrap_options = symbolize_keys(machine_options[:bootstrap_options] || {})
|
25
|
+
if bootstrap_options[:key_path] || bootstrap_options[:key_name]
|
26
|
+
bootstrap_options[:key_name] ||= File.basename(bootstrap_options[:key_path])
|
27
|
+
# Verify that the provided key name and path are in line (or create the key pair if not!)
|
28
|
+
driver = self
|
29
|
+
Provisioning.inline_resource(action_handler) do
|
30
|
+
fog_key_pair bootstrap_options[:key_name] do
|
31
|
+
private_key_path bootstrap_options[:key_path]
|
32
|
+
driver driver
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
bootstrap_options[:key_name] ||= overwrite_default_key_willy_nilly(action_handler, machine_spec)
|
34
37
|
end
|
35
|
-
end
|
36
|
-
else
|
37
|
-
bootstrap_options[:key_name] ||= overwrite_default_key_willy_nilly(action_handler, machine_spec)
|
38
|
-
end
|
39
38
|
|
40
|
-
|
39
|
+
bootstrap_options[:tags] = default_tags(machine_spec, bootstrap_options[:tags] || {})
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
41
|
+
if !bootstrap_options[:image_id] && !bootstrap_options[:image]
|
42
|
+
if !bootstrap_options[:image_distribution] && !bootstrap_options[:image_name]
|
43
|
+
bootstrap_options[:image_distribution] = "CentOS"
|
44
|
+
bootstrap_options[:image_name] = "6.5 x64"
|
45
|
+
end
|
46
|
+
distributions = compute.images.select { |image| image.distribution == bootstrap_options[:image_distribution] }
|
47
|
+
if distributions.empty?
|
48
|
+
raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect}"
|
49
|
+
end
|
50
|
+
images = distributions.select { |image| image.name == bootstrap_options[:image_name] } if bootstrap_options[:image_name]
|
51
|
+
if images.empty?
|
52
|
+
raise "No images on DigitalOcean with distribution #{bootstrap_options[:image_distribution].inspect} and name #{bootstrap_options[:image_name].inspect}"
|
53
|
+
end
|
54
|
+
bootstrap_options[:image] = images.first.id
|
55
|
+
end
|
56
|
+
if !bootstrap_options[:flavor_id] && !bootstrap_options[:size]
|
57
|
+
bootstrap_options[:flavor_name] ||= "512MB"
|
58
|
+
flavors = compute.flavors.select do |f|
|
59
|
+
f.slug.casecmp(bootstrap_options[:flavor_name]).zero?
|
60
|
+
end
|
61
|
+
if flavors.empty?
|
62
|
+
raise "Could not find flavor named '#{bootstrap_options[:flavor_name]}' on #{driver_url}"
|
63
|
+
end
|
64
|
+
bootstrap_options[:size] = flavors.first.slug
|
65
|
+
end
|
66
|
+
unless bootstrap_options[:region]
|
67
|
+
bootstrap_options[:region_name] ||= "San Francisco 1"
|
68
|
+
regions = compute.regions.select { |region| region.name == bootstrap_options[:region_name] }
|
69
|
+
if regions.empty?
|
70
|
+
raise "Could not find region named '#{bootstrap_options[:region_name]}' on #{driver_url}"
|
71
|
+
end
|
72
|
+
bootstrap_options[:region] = regions.first.slug
|
73
|
+
end
|
74
|
+
keys = compute.ssh_keys.select { |k| k.name == bootstrap_options[:key_name] }
|
75
|
+
if keys.empty?
|
76
|
+
raise "Could not find key named '#{bootstrap_options[:key_name]}' on #{driver_url}"
|
77
|
+
end
|
78
|
+
found_key = keys.first
|
79
|
+
bootstrap_options[:ssh_keys] ||= [found_key.id]
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
# You don't get to specify name yourself
|
82
|
+
bootstrap_options[:name] = machine_spec.name
|
83
|
+
bootstrap_options[:version] ||= :v2
|
84
|
+
bootstrap_options
|
85
|
+
end
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
88
|
+
server = server_for(machine_spec)
|
89
|
+
if server && server.status != "archive"
|
90
|
+
action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.location['server_id']} at #{driver_url})" do
|
91
|
+
server.delete
|
92
|
+
end
|
93
|
+
end
|
94
|
+
machine_spec.location = nil
|
95
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
96
|
+
strategy.cleanup_convergence(action_handler, machine_spec)
|
93
97
|
end
|
94
|
-
end
|
95
|
-
machine_spec.location = nil
|
96
|
-
strategy = convergence_strategy_for(machine_spec, machine_options)
|
97
|
-
strategy.cleanup_convergence(action_handler, machine_spec)
|
98
|
-
end
|
99
98
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
99
|
+
def self.compute_options_for(provider, id, config)
|
100
|
+
new_compute_options = {}
|
101
|
+
new_compute_options[:provider] = provider
|
102
|
+
new_config = { driver_options: { compute_options: new_compute_options } }
|
103
|
+
new_defaults = {
|
104
|
+
driver_options: { compute_options: { version: :v2 } },
|
105
|
+
machine_options: { bootstrap_options: {}, ssh_options: {} }
|
106
|
+
}
|
107
|
+
result = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
109
108
|
|
110
|
-
|
109
|
+
new_compute_options[:digitalocean_token] = id if id && id != ""
|
111
110
|
|
112
|
-
|
111
|
+
[result, new_compute_options[:digitalocean_token]]
|
112
|
+
end
|
113
|
+
end
|
113
114
|
end
|
114
|
-
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
|
-
end
|
119
|
-
end
|