chef-provisioning-aws 0.1.1 → 0.1.2
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 +14 -0
- data/lib/chef/provider/aws_key_pair.rb +16 -11
- data/lib/chef/provider/aws_security_group.rb +89 -0
- data/lib/chef/provider/aws_sns_topic.rb +1 -1
- data/lib/chef/provider/aws_vpc.rb +42 -0
- data/lib/chef/provisioning/aws_driver/driver.rb +205 -88
- data/lib/chef/provisioning/aws_driver/resources.rb +1 -1
- data/lib/chef/provisioning/aws_driver/version.rb +1 -1
- data/lib/chef/resource/.DS_Store +0 -0
- data/lib/chef/resource/aws_ebs_mount.rb +31 -0
- data/lib/chef/resource/aws_key_pair.rb +3 -2
- data/lib/chef/resource/aws_security_group.rb +26 -0
- data/lib/chef/resource/aws_sqs_queue.rb +0 -3
- data/lib/chef/resource/aws_vpc.rb +23 -0
- metadata +20 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d4c4e48ec76622cc159966e0862a69e92dcc794
|
4
|
+
data.tar.gz: 6db5dc3f481f314c3abc02d8389d773e84cd01b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31a85827c948b002ccc16889f9e075f1689b05d26a38a24ce6bf871b94b609dcf828b7baf3f1cec46e4d0f270bd129fed9a1bf66fe0ad63fb4413c3ba41a712f
|
7
|
+
data.tar.gz: f7d87089964113885f12dcfe193af3dbc7fb39d0bbb955fd4da53bb30c682701c54d6b35a051f922300ecbd848dd1ac87e0b963509af212f1a8d8ef02469c801
|
data/README.md
CHANGED
@@ -10,3 +10,17 @@ development.
|
|
10
10
|
|
11
11
|
This requires the latest from chef-provisioning's load_balancer branch for some
|
12
12
|
features like region support (until it gets merged into master, which should be soon)
|
13
|
+
|
14
|
+
|
15
|
+
List of resources (these may not have 100% of SDK functionality mapped but can be provisioned):
|
16
|
+
|
17
|
+
* SQS Queues
|
18
|
+
* SNS Topics
|
19
|
+
* Elastic Load Balancers
|
20
|
+
* VPCs
|
21
|
+
* Security Groups
|
22
|
+
* Instances
|
23
|
+
* Images
|
24
|
+
* Autoscaling Groups
|
25
|
+
* SSH Key pairs
|
26
|
+
* Launch configs
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'chef/provider/lwrp_base'
|
2
|
-
require 'chef/provisioning/aws_driver
|
2
|
+
require 'chef/provisioning/aws_driver'
|
3
|
+
require 'chef/provider/aws_provider'
|
3
4
|
require 'aws-sdk-v1'
|
4
5
|
|
5
6
|
|
6
|
-
class Chef::Provider::AwsKeyPair < Chef::Provider::
|
7
|
+
class Chef::Provider::AwsKeyPair < Chef::Provider::AwsProvider
|
7
8
|
|
8
9
|
use_inline_resources
|
9
10
|
|
@@ -17,7 +18,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
17
18
|
|
18
19
|
action :delete do
|
19
20
|
if current_resource_exists?
|
20
|
-
|
21
|
+
ec2.key_pairs[new_resource.name].delete
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -78,8 +79,8 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
78
79
|
if !new_fingerprints.any? { |f| compare_public_key f }
|
79
80
|
if new_resource.allow_overwrite
|
80
81
|
converge_by "update #{key_description} to match local key at #{new_resource.private_key_path}" do
|
81
|
-
ec2.
|
82
|
-
|
82
|
+
ec2.key_pairs[new_resource.name].delete
|
83
|
+
ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
83
84
|
end
|
84
85
|
else
|
85
86
|
raise "#{key_description} with fingerprint #{@current_fingerprint} does not match local key fingerprint(s) #{new_fingerprints}, and allow_overwrite is false!"
|
@@ -91,7 +92,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
91
92
|
|
92
93
|
# Create key
|
93
94
|
converge_by "create #{key_description} from local key at #{new_resource.private_key_path}" do
|
94
|
-
|
95
|
+
ec2.key_pairs.import(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
|
95
96
|
end
|
96
97
|
end
|
97
98
|
end
|
@@ -133,6 +134,14 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
137
|
+
def existing_keypair
|
138
|
+
@existing_keypair ||= begin
|
139
|
+
ec2.key_pairs[fqn]
|
140
|
+
rescue
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
136
145
|
def current_resource_exists?
|
137
146
|
@current_resource.action != [ :delete ]
|
138
147
|
end
|
@@ -143,10 +152,6 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
143
152
|
c == n
|
144
153
|
end
|
145
154
|
|
146
|
-
def compute
|
147
|
-
new_driver.compute
|
148
|
-
end
|
149
|
-
|
150
155
|
def current_public_key
|
151
156
|
current_resource.source_key
|
152
157
|
end
|
@@ -170,7 +175,7 @@ class Chef::Provider::AwsKeyPair < Chef::Provider::LWRPBase
|
|
170
175
|
def load_current_resource
|
171
176
|
@current_resource = Chef::Resource::AwsKeyPair.new(new_resource.name, run_context)
|
172
177
|
|
173
|
-
current_key_pair =
|
178
|
+
current_key_pair = ec2.key_pairs[new_resource.name]
|
174
179
|
if current_key_pair
|
175
180
|
@current_fingerprint = current_key_pair ? current_key_pair.fingerprint : nil
|
176
181
|
else
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'chef/provider/aws_provider'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
class Chef::Provider::AwsSecurityGroup < Chef::Provider::AwsProvider
|
5
|
+
|
6
|
+
action :create do
|
7
|
+
if existing_sg == nil
|
8
|
+
converge_by "Creating new SG #{new_resource.name} in #{new_resource.region_name}" do
|
9
|
+
opts = {
|
10
|
+
:description => new_resource.description,
|
11
|
+
:vpc => nil
|
12
|
+
}
|
13
|
+
# Use VPC ID if provided, otherwise lookup VPC by name
|
14
|
+
if new_resource.vpc_id
|
15
|
+
opts[:vpc] = new_resource.vpc_id
|
16
|
+
elsif new_resource.vpc_name
|
17
|
+
existing_vpc = ec2.vpcs.with_tag('Name', new_resource.vpc_name).first
|
18
|
+
Chef::Log.debug("Existing VPC: #{existing_vpc.inspect}")
|
19
|
+
if existing_vpc
|
20
|
+
opts[:vpc] = existing_vpc
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
sg = ec2.security_groups.create(new_resource.name, opts)
|
25
|
+
new_resource.security_group_id sg.group_id
|
26
|
+
new_resource.save
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Update rules
|
31
|
+
apply_rules(existing_sg)
|
32
|
+
end
|
33
|
+
|
34
|
+
action :delete do
|
35
|
+
if existing_vpc
|
36
|
+
converge_by "Deleting SG #{new_resource.name} in #{new_resource.region_name}" do
|
37
|
+
existing_sg.delete
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
new_resource.delete
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO check existing rules and compare / remove?
|
45
|
+
def apply_rules(security_group)
|
46
|
+
# Incoming
|
47
|
+
if new_resource.inbound_rules
|
48
|
+
new_resource.inbound_rules.each do |rule|
|
49
|
+
begin
|
50
|
+
converge_by "Updating SG #{new_resource.name} in #{new_resource.region_name} to allow inbound #{rule[:protocol]}/#{rule[:ports]} from #{rule[:sources]}" do
|
51
|
+
security_group.authorize_ingress(rule[:protocol], rule[:ports], *rule[:sources])
|
52
|
+
end
|
53
|
+
rescue AWS::EC2::Errors::InvalidPermission::Duplicate
|
54
|
+
Chef::Log.debug 'Duplicate rule, ignoring.'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Outgoing
|
60
|
+
if new_resource.outbound_rules
|
61
|
+
new_resource.outbound_rules.each do |rule|
|
62
|
+
begin
|
63
|
+
converge_by "Updating SG #{new_resource.name} in #{new_resource.region_name} to allow outbound #{rule[:protocol]}/#{rule[:ports]} to #{rule[:destinations]}" do
|
64
|
+
security_group.authorize_egress( *rule[:destinations], :protocol => rule[:protocol], :ports => rule[:ports])
|
65
|
+
end
|
66
|
+
rescue AWS::EC2::Errors::InvalidPermission::Duplicate
|
67
|
+
Chef::Log.debug 'Duplicate rule, ignoring.'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def existing_sg
|
74
|
+
@existing_sg ||= begin
|
75
|
+
if id != nil
|
76
|
+
ec2.security_groups[id]
|
77
|
+
else
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
rescue
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def id
|
86
|
+
new_resource.security_group_id
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -8,7 +8,7 @@ class Chef::Provider::AwsSnsTopic < Chef::Provider::AwsProvider
|
|
8
8
|
converge_by "Creating new SNS topic #{fqn} in #{new_resource.region_name}" do
|
9
9
|
sns.topics.create(fqn)
|
10
10
|
|
11
|
-
new_resource.created_at
|
11
|
+
new_resource.created_at DateTime.now.to_s
|
12
12
|
new_resource.save
|
13
13
|
end
|
14
14
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'chef/provider/aws_provider'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
class Chef::Provider::AwsVpc < Chef::Provider::AwsProvider
|
5
|
+
|
6
|
+
action :create do
|
7
|
+
fail "Can't create a VPC without a CIDR block" if new_resource.cidr_block.nil?
|
8
|
+
|
9
|
+
if existing_vpc == nil
|
10
|
+
converge_by "Creating new VPC #{fqn} in #{new_resource.region_name}" do
|
11
|
+
opts = { :instance_tenancy => :default}
|
12
|
+
vpc = ec2.vpcs.create(new_resource.cidr_block, opts)
|
13
|
+
vpc.tags['Name'] = new_resource.name
|
14
|
+
new_resource.vpc_id vpc.id
|
15
|
+
new_resource.save
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
action :delete do
|
21
|
+
if existing_vpc
|
22
|
+
converge_by "Deleting VPC #{fqn} in #{new_resource.region_name}" do
|
23
|
+
existing_vpc.delete
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
new_resource.delete
|
28
|
+
end
|
29
|
+
|
30
|
+
def existing_vpc
|
31
|
+
@existing_vpc ||= begin
|
32
|
+
ec2.vpcs.with_tag('Name', new_resource.name).first
|
33
|
+
rescue
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def id
|
39
|
+
new_resource.vpc_id
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -8,6 +8,8 @@ require 'chef/provisioning/machine/windows_machine'
|
|
8
8
|
require 'chef/provisioning/machine/unix_machine'
|
9
9
|
require 'chef/provisioning/machine_spec'
|
10
10
|
|
11
|
+
require 'chef/provider/aws_key_pair'
|
12
|
+
require 'chef/resource/aws_key_pair'
|
11
13
|
require 'chef/provisioning/aws_driver/version'
|
12
14
|
require 'chef/provisioning/aws_driver/credentials'
|
13
15
|
|
@@ -50,79 +52,142 @@ module AWSDriver
|
|
50
52
|
|
51
53
|
|
52
54
|
# Load balancer methods
|
53
|
-
def allocate_load_balancer(action_handler, lb_spec, lb_options)
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
def allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
|
56
|
+
security_group_name = lb_options[:security_group_name] || 'default'
|
57
|
+
security_group_id = lb_options[:security_group_id]
|
58
|
+
|
59
|
+
# TODO confused: this variable doesn't appear to be used?
|
60
|
+
# default_sg = ec2.security_groups.filter('group-name', 'default')
|
61
|
+
security_group = if security_group_id.nil?
|
62
|
+
ec2.security_groups.filter('group-name', security_group_name).first
|
63
|
+
else
|
64
|
+
ec2.security_groups[security_group_id]
|
65
|
+
end
|
66
|
+
availability_zones = lb_options[:availability_zones]
|
67
|
+
listeners = lb_options[:listeners]
|
68
|
+
|
69
|
+
actual_elb = load_balancer_for(lb_spec)
|
70
|
+
if !actual_elb.exists?
|
71
|
+
perform_action = proc { |desc, &block| action_handler.perform_action(desc, &block) }
|
72
|
+
|
73
|
+
updates = [ "Create load balancer #{lb_spec.name} in #{@region}" ]
|
74
|
+
updates << " enable availability zones #{availability_zones.join(', ')}" if availability_zones && availability_zones.size > 0
|
75
|
+
updates << " with listeners #{listeners.join(', ')}" if listeners && listeners.size > 0
|
76
|
+
updates << " with security group #{security_group.name}" if security_group
|
77
|
+
|
78
|
+
action_handler.perform_action updates do
|
79
|
+
actual_elb = elb.load_balancers.create(lb_spec.name,
|
80
|
+
availability_zones: availability_zones,
|
81
|
+
listeners: listeners,
|
82
|
+
security_groups: [security_group])
|
83
|
+
|
84
|
+
lb_spec.location = {
|
57
85
|
'driver_url' => driver_url,
|
58
86
|
'driver_version' => Chef::Provisioning::AWSDriver::VERSION,
|
59
87
|
'allocated_at' => Time.now.utc.to_s,
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
ec2.security_groups.filter('group-name', security_group_name).first
|
69
|
-
else
|
70
|
-
ec2.security_groups[security_group_id]
|
71
|
-
end
|
72
|
-
|
73
|
-
availability_zones = lb_options[:availability_zones]
|
74
|
-
listeners = lb_options[:listeners]
|
75
|
-
elb.load_balancers.create(lb_spec.name,
|
76
|
-
:availability_zones => availability_zones,
|
77
|
-
:listeners => listeners,
|
78
|
-
:security_groups => [security_group])
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def ready_load_balancer(action_handler, lb_spec, lb_options)
|
83
|
-
end
|
84
|
-
|
85
|
-
def destroy_load_balancer(action_handler, lb_spec, lb_options)
|
86
|
-
end
|
87
|
-
|
88
|
-
# TODO update listeners and zones, and other bits
|
89
|
-
def update_load_balancer(action_handler, lb_spec, lb_options, opts = {})
|
90
|
-
existing_elb = load_balancer_for(lb_spec)
|
91
|
-
|
92
|
-
# Try to recreate it if it doesn't exist in AWS
|
93
|
-
action_handler.report_progress "Checking for ELB named #{lb_spec.name}..."
|
94
|
-
allocate_load_balancer(action_handler, lb_spec, lb_options) unless existing_elb.exists?
|
95
|
-
|
96
|
-
# Try to find it again -- if we can't, consider it fatal
|
97
|
-
existing_elb = load_balancer_for(lb_spec)
|
98
|
-
fail "Unable to find specified ELB instance. Already tried to recreate it!" if !existing_elb.exists?
|
99
|
-
|
100
|
-
action_handler.report_progress "Updating ELB named #{lb_spec.name}..."
|
88
|
+
}
|
89
|
+
end
|
90
|
+
else
|
91
|
+
# Header gets printed the first time we make an update
|
92
|
+
perform_action = proc do |desc, &block|
|
93
|
+
perform_action = proc { |desc, &block| action_handler.perform_action(desc, &block) }
|
94
|
+
action_handler.perform_action [ "Update load balancer #{lb_spec.name} in #{@region}", desc ].flatten, &block
|
95
|
+
end
|
101
96
|
|
102
|
-
|
103
|
-
|
97
|
+
# Update availability zones
|
98
|
+
enable_zones = (availability_zones || []).dup
|
99
|
+
disable_zones = []
|
100
|
+
actual_elb.availability_zones.each do |availability_zone|
|
101
|
+
if !enable_zones.delete(availability_zone.name)
|
102
|
+
disable_zones << availability_zone.name
|
103
|
+
end
|
104
|
+
end
|
105
|
+
if enable_zones.size > 0
|
106
|
+
perform_action.call(" enable availability zones #{enable_zones.join(', ')}") do
|
107
|
+
actual_elb.availability_zones.enable(*enable_zones)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
if disable_zones.size > 0
|
111
|
+
perform_action.call(" disable availability zones #{disable_zones.join(', ')}") do
|
112
|
+
actual_elb.availability_zones.disable(*disable_zones)
|
113
|
+
end
|
114
|
+
end
|
104
115
|
|
105
|
-
|
106
|
-
|
107
|
-
|
116
|
+
# Update listeners
|
117
|
+
perform_listener_action = proc do |desc, &block|
|
118
|
+
perform_listener_action = proc { |desc, &block| perform_action(desc, &block) }
|
119
|
+
perform_action([ " update listener #{listener.port}", desc ], &block)
|
120
|
+
end
|
121
|
+
add_listeners = {}
|
122
|
+
listeners.each { |l| add_listeners[l[:port]] = l } if listeners
|
123
|
+
actual_elb.listeners.each do |listener|
|
124
|
+
desired_listener = add_listeners.delete(listener.port)
|
125
|
+
if desired_listener
|
126
|
+
if listener.protocol != desired_listener[:protocol]
|
127
|
+
perform_listener_action.call(" update protocol from #{listener.protocol.inspect} to #{desired_listener[:protocol].inspect}'") do
|
128
|
+
listener.protocol = desired_listener[:protocol]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
if listener.instance_port != desired_listener[:instance_port]
|
132
|
+
perform_listener_action.call(" update instance port from #{listener.instance_port.inspect} to #{desired_listener[:instance_port].inspect}'") do
|
133
|
+
listener.instance_port = desired_listener[:instance_port]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
if listener.instance_protocol != desired_listener[:instance_protocol]
|
137
|
+
perform_listener_action.call(" update instance protocol from #{listener.instance_protocol.inspect} to #{desired_listener[:instance_protocol].inspect}'") do
|
138
|
+
listener.instance_protocol = desired_listener[:instance_protocol]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
if listener.server_certificate != desired_listener[:server_certificate]
|
142
|
+
perform_listener_action.call(" update server certificate from #{listener.server_certificate} to #{desired_listener[:server_certificate]}'") do
|
143
|
+
listener.server_certificate = desired_listener[:server_certificate]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
else
|
147
|
+
perform_action.call(" remove listener #{listener.port}") do
|
148
|
+
listener.delete
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
add_listeners.each do |listener|
|
153
|
+
updates = [ " add listener #{listener[:port]}" ]
|
154
|
+
updates << " set protocol to #{listener[:protocol].inspect}"
|
155
|
+
updates << " set instance port to #{listener[:instance_port].inspect}"
|
156
|
+
updates << " set instance protocol to #{listener[:instance_protocol].inspect}"
|
157
|
+
updates << " set server certificate to #{listener[:server_certificate]}" if listener[:server_certificate]
|
158
|
+
perform_action.call(updates) do
|
159
|
+
actual_elb.listeners.create(listener)
|
160
|
+
end
|
161
|
+
end
|
108
162
|
end
|
109
163
|
|
110
|
-
|
111
|
-
|
164
|
+
# Update instance list
|
165
|
+
actual_instance_ids = Set.new(actual_elb.instances.map { |i| i.instance_id })
|
166
|
+
|
167
|
+
instances_to_add = machine_specs.select { |s| !actual_instance_ids.include?(s.location['instance_id']) }
|
168
|
+
instance_ids_to_remove = actual_instance_ids - machine_specs.map { |s| s.location['instance_id'] }
|
112
169
|
|
113
|
-
if
|
114
|
-
|
115
|
-
|
170
|
+
if instances_to_add.size > 0
|
171
|
+
perform_action.call(" add machines #{instances_to_add.map { |s| s.name }.join(', ')}") do
|
172
|
+
instance_ids_to_add = instances_to_add.map { |s| s.location['instance_id'] }
|
173
|
+
Chef::Log.debug("Adding instances #{instance_ids_to_add.join(', ')} to load balancer #{actual_elb.name} in region #{@region}")
|
174
|
+
actual_elb.instances.add(instance_ids_to_add)
|
116
175
|
end
|
117
176
|
end
|
118
177
|
|
119
|
-
if instance_ids_to_remove
|
120
|
-
|
121
|
-
|
178
|
+
if instance_ids_to_remove.size > 0
|
179
|
+
perform_action.call(" remove instances #{instance_ids_to_remove}") do
|
180
|
+
actual_elb.instances.remove(instance_ids_to_remove)
|
122
181
|
end
|
123
182
|
end
|
124
183
|
end
|
125
184
|
|
185
|
+
def ready_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
|
186
|
+
end
|
187
|
+
|
188
|
+
def destroy_load_balancer(action_handler, lb_spec, lb_options)
|
189
|
+
end
|
190
|
+
|
126
191
|
# Image methods
|
127
192
|
def allocate_image(action_handler, image_spec, image_options, machine_spec)
|
128
193
|
end
|
@@ -135,26 +200,31 @@ module AWSDriver
|
|
135
200
|
|
136
201
|
# Machine methods
|
137
202
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
138
|
-
|
139
|
-
if
|
140
|
-
|
141
|
-
machine_spec.location = {
|
142
|
-
'driver_url' => driver_url,
|
143
|
-
'driver_version' => Chef::Provisioning::AWSDriver::VERSION,
|
144
|
-
'allocated_at' => Time.now.utc.to_s,
|
145
|
-
'host_node' => action_handler.host_node,
|
146
|
-
'image_id' => machine_options[:image_id]
|
147
|
-
}
|
148
|
-
|
203
|
+
actual_instance = instance_for(machine_spec)
|
204
|
+
if actual_instance == nil || !actual_instance.exists?
|
149
205
|
image_id = machine_options[:image_id] || default_ami_for_region(@region)
|
150
|
-
action_handler.report_progress "Creating #{machine_spec.name} with AMI #{image_id} in #{@region}..."
|
151
206
|
bootstrap_options = machine_options[:bootstrap_options] || {}
|
152
207
|
bootstrap_options[:image_id] = image_id
|
208
|
+
if !bootstrap_options[:key_name]
|
209
|
+
Chef::Log.debug('No key specified, generating a default one...')
|
210
|
+
bootstrap_options[:key_name] = default_aws_keypair(action_handler, machine_spec)
|
211
|
+
end
|
153
212
|
Chef::Log.debug "AWS Bootstrap options: #{bootstrap_options.inspect}"
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
213
|
+
|
214
|
+
action_handler.perform_action "Create #{machine_spec.name} with AMI #{image_id} in #{@region}" do
|
215
|
+
Chef::Log.debug "Creating instance with bootstrap options #{bootstrap_options}"
|
216
|
+
instance = ec2.instances.create(bootstrap_options)
|
217
|
+
# TODO add other tags identifying user / node url (same as fog)
|
218
|
+
instance.tags['Name'] = machine_spec.name
|
219
|
+
machine_spec.location = {
|
220
|
+
'driver_url' => driver_url,
|
221
|
+
'driver_version' => Chef::Provisioning::AWSDriver::VERSION,
|
222
|
+
'allocated_at' => Time.now.utc.to_s,
|
223
|
+
'host_node' => action_handler.host_node,
|
224
|
+
'image_id' => machine_options[:image_id],
|
225
|
+
'instance_id' => instance.id
|
226
|
+
}
|
227
|
+
end
|
158
228
|
end
|
159
229
|
end
|
160
230
|
|
@@ -166,11 +236,14 @@ module AWSDriver
|
|
166
236
|
end
|
167
237
|
|
168
238
|
if instance.status != :running
|
169
|
-
action_handler
|
170
|
-
|
239
|
+
wait_until(action_handler, machine_spec, instance) { instance.status != :stopping }
|
240
|
+
if instance.status == :stopped
|
241
|
+
action_handler.perform_action "Start #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{@region} ..." do
|
242
|
+
instance.start
|
243
|
+
end
|
244
|
+
end
|
245
|
+
wait_until_ready(action_handler, machine_spec, instance)
|
171
246
|
wait_for_transport(action_handler, machine_spec, machine_options)
|
172
|
-
else
|
173
|
-
action_handler.report_progress "#{machine_spec.name} (#{machine_spec.location['instance_id']}) already running in #{@region}..."
|
174
247
|
end
|
175
248
|
|
176
249
|
machine_for(machine_spec, machine_options, instance)
|
@@ -180,14 +253,24 @@ module AWSDriver
|
|
180
253
|
def destroy_machine(action_handler, machine_spec, machine_options)
|
181
254
|
instance = instance_for(machine_spec)
|
182
255
|
if instance
|
183
|
-
instance.
|
256
|
+
# TODO do we need to wait_until(action_handler, machine_spec, instance) { instance.status != :shutting_down } ?
|
257
|
+
action_handler.perform_action "Terminate #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{@region} ..." do
|
258
|
+
instance.terminate
|
259
|
+
machine_spec.location = nil
|
260
|
+
end
|
261
|
+
else
|
262
|
+
Chef::Log.warn "Unable to find and destroy instance for #{machine_spec.inspect}"
|
184
263
|
end
|
185
|
-
end
|
186
264
|
|
265
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
266
|
+
strategy.cleanup_convergence(action_handler, machine_spec)
|
267
|
+
end
|
187
268
|
|
269
|
+
private
|
188
270
|
|
271
|
+
# For creating things like AWS keypairs exclusively
|
272
|
+
@@chef_default_lock = Mutex.new
|
189
273
|
|
190
|
-
private
|
191
274
|
def machine_for(machine_spec, machine_options, instance = nil)
|
192
275
|
instance ||= instance_for(machine_spec)
|
193
276
|
|
@@ -220,11 +303,11 @@ module AWSDriver
|
|
220
303
|
def keypair_for(bootstrap_options)
|
221
304
|
if bootstrap_options[:key_name]
|
222
305
|
keypair_name = bootstrap_options[:key_name]
|
223
|
-
|
224
|
-
if !
|
306
|
+
actual_key_pair = ec2.key_pairs[keypair_name]
|
307
|
+
if !actual_key_pair.exists?
|
225
308
|
ec2.key_pairs.create(keypair_name)
|
226
309
|
end
|
227
|
-
|
310
|
+
actual_key_pair
|
228
311
|
end
|
229
312
|
end
|
230
313
|
|
@@ -375,15 +458,19 @@ module AWSDriver
|
|
375
458
|
end
|
376
459
|
end
|
377
460
|
|
378
|
-
def wait_until_ready(action_handler, machine_spec)
|
379
|
-
instance
|
461
|
+
def wait_until_ready(action_handler, machine_spec, instance=nil)
|
462
|
+
wait_until(action_handler, machine_spec, instance) { instance.status == :running }
|
463
|
+
end
|
464
|
+
|
465
|
+
def wait_until(action_handler, machine_spec, instance=nil, &block)
|
466
|
+
instance ||= instance_for(machine_spec)
|
380
467
|
time_elapsed = 0
|
381
468
|
sleep_time = 10
|
382
469
|
max_wait_time = 120
|
383
|
-
|
470
|
+
if !yield(instance)
|
384
471
|
if action_handler.should_perform_actions
|
385
472
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{instance.id} on #{driver_url}) to be ready ..."
|
386
|
-
while time_elapsed < 120 && instance
|
473
|
+
while time_elapsed < 120 && !yield(instance)
|
387
474
|
action_handler.report_progress "been waiting #{time_elapsed}/#{max_wait_time} -- sleeping #{sleep_time} seconds for #{machine_spec.name} (#{instance.id} on #{driver_url}) to be ready ..."
|
388
475
|
sleep(sleep_time)
|
389
476
|
time_elapsed += sleep_time
|
@@ -413,6 +500,36 @@ module AWSDriver
|
|
413
500
|
end
|
414
501
|
end
|
415
502
|
|
503
|
+
def default_aws_keypair_name(machine_spec)
|
504
|
+
if machine_spec.location &&
|
505
|
+
Gem::Version.new(machine_spec.location['driver_version']) < Gem::Version.new('0.10')
|
506
|
+
'metal_default'
|
507
|
+
else
|
508
|
+
'chef_default'
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
def default_aws_keypair(action_handler, machine_spec)
|
513
|
+
driver = self
|
514
|
+
default_key_name = default_aws_keypair_name(machine_spec)
|
515
|
+
_region = region
|
516
|
+
updated = @@chef_default_lock.synchronize do
|
517
|
+
Provisioning.inline_resource(action_handler) do
|
518
|
+
aws_key_pair default_key_name do
|
519
|
+
driver driver
|
520
|
+
allow_overwrite true
|
521
|
+
region_name _region
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
# Only warn the first time
|
527
|
+
default_warning = 'Using default key, which is not shared between machines! It is recommended to create an AWS key pair with the fog_key_pair resource, and set :bootstrap_options => { :key_name => <key name> }'
|
528
|
+
Chef::Log.warn(default_warning) if updated
|
529
|
+
|
530
|
+
default_key_name
|
531
|
+
end
|
532
|
+
|
416
533
|
end
|
417
534
|
end
|
418
535
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
resources = %w(sqs_queue sns_topic ebs_volume s3_bucket auto_scaling_group launch_config)
|
1
|
+
resources = %w(sqs_queue sns_topic ebs_volume s3_bucket auto_scaling_group launch_config vpc security_group)
|
2
2
|
|
3
3
|
resources.each do |r|
|
4
4
|
Chef::Log.debug "AWS driver loading resource: #{r}"
|
Binary file
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'chef/resource/aws_resource'
|
2
|
+
require 'chef_metal_aws'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsEbsVolume < Chef::Resource::AwsResource
|
5
|
+
self.resource_name = 'aws_ebs_mount'
|
6
|
+
self.databag_name = 'ebs_mounts'
|
7
|
+
|
8
|
+
actions :create, :delete, :nothing
|
9
|
+
default_action :create
|
10
|
+
|
11
|
+
stored_attribute :instance_id
|
12
|
+
stored_attribute :volume_id
|
13
|
+
|
14
|
+
attribute :name, :kind_of => String, :name_attribute => true
|
15
|
+
attribute :volume_name, :kind_of => String
|
16
|
+
|
17
|
+
attribute :size
|
18
|
+
attribute :mount_point
|
19
|
+
attribute :availability_zone
|
20
|
+
|
21
|
+
|
22
|
+
def initialize(*args)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def after_created
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'chef/provisioning'
|
2
|
+
require 'chef/resource/aws_resource'
|
2
3
|
|
3
|
-
class Chef::Resource::
|
4
|
-
self.resource_name = '
|
4
|
+
class Chef::Resource::AwsKeyPair < Chef::Resource::AwsResource
|
5
|
+
self.resource_name = 'aws_key_pair'
|
5
6
|
|
6
7
|
def initialize(*args)
|
7
8
|
super
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'chef/resource/aws_resource'
|
2
|
+
require 'chef/provisioning/aws_driver'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsSecurityGroup < Chef::Resource::AwsResource
|
5
|
+
self.resource_name = 'aws_security_group'
|
6
|
+
self.databag_name = 'aws_security_groups'
|
7
|
+
|
8
|
+
actions :create, :delete, :nothing
|
9
|
+
default_action :create
|
10
|
+
|
11
|
+
attribute :name, :kind_of => String, :name_attribute => true
|
12
|
+
attribute :vpc_id, :kind_of => String
|
13
|
+
attribute :vpc_name, :kind_of => String
|
14
|
+
attribute :inbound_rules
|
15
|
+
attribute :outbound_rules
|
16
|
+
stored_attribute :security_group_id
|
17
|
+
stored_attribute :description
|
18
|
+
|
19
|
+
def initialize(*args)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_created
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
@@ -7,9 +7,6 @@ class Chef::Resource::AwsSqsQueue < Chef::Resource::AwsResource
|
|
7
7
|
actions :create, :delete, :nothing
|
8
8
|
default_action :create
|
9
9
|
|
10
|
-
attribute :name, String, :name_attribute => true
|
11
|
-
attribute :queue_name, String
|
12
|
-
stored_attribute :created_at, DateTime
|
13
10
|
attribute :name, :kind_of => String, :name_attribute => true
|
14
11
|
attribute :queue_name, :kind_of => String
|
15
12
|
stored_attribute :created_at
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'chef/resource/aws_resource'
|
2
|
+
require 'chef/provisioning/aws_driver'
|
3
|
+
|
4
|
+
class Chef::Resource::AwsVpc < Chef::Resource::AwsResource
|
5
|
+
self.resource_name = 'aws_vpc'
|
6
|
+
self.databag_name = 'aws_vpc'
|
7
|
+
|
8
|
+
actions :create, :delete, :nothing
|
9
|
+
default_action :create
|
10
|
+
|
11
|
+
attribute :name, :kind_of => String, :name_attribute => true
|
12
|
+
attribute :cidr_block, :kind_of => String
|
13
|
+
|
14
|
+
stored_attribute :vpc_id
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_created
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-provisioning-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Ewart
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-provisioning
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.9'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.9'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: aws-sdk-v1
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: Provisioner for creating aws containers in Chef Provisioning.
|
@@ -97,8 +97,10 @@ files:
|
|
97
97
|
- lib/chef/provider/aws_launch_config.rb
|
98
98
|
- lib/chef/provider/aws_provider.rb
|
99
99
|
- lib/chef/provider/aws_s3_bucket.rb
|
100
|
+
- lib/chef/provider/aws_security_group.rb
|
100
101
|
- lib/chef/provider/aws_sns_topic.rb
|
101
102
|
- lib/chef/provider/aws_sqs_queue.rb
|
103
|
+
- lib/chef/provider/aws_vpc.rb
|
102
104
|
- lib/chef/provisioning/aws_driver.rb
|
103
105
|
- lib/chef/provisioning/aws_driver/aws_profile.rb
|
104
106
|
- lib/chef/provisioning/aws_driver/credentials.rb
|
@@ -106,14 +108,18 @@ files:
|
|
106
108
|
- lib/chef/provisioning/aws_driver/resources.rb
|
107
109
|
- lib/chef/provisioning/aws_driver/version.rb
|
108
110
|
- lib/chef/provisioning/driver_init/aws.rb
|
111
|
+
- lib/chef/resource/.DS_Store
|
109
112
|
- lib/chef/resource/aws_auto_scaling_group.rb
|
113
|
+
- lib/chef/resource/aws_ebs_mount.rb
|
110
114
|
- lib/chef/resource/aws_ebs_volume.rb
|
111
115
|
- lib/chef/resource/aws_key_pair.rb
|
112
116
|
- lib/chef/resource/aws_launch_config.rb
|
113
117
|
- lib/chef/resource/aws_resource.rb
|
114
118
|
- lib/chef/resource/aws_s3_bucket.rb
|
119
|
+
- lib/chef/resource/aws_security_group.rb
|
115
120
|
- lib/chef/resource/aws_sns_topic.rb
|
116
121
|
- lib/chef/resource/aws_sqs_queue.rb
|
122
|
+
- lib/chef/resource/aws_vpc.rb
|
117
123
|
homepage: https://github.com/opscode/chef-provisioning-aws
|
118
124
|
licenses: []
|
119
125
|
metadata: {}
|
@@ -123,12 +129,12 @@ require_paths:
|
|
123
129
|
- lib
|
124
130
|
required_ruby_version: !ruby/object:Gem::Requirement
|
125
131
|
requirements:
|
126
|
-
- -
|
132
|
+
- - '>='
|
127
133
|
- !ruby/object:Gem::Version
|
128
134
|
version: '0'
|
129
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
136
|
requirements:
|
131
|
-
- -
|
137
|
+
- - '>='
|
132
138
|
- !ruby/object:Gem::Version
|
133
139
|
version: '0'
|
134
140
|
requirements: []
|
@@ -138,4 +144,3 @@ signing_key:
|
|
138
144
|
specification_version: 4
|
139
145
|
summary: Provisioner for creating aws containers in Chef Provisioning.
|
140
146
|
test_files: []
|
141
|
-
has_rdoc:
|