chef-provisioning-aws 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|