chef-provisioning-fog 0.26.1 → 0.26.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|