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 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: