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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3acb67df3a046b0298b40a390a7cacee7e700b51
4
- data.tar.gz: 0e7d8231c5a682d1b25c6c8ca138abbec7422494
3
+ metadata.gz: 5d4c4e48ec76622cc159966e0862a69e92dcc794
4
+ data.tar.gz: 6db5dc3f481f314c3abc02d8389d773e84cd01b7
5
5
  SHA512:
6
- metadata.gz: dca5eec228b058b87d02c7da2098806073c904e1369672f724a2dfd4ad5115b248241defe1aa5a8dd9c5b1d1b18340fbdabe9e4c66bff7a3f9099e8eae8e4729
7
- data.tar.gz: 821c4ba12a4dedba7cdd7da366f277e2c32ab14215a9de36d30078dc9c1ea1eb9c3bb9619bec6aad11b27922fdf6d94566d89747dd55a1cc0347cb07257c488e
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/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::LWRPBase
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
- compute.key_pairs.delete(new_resource.name)
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.key.key_pairs.get(new_resource.name).destroy
82
- compute.import_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
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
- compute.import_key_pair(new_resource.name, Cheffish::KeyFormatter.encode(desired_key, :format => :openssh))
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 = compute.key_pairs.get(new_resource.name)
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 DataTime.now.to_s
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
- existing_elb = load_balancer_for(lb_spec)
55
- if !existing_elb.exists?
56
- lb_spec.location = {
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
- 'host_node' => action_handler.host_node,
61
- }
62
-
63
- security_group_name = lb_options[:security_group_name] || 'default'
64
- security_group_id = lb_options[:security_group_id]
65
-
66
- default_sg = ec2.security_groups.filter('group-name', 'default')
67
- security_group = if security_group_id.nil?
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
- machines = opts[:machines]
103
- existing_instance_ids = existing_elb.instances.collect { |i| i.instance_id }
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
- new_instance_ids = machines.keys.collect do |machine_name|
106
- machine_spec = machines[machine_name]
107
- machine_spec.location['instance_id']
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
- instance_ids_to_add = new_instance_ids - existing_instance_ids
111
- instance_ids_to_remove = existing_instance_ids - new_instance_ids
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 instance_ids_to_add && instance_ids_to_add.size > 0
114
- action_handler.perform_action "Adding instances: #{instance_ids_to_add}" do
115
- existing_elb.instances.add(instance_ids_to_add)
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 && instance_ids_to_remove.size > 0
120
- action_handler.perform_action "Removing instances: #{instance_ids_to_remove}" do
121
- existing_elb.instances.remove(instance_ids_to_remove)
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
- existing_instance = instance_for(machine_spec)
139
- if existing_instance == nil || !existing_instance.exists?
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
- instance = ec2.instances.create(bootstrap_options)
155
- instance.tags['Name'] = machine_spec.name
156
- machine_spec.location['instance_id'] = instance.id
157
- action_handler.report_progress "Created #{instance.id} in #{@region}..."
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.report_progress "Starting #{machine_spec.name} (#{machine_spec.location['instance_id']}) in #{@region}..."
170
- wait_until_ready(action_handler, machine_spec)
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.terminate
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
- existing_key_pair = ec2.key_pairs[keypair_name]
224
- if !existing_key_pair.exists?
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
- existing_key_pair
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 = instance_for(machine_spec)
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
- unless instance.status == :running
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.status != :running
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}"
@@ -1,7 +1,7 @@
1
1
  class Chef
2
2
  module Provisioning
3
3
  module AWSDriver
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
6
6
  end
7
7
  end
@@ -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::FogKeyPair < Chef::Resource::LWRPBase
4
- self.resource_name = 'fog_key_pair'
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.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-05 00:00:00.000000000 Z
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: