rubber 3.1.0 → 3.2.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4949f1406f5da62d1236bf1757dcf5a70e262094
4
+ data.tar.gz: 1b8dc7e8d6a18880408f5b1017d845f5ea4ef272
5
+ SHA512:
6
+ metadata.gz: b3aadb75637b09101862f6f118a37ee0c9349944416aca49fad689eacf6e6b493d98fbb2abec1a15abc593ada43239284afa7cd544f844165269c3681be08651
7
+ data.tar.gz: f61a46a4d8923082c1c4610bf6f45bba4b0ec0734657d6f8b1764b2d31b2529e8774499937bedf45b6d150035da7675f4052c5823f6b3b43e250e313a7fddd81
data/CHANGELOG CHANGED
@@ -1,9 +1,18 @@
1
+ 3.2.0 (01/09/2016)
2
+
3
+ New Features:
4
+ ============
5
+
6
+ [core] Added support for AWS VPCs.
7
+ [core] Added support for DigitalOcean v2 API.
8
+
9
+
1
10
  3.1.0 (05/31/2015)
2
11
 
3
12
  Improvements:
4
13
  ============
5
14
 
6
- [core] Removed explicit dependency on 'json' gem. <61db9cc>
15
+ [core] Removed explicit dependency on 'json' gem. <61db9cc>
7
16
  [core] Introduced env.enable_root_login_timeout parameter to configure timeout in enabling root login. <f8d1b65>
8
17
  [passenger] Updated to Passenger 5.0.8. <c4a8261>
9
18
  [passenger_nginx] Updated to Passenger 5.0.8. <c4a8261>
data/Gemfile CHANGED
@@ -4,9 +4,8 @@ gem 'jruby-openssl', :platform => :jruby
4
4
  gem 'unlimited-strength-crypto', :platform => :jruby
5
5
 
6
6
  group :development do
7
- # Need to run off master for tests until updated Digital Ocean mocking
8
- # makes it into a release
9
- gem 'fog', :git => 'https://github.com/fog/fog.git', :branch => 'master'
7
+ gem 'fog', '~> 1.36'
8
+ gem 'mime-types', '2.99'
10
9
  end
11
10
 
12
11
  # Specify your gem's dependencies in rubber.gemspec
@@ -0,0 +1,82 @@
1
+ require 'fog'
2
+ require 'fog/digitalocean/compute_v2'
3
+ require 'fog/digitalocean/requests/compute_v2/create_ssh_key'
4
+ require 'fog/digitalocean/requests/compute_v2/list_ssh_keys'
5
+ require 'fog/digitalocean/requests/compute_v2/delete_ssh_key'
6
+
7
+ module ::Fog
8
+ module Compute
9
+ class DigitalOceanV2
10
+ # Fixes an ssh key creation issue currently in fog 1.35.0
11
+ # This change currently in fog master:
12
+ # https://github.com/fog/fog/pull/3743
13
+ # However, unless it gets backported into 1.x, we'll need this patch until
14
+ # we update fog to 2.x
15
+ class Real
16
+ def create_ssh_key(name, public_key)
17
+ create_options = {
18
+ :name => name,
19
+ :public_key => public_key,
20
+ }
21
+
22
+ encoded_body = Fog::JSON.encode(create_options)
23
+
24
+ request(
25
+ :expects => [201],
26
+ :headers => {
27
+ 'Content-Type' => "application/json; charset=UTF-8",
28
+ },
29
+ :method => 'POST',
30
+ :path => '/v2/account/keys',
31
+ :body => encoded_body,
32
+ )
33
+ end
34
+ end
35
+
36
+ # These mocking improvements are not yet in fog master:
37
+ # https://github.com/fog/fog/pull/3748
38
+ class Mock
39
+ def create_ssh_key(name, public_key)
40
+ response = Excon::Response.new
41
+ response.status = 201
42
+
43
+ data[:ssh_keys] << {
44
+ "id" => Fog::Mock.random_numbers(6).to_i,
45
+ "fingerprint" => (["00"] * 16).join(':'),
46
+ "public_key" => public_key,
47
+ "name" => name
48
+ }
49
+
50
+ response.body ={
51
+ 'ssh_key' => data[:ssh_keys].last
52
+ }
53
+
54
+ response
55
+ end
56
+
57
+ def list_ssh_keys
58
+ response = Excon::Response.new
59
+ response.status = 200
60
+ response.body = {
61
+ "ssh_keys" => data[:ssh_keys],
62
+ "links" => {},
63
+ "meta" => {
64
+ "total" => data[:ssh_keys].count
65
+ }
66
+ }
67
+ response
68
+ end
69
+
70
+ def delete_ssh_key(id)
71
+ self.data[:ssh_keys].select! do |key|
72
+ key["id"] != id
73
+ end
74
+
75
+ response = Excon::Response.new
76
+ response.status = 204
77
+ response
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -5,10 +5,19 @@ module Rubber
5
5
 
6
6
  def self.get_provider(provider, env, capistrano)
7
7
  require "rubber/cloud/#{provider}"
8
- clazz = Rubber::Cloud.const_get(Rubber::Util.camelcase(provider))
9
8
  provider_env = env.cloud_providers[provider]
10
- return clazz.new(provider_env, capistrano)
9
+
10
+ # Check to see if we have a Rubber::Cloud::Provider::Factory class. If
11
+ # not, fall back to Rubber::Cloud::Provider
12
+ begin
13
+ factory = Rubber::Cloud.const_get(Rubber::Util.camelcase(provider))::Factory
14
+ return factory.get_provider(provider_env, capistrano)
15
+ rescue NameError
16
+ clazz = Rubber::Cloud.const_get(Rubber::Util.camelcase(provider))
17
+ return clazz.new(provider_env, capistrano)
18
+ end
11
19
  end
12
20
 
13
21
  end
14
22
  end
23
+
@@ -1,545 +1,18 @@
1
- require 'rubber/cloud/fog'
2
- require 'rubber/cloud/aws_table_store'
3
-
4
1
  module Rubber
5
- module Cloud
6
-
7
- class Aws < Fog
8
-
9
- def initialize(env, capistrano)
10
-
11
- compute_credentials = {
12
- :aws_access_key_id => env.access_key,
13
- :aws_secret_access_key => env.secret_access_key
14
- }
15
-
16
- storage_credentials = {
17
- :provider => 'AWS',
18
- :aws_access_key_id => env.access_key,
19
- :aws_secret_access_key => env.secret_access_key,
20
- :path_style => true
21
- }
22
-
23
- @table_store = ::Fog::AWS::SimpleDB.new(compute_credentials)
24
-
25
- compute_credentials[:region] = env.region
26
- @elb = ::Fog::AWS::ELB.new(compute_credentials)
27
-
28
- compute_credentials[:provider] = 'AWS' # We need to set the provider after the SimpleDB init because it fails if the provider value is specified.
29
-
30
- storage_credentials[:region] = env.region
31
-
32
- env['compute_credentials'] = compute_credentials
33
- env['storage_credentials'] = storage_credentials
34
- super(env, capistrano)
35
- end
36
-
37
- def table_store(table_key)
38
- return Rubber::Cloud::AwsTableStore.new(@table_store, table_key)
39
- end
40
-
41
- def describe_instances(instance_id=nil)
42
- instances = []
43
- opts = {}
44
- opts["instance-id"] = instance_id if instance_id
45
-
46
- response = compute_provider.servers.all(opts)
47
- response.each do |item|
48
- instance = {}
49
- instance[:id] = item.id
50
- instance[:type] = item.flavor_id
51
- instance[:external_host] = item.dns_name
52
- instance[:external_ip] = item.public_ip_address
53
- instance[:internal_host] = item.private_dns_name
54
- instance[:internal_ip] = item.private_ip_address
55
- instance[:state] = item.state
56
- instance[:zone] = item.availability_zone
57
- instance[:provider] = 'aws'
58
- instance[:platform] = item.platform || Rubber::Platforms::LINUX
59
- instance[:root_device_type] = item.root_device_type
60
- instances << instance
61
- end
62
-
63
- return instances
64
- end
65
-
66
- def active_state
67
- 'running'
68
- end
69
-
70
- def stopped_state
71
- 'stopped'
72
- end
73
-
74
- def before_create_instance(instance_alias, role_names)
75
- setup_security_groups(instance_alias, role_names)
76
- end
77
-
78
- def after_create_instance(instance)
79
- # Sometimes tag creation will fail, indicating that the instance doesn't exist yet even though it does. It seems to
80
- # be a propagation delay on Amazon's end, so the best we can do is wait and try again.
81
- Rubber::Util.retry_on_failure(StandardError, :retry_sleep => 1, :retry_count => 120) do
82
- Rubber::Tag::update_instance_tags(instance.name)
83
- end
84
- end
85
-
86
- def after_refresh_instance(instance)
87
- # Sometimes tag creation will fail, indicating that the instance doesn't exist yet even though it does. It seems to
88
- # be a propagation delay on Amazon's end, so the best we can do is wait and try again.
89
- Rubber::Util.retry_on_failure(StandardError, :retry_sleep => 1, :retry_count => 120) do
90
- Rubber::Tag::update_instance_tags(instance.name)
91
- end
92
- end
93
-
94
- def before_stop_instance(instance)
95
- capistrano.fatal "Cannot stop spot instances!" if ! instance.spot_instance_request_id.nil?
96
- capistrano.fatal "Cannot stop instances with instance-store root device!" if (instance.root_device_type != 'ebs')
97
- end
98
-
99
- def before_start_instance(instance)
100
- capistrano.fatal "Cannot start spot instances!" if ! instance.spot_instance_request_id.nil?
101
- capistrano.fatal "Cannot start instances with instance-store root device!" if (instance.root_device_type != 'ebs')
102
- end
103
-
104
- def after_start_instance(instance)
105
- # Re-starting an instance will almost certainly give it a new set of IPs and DNS entries, so refresh the values.
106
- capistrano.rubber.refresh_instance(instance.name)
107
-
108
- # Static IPs, DNS, etc. need to be set up for the started instance.
109
- capistrano.rubber.post_refresh
110
- end
2
+ module Cloud
3
+ module Aws
111
4
 
112
- def create_image(image_name)
5
+ class Factory
6
+ def self.get_provider(provider_env, capistrano)
7
+ require 'rubber/cloud/aws/vpc'
8
+ require 'rubber/cloud/aws/classic'
113
9
 
114
- # validate all needed config set
115
- ["key_file", "pk_file", "cert_file", "account", "secret_access_key", "image_bucket"].each do |k|
116
- raise "Set #{k} in rubber.yml" unless "#{env[k]}".strip.size > 0
10
+ klazz = provider_env.vpc_alias ? Rubber::Cloud::Aws::Vpc : Rubber::Cloud::Aws::Classic
11
+ klazz.new provider_env, capistrano
117
12
  end
118
- raise "create_image can only be called from a capistrano scope" unless capistrano
119
-
120
- ec2_key = env.key_file
121
- ec2_pk = env.pk_file
122
- ec2_cert = env.cert_file
123
-
124
- ec2_key_dest = "/mnt/#{File.basename(ec2_key)}"
125
- ec2_pk_dest = "/mnt/#{File.basename(ec2_pk)}"
126
- ec2_cert_dest = "/mnt/#{File.basename(ec2_cert)}"
127
-
128
- storage(env.image_bucket).ensure_bucket
129
-
130
- capistrano.put(File.read(ec2_key), ec2_key_dest)
131
- capistrano.put(File.read(ec2_pk), ec2_pk_dest)
132
- capistrano.put(File.read(ec2_cert), ec2_cert_dest)
133
-
134
- arch = capistrano.capture("uname -m").strip
135
- arch = case arch when /i\d86/ then "i386" else arch end
136
-
137
- capistrano.sudo_script "create_bundle", <<-CMD
138
- export RUBYLIB=/usr/lib/site_ruby/
139
- unset RUBYOPT
140
- nohup ec2-bundle-vol --batch -d /mnt -k #{ec2_pk_dest} -c #{ec2_cert_dest} -u #{env.account} -p #{image_name} -r #{arch} &> /tmp/ec2-bundle-vol.log &
141
- bg_pid=$!
142
- sleep 1
143
-
144
- echo "Creating image from instance volume..."
145
- while kill -0 $bg_pid &> /dev/null; do
146
- echo -n .
147
- sleep 5
148
- done
149
-
150
- # this returns exit code even if pid has already died, and thus triggers fail fast shell error
151
- wait $bg_pid
152
- CMD
153
-
154
- capistrano.sudo_script "register_bundle", <<-CMD
155
- export RUBYLIB=/usr/lib/site_ruby/
156
- unset RUBYOPT
157
- echo "Uploading image to S3..."
158
- ec2-upload-bundle --batch -b #{env.image_bucket} -m /mnt/#{image_name}.manifest.xml -a #{env.access_key} -s #{env.secret_access_key}
159
- CMD
160
-
161
- image_location = "#{env.image_bucket}/#{image_name}.manifest.xml"
162
- response = compute_provider.register_image(image_name,
163
- "rubber bundled image",
164
- image_location)
165
- return response.body["imageId"]
166
- end
167
-
168
- def destroy_image(image_id)
169
- image = compute_provider.images.get(image_id)
170
- raise "Could not find image: #{image_id}, aborting destroy_image" if image.nil?
171
-
172
- location_parts = image.location.split('/')
173
- bucket = location_parts.first
174
- image_name = location_parts.last.gsub(/\.manifest\.xml$/, '')
175
-
176
- image.deregister
177
-
178
- storage(bucket).walk_tree(image_name) do |f|
179
- f.destroy
180
- end
181
- end
182
-
183
- def describe_load_balancers(name=nil)
184
- lbs = []
185
- response = name.nil? ? @elb.load_balancers.all() : [@elb.load_balancers.get(name)].compact
186
- response.each do |item|
187
- lb = {}
188
- lb[:name] = item.id
189
- lb[:dns_name] = item.dns_name
190
- lb[:zones] = item.availability_zones
191
-
192
- item.listeners.each do |litem|
193
- listener = {}
194
- listener[:protocol] = litem.protocol
195
- listener[:port] = litem.lb_portPort
196
- listener[:instance_port] = litem.instance_port
197
- lb[:listeners] ||= []
198
- lb[:listeners] << listener
199
- end
200
-
201
- lbs << lb
202
- end
203
- return lbs
204
- end
205
-
206
- def describe_availability_zones
207
- zones = []
208
- response = compute_provider.describe_availability_zones()
209
- items = response.body["availabilityZoneInfo"]
210
- items.each do |item|
211
- zone = {}
212
- zone[:name] = item["zoneName"]
213
- zone[:state] =item["zoneState"]
214
- zones << zone
215
- end
216
- return zones
217
- end
218
-
219
- def create_spot_instance_request(spot_price, ami, ami_type, security_groups, availability_zone, fog_options={})
220
- response = compute_provider.spot_requests.create({:price => spot_price,
221
- :image_id => ami,
222
- :flavor_id => ami_type,
223
- :groups => security_groups,
224
- :availability_zone => availability_zone,
225
- :key_name => env.key_name}.merge(Rubber::Util.symbolize_keys(fog_options)))
226
- request_id = response.id
227
- return request_id
228
- end
229
-
230
- def describe_spot_instance_requests(request_id=nil)
231
- requests = []
232
- opts = {}
233
- opts["spot-instance-request-id"] = request_id if request_id
234
- response = compute_provider.spot_requests.all(opts)
235
- response.each do |item|
236
- request = {}
237
- request[:id] = item.id
238
- request[:spot_price] = item.price
239
- request[:state] = item.state
240
- request[:created_at] = item.created_at
241
- request[:type] = item.flavor_id
242
- request[:image_id] = item.image_id
243
- request[:instance_id] = item.instance_id
244
- requests << request
245
- end
246
- return requests
247
- end
248
-
249
- def setup_security_groups(host=nil, roles=[])
250
- rubber_cfg = Rubber::Configuration.get_configuration(Rubber.env)
251
- scoped_env = rubber_cfg.environment.bind(roles, host)
252
- security_group_defns = Hash[scoped_env.security_groups.to_a]
253
-
254
- if scoped_env.auto_security_groups
255
- sghosts = (scoped_env.rubber_instances.collect{|ic| ic.name } + [host]).uniq.compact
256
- sgroles = (scoped_env.rubber_instances.all_roles + roles).uniq.compact
257
- security_group_defns = inject_auto_security_groups(security_group_defns, sghosts, sgroles)
258
- end
259
-
260
- sync_security_groups(security_group_defns)
261
13
  end
262
14
 
263
- def describe_security_groups(group_name=nil)
264
- groups = []
265
-
266
- opts = {}
267
- opts["group-name"] = group_name if group_name
268
- response = compute_provider.security_groups.all(opts)
269
-
270
- response.each do |item|
271
- group = {}
272
- group[:name] = item.name
273
- group[:description] = item.description
274
-
275
- item.ip_permissions.each do |ip_item|
276
- group[:permissions] ||= []
277
- rule = {}
278
-
279
- rule[:protocol] = ip_item["ipProtocol"]
280
- rule[:from_port] = ip_item["fromPort"]
281
- rule[:to_port] = ip_item["toPort"]
282
-
283
- ip_item["groups"].each do |rule_group|
284
- rule[:source_groups] ||= []
285
- source_group = {}
286
- source_group[:account] = rule_group["userId"]
287
-
288
- # Amazon doesn't appear to be returning the groupName value when running in a default VPC. It's possible
289
- # it's only returned for EC2 Classic. This is distinctly in conflict with the API documents and thus
290
- # appears to be a bug on Amazon's end. Nonetheless, we need to handle it because otherwise our security
291
- # group rule matching logic will fail and it messes up our users.
292
- #
293
- # Since every top-level item has both an ID and a name, if we're lacking the groupName we can search
294
- # through the items for the one matching the groupId we have and then use its name value. This should
295
- # represent precisely the same data.
296
- source_group[:name] = if rule_group["groupName"]
297
- rule_group["groupName"]
298
- elsif rule_group["groupId"]
299
- matching_security_group = response.find { |item| item.group_id == rule_group["groupId"] }
300
- matching_security_group ? matching_security_group.name : nil
301
- else
302
- nil
303
- end
304
-
305
- rule[:source_groups] << source_group
306
- end if ip_item["groups"]
307
-
308
- ip_item["ipRanges"].each do |ip_range|
309
- rule[:source_ips] ||= []
310
- rule[:source_ips] << ip_range["cidrIp"]
311
- end if ip_item["ipRanges"]
312
-
313
- group[:permissions] << rule
314
- end
315
-
316
- groups << group
317
- end
318
-
319
- groups
320
- end
321
-
322
- def create_volume(instance, volume_spec)
323
- fog_options = Rubber::Util.symbolize_keys(volume_spec['fog_options'] || {})
324
- volume_data = {
325
- :size => volume_spec['size'], :availability_zone => volume_spec['zone']
326
- }.merge(fog_options)
327
- volume = compute_provider.volumes.create(volume_data)
328
- volume.id
329
- end
330
-
331
- def after_create_volume(instance, volume_id, volume_spec)
332
- # After we create an EBS volume, we need to attach it to the instance.
333
- volume = compute_provider.volumes.get(volume_id)
334
- server = compute_provider.servers.get(instance.instance_id)
335
- volume.device = volume_spec['device']
336
- volume.server = server
337
- end
338
-
339
- def before_destroy_volume(volume_id)
340
- # Before we can destroy an EBS volume, we must detach it from any running instances.
341
- volume = compute_provider.volumes.get(volume_id)
342
- volume.force_detach
343
- end
344
-
345
- def destroy_volume(volume_id)
346
- compute_provider.volumes.get(volume_id).destroy
347
- end
348
-
349
- def describe_volumes(volume_id=nil)
350
- volumes = []
351
- opts = {}
352
- opts[:'volume-id'] = volume_id if volume_id
353
- response = compute_provider.volumes.all(opts)
354
-
355
- response.each do |item|
356
- volume = {}
357
- volume[:id] = item.id
358
- volume[:status] = item.state
359
-
360
- if item.server_id
361
- volume[:attachment_instance_id] = item.server_id
362
- volume[:attachment_status] = item.attached_at ? "attached" : "waiting"
363
- end
364
-
365
- volumes << volume
366
- end
367
-
368
- volumes
369
- end
370
-
371
- # resource_id is any Amazon resource ID (e.g., instance ID or volume ID)
372
- # tags is a hash of tag_name => tag_value pairs
373
- def create_tags(resource_id, tags)
374
- # Tags need to be created individually in fog
375
- tags.each do |k, v|
376
- compute_provider.tags.create(:resource_id => resource_id,
377
- :key => k.to_s, :value => v.to_s)
378
- end
379
- end
380
-
381
- private
382
-
383
- def create_security_group(group_name, group_description)
384
- compute_provider.security_groups.create(:name => group_name, :description => group_description)
385
- end
386
-
387
- def destroy_security_group(group_name)
388
- compute_provider.security_groups.get(group_name).destroy
389
- end
390
-
391
- def add_security_group_rule(group_name, protocol, from_port, to_port, source)
392
- group = compute_provider.security_groups.get(group_name)
393
- opts = {:ip_protocol => protocol || 'tcp'}
394
-
395
- if source.instance_of? Hash
396
- opts[:group] = {source[:account] => source[:name]}
397
- else
398
- opts[:cidr_ip] = source
399
- end
400
-
401
- group.authorize_port_range(from_port.to_i..to_port.to_i, opts)
402
- end
403
-
404
- def remove_security_group_rule(group_name, protocol, from_port, to_port, source)
405
- group = compute_provider.security_groups.get(group_name)
406
- opts = {:ip_protocol => protocol || 'tcp'}
407
-
408
- if source.instance_of? Hash
409
- opts[:group] = {source[:account] => source[:name]}
410
- else
411
- opts[:cidr_ip] = source
412
- end
413
-
414
- group.revoke_port_range(from_port.to_i..to_port.to_i, opts)
415
- end
416
-
417
- def sync_security_groups(groups)
418
- return unless groups
419
-
420
- groups = Rubber::Util::stringify(groups)
421
- groups = isolate_groups(groups)
422
- group_keys = groups.keys.clone()
423
-
424
- # For each group that does already exist in cloud
425
- cloud_groups = describe_security_groups()
426
- cloud_groups.each do |cloud_group|
427
- group_name = cloud_group[:name]
428
-
429
- # skip those groups that don't belong to this project/env
430
- next if env.isolate_security_groups && group_name !~ /^#{isolate_prefix}/
431
-
432
- if group_keys.delete(group_name)
433
- # sync rules
434
- capistrano.logger.debug "Security Group already in cloud, syncing rules: #{group_name}"
435
- group = groups[group_name]
436
-
437
- # convert the special case default rule into what it actually looks like when
438
- # we query ec2 so that we can match things up when syncing
439
- rules = group['rules'].clone
440
- group['rules'].each do |rule|
441
- if [2, 3].include?(rule.size) && rule['source_group_name'] && rule['source_group_account']
442
- rules << rule.merge({'protocol' => 'tcp', 'from_port' => '1', 'to_port' => '65535' })
443
- rules << rule.merge({'protocol' => 'udp', 'from_port' => '1', 'to_port' => '65535' })
444
- rules << rule.merge({'protocol' => 'icmp', 'from_port' => '-1', 'to_port' => '-1' })
445
- rules.delete(rule)
446
- end
447
- end
448
-
449
- rule_maps = []
450
-
451
- # first collect the rule maps from the request (group/user pairs are duplicated for tcp/udp/icmp,
452
- # so we need to do this up frnot and remove duplicates before checking against the local rubber rules)
453
- cloud_group[:permissions].each do |rule|
454
- source_groups = rule.delete(:source_groups)
455
- if source_groups
456
- source_groups.each do |source_group|
457
- rule_map = rule.clone
458
- rule_map.delete(:source_ips)
459
- rule_map[:source_group_name] = source_group[:name]
460
- rule_map[:source_group_account] = source_group[:account]
461
- rule_map = Rubber::Util::stringify(rule_map)
462
- rule_maps << rule_map unless rule_maps.include?(rule_map)
463
- end
464
- else
465
- rule_map = Rubber::Util::stringify(rule)
466
- rule_maps << rule_map unless rule_maps.include?(rule_map)
467
- end
468
- end if cloud_group[:permissions]
469
- # For each rule, if it exists, do nothing, otherwise remove it as its no longer defined locally
470
- rule_maps.each do |rule_map|
471
- if rules.delete(rule_map)
472
- # rules match, don't need to do anything
473
- # logger.debug "Rule in sync: #{rule_map.inspect}"
474
- else
475
- # rules don't match, remove them from cloud and re-add below
476
- answer = nil
477
- msg = "Rule '#{rule_map.inspect}' exists in cloud, but not locally"
478
- if env.prompt_for_security_group_sync
479
- answer = Capistrano::CLI.ui.ask("#{msg}, remove from cloud? [y/N]: ")
480
- else
481
- capistrano.logger.info(msg)
482
- end
483
-
484
- if answer =~ /^y/
485
- rule_map = Rubber::Util::symbolize_keys(rule_map)
486
- if rule_map[:source_group_name]
487
- remove_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
488
- else
489
- rule_map[:source_ips].each do |source_ip|
490
- remove_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
491
- end if rule_map[:source_ips]
492
- end
493
- end
494
- end
495
- end
496
-
497
- rules.each do |rule_map|
498
- # create non-existing rules
499
- capistrano.logger.debug "Missing rule, creating: #{rule_map.inspect}"
500
- rule_map = Rubber::Util::symbolize_keys(rule_map)
501
- if rule_map[:source_group_name]
502
- add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
503
- else
504
- rule_map[:source_ips].each do |source_ip|
505
- add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
506
- end if rule_map[:source_ips]
507
- end
508
- end
509
- else
510
- # delete group
511
- answer = nil
512
- msg = "Security group '#{group_name}' exists in cloud but not locally"
513
- if env.prompt_for_security_group_sync
514
- answer = Capistrano::CLI.ui.ask("#{msg}, remove from cloud? [y/N]: ")
515
- else
516
- capistrano.logger.debug(msg)
517
- end
518
- destroy_security_group(group_name) if answer =~ /^y/
519
- end
520
- end
521
-
522
- # For each group that didnt already exist in cloud
523
- group_keys.each do |group_name|
524
- group = groups[group_name]
525
- capistrano.logger.debug "Creating new security group: #{group_name}"
526
- # create each group
527
- create_security_group(group_name, group['description'])
528
- # create rules for group
529
- group['rules'].each do |rule_map|
530
- capistrano.logger.debug "Creating new rule: #{rule_map.inspect}"
531
- rule_map = Rubber::Util::symbolize_keys(rule_map)
532
- if rule_map[:source_group_name]
533
- add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], {:name => rule_map[:source_group_name], :account => rule_map[:source_group_account]})
534
- else
535
- rule_map[:source_ips].each do |source_ip|
536
- add_security_group_rule(group_name, rule_map[:protocol], rule_map[:from_port], rule_map[:to_port], source_ip)
537
- end if rule_map[:source_ips]
538
- end
539
- end
540
- end
541
- end
542
15
  end
543
-
544
16
  end
545
17
  end
18
+