right_aws 1.9.0 → 3.1.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.
Files changed (70) hide show
  1. data/History.txt +164 -13
  2. data/Manifest.txt +28 -1
  3. data/README.txt +12 -10
  4. data/Rakefile +56 -29
  5. data/lib/acf/right_acf_interface.rb +343 -172
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +229 -0
  9. data/lib/acw/right_acw_interface.rb +248 -0
  10. data/lib/as/right_as_interface.rb +698 -0
  11. data/lib/awsbase/right_awsbase.rb +755 -115
  12. data/lib/awsbase/support.rb +2 -78
  13. data/lib/awsbase/version.rb +9 -0
  14. data/lib/ec2/right_ec2.rb +274 -1294
  15. data/lib/ec2/right_ec2_ebs.rb +514 -0
  16. data/lib/ec2/right_ec2_images.rb +444 -0
  17. data/lib/ec2/right_ec2_instances.rb +797 -0
  18. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  19. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  20. data/lib/ec2/right_ec2_reserved_instances.rb +243 -0
  21. data/lib/ec2/right_ec2_security_groups.rb +496 -0
  22. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  23. data/lib/ec2/right_ec2_tags.rb +139 -0
  24. data/lib/ec2/right_ec2_vpc.rb +598 -0
  25. data/lib/ec2/right_ec2_vpc2.rb +382 -0
  26. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  27. data/lib/elb/right_elb_interface.rb +573 -0
  28. data/lib/emr/right_emr_interface.rb +728 -0
  29. data/lib/iam/right_iam_access_keys.rb +71 -0
  30. data/lib/iam/right_iam_groups.rb +195 -0
  31. data/lib/iam/right_iam_interface.rb +341 -0
  32. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  33. data/lib/iam/right_iam_users.rb +251 -0
  34. data/lib/rds/right_rds_interface.rb +1657 -0
  35. data/lib/right_aws.rb +30 -13
  36. data/lib/route_53/right_route_53_interface.rb +641 -0
  37. data/lib/s3/right_s3.rb +108 -41
  38. data/lib/s3/right_s3_interface.rb +349 -118
  39. data/lib/sdb/active_sdb.rb +388 -54
  40. data/lib/sdb/right_sdb_interface.rb +323 -64
  41. data/lib/sns/right_sns_interface.rb +286 -0
  42. data/lib/sqs/right_sqs.rb +1 -2
  43. data/lib/sqs/right_sqs_gen2.rb +73 -17
  44. data/lib/sqs/right_sqs_gen2_interface.rb +146 -73
  45. data/lib/sqs/right_sqs_interface.rb +12 -22
  46. data/right_aws.gemspec +91 -0
  47. data/test/README.mdown +39 -0
  48. data/test/acf/test_right_acf.rb +11 -19
  49. data/test/awsbase/test_helper.rb +2 -0
  50. data/test/awsbase/test_right_awsbase.rb +11 -0
  51. data/test/ec2/test_right_ec2.rb +32 -1
  52. data/test/elb/test_helper.rb +2 -0
  53. data/test/elb/test_right_elb.rb +43 -0
  54. data/test/rds/test_helper.rb +2 -0
  55. data/test/rds/test_right_rds.rb +120 -0
  56. data/test/route_53/fixtures/a_record.xml +18 -0
  57. data/test/route_53/fixtures/alias_record.xml +18 -0
  58. data/test/route_53/test_helper.rb +2 -0
  59. data/test/route_53/test_right_route_53.rb +141 -0
  60. data/test/s3/test_right_s3.rb +176 -42
  61. data/test/s3/test_right_s3_stubbed.rb +6 -4
  62. data/test/sdb/test_active_sdb.rb +120 -19
  63. data/test/sdb/test_batch_put_attributes.rb +54 -0
  64. data/test/sdb/test_right_sdb.rb +71 -16
  65. data/test/sns/test_helper.rb +2 -0
  66. data/test/sns/test_right_sns.rb +153 -0
  67. data/test/sqs/test_right_sqs.rb +0 -6
  68. data/test/sqs/test_right_sqs_gen2.rb +104 -49
  69. data/test/ts_right_aws.rb +1 -0
  70. metadata +181 -22
@@ -1,7 +1,3 @@
1
- # If ActiveSupport is loaded, then great - use it. But we don't
2
- # want a dependency on it, so if it's not present, define the few
3
- # extensions that we want to use...
4
- unless defined? ActiveSupport::CoreExtensions
5
1
  # These are ActiveSupport-;like extensions to do a few handy things in the gems
6
2
  # Derived from ActiveSupport, so the AS copyright notice applies:
7
3
  #
@@ -32,80 +28,8 @@ unless defined? ActiveSupport::CoreExtensions
32
28
  #
33
29
  class String #:nodoc:
34
30
 
35
- # Constantize tries to find a declared constant with the name specified
36
- # in the string. It raises a NameError when the name is not in CamelCase
37
- # or is not initialized.
38
- #
39
- # Examples
40
- # "Module".constantize #=> Module
41
- # "Class".constantize #=> Class
42
- def constantize()
43
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
44
- raise NameError, "#{self.inspect} is not a valid constant name!"
45
- end
46
-
47
- Object.module_eval("::#{$1}", __FILE__, __LINE__)
48
- end
49
-
50
- end
51
-
52
-
53
- class Object #:nodoc:
54
- # "", " ", nil, [], and {} are blank
55
- def blank?
56
- if respond_to?(:empty?) && respond_to?(:strip)
57
- empty? or strip.empty?
58
- elsif respond_to?(:empty?)
59
- empty?
60
- else
61
- !self
62
- end
63
- end
64
- end
65
-
66
- class NilClass #:nodoc:
67
- def blank?
68
- true
31
+ def right_underscore
32
+ self.gsub(/[A-Z]/){|match| "#{$`=='' ? '' : '_'}#{match.downcase}" }
69
33
  end
70
- end
71
-
72
- class FalseClass #:nodoc:
73
- def blank?
74
- true
75
- end
76
- end
77
-
78
- class TrueClass #:nodoc:
79
- def blank?
80
- false
81
- end
82
- end
83
-
84
- class Array #:nodoc:
85
- alias_method :blank?, :empty?
86
- end
87
-
88
- class Hash #:nodoc:
89
- alias_method :blank?, :empty?
90
34
 
91
- # Return a new hash with all keys converted to symbols.
92
- def symbolize_keys
93
- inject({}) do |options, (key, value)|
94
- options[key.to_sym] = value
95
- options
96
- end
97
- end
98
- end
99
-
100
- class String #:nodoc:
101
- def blank?
102
- empty? || strip.empty?
103
- end
104
- end
105
-
106
- class Numeric #:nodoc:
107
- def blank?
108
- false
109
- end
110
35
  end
111
- end
@@ -0,0 +1,9 @@
1
+ module RightAws #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 3 unless defined?(MAJOR)
4
+ MINOR = 1 unless defined?(MINOR)
5
+ TINY = 0 unless defined?(TINY)
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.') unless defined?(STRING)
8
+ end
9
+ end
data/lib/ec2/right_ec2.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2007-2008 RightScale Inc
2
+ # Copyright (c) 2007-2009 RightScale Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -68,7 +68,7 @@ module RightAws
68
68
  include RightAwsBaseInterface
69
69
 
70
70
  # Amazon EC2 API version being used
71
- API_VERSION = "2008-08-08"
71
+ API_VERSION = "2011-02-28"
72
72
  DEFAULT_HOST = "ec2.amazonaws.com"
73
73
  DEFAULT_PATH = '/'
74
74
  DEFAULT_PROTOCOL = 'https'
@@ -81,7 +81,25 @@ module RightAws
81
81
  # Amazon EC2 Instance Types : http://www.amazon.com/b?ie=UTF8&node=370375011
82
82
  # Default EC2 instance type (platform)
83
83
  DEFAULT_INSTANCE_TYPE = 'm1.small'
84
- INSTANCE_TYPES = ['m1.small','c1.medium','m1.large','m1.xlarge','c1.xlarge']
84
+ INSTANCE_TYPES = [ 't1.micro' ,
85
+ 'm1.small' ,
86
+ 'm1.medium' ,
87
+ 'm1.large' ,
88
+ 'm1.xlarge' ,
89
+ 'c1.medium' ,
90
+ 'c1.xlarge' ,
91
+ 'm2.xlarge' ,
92
+ 'm2.2xlarge',
93
+ 'm2.4xlarge',
94
+ 'm3.xlarge' ,
95
+ 'm3.2xlarge',
96
+ 'cc1.4xlarge',
97
+ 'cg1.4xlarge',
98
+ 'cc2.8xlarge',
99
+ 'hi1.4xlarge',
100
+ 'hs1.8xlarge',
101
+ 'cr1.8xlarge'
102
+ ]
85
103
 
86
104
  @@bench = AwsBenchmarkingBlock.new
87
105
  def self.bench_xml
@@ -100,769 +118,141 @@ module RightAws
100
118
  # Create a new handle to an EC2 account. All handles share the same per process or per thread
101
119
  # HTTP connection to Amazon EC2. Each handle is for a specific account. The params have the
102
120
  # following options:
121
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol and :region). Example: 'https://eu-west-1.ec2.amazonaws.com/'
103
122
  # * <tt>:server</tt>: EC2 service host, default: DEFAULT_HOST
123
+ # * <tt>:region</tt>: EC2 region (North America by default)
104
124
  # * <tt>:port</tt>: EC2 service port, default: DEFAULT_PORT
105
125
  # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
106
- # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
107
126
  # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
108
- # * <tt>:signature_version</tt>: The signature version : '0' or '1'(default)
127
+ # * <tt>:signature_version</tt>: The signature version : '0','1' or '2'(default)
109
128
  # * <tt>:cache</tt>: true/false: caching for: ec2_describe_images, describe_instances,
129
+ # * <tt>:token</tt>: Option SecurityToken for temporary credentials
110
130
  # describe_images_by_owner, describe_images_by_executable_by, describe_availability_zones,
111
131
  # describe_security_groups, describe_key_pairs, describe_addresses,
112
132
  # describe_volumes, describe_snapshots methods, default: false.
113
133
  #
114
134
  def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
115
- init({ :name => 'EC2',
116
- :default_host => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).host : DEFAULT_HOST,
117
- :default_port => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).port : DEFAULT_PORT,
118
- :default_service => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).path : DEFAULT_PATH,
119
- :default_protocol => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).scheme : DEFAULT_PROTOCOL },
135
+ init({ :name => 'EC2',
136
+ :default_host => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).host : DEFAULT_HOST,
137
+ :default_port => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).port : DEFAULT_PORT,
138
+ :default_service => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).path : DEFAULT_PATH,
139
+ :default_protocol => ENV['EC2_URL'] ? URI.parse(ENV['EC2_URL']).scheme : DEFAULT_PROTOCOL,
140
+ :default_api_version => @@api },
120
141
  aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] ,
121
142
  aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'],
122
143
  params)
144
+ # Eucalyptus supports some yummy features but Amazon does not
145
+ #if @params[:eucalyptus]
146
+ # @params[:port_based_group_ingress] = true unless @params.has_key?(:port_based_group_ingress)
147
+ #end
123
148
  end
124
149
 
125
-
126
- def generate_request(action, params={}) #:nodoc:
127
- service_hash = {"Action" => action,
128
- "AWSAccessKeyId" => @aws_access_key_id,
129
- "Version" => @@api,
130
- "Timestamp" => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
131
- "SignatureVersion" => signature_version }
132
- service_hash.update(params)
133
- # prepare string to sign
134
- string_to_sign = case signature_version
135
- when '0' then service_hash["Action"] + service_hash["Timestamp"]
136
- when '1' then service_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
137
- end
138
- service_hash.update('Signature' => AwsUtils::sign(@aws_secret_access_key, string_to_sign))
139
- request_params = service_hash.to_a.collect{|key,val| key + "=" + CGI::escape(val) }.join("&")
140
- request = Net::HTTP::Get.new("#{@params[:service]}?#{request_params}")
141
- # prepare output hash
142
- { :request => request,
143
- :server => @params[:server],
144
- :port => @params[:port],
145
- :protocol => @params[:protocol] }
150
+ def generate_request(action, params={}, custom_options={}) #:nodoc:
151
+ generate_request_impl(:get, action, params, custom_options)
146
152
  end
147
153
 
148
154
  # Sends request to Amazon and parses the response
149
155
  # Raises AwsError if any banana happened
150
156
  def request_info(request, parser) #:nodoc:
151
- thread = @params[:multi_thread] ? Thread.current : Thread.main
152
- thread[:ec2_connection] ||= Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
153
- request_info_impl(thread[:ec2_connection], @@bench, request, parser)
154
- end
155
-
156
- def hash_params(prefix, list) #:nodoc:
157
- groups = {}
158
- list.each_index{|i| groups.update("#{prefix}.#{i+1}"=>list[i])} if list
159
- return groups
160
- end
161
-
162
- #-----------------------------------------------------------------
163
- # Images
164
- #-----------------------------------------------------------------
165
-
166
- # params:
167
- # { 'ImageId' => ['id1', ..., 'idN'],
168
- # 'Owner' => ['self', ..., 'userN'],
169
- # 'ExecutableBy' => ['self', 'all', ..., 'userN']
170
- # }
171
- def ec2_describe_images(params={}, image_type=nil, cache_for=nil) #:nodoc:
172
- request_hash = {}
173
- params.each do |list_by, list|
174
- request_hash.merge! hash_params(list_by, list.to_a)
175
- end
176
- request_hash['ImageType'] = image_type if image_type
177
- link = generate_request("DescribeImages", request_hash)
178
- request_cache_or_info cache_for, link, QEc2DescribeImagesParser, @@bench, cache_for
179
- rescue Exception
180
- on_exception
181
- end
182
-
183
- # Retrieve a list of images. Returns array of hashes describing the images or an exception:
184
- # +image_type+ = 'machine' || 'kernel' || 'ramdisk'
185
- #
186
- # ec2.describe_images #=>
187
- # [{:aws_owner => "522821470517",
188
- # :aws_id => "ami-e4b6538d",
189
- # :aws_state => "available",
190
- # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
191
- # :aws_is_public => true,
192
- # :aws_architecture => "i386",
193
- # :aws_image_type => "machine"},
194
- # {...},
195
- # {...} ]
196
- #
197
- # If +list+ param is set, then retrieve information about the listed images only:
198
- #
199
- # ec2.describe_images(['ami-e4b6538d']) #=>
200
- # [{:aws_owner => "522821470517",
201
- # :aws_id => "ami-e4b6538d",
202
- # :aws_state => "available",
203
- # :aws_location => "marcins_cool_public_images/ubuntu-6.10.manifest.xml",
204
- # :aws_is_public => true,
205
- # :aws_architecture => "i386",
206
- # :aws_image_type => "machine"}]
207
- #
208
- def describe_images(list=[], image_type=nil)
209
- list = list.to_a
210
- cache_for = list.empty? && !image_type ? :describe_images : nil
211
- ec2_describe_images({ 'ImageId' => list }, image_type, cache_for)
212
- end
213
-
214
- #
215
- # Example:
216
- #
217
- # ec2.describe_images_by_owner('522821470517')
218
- # ec2.describe_images_by_owner('self')
219
- #
220
- def describe_images_by_owner(list=['self'], image_type=nil)
221
- list = list.to_a
222
- cache_for = list==['self'] && !image_type ? :describe_images_by_owner : nil
223
- ec2_describe_images({ 'Owner' => list }, image_type, cache_for)
224
- end
225
-
226
- #
227
- # Example:
228
- #
229
- # ec2.describe_images_by_executable_by('522821470517')
230
- # ec2.describe_images_by_executable_by('self')
231
- # ec2.describe_images_by_executable_by('all')
232
- #
233
- def describe_images_by_executable_by(list=['self'], image_type=nil)
234
- list = list.to_a
235
- cache_for = list==['self'] && !image_type ? :describe_images_by_executable_by : nil
236
- ec2_describe_images({ 'ExecutableBy' => list }, image_type, cache_for)
237
- end
238
-
239
-
240
- # Register new image at Amazon.
241
- # Returns new image id or an exception.
242
- #
243
- # ec2.register_image('bucket/key/manifest') #=> 'ami-e444444d'
244
- #
245
- def register_image(image_location)
246
- link = generate_request("RegisterImage",
247
- 'ImageLocation' => image_location.to_s)
248
- request_info(link, QEc2RegisterImageParser.new(:logger => @logger))
249
- rescue Exception
250
- on_exception
251
- end
252
-
253
- # Deregister image at Amazon. Returns +true+ or an exception.
254
- #
255
- # ec2.deregister_image('ami-e444444d') #=> true
256
- #
257
- def deregister_image(image_id)
258
- link = generate_request("DeregisterImage",
259
- 'ImageId' => image_id.to_s)
260
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
261
- rescue Exception
262
- on_exception
263
- end
264
-
265
-
266
- # Describe image attributes. Currently 'launchPermission', 'productCodes', 'kernel', 'ramdisk' and 'blockDeviceMapping' are supported.
267
- #
268
- # ec2.describe_image_attribute('ami-e444444d') #=> {:groups=>["all"], :users=>["000000000777"]}
269
- #
270
- def describe_image_attribute(image_id, attribute='launchPermission')
271
- link = generate_request("DescribeImageAttribute",
272
- 'ImageId' => image_id,
273
- 'Attribute' => attribute)
274
- request_info(link, QEc2DescribeImageAttributeParser.new(:logger => @logger))
275
- rescue Exception
276
- on_exception
277
- end
278
-
279
- # Reset image attribute. Currently, only 'launchPermission' is supported. Returns +true+ or an exception.
280
- #
281
- # ec2.reset_image_attribute('ami-e444444d') #=> true
282
- #
283
- def reset_image_attribute(image_id, attribute='launchPermission')
284
- link = generate_request("ResetImageAttribute",
285
- 'ImageId' => image_id,
286
- 'Attribute' => attribute)
287
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
288
- rescue Exception
289
- on_exception
290
- end
291
-
292
- # Modify an image's attributes. It is recommended that you use
293
- # modify_image_launch_perm_add_users, modify_image_launch_perm_remove_users, etc.
294
- # instead of modify_image_attribute because the signature of
295
- # modify_image_attribute may change with EC2 service changes.
296
- #
297
- # attribute : currently, only 'launchPermission' is supported.
298
- # operation_type : currently, only 'add' & 'remove' are supported.
299
- # vars:
300
- # :user_group : currently, only 'all' is supported.
301
- # :user_id
302
- # :product_code
303
- def modify_image_attribute(image_id, attribute, operation_type = nil, vars = {})
304
- params = {'ImageId' => image_id,
305
- 'Attribute' => attribute}
306
- params['OperationType'] = operation_type if operation_type
307
- params.update(hash_params('UserId', vars[:user_id].to_a)) if vars[:user_id]
308
- params.update(hash_params('UserGroup', vars[:user_group].to_a)) if vars[:user_group]
309
- params.update(hash_params('ProductCode', vars[:product_code])) if vars[:product_code]
310
- link = generate_request("ModifyImageAttribute", params)
311
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
312
- rescue Exception
313
- on_exception
314
- end
315
-
316
- # Grant image launch permissions to users.
317
- # Parameter +userId+ is a list of user AWS account ids.
318
- # Returns +true+ or an exception.
319
- #
320
- # ec2.modify_image_launch_perm_add_users('ami-e444444d',['000000000777','000000000778']) #=> true
321
- def modify_image_launch_perm_add_users(image_id, user_id=[])
322
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id.to_a)
323
- end
324
-
325
- # Revokes image launch permissions for users. +userId+ is a list of users AWS accounts ids. Returns +true+ or an exception.
326
- #
327
- # ec2.modify_image_launch_perm_remove_users('ami-e444444d',['000000000777','000000000778']) #=> true
328
- #
329
- def modify_image_launch_perm_remove_users(image_id, user_id=[])
330
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id.to_a)
331
- end
332
-
333
- # Add image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
334
- # Returns +true+ or an exception.
335
- #
336
- # ec2.modify_image_launch_perm_add_groups('ami-e444444d') #=> true
337
- #
338
- def modify_image_launch_perm_add_groups(image_id, user_group=['all'])
339
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => user_group.to_a)
340
- end
341
-
342
- # Remove image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
343
- #
344
- # ec2.modify_image_launch_perm_remove_groups('ami-e444444d') #=> true
345
- #
346
- def modify_image_launch_perm_remove_groups(image_id, user_group=['all'])
347
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => user_group.to_a)
348
- end
349
-
350
- # Add product code to image
351
- #
352
- # ec2.modify_image_product_code('ami-e444444d','0ABCDEF') #=> true
353
- #
354
- def modify_image_product_code(image_id, product_code=[])
355
- modify_image_attribute(image_id, 'productCodes', nil, :product_code => product_code.to_a)
356
- end
357
-
358
- #-----------------------------------------------------------------
359
- # Instances
360
- #-----------------------------------------------------------------
361
-
362
- def get_desc_instances(instances) # :nodoc:
363
- result = []
364
- instances.each do |reservation|
365
- reservation[:instances_set].each do |instance|
366
- # Parse and remove timestamp from the reason string. The timestamp is of
367
- # the request, not when EC2 took action, thus confusing & useless...
368
- instance[:aws_reason] = instance[:aws_reason].sub(/\(\d[^)]*GMT\) */, '')
369
- instance[:aws_owner] = reservation[:aws_owner]
370
- instance[:aws_reservation_id] = reservation[:aws_reservation_id]
371
- instance[:aws_groups] = reservation[:aws_groups]
372
- result << instance
157
+ request_info_impl(:ec2_connection, @@bench, request, parser)
158
+ end
159
+
160
+ def describe_resources_with_list_and_options(remote_function_name, remote_item_name, parser_class, list_and_options, &block) # :nodoc:
161
+ # 'RemoteFunctionName' -> :remote_funtion_name
162
+ cache_name = remote_function_name.right_underscore.to_sym
163
+ list, options = AwsUtils::split_items_and_params(list_and_options)
164
+ custom_options = {}
165
+ # Resource IDs to fetch
166
+ request_hash = amazonize_list(remote_item_name, list)
167
+ # Other custom options
168
+ options.each do |key, values|
169
+ next if values.right_blank?
170
+ case key
171
+ when :options
172
+ custom_options = values
173
+ when :filters then
174
+ request_hash.merge!(amazonize_list(['Filter.?.Name', 'Filter.?.Value.?'], values))
175
+ else
176
+ request_hash.merge!(amazonize_list(key.to_s.right_camelize, values))
373
177
  end
374
178
  end
375
- result
376
- rescue Exception
377
- on_exception
378
- end
379
-
380
- # Retrieve information about EC2 instances. If +list+ is omitted then returns the
381
- # list of all instances.
382
- #
383
- # ec2.describe_instances #=>
384
- # [{:aws_image_id => "ami-e444444d",
385
- # :aws_reason => "",
386
- # :aws_state_code => "16",
387
- # :aws_owner => "000000000888",
388
- # :aws_instance_id => "i-123f1234",
389
- # :aws_reservation_id => "r-aabbccdd",
390
- # :aws_state => "running",
391
- # :dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
392
- # :ssh_key_name => "staging",
393
- # :aws_groups => ["default"],
394
- # :private_dns_name => "domU-12-34-67-89-01-C9.usma2.compute.amazonaws.com",
395
- # :aws_instance_type => "m1.small",
396
- # :aws_launch_time => "2008-1-1T00:00:00.000Z"},
397
- # :aws_availability_zone => "us-east-1b",
398
- # :aws_kernel_id => "aki-ba3adfd3",
399
- # :aws_ramdisk_id => "ari-badbad00",
400
- # ..., {...}]
401
- #
402
- def describe_instances(list=[])
403
- link = generate_request("DescribeInstances", hash_params('InstanceId',list.to_a))
404
- request_cache_or_info(:describe_instances, link, QEc2DescribeInstancesParser, @@bench, list.blank?) do |parser|
405
- get_desc_instances(parser.result)
406
- end
407
- rescue Exception
408
- on_exception
409
- end
410
-
411
- # Return the product code attached to instance or +nil+ otherwise.
412
- #
413
- # ec2.confirm_product_instance('ami-e444444d','12345678') #=> nil
414
- # ec2.confirm_product_instance('ami-e444444d','00001111') #=> "000000000888"
415
- #
416
- def confirm_product_instance(instance, product_code)
417
- link = generate_request("ConfirmProductInstance", { 'ProductCode' => product_code,
418
- 'InstanceId' => instance })
419
- request_info(link, QEc2ConfirmProductInstanceParser.new(:logger => @logger))
420
- end
421
-
422
- # Launch new EC2 instances. Returns a list of launched instances or an exception.
423
- #
424
- # ec2.run_instances('ami-e444444d',1,1,['my_awesome_group'],'my_awesome_key', 'Woohoo!!!', 'public') #=>
425
- # [{:aws_image_id => "ami-e444444d",
426
- # :aws_reason => "",
427
- # :aws_state_code => "0",
428
- # :aws_owner => "000000000888",
429
- # :aws_instance_id => "i-123f1234",
430
- # :aws_reservation_id => "r-aabbccdd",
431
- # :aws_state => "pending",
432
- # :dns_name => "",
433
- # :ssh_key_name => "my_awesome_key",
434
- # :aws_groups => ["my_awesome_group"],
435
- # :private_dns_name => "",
436
- # :aws_instance_type => "m1.small",
437
- # :aws_launch_time => "2008-1-1T00:00:00.000Z"
438
- # :aws_ramdisk_id => "ari-8605e0ef"
439
- # :aws_kernel_id => "aki-9905e0f0",
440
- # :ami_launch_index => "0",
441
- # :aws_availability_zone => "us-east-1b"
442
- # }]
443
- #
444
- def run_instances(image_id, min_count, max_count, group_ids, key_name, user_data='',
445
- addressing_type = nil, instance_type = nil,
446
- kernel_id = nil, ramdisk_id = nil, availability_zone = nil,
447
- block_device_mappings = nil)
448
- launch_instances(image_id, { :min_count => min_count,
449
- :max_count => max_count,
450
- :user_data => user_data,
451
- :group_ids => group_ids,
452
- :key_name => key_name,
453
- :instance_type => instance_type,
454
- :addressing_type => addressing_type,
455
- :kernel_id => kernel_id,
456
- :ramdisk_id => ramdisk_id,
457
- :availability_zone => availability_zone,
458
- :block_device_mappings => block_device_mappings
459
- })
460
- end
461
-
462
-
463
- # Launch new EC2 instances. Returns a list of launched instances or an exception.
464
- #
465
- # +lparams+ keys (default values in parenthesis):
466
- # :min_count fixnum, (1)
467
- # :max_count fixnum, (1)
468
- # :group_ids array or string ([] == 'default')
469
- # :instance_type string (DEFAULT_INSTACE_TYPE)
470
- # :addressing_type string (DEFAULT_ADDRESSING_TYPE
471
- # :key_name string
472
- # :kernel_id string
473
- # :ramdisk_id string
474
- # :availability_zone string
475
- # :block_device_mappings string
476
- # :user_data string
477
- #
478
- # ec2.launch_instances('ami-e444444d', :group_ids => 'my_awesome_group',
479
- # :user_data => "Woohoo!!!",
480
- # :addressing_type => "public",
481
- # :key_name => "my_awesome_key",
482
- # :availability_zone => "us-east-1c") #=>
483
- # [{:aws_image_id => "ami-e444444d",
484
- # :aws_reason => "",
485
- # :aws_state_code => "0",
486
- # :aws_owner => "000000000888",
487
- # :aws_instance_id => "i-123f1234",
488
- # :aws_reservation_id => "r-aabbccdd",
489
- # :aws_state => "pending",
490
- # :dns_name => "",
491
- # :ssh_key_name => "my_awesome_key",
492
- # :aws_groups => ["my_awesome_group"],
493
- # :private_dns_name => "",
494
- # :aws_instance_type => "m1.small",
495
- # :aws_launch_time => "2008-1-1T00:00:00.000Z",
496
- # :aws_ramdisk_id => "ari-8605e0ef"
497
- # :aws_kernel_id => "aki-9905e0f0",
498
- # :ami_launch_index => "0",
499
- # :aws_availability_zone => "us-east-1c"
500
- # }]
501
- #
502
- def launch_instances(image_id, lparams={})
503
- @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, " +
504
- "key: #{lparams[:key_name]}, groups: #{(lparams[:group_ids]).to_a.join(',')}")
505
- # careful: keyName and securityGroups may be nil
506
- params = hash_params('SecurityGroup', lparams[:group_ids].to_a)
507
- params.update( {'ImageId' => image_id,
508
- 'MinCount' => (lparams[:min_count] || 1).to_s,
509
- 'MaxCount' => (lparams[:max_count] || 1).to_s,
510
- 'AddressingType' => lparams[:addressing_type] || DEFAULT_ADDRESSING_TYPE,
511
- 'InstanceType' => lparams[:instance_type] || DEFAULT_INSTANCE_TYPE })
512
- # optional params
513
- params['KeyName'] = lparams[:key_name] unless lparams[:key_name].blank?
514
- params['KernelId'] = lparams[:kernel_id] unless lparams[:kernel_id].blank?
515
- params['RamdiskId'] = lparams[:ramdisk_id] unless lparams[:ramdisk_id].blank?
516
- params['Placement.AvailabilityZone'] = lparams[:availability_zone] unless lparams[:availability_zone].blank?
517
- params['BlockDeviceMappings'] = lparams[:block_device_mappings] unless lparams[:block_device_mappings].blank?
518
- unless lparams[:user_data].blank?
519
- lparams[:user_data].strip!
520
- # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library.
521
- # Amazon 169.254.169.254 does not like escaped symbols!
522
- # And it doesn't like "\n" inside of encoded string! Grrr....
523
- # Otherwise, some of UserData symbols will be lost...
524
- params['UserData'] = Base64.encode64(lparams[:user_data]).delete("\n") unless lparams[:user_data].blank?
525
- end
526
- link = generate_request("RunInstances", params)
527
- #debugger
528
- instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger))
529
- get_desc_instances(instances)
530
- rescue Exception
531
- on_exception
532
- end
533
-
534
- # Terminates EC2 instances. Returns a list of termination params or an exception.
535
- #
536
- # ec2.terminate_instances(['i-f222222d','i-f222222e']) #=>
537
- # [{:aws_shutdown_state => "shutting-down",
538
- # :aws_instance_id => "i-f222222d",
539
- # :aws_shutdown_state_code => 32,
540
- # :aws_prev_state => "running",
541
- # :aws_prev_state_code => 16},
542
- # {:aws_shutdown_state => "shutting-down",
543
- # :aws_instance_id => "i-f222222e",
544
- # :aws_shutdown_state_code => 32,
545
- # :aws_prev_state => "running",
546
- # :aws_prev_state_code => 16}]
547
- #
548
- def terminate_instances(list=[])
549
- link = generate_request("TerminateInstances", hash_params('InstanceId',list.to_a))
550
- request_info(link, QEc2TerminateInstancesParser.new(:logger => @logger))
551
- rescue Exception
552
- on_exception
553
- end
554
-
555
- # Retreive EC2 instance OS logs. Returns a hash of data or an exception.
556
- #
557
- # ec2.get_console_output('i-f222222d') =>
558
- # {:aws_instance_id => 'i-f222222d',
559
- # :aws_timestamp => "2007-05-23T14:36:07.000-07:00",
560
- # :timestamp => Wed May 23 21:36:07 UTC 2007, # Time instance
561
- # :aws_output => "Linux version 2.6.16-xenU (builder@patchbat.amazonsa) (gcc version 4.0.1 20050727 ..."
562
- def get_console_output(instance_id)
563
- link = generate_request("GetConsoleOutput", { 'InstanceId.1' => instance_id })
564
- request_info(link, QEc2GetConsoleOutputParser.new(:logger => @logger))
565
- rescue Exception
566
- on_exception
567
- end
568
-
569
- # Reboot an EC2 instance. Returns +true+ or an exception.
570
- #
571
- # ec2.reboot_instances(['i-f222222d','i-f222222e']) #=> true
572
- #
573
- def reboot_instances(list)
574
- link = generate_request("RebootInstances", hash_params('InstanceId', list.to_a))
575
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
576
- rescue Exception
577
- on_exception
578
- end
579
-
580
- #-----------------------------------------------------------------
581
- # Instances: Windows addons
582
- #-----------------------------------------------------------------
583
-
584
- # Get initial Windows Server setup password from an instance console output.
585
- #
586
- # my_awesome_key = ec2.create_key_pair('my_awesome_key') #=>
587
- # {:aws_key_name => "my_awesome_key",
588
- # :aws_fingerprint => "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03",
589
- # :aws_material => "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAK...Q8MDrCbuQ=\n-----END RSA PRIVATE KEY-----"}
590
- #
591
- # my_awesome_instance = ec2.run_instances('ami-a000000a',1,1,['my_awesome_group'],'my_awesome_key', 'WindowsInstance!!!') #=>
592
- # [{:aws_image_id => "ami-a000000a",
593
- # :aws_instance_id => "i-12345678",
594
- # ...
595
- # :aws_availability_zone => "us-east-1b"
596
- # }]
597
- #
598
- # # wait until instance enters 'operational' state and get it's initial password
599
- #
600
- # puts ec2.get_initial_password(my_awesome_instance[:aws_instance_id], my_awesome_key[:aws_material]) #=> "MhjWcgZuY6"
601
- #
602
- def get_initial_password(instance_id, private_key)
603
- console_output = get_console_output(instance_id)
604
- crypted_password = console_output[:aws_output][%r{<Password>(.+)</Password>}m] && $1
605
- unless crypted_password
606
- raise AwsError.new("Initial password was not found in console output for #{instance_id}")
607
- else
608
- OpenSSL::PKey::RSA.new(private_key).private_decrypt(Base64.decode64(crypted_password))
609
- end
179
+ cache_for = (list.right_blank? && options.right_blank?) ? cache_name : nil
180
+ link = generate_request(remote_function_name, request_hash, custom_options)
181
+ request_cache_or_info(cache_for, link, parser_class, @@bench, cache_for, &block)
610
182
  rescue Exception
611
183
  on_exception
612
184
  end
613
185
 
614
- # Bundle a Windows image.
615
- # Internally, it queues the bundling task and shuts down the instance.
616
- # It then takes a snapshot of the Windows volume bundles it, and uploads it to
617
- # S3. After bundling completes, Rightaws::Ec2#register_image may be used to
618
- # register the new Windows AMI for subsequent launches.
186
+ # Incrementally lists given API call.
619
187
  #
620
- # ec2.bundle_instance('i-e3e24e8a', 'my-awesome-bucket', 'my-win-image-1') #=>
621
- # [{:aws_update_time => "2008-10-16T13:58:25.000Z",
622
- # :s3_bucket => "kd-win-1",
623
- # :s3_prefix => "win2pr",
624
- # :aws_state => "pending",
625
- # :aws_id => "bun-26a7424f",
626
- # :aws_instance_id => "i-878a25ee",
627
- # :aws_start_time => "2008-10-16T13:58:02.000Z"}]
188
+ # All params are the same as for describe_resources_with_list_and_options call.
628
189
  #
629
- def bundle_instance(instance_id, s3_bucket, s3_prefix,
630
- s3_owner_aws_access_key_id=nil, s3_owner_aws_secret_access_key=nil,
631
- s3_expires = S3Interface::DEFAULT_EXPIRES_AFTER,
632
- s3_upload_policy='ec2-bundle-read')
633
- # S3 access and signatures
634
- s3_owner_aws_access_key_id ||= @aws_access_key_id
635
- s3_owner_aws_secret_access_key ||= @aws_secret_access_key
636
- s3_expires = Time.now.utc + s3_expires if s3_expires.is_a?(Fixnum) && (s3_expires < S3Interface::ONE_YEAR_IN_SECONDS)
637
- # policy
638
- policy = { 'expiration' => s3_expires.strftime('%Y-%m-%dT%H:%M:%SZ'),
639
- 'conditions' => [ { 'bucket' => s3_bucket },
640
- { 'acl' => s3_upload_policy },
641
- [ 'starts-with', '$key', s3_prefix ] ] }.to_json
642
- policy64 = Base64.encode64(policy).gsub("\n","")
643
- signed_policy64 = AwsUtils.sign(s3_owner_aws_secret_access_key, policy64)
644
- # fill request params
645
- params = { 'InstanceId' => instance_id,
646
- 'Storage.S3.AWSAccessKeyId' => s3_owner_aws_access_key_id,
647
- 'Storage.S3.UploadPolicy' => policy64,
648
- 'Storage.S3.UploadPolicySignature' => signed_policy64,
649
- 'Storage.S3.Bucket' => s3_bucket,
650
- 'Storage.S3.Prefix' => s3_prefix,
651
- }
652
- link = generate_request("BundleInstance", params)
653
- request_info(link, QEc2BundleInstanceParser.new)
654
- rescue Exception
655
- on_exception
656
- end
657
-
658
- # Describe the status of the Windows AMI bundlings.
659
- # If +list+ is omitted the returns the whole list of tasks.
660
- #
661
- # ec2.describe_bundle_tasks(['bun-4fa74226']) #=>
662
- # [{:s3_bucket => "my-awesome-bucket"
663
- # :aws_id => "bun-0fa70206",
664
- # :s3_prefix => "win1pr",
665
- # :aws_start_time => "2008-10-14T16:27:57.000Z",
666
- # :aws_update_time => "2008-10-14T16:37:10.000Z",
667
- # :aws_error_code => "Client.S3Error",
668
- # :aws_error_message =>
669
- # "AccessDenied(403)- Invalid according to Policy: Policy Condition failed: [\"eq\", \"$acl\", \"aws-exec-read\"]",
670
- # :aws_state => "failed",
671
- # :aws_instance_id => "i-e3e24e8a"}]
672
- #
673
- def describe_bundle_tasks(list=[])
674
- link = generate_request("DescribeBundleTasks", hash_params('BundleId', list.to_a))
675
- request_info(link, QEc2DescribeBundleTasksParser.new)
676
- rescue Exception
677
- on_exception
190
+ # Block is called on every chunk of resources received. If you need to stop the loop
191
+ # just make the block to return nil or false.
192
+ #
193
+ # The API call should support 'NextToken' parameter and the response should return :next_token
194
+ # as well.
195
+ #
196
+ # Returns the last response from the cloud.
197
+ #
198
+ def incrementally_list_items(remote_function_name, remote_item_name, parser_class, list_and_options, &block) # :nodoc:
199
+ last_response = nil
200
+ loop do
201
+ last_response = describe_resources_with_list_and_options(remote_function_name, remote_item_name, parser_class, list_and_options)
202
+ break unless block && block.call(last_response) && !last_response[:next_token].right_blank?
203
+ list, options = AwsUtils::split_items_and_params(list_and_options)
204
+ options[:next_token] = last_response[:next_token]
205
+ list_and_options = list + [options]
206
+ end
207
+ last_response
678
208
  end
679
209
 
680
- # Cancel an in‐progress or pending bundle task by id.
681
- #
682
- # ec2.cancel_bundle_task('bun-73a7421a') #=>
683
- # [{:s3_bucket => "my-awesome-bucket"
684
- # :aws_id => "bun-0fa70206",
685
- # :s3_prefix => "win02",
686
- # :aws_start_time => "2008-10-14T13:00:29.000Z",
687
- # :aws_error_message => "User has requested bundling operation cancellation",
688
- # :aws_state => "failed",
689
- # :aws_update_time => "2008-10-14T13:01:31.000Z",
690
- # :aws_error_code => "Client.Cancelled",
691
- # :aws_instance_id => "i-e3e24e8a"}
692
- #
693
- def cancel_bundle_task(bundle_id)
694
- link = generate_request("CancelBundleTask", { 'BundleId' => bundle_id })
695
- request_info(link, QEc2BundleInstanceParser.new)
696
- rescue Exception
697
- on_exception
210
+ def merge_new_options_into_list_and_options(list_and_options, new_options)
211
+ list, options = AwsUtils::split_items_and_params(list_and_options)
212
+ list << options.merge(new_options)
698
213
  end
699
214
 
700
215
  #-----------------------------------------------------------------
701
- # Security groups
216
+ # Keys
702
217
  #-----------------------------------------------------------------
703
-
704
- # Retrieve Security Group information. If +list+ is omitted the returns the whole list of groups.
705
- #
706
- # ec2.describe_security_groups #=>
707
- # [{:aws_group_name => "default-1",
708
- # :aws_owner => "000000000888",
709
- # :aws_description => "Default allowing SSH, HTTP, and HTTPS ingress",
710
- # :aws_perms =>
711
- # [{:owner => "000000000888", :group => "default"},
712
- # {:owner => "000000000888", :group => "default-1"},
713
- # {:to_port => "-1", :protocol => "icmp", :from_port => "-1", :cidr_ips => "0.0.0.0/0"},
714
- # {:to_port => "22", :protocol => "tcp", :from_port => "22", :cidr_ips => "0.0.0.0/0"},
715
- # {:to_port => "80", :protocol => "tcp", :from_port => "80", :cidr_ips => "0.0.0.0/0"},
716
- # {:to_port => "443", :protocol => "tcp", :from_port => "443", :cidr_ips => "0.0.0.0/0"}]},
717
- # ..., {...}]
718
- #
719
- def describe_security_groups(list=[])
720
- link = generate_request("DescribeSecurityGroups", hash_params('GroupName',list.to_a))
721
- request_cache_or_info( :describe_security_groups, link, QEc2DescribeSecurityGroupsParser, @@bench, list.blank?) do |parser|
722
- result = []
723
- parser.result.each do |item|
724
- perms = []
725
- item.ipPermissions.each do |perm|
726
- perm.groups.each do |ngroup|
727
- perms << {:group => ngroup.groupName,
728
- :owner => ngroup.userId}
729
- end
730
- perm.ipRanges.each do |cidr_ip|
731
- perms << {:from_port => perm.fromPort,
732
- :to_port => perm.toPort,
733
- :protocol => perm.ipProtocol,
734
- :cidr_ips => cidr_ip}
735
- end
736
- end
737
-
738
- # delete duplication
739
- perms.each_index do |i|
740
- (0...i).each do |j|
741
- if perms[i] == perms[j] then perms[i] = nil; break; end
742
- end
743
- end
744
- perms.compact!
745
-
746
- result << {:aws_owner => item.ownerId,
747
- :aws_group_name => item.groupName,
748
- :aws_description => item.groupDescription,
749
- :aws_perms => perms}
750
-
751
- end
752
- result
753
- end
754
- rescue Exception
755
- on_exception
756
- end
757
-
758
- # Create new Security Group. Returns +true+ or an exception.
759
- #
760
- # ec2.create_security_group('default-1',"Default allowing SSH, HTTP, and HTTPS ingress") #=> true
218
+
219
+ # Retrieve a list of SSH keys.
761
220
  #
762
- def create_security_group(name, description)
763
- # EC2 doesn't like an empty description...
764
- description = " " if description.blank?
765
- link = generate_request("CreateSecurityGroup",
766
- 'GroupName' => name.to_s,
767
- 'GroupDescription' => description.to_s)
768
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
769
- rescue Exception
770
- on_exception
771
- end
772
-
773
- # Remove Security Group. Returns +true+ or an exception.
221
+ # Accepts a list of ssh keys and/or a set of filters as the last parameter.
774
222
  #
775
- # ec2.delete_security_group('default-1') #=> true
223
+ # Filters: fingerprint, key-name
776
224
  #
777
- def delete_security_group(name)
778
- link = generate_request("DeleteSecurityGroup",
779
- 'GroupName' => name.to_s)
780
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
781
- rescue Exception
782
- on_exception
783
- end
784
-
785
- # Authorize named ingress for security group. Allows instances that are member of someone
786
- # else's security group to open connections to instances in my group.
225
+ # Returns an array of keys or an exception. Each key is represented as a two-element hash.
787
226
  #
788
- # ec2.authorize_security_group_named_ingress('my_awesome_group', '7011-0219-8268', 'their_group_name') #=> true
227
+ # ec2.describe_key_pairs #=>
228
+ # [{:aws_fingerprint=> "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03", :aws_key_name=>"key-1"},
229
+ # {:aws_fingerprint=> "1e:29:30:47:58:6d:7b:8c:9f:08:11:20:3c:44:52:69:74:80:97:08", :aws_key_name=>"key-2"},
230
+ # ..., {...} ]
789
231
  #
790
- def authorize_security_group_named_ingress(name, owner, group)
791
- link = generate_request("AuthorizeSecurityGroupIngress",
792
- 'GroupName' => name.to_s,
793
- 'SourceSecurityGroupName' => group.to_s,
794
- 'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
795
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
796
- rescue Exception
797
- on_exception
798
- end
799
-
800
- # Revoke named ingress for security group.
232
+ # ec2.describe_key_pairs(:filters => {'fingerprint' => ["53:0b:73:c9:c8:18:98:6e:bc:98:9e:51:97:04:74:4b:07:f9:00:00",
233
+ # "9f:57:a5:bb:4b:e8:a7:f8:3c:fe:d6:db:41:f5:7e:97:b5:b2:00:00"]})
801
234
  #
802
- # ec2.revoke_security_group_named_ingress('my_awesome_group', aws_user_id, 'another_group_name') #=> true
235
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeKeyPairs.html
803
236
  #
804
- def revoke_security_group_named_ingress(name, owner, group)
805
- link = generate_request("RevokeSecurityGroupIngress",
806
- 'GroupName' => name.to_s,
807
- 'SourceSecurityGroupName' => group.to_s,
808
- 'SourceSecurityGroupOwnerId' => owner.to_s.gsub(/-/,''))
809
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
810
- rescue Exception
811
- on_exception
237
+ def describe_key_pairs(*list_and_options)
238
+ describe_resources_with_list_and_options('DescribeKeyPairs', 'KeyName', QEc2DescribeKeyPairParser, list_and_options)
812
239
  end
813
-
814
- # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp'.
815
- #
816
- # ec2.authorize_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
817
- # ec2.authorize_security_group_IP_ingress('my_awesome_group', -1, -1, 'icmp') #=> true
818
- #
819
- def authorize_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
820
- link = generate_request("AuthorizeSecurityGroupIngress",
821
- 'GroupName' => name.to_s,
822
- 'IpProtocol' => protocol.to_s,
823
- 'FromPort' => from_port.to_s,
824
- 'ToPort' => to_port.to_s,
825
- 'CidrIp' => cidr_ip.to_s)
826
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
827
- rescue Exception
828
- on_exception
829
- end
830
-
831
- # Remove permission from a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp' ('tcp' is default).
240
+
241
+ # Import new SSH key. Returns a hash of the key's data or an exception.
832
242
  #
833
- # ec2.revoke_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
243
+ # ec2.import_key_pair('my_awesome_key', 'C:\keys\myfavoritekeypair_public.ppk') #=>
244
+ # {:aws_key_name => "my_awesome_key",
245
+ # :aws_fingerprint => "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03"}
834
246
  #
835
- def revoke_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
836
- link = generate_request("RevokeSecurityGroupIngress",
837
- 'GroupName' => name.to_s,
838
- 'IpProtocol' => protocol.to_s,
839
- 'FromPort' => from_port.to_s,
840
- 'ToPort' => to_port.to_s,
841
- 'CidrIp' => cidr_ip.to_s)
842
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
247
+ def import_key_pair(name, public_key_material)
248
+ link = generate_request("ImportKeyPair",
249
+ 'KeyName' => name.to_s,
250
+ 'PublicKeyMaterial' => Base64.encode64(public_key_material.to_s))
251
+ request_info(link, QEc2ImportKeyPairParser.new(:logger => @logger))
843
252
  rescue Exception
844
253
  on_exception
845
254
  end
846
255
 
847
- #-----------------------------------------------------------------
848
- # Keys
849
- #-----------------------------------------------------------------
850
-
851
- # Retrieve a list of SSH keys. Returns an array of keys or an exception. Each key is
852
- # represented as a two-element hash.
853
- #
854
- # ec2.describe_key_pairs #=>
855
- # [{:aws_fingerprint=> "01:02:03:f4:25:e6:97:e8:9b:02:1a:26:32:4e:58:6b:7a:8c:9f:03", :aws_key_name=>"key-1"},
856
- # {:aws_fingerprint=> "1e:29:30:47:58:6d:7b:8c:9f:08:11:20:3c:44:52:69:74:80:97:08", :aws_key_name=>"key-2"},
857
- # ..., {...} ]
858
- #
859
- def describe_key_pairs(list=[])
860
- link = generate_request("DescribeKeyPairs", hash_params('KeyName',list.to_a))
861
- request_cache_or_info :describe_key_pairs, link, QEc2DescribeKeyPairParser, @@bench, list.blank?
862
- rescue Exception
863
- on_exception
864
- end
865
-
866
256
  # Create new SSH key. Returns a hash of the key's data or an exception.
867
257
  #
868
258
  # ec2.create_key_pair('my_awesome_key') #=>
@@ -871,7 +261,7 @@ module RightAws
871
261
  # :aws_material => "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAK...Q8MDrCbuQ=\n-----END RSA PRIVATE KEY-----"}
872
262
  #
873
263
  def create_key_pair(name)
874
- link = generate_request("CreateKeyPair",
264
+ link = generate_request("CreateKeyPair",
875
265
  'KeyName' => name.to_s)
876
266
  request_info(link, QEc2CreateKeyPairParser.new(:logger => @logger))
877
267
  rescue Exception
@@ -895,68 +285,112 @@ module RightAws
895
285
  #-----------------------------------------------------------------
896
286
 
897
287
  # Acquire a new elastic IP address for use with your account.
898
- # Returns allocated IP address or an exception.
288
+ # Options: :domain.
289
+ # Returns allocated IP address or or an exception.
899
290
  #
900
- # ec2.allocate_address #=> '75.101.154.140'
291
+ # ec2.allocate_address #=>
292
+ # { :public_ip => "50.19.214.224",
293
+ # :domain => "standard"}
901
294
  #
902
- def allocate_address
903
- link = generate_request("AllocateAddress")
295
+ # ec2.allocate_address(:domain => 'vpc') #=>
296
+ # { :allocation_id => "eipalloc-c6abfeaf",
297
+ # :domain => "vpc",
298
+ # :public_ip => "184.72.112.39"}
299
+ #
300
+ def allocate_address(options={})
301
+ request_hash = {}
302
+ request_hash['Domain'] = options[:domain] unless options[:domain].right_blank?
303
+ link = generate_request("AllocateAddress", request_hash)
904
304
  request_info(link, QEc2AllocateAddressParser.new(:logger => @logger))
905
305
  rescue Exception
906
306
  on_exception
907
307
  end
908
308
 
909
309
  # Associate an elastic IP address with an instance.
910
- # Returns +true+ or an exception.
310
+ # Options: :public_ip, :allocation_id.
311
+ # Returns a hash of data or an exception.
911
312
  #
912
- # ec2.associate_address('i-d630cbbf', '75.101.154.140') #=> true
313
+ # ec2.associate_address('i-d630cbbf', :public_ip => '75.101.154.140') #=>
314
+ # { :return => true }
913
315
  #
914
- def associate_address(instance_id, public_ip)
915
- link = generate_request("AssociateAddress",
916
- "InstanceId" => instance_id.to_s,
917
- "PublicIp" => public_ip.to_s)
918
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
316
+ # ec2.associate_address(inst, :allocation_id => "eipalloc-c6abfeaf") #=>
317
+ # { :return => true,
318
+ # :association_id => 'eipassoc-fc5ca095'}
319
+ #
320
+ def associate_address(instance_id, options={})
321
+ request_hash = { "InstanceId" => instance_id.to_s }
322
+ request_hash['PublicIp'] = options[:public_ip] unless options[:public_ip].right_blank?
323
+ request_hash['AllocationId'] = options[:allocation_id] unless options[:allocation_id].right_blank?
324
+ link = generate_request("AssociateAddress", request_hash)
325
+ request_info(link, QEc2AssociateAddressParser.new(:logger => @logger))
919
326
  rescue Exception
920
327
  on_exception
921
328
  end
922
329
 
923
- # List elastic IP addresses assigned to your account.
330
+ # List elastic IPs by public addresses.
331
+ #
332
+ # Accepts a list of addresses and/or a set of filters as the last parameter.
333
+ #
334
+ # Filters: instance-id, public-ip
335
+ #
924
336
  # Returns an array of 2 keys (:instance_id and :public_ip) hashes:
925
337
  #
926
- # ec2.describe_addresses #=> [{:instance_id=>"i-d630cbbf", :public_ip=>"75.101.154.140"},
927
- # {:instance_id=>nil, :public_ip=>"75.101.154.141"}]
338
+ # ec2.describe_addresses #=> [{:instance_id=>"i-75ebd41b", :domain=>"standard", :public_ip=>"50.17.211.96"},
339
+ # :domain=>"vpc", :public_ip=>"184.72.112.39", :allocation_id=>"eipalloc-c6abfeaf"}]
928
340
  #
929
- # ec2.describe_addresses('75.101.154.140') #=> [{:instance_id=>"i-d630cbbf", :public_ip=>"75.101.154.140"}]
341
+ # ec2.describe_addresses('75.101.154.140') #=> [{:instance_id=>"i-d630cbbf", :public_ip=>"75.101.154.140", :domain=>"standard"}]
930
342
  #
931
- def describe_addresses(list=[])
932
- link = generate_request("DescribeAddresses",
933
- hash_params('PublicIp',list.to_a))
934
- request_cache_or_info :describe_addresses, link, QEc2DescribeAddressesParser, @@bench, list.blank?
935
- rescue Exception
936
- on_exception
343
+ # ec2.describe_addresses(:filters => { 'public-ip' => "75.101.154.140" })
344
+ #
345
+ # P.S. http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeAddresses.html
346
+ #
347
+ def describe_addresses(*list_and_options)
348
+ describe_resources_with_list_and_options('DescribeAddresses', 'PublicIp', QEc2DescribeAddressesParser, list_and_options)
349
+ end
350
+
351
+
352
+ # List elastic IPs by allocation ids.
353
+ #
354
+ # Accepts a list of allocations and/or a set of filters as the last parameter.
355
+ #
356
+ # describe_addresses_by_allocation_ids("eipalloc-c6abfeaf") #=>
357
+ # [{:domain=>"vpc",
358
+ # :public_ip=>"184.72.112.39",
359
+ # :allocation_id=>"eipalloc-c6abfeaf"}]
360
+ #
361
+ # P.S. http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeAddresses.html
362
+ #
363
+ def describe_addresses_by_allocation_ids(*list_and_options)
364
+ describe_resources_with_list_and_options('DescribeAddresses', 'AllocationId', QEc2DescribeAddressesParser, list_and_options)
937
365
  end
938
366
 
939
367
  # Disassociate the specified elastic IP address from the instance to which it is assigned.
368
+ # Options: :public_ip, :association_id.
940
369
  # Returns +true+ or an exception.
941
370
  #
942
- # ec2.disassociate_address('75.101.154.140') #=> true
371
+ # ec2.disassociate_address(:public_ip => '75.101.154.140') #=> true
943
372
  #
944
- def disassociate_address(public_ip)
945
- link = generate_request("DisassociateAddress",
946
- "PublicIp" => public_ip.to_s)
373
+ def disassociate_address(options = {})
374
+ request_hash = {}
375
+ request_hash['PublicIp'] = options[:public_ip] unless options[:public_ip].right_blank?
376
+ request_hash['AssociationId'] = options[:association_id] unless options[:association_id].right_blank?
377
+ link = generate_request("DisassociateAddress", request_hash)
947
378
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
948
379
  rescue Exception
949
380
  on_exception
950
381
  end
951
382
 
952
383
  # Release an elastic IP address associated with your account.
384
+ # Options: :public_ip, :allocation_id.
953
385
  # Returns +true+ or an exception.
954
386
  #
955
- # ec2.release_address('75.101.154.140') #=> true
387
+ # ec2.release_address(:public_ip => '75.101.154.140') #=> true
956
388
  #
957
- def release_address(public_ip)
958
- link = generate_request("ReleaseAddress",
959
- "PublicIp" => public_ip.to_s)
389
+ def release_address(options = {})
390
+ request_hash = {}
391
+ request_hash['PublicIp'] = options[:public_ip] unless options[:public_ip].right_blank?
392
+ request_hash['AllocationId'] = options[:allocation_id] unless options[:allocation_id].right_blank?
393
+ link = generate_request("ReleaseAddress", request_hash)
960
394
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
961
395
  rescue Exception
962
396
  on_exception
@@ -967,193 +401,69 @@ module RightAws
967
401
  #-----------------------------------------------------------------
968
402
 
969
403
  # Describes availability zones that are currently available to the account and their states.
970
- # Returns an array of 2 keys (:zone_name and :zone_state) hashes:
971
404
  #
972
- # ec2.describe_availability_zones #=> [{:zone_state=>"available", :zone_name=>"us-east-1a"},
973
- # {:zone_state=>"available", :zone_name=>"us-east-1b"},
974
- # {:zone_state=>"available", :zone_name=>"us-east-1c"}]
405
+ # Accepts a list of availability zones and/or a set of filters as the last parameter.
975
406
  #
976
- # ec2.describe_availability_zones('us-east-1c') #=> [{:zone_state=>"available", :zone_name=>"us-east-1c"}]
407
+ # Filters: message, region-name, state, zone-name
977
408
  #
978
- def describe_availability_zones(list=[])
979
- link = generate_request("DescribeAvailabilityZones",
980
- hash_params('ZoneName',list.to_a))
981
- request_cache_or_info :describe_availability_zones, link, QEc2DescribeAvailabilityZonesParser, @@bench, list.blank?
982
- rescue Exception
983
- on_exception
984
- end
985
-
986
- #-----------------------------------------------------------------
987
- # EBS: Volumes
988
- #-----------------------------------------------------------------
989
-
990
- # Describe all EBS volumes.
409
+ # Returns an array of 2 keys (:zone_name and :zone_state) hashes:
991
410
  #
992
- # ec2.describe_volumes #=>
993
- # [{:aws_size => 94,
994
- # :aws_device => "/dev/sdc",
995
- # :aws_attachment_status => "attached",
996
- # :zone => "merlot",
997
- # :snapshot_id => nil,
998
- # :aws_attached_at => Wed Jun 18 08:19:28 UTC 2008,
999
- # :aws_status => "in-use",
1000
- # :aws_id => "vol-60957009",
1001
- # :aws_created_at => Wed Jun 18 08:19:20s UTC 2008,
1002
- # :aws_instance_id => "i-c014c0a9"},
1003
- # {:aws_size => 1,
1004
- # :zone => "merlot",
1005
- # :snapshot_id => nil,
1006
- # :aws_status => "available",
1007
- # :aws_id => "vol-58957031",
1008
- # :aws_created_at => Wed Jun 18 08:19:21 UTC 2008,}, ... ]
411
+ # ec2.describe_availability_zones #=> [{:region_name=>"us-east-1",
412
+ # :zone_name=>"us-east-1a",
413
+ # :zone_state=>"available"}, ... ]
1009
414
  #
1010
- def describe_volumes(list=[])
1011
- link = generate_request("DescribeVolumes",
1012
- hash_params('VolumeId',list.to_a))
1013
- request_cache_or_info :describe_volumes, link, QEc2DescribeVolumesParser, @@bench, list.blank?
1014
- rescue Exception
1015
- on_exception
1016
- end
1017
-
1018
- # Create new EBS volume based on previously created snapshot.
1019
- # +Size+ in Gigabytes.
415
+ # ec2.describe_availability_zones('us-east-1c') #=> [{:region_name=>"us-east-1",
416
+ # :zone_state=>"available",
417
+ # :zone_name=>"us-east-1c"}]
1020
418
  #
1021
- # ec2.create_volume('snap-000000', 10, zone) #=>
1022
- # {:snapshot_id => "snap-e21df98b",
1023
- # :aws_status => "creating",
1024
- # :aws_id => "vol-fc9f7a95",
1025
- # :zone => "merlot",
1026
- # :aws_created_at => Tue Jun 24 18:13:32 UTC 2008,
1027
- # :aws_size => 94}
419
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeAvailabilityZones.html
1028
420
  #
1029
- def create_volume(snapshot_id, size, zone)
1030
- link = generate_request("CreateVolume",
1031
- "SnapshotId" => snapshot_id.to_s,
1032
- "Size" => size.to_s,
1033
- "AvailabilityZone" => zone.to_s )
1034
- request_info(link, QEc2CreateVolumeParser.new(:logger => @logger))
1035
- rescue Exception
1036
- on_exception
421
+ def describe_availability_zones(*list_and_options)
422
+ describe_resources_with_list_and_options('DescribeAvailabilityZones', 'ZoneName', QEc2DescribeAvailabilityZonesParser, list_and_options)
1037
423
  end
1038
424
 
1039
- # Delete the specified EBS volume.
1040
- # This does not deletes any snapshots created from this volume.
425
+ #-----------------------------------------------------------------
426
+ # Regions
427
+ #-----------------------------------------------------------------
428
+
429
+ # Describe regions.
1041
430
  #
1042
- # ec2.delete_volume('vol-b48a6fdd') #=> true
431
+ # Accepts a list of regions and/or a set of filters as the last parameter.
1043
432
  #
1044
- def delete_volume(volume_id)
1045
- link = generate_request("DeleteVolume",
1046
- "VolumeId" => volume_id.to_s)
1047
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1048
- rescue Exception
1049
- on_exception
1050
- end
1051
-
1052
- # Attach the specified EBS volume to a specified instance, exposing the
1053
- # volume using the specified device name.
433
+ # Filters: endpoint, region-name
1054
434
  #
1055
- # ec2.attach_volume('vol-898a6fe0', 'i-7c905415', '/dev/sdh') #=>
1056
- # { :aws_instance_id => "i-7c905415",
1057
- # :aws_device => "/dev/sdh",
1058
- # :aws_status => "attaching",
1059
- # :aws_attached_at => "2008-03-28T14:14:39.000Z",
1060
- # :aws_id => "vol-898a6fe0" }
435
+ # ec2.describe_regions #=>
436
+ # [{:region_endpoint=>"ec2.eu-west-1.amazonaws.com", :region_name=>"eu-west-1"},
437
+ # {:region_endpoint=>"ec2.us-east-1.amazonaws.com", :region_name=>"us-east-1"},
438
+ # {:region_endpoint=>"ec2.ap-northeast-1.amazonaws.com", :region_name=>"ap-northeast-1"},
439
+ # {:region_endpoint=>"ec2.us-west-1.amazonaws.com", :region_name=>"us-west-1"},
440
+ # {:region_endpoint=>"ec2.ap-southeast-1.amazonaws.com", :region_name=>"ap-southeast-1"}]
1061
441
  #
1062
- def attach_volume(volume_id, instance_id, device)
1063
- link = generate_request("AttachVolume",
1064
- "VolumeId" => volume_id.to_s,
1065
- "InstanceId" => instance_id.to_s,
1066
- "Device" => device.to_s)
1067
- request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger))
1068
- rescue Exception
1069
- on_exception
1070
- end
1071
-
1072
- # Detach the specified EBS volume from the instance to which it is attached.
1073
- #
1074
- # ec2.detach_volume('vol-898a6fe0') #=>
1075
- # { :aws_instance_id => "i-7c905415",
1076
- # :aws_device => "/dev/sdh",
1077
- # :aws_status => "detaching",
1078
- # :aws_attached_at => "2008-03-28T14:38:34.000Z",
1079
- # :aws_id => "vol-898a6fe0"}
442
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeRegions.html
1080
443
  #
1081
- def detach_volume(volume_id, instance_id=nil, device=nil, force=nil)
1082
- hash = { "VolumeId" => volume_id.to_s }
1083
- hash["InstanceId"] = instance_id.to_s unless instance_id.blank?
1084
- hash["Device"] = device.to_s unless device.blank?
1085
- hash["Force"] = 'true' if force
1086
- #
1087
- link = generate_request("DetachVolume", hash)
1088
- request_info(link, QEc2AttachAndDetachVolumeParser.new(:logger => @logger))
1089
- rescue Exception
1090
- on_exception
444
+ def describe_regions(*list_and_options)
445
+ describe_resources_with_list_and_options('DescribeRegions', 'RegionName', QEc2DescribeRegionsParser, list_and_options)
1091
446
  end
1092
447
 
1093
-
1094
- #-----------------------------------------------------------------
1095
- # EBS: Snapshots
1096
- #-----------------------------------------------------------------
1097
-
1098
- # Describe all EBS snapshots.
1099
- #
1100
- # ec2.describe_snapshots #=>
1101
- # [ { :aws_progress => "100%",
1102
- # :aws_status => "completed",
1103
- # :aws_id => "snap-72a5401b",
1104
- # :aws_volume_id => "vol-5582673c",
1105
- # :aws_started_at => "2008-02-23T02:50:48.000Z"},
1106
- # { :aws_progress => "100%",
1107
- # :aws_status => "completed",
1108
- # :aws_id => "snap-75a5401c",
1109
- # :aws_volume_id => "vol-5582673c",
1110
- # :aws_started_at => "2008-02-23T16:23:19.000Z" },...]
1111
- #
1112
- def describe_snapshots(list=[])
1113
- link = generate_request("DescribeSnapshots",
1114
- hash_params('SnapshotId',list.to_a))
1115
- request_cache_or_info :describe_snapshots, link, QEc2DescribeSnapshotsParser, @@bench, list.blank?
1116
- rescue Exception
1117
- on_exception
1118
- end
448
+ #-----------------------------------------------------------------
449
+ # Accounts
450
+ #-----------------------------------------------------------------
1119
451
 
1120
- # Create a snapshot of specified volume.
452
+ # Describe the specified attribute of your AWS account.
1121
453
  #
1122
- # ec2.create_snapshot('vol-898a6fe0') #=>
1123
- # {:aws_volume_id => "vol-fd9f7a94",
1124
- # :aws_started_at => Tue Jun 24 18:40:40 UTC 2008,
1125
- # :aws_progress => "",
1126
- # :aws_status => "pending",
1127
- # :aws_id => "snap-d56783bc"}
454
+ # ec2.describe_account_attributes(:attribute_name => ['default-vpc','supported-platforms']) #=>
455
+ # {"default-vpc" => "vpc-8c3b00e7",
456
+ # "supported-platforms" => "VPC"}
1128
457
  #
1129
- def create_snapshot(volume_id)
1130
- link = generate_request("CreateSnapshot",
1131
- "VolumeId" => volume_id.to_s)
1132
- request_info(link, QEc2CreateSnapshotParser.new(:logger => @logger))
1133
- rescue Exception
1134
- on_exception
1135
- end
1136
-
1137
- # Delete the specified snapshot.
458
+ # ec2.describe_account_attributes #=>
459
+ # {"vpc-max-security-groups-per-interface" => "5",
460
+ # "max-instances" => "150",
461
+ # "supported-platforms" => ["EC2", "VPC"],
462
+ # "default-vpc" => "none"}
1138
463
  #
1139
- # ec2.delete_snapshot('snap-55a5403c') #=> true
1140
- #
1141
- def delete_snapshot(snapshot_id)
1142
- link = generate_request("DeleteSnapshot",
1143
- "SnapshotId" => snapshot_id.to_s)
1144
- request_info(link, RightBoolResponseParser.new(:logger => @logger))
1145
- rescue Exception
1146
- on_exception
1147
- end
1148
-
1149
- #-----------------------------------------------------------------
1150
- # PARSERS: Boolean Response Parser
1151
- #-----------------------------------------------------------------
1152
-
1153
- class RightBoolResponseParser < RightAWSParser #:nodoc:
1154
- def tagend(name)
1155
- @result = @text=='true' ? true : false if name == 'return'
1156
- end
464
+ def describe_account_attributes(*list_and_options)
465
+ list_and_options = merge_new_options_into_list_and_options(list_and_options, :options => {:api_version => VPC_API_VERSION})
466
+ describe_resources_with_list_and_options('DescribeAccountAttributes', 'accountAttributeValues', QEc2DescribeAccountAttributesParser, list_and_options)
1157
467
  end
1158
468
 
1159
469
  #-----------------------------------------------------------------
@@ -1189,252 +499,28 @@ module RightAws
1189
499
  end
1190
500
  end
1191
501
 
1192
- #-----------------------------------------------------------------
1193
- # PARSERS: Security Groups
1194
- #-----------------------------------------------------------------
1195
-
1196
- class QEc2UserIdGroupPairType #:nodoc:
1197
- attr_accessor :userId
1198
- attr_accessor :groupName
1199
- end
1200
-
1201
- class QEc2IpPermissionType #:nodoc:
1202
- attr_accessor :ipProtocol
1203
- attr_accessor :fromPort
1204
- attr_accessor :toPort
1205
- attr_accessor :groups
1206
- attr_accessor :ipRanges
1207
- end
1208
-
1209
- class QEc2SecurityGroupItemType #:nodoc:
1210
- attr_accessor :groupName
1211
- attr_accessor :groupDescription
1212
- attr_accessor :ownerId
1213
- attr_accessor :ipPermissions
1214
- end
1215
-
1216
-
1217
- class QEc2DescribeSecurityGroupsParser < RightAWSParser #:nodoc:
1218
- def tagstart(name, attributes)
1219
- case name
1220
- when 'item'
1221
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo'
1222
- @group = QEc2SecurityGroupItemType.new
1223
- @group.ipPermissions = []
1224
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions'
1225
- @perm = QEc2IpPermissionType.new
1226
- @perm.ipRanges = []
1227
- @perm.groups = []
1228
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups'
1229
- @sgroup = QEc2UserIdGroupPairType.new
1230
- end
1231
- end
1232
- end
1233
- def tagend(name)
1234
- case name
1235
- when 'ownerId' then @group.ownerId = @text
1236
- when 'groupDescription' then @group.groupDescription = @text
1237
- when 'groupName'
1238
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item'
1239
- @group.groupName = @text
1240
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups/item'
1241
- @sgroup.groupName = @text
1242
- end
1243
- when 'ipProtocol' then @perm.ipProtocol = @text
1244
- when 'fromPort' then @perm.fromPort = @text
1245
- when 'toPort' then @perm.toPort = @text
1246
- when 'userId' then @sgroup.userId = @text
1247
- when 'cidrIp' then @perm.ipRanges << @text
1248
- when 'item'
1249
- if @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions/item/groups'
1250
- @perm.groups << @sgroup
1251
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo/item/ipPermissions'
1252
- @group.ipPermissions << @perm
1253
- elsif @xmlpath=='DescribeSecurityGroupsResponse/securityGroupInfo'
1254
- @result << @group
1255
- end
1256
- end
1257
- end
1258
- def reset
1259
- @result = []
1260
- end
1261
- end
1262
-
1263
- #-----------------------------------------------------------------
1264
- # PARSERS: Images
1265
- #-----------------------------------------------------------------
1266
-
1267
- class QEc2DescribeImagesParser < RightAWSParser #:nodoc:
1268
- def tagstart(name, attributes)
1269
- if name == 'item' && @xmlpath[%r{.*/imagesSet$}]
1270
- @image = {}
1271
- end
1272
- end
1273
- def tagend(name)
1274
- case name
1275
- when 'imageId' then @image[:aws_id] = @text
1276
- when 'imageLocation' then @image[:aws_location] = @text
1277
- when 'imageState' then @image[:aws_state] = @text
1278
- when 'imageOwnerId' then @image[:aws_owner] = @text
1279
- when 'isPublic' then @image[:aws_is_public]= @text == 'true' ? true : false
1280
- when 'productCode' then (@image[:aws_product_codes] ||= []) << @text
1281
- when 'architecture' then @image[:aws_architecture] = @text
1282
- when 'imageType' then @image[:aws_image_type] = @text
1283
- when 'kernelId' then @image[:aws_kernel_id] = @text
1284
- when 'ramdiskId' then @image[:aws_ramdisk_id] = @text
1285
- when 'item' then @result << @image if @xmlpath[%r{.*/imagesSet$}]
1286
- end
1287
- end
1288
- def reset
1289
- @result = []
1290
- end
1291
- end
1292
-
1293
- class QEc2RegisterImageParser < RightAWSParser #:nodoc:
1294
- def tagend(name)
1295
- @result = @text if name == 'imageId'
1296
- end
1297
- end
1298
-
1299
- #-----------------------------------------------------------------
1300
- # PARSERS: Image Attribute
1301
- #-----------------------------------------------------------------
1302
-
1303
- class QEc2DescribeImageAttributeParser < RightAWSParser #:nodoc:
1304
- def tagstart(name, attributes)
1305
- case name
1306
- when 'launchPermission'
1307
- @result[:groups] = []
1308
- @result[:users] = []
1309
- when 'productCodes'
1310
- @result[:aws_product_codes] = []
1311
- end
1312
- end
1313
- def tagend(name)
1314
- # right now only 'launchPermission' is supported by Amazon.
1315
- # But nobody know what will they xml later as attribute. That is why we
1316
- # check for 'group' and 'userId' inside of 'launchPermission/item'
1317
- case name
1318
- when 'imageId' then @result[:aws_id] = @text
1319
- when 'group' then @result[:groups] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
1320
- when 'userId' then @result[:users] << @text if @xmlpath == 'DescribeImageAttributeResponse/launchPermission/item'
1321
- when 'productCode' then @result[:aws_product_codes] << @text
1322
- when 'kernel' then @result[:aws_kernel] = @text
1323
- when 'ramdisk' then @result[:aws_ramdisk] = @text
1324
- when 'blockDeviceMapping' then @result[:block_device_mapping] = @text
1325
- end
1326
- end
1327
- def reset
1328
- @result = {}
1329
- end
1330
- end
1331
-
1332
- #-----------------------------------------------------------------
1333
- # PARSERS: Instances
1334
- #-----------------------------------------------------------------
1335
-
1336
- class QEc2DescribeInstancesParser < RightAWSParser #:nodoc:
1337
- def tagstart(name, attributes)
1338
- # DescribeInstances property
1339
- if (name == 'item' && @xmlpath == 'DescribeInstancesResponse/reservationSet') ||
1340
- # RunInstances property
1341
- (name == 'RunInstancesResponse')
1342
- @reservation = { :aws_groups => [],
1343
- :instances_set => [] }
1344
-
1345
- elsif (name == 'item') &&
1346
- # DescribeInstances property
1347
- ( @xmlpath=='DescribeInstancesResponse/reservationSet/item/instancesSet' ||
1348
- # RunInstances property
1349
- @xmlpath=='RunInstancesResponse/instancesSet' )
1350
- # the optional params (sometimes are missing and we dont want them to be nil)
1351
- @instance = { :aws_reason => '',
1352
- :dns_name => '',
1353
- :private_dns_name => '',
1354
- :ami_launch_index => '',
1355
- :ssh_key_name => '',
1356
- :aws_state => '',
1357
- :aws_product_codes => [] }
1358
- end
1359
- end
1360
- def tagend(name)
1361
- case name
1362
- # reservation
1363
- when 'reservationId' then @reservation[:aws_reservation_id] = @text
1364
- when 'ownerId' then @reservation[:aws_owner] = @text
1365
- when 'groupId' then @reservation[:aws_groups] << @text
1366
- # instance
1367
- when 'instanceId' then @instance[:aws_instance_id] = @text
1368
- when 'imageId' then @instance[:aws_image_id] = @text
1369
- when 'dnsName' then @instance[:dns_name] = @text
1370
- when 'privateDnsName' then @instance[:private_dns_name] = @text
1371
- when 'reason' then @instance[:aws_reason] = @text
1372
- when 'keyName' then @instance[:ssh_key_name] = @text
1373
- when 'amiLaunchIndex' then @instance[:ami_launch_index] = @text
1374
- when 'code' then @instance[:aws_state_code] = @text
1375
- when 'name' then @instance[:aws_state] = @text
1376
- when 'productCode' then @instance[:aws_product_codes] << @text
1377
- when 'instanceType' then @instance[:aws_instance_type] = @text
1378
- when 'launchTime' then @instance[:aws_launch_time] = @text
1379
- when 'kernelId' then @instance[:aws_kernel_id] = @text
1380
- when 'ramdiskId' then @instance[:aws_ramdisk_id] = @text
1381
- when 'platform' then @instance[:aws_platform] = @text
1382
- when 'availabilityZone' then @instance[:aws_availability_zone] = @text
1383
- when 'item'
1384
- if @xmlpath == 'DescribeInstancesResponse/reservationSet/item/instancesSet' || # DescribeInstances property
1385
- @xmlpath == 'RunInstancesResponse/instancesSet' # RunInstances property
1386
- @reservation[:instances_set] << @instance
1387
- elsif @xmlpath=='DescribeInstancesResponse/reservationSet' # DescribeInstances property
1388
- @result << @reservation
1389
- end
1390
- when 'RunInstancesResponse' then @result << @reservation # RunInstances property
1391
- end
1392
- end
1393
- def reset
1394
- @result = []
1395
- end
1396
- end
1397
-
1398
- class QEc2ConfirmProductInstanceParser < RightAWSParser #:nodoc:
1399
- def tagend(name)
1400
- @result = @text if name == 'ownerId'
1401
- end
1402
- end
1403
-
1404
- class QEc2TerminateInstancesParser < RightAWSParser #:nodoc:
502
+ class QEc2ImportKeyPairParser < RightAWSParser #:nodoc:
1405
503
  def tagstart(name, attributes)
1406
- @instance = {} if name == 'item'
504
+ @result = {} if name == 'ImportKeyPairResponse'
1407
505
  end
1408
506
  def tagend(name)
1409
507
  case name
1410
- when 'instanceId' then @instance[:aws_instance_id] = @text
1411
- when 'code'
1412
- if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState'
1413
- @instance[:aws_shutdown_state_code] = @text.to_i
1414
- else @instance[:aws_prev_state_code] = @text.to_i end
1415
- when 'name'
1416
- if @xmlpath == 'TerminateInstancesResponse/instancesSet/item/shutdownState'
1417
- @instance[:aws_shutdown_state] = @text
1418
- else @instance[:aws_prev_state] = @text end
1419
- when 'item' then @result << @instance
508
+ when 'keyName' then @result[:aws_key_name] = @text
509
+ when 'keyFingerprint' then @result[:aws_fingerprint] = @text
1420
510
  end
1421
511
  end
1422
- def reset
1423
- @result = []
1424
- end
1425
512
  end
1426
513
 
1427
514
  #-----------------------------------------------------------------
1428
- # PARSERS: Console
515
+ # PARSERS: Elastic IPs
1429
516
  #-----------------------------------------------------------------
1430
-
1431
- class QEc2GetConsoleOutputParser < RightAWSParser #:nodoc:
517
+
518
+ class QEc2AllocateAddressParser < RightAWSParser #:nodoc:
1432
519
  def tagend(name)
1433
520
  case name
1434
- when 'instanceId' then @result[:aws_instance_id] = @text
1435
- when 'timestamp' then @result[:aws_timestamp] = @text
1436
- @result[:timestamp] = (Time.parse(@text)).utc
1437
- when 'output' then @result[:aws_output] = Base64.decode64(@text)
521
+ when 'publicIp' then @result[:public_ip] = @text
522
+ when 'allocationId' then @result[:allocation_id] = @text
523
+ when 'domain' then @result[:domain] = @text
1438
524
  end
1439
525
  end
1440
526
  def reset
@@ -1442,48 +528,11 @@ module RightAws
1442
528
  end
1443
529
  end
1444
530
 
1445
- #-----------------------------------------------------------------
1446
- # Instances: Wondows related part
1447
- #-----------------------------------------------------------------
1448
- class QEc2DescribeBundleTasksParser < RightAWSParser #:nodoc:
1449
- def tagstart(name, attributes)
1450
- @bundle = {} if name == 'item'
1451
- end
531
+ class QEc2AssociateAddressParser < RightAWSParser #:nodoc:
1452
532
  def tagend(name)
1453
533
  case name
1454
- # when 'requestId' then @bundle[:request_id] = @text
1455
- when 'instanceId' then @bundle[:aws_instance_id] = @text
1456
- when 'bundleId' then @bundle[:aws_id] = @text
1457
- when 'bucket' then @bundle[:s3_bucket] = @text
1458
- when 'prefix' then @bundle[:s3_prefix] = @text
1459
- when 'startTime' then @bundle[:aws_start_time] = @text
1460
- when 'updateTime' then @bundle[:aws_update_time] = @text
1461
- when 'state' then @bundle[:aws_state] = @text
1462
- when 'progress' then @bundle[:aws_progress] = @text
1463
- when 'code' then @bundle[:aws_error_code] = @text
1464
- when 'message' then @bundle[:aws_error_message] = @text
1465
- when 'item' then @result << @bundle
1466
- end
1467
- end
1468
- def reset
1469
- @result = []
1470
- end
1471
- end
1472
-
1473
- class QEc2BundleInstanceParser < RightAWSParser #:nodoc:
1474
- def tagend(name)
1475
- case name
1476
- # when 'requestId' then @result[:request_id] = @text
1477
- when 'instanceId' then @result[:aws_instance_id] = @text
1478
- when 'bundleId' then @result[:aws_id] = @text
1479
- when 'bucket' then @result[:s3_bucket] = @text
1480
- when 'prefix' then @result[:s3_prefix] = @text
1481
- when 'startTime' then @result[:aws_start_time] = @text
1482
- when 'updateTime' then @result[:aws_update_time] = @text
1483
- when 'state' then @result[:aws_state] = @text
1484
- when 'progress' then @result[:aws_progress] = @text
1485
- when 'code' then @result[:aws_error_code] = @text
1486
- when 'message' then @result[:aws_error_message] = @text
534
+ when 'return' then @result[:return] = @text == 'true'
535
+ when 'associationId' then @result[:association_id] = @text
1487
536
  end
1488
537
  end
1489
538
  def reset
@@ -1491,25 +540,18 @@ module RightAws
1491
540
  end
1492
541
  end
1493
542
 
1494
- #-----------------------------------------------------------------
1495
- # PARSERS: Elastic IPs
1496
- #-----------------------------------------------------------------
1497
-
1498
- class QEc2AllocateAddressParser < RightAWSParser #:nodoc:
1499
- def tagend(name)
1500
- @result = @text if name == 'publicIp'
1501
- end
1502
- end
1503
-
1504
543
  class QEc2DescribeAddressesParser < RightAWSParser #:nodoc:
1505
544
  def tagstart(name, attributes)
1506
- @address = {} if name == 'item'
545
+ @item = {} if name == 'item'
1507
546
  end
1508
547
  def tagend(name)
1509
548
  case name
1510
- when 'instanceId' then @address[:instance_id] = @text.blank? ? nil : @text
1511
- when 'publicIp' then @address[:public_ip] = @text
1512
- when 'item' then @result << @address
549
+ when 'instanceId' then (@item[:instance_id] = @text unless @text.right_blank?)
550
+ when 'publicIp' then @item[:public_ip] = @text
551
+ when 'allocationId' then @item[:allocation_id] = @text
552
+ when 'associationId' then @item[:association_id] = @text
553
+ when 'domain' then @item[:domain] = @text
554
+ when 'item' then @result << @item
1513
555
  end
1514
556
  end
1515
557
  def reset
@@ -1523,13 +565,20 @@ module RightAws
1523
565
 
1524
566
  class QEc2DescribeAvailabilityZonesParser < RightAWSParser #:nodoc:
1525
567
  def tagstart(name, attributes)
1526
- @zone = {} if name == 'item'
568
+ case full_tag_name
569
+ when %r{/availabilityZoneInfo/item$} then @item = {}
570
+ end
1527
571
  end
1528
572
  def tagend(name)
1529
573
  case name
1530
- when 'zoneName' then @zone[:zone_name] = @text
1531
- when 'zoneState' then @zone[:zone_state] = @text
1532
- when 'item' then @result << @zone
574
+ when 'regionName' then @item[:region_name] = @text
575
+ when 'zoneName' then @item[:zone_name] = @text
576
+ when 'zoneState' then @item[:zone_state] = @text
577
+ else
578
+ case full_tag_name
579
+ when %r{/messageSet/item/message$} then (@item[:messages] ||= []) << @text
580
+ when %r{/availabilityZoneInfo/item$} then @result << @item
581
+ end
1533
582
  end
1534
583
  end
1535
584
  def reset
@@ -1538,71 +587,18 @@ module RightAws
1538
587
  end
1539
588
 
1540
589
  #-----------------------------------------------------------------
1541
- # PARSERS: EBS - Volumes
590
+ # PARSERS: Regions
1542
591
  #-----------------------------------------------------------------
1543
-
1544
- class QEc2CreateVolumeParser < RightAWSParser #:nodoc:
1545
- def tagend(name)
1546
- case name
1547
- when 'volumeId' then @result[:aws_id] = @text
1548
- when 'status' then @result[:aws_status] = @text
1549
- when 'createTime' then @result[:aws_created_at] = Time.parse(@text)
1550
- when 'size' then @result[:aws_size] = @text.to_i ###
1551
- when 'snapshotId' then @result[:snapshot_id] = @text.blank? ? nil : @text ###
1552
- when 'availabilityZone' then @result[:zone] = @text ###
1553
- end
1554
- end
1555
- def reset
1556
- @result = {}
1557
- end
1558
- end
1559
-
1560
- class QEc2AttachAndDetachVolumeParser < RightAWSParser #:nodoc:
1561
- def tagend(name)
1562
- case name
1563
- when 'volumeId' then @result[:aws_id] = @text
1564
- when 'instanceId' then @result[:aws_instance_id] = @text
1565
- when 'device' then @result[:aws_device] = @text
1566
- when 'status' then @result[:aws_attachment_status] = @text
1567
- when 'attachTime' then @result[:aws_attached_at] = Time.parse(@text)
1568
- end
1569
- end
1570
- def reset
1571
- @result = {}
1572
- end
1573
- end
1574
-
1575
- class QEc2DescribeVolumesParser < RightAWSParser #:nodoc:
592
+
593
+ class QEc2DescribeRegionsParser < RightAWSParser #:nodoc:
1576
594
  def tagstart(name, attributes)
1577
- case name
1578
- when 'item'
1579
- case @xmlpath
1580
- when 'DescribeVolumesResponse/volumeSet' then @volume = {}
1581
- end
1582
- end
595
+ @item = {} if name == 'item'
1583
596
  end
1584
597
  def tagend(name)
1585
- case name
1586
- when 'volumeId'
1587
- case @xmlpath
1588
- when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_id] = @text
1589
- end
1590
- when 'status'
1591
- case @xmlpath
1592
- when 'DescribeVolumesResponse/volumeSet/item' then @volume[:aws_status] = @text
1593
- when 'DescribeVolumesResponse/volumeSet/item/attachmentSet/item' then @volume[:aws_attachment_status] = @text
1594
- end
1595
- when 'size' then @volume[:aws_size] = @text.to_i
1596
- when 'createTime' then @volume[:aws_created_at] = Time.parse(@text)
1597
- when 'instanceId' then @volume[:aws_instance_id] = @text
1598
- when 'device' then @volume[:aws_device] = @text
1599
- when 'attachTime' then @volume[:aws_attached_at] = Time.parse(@text)
1600
- when 'snapshotId' then @volume[:snapshot_id] = @text.blank? ? nil : @text
1601
- when 'availabilityZone' then @volume[:zone] = @text
1602
- when 'item'
1603
- case @xmlpath
1604
- when 'DescribeVolumesResponse/volumeSet' then @result << @volume
1605
- end
598
+ case name
599
+ when 'regionName' then @item[:region_name] = @text
600
+ when 'regionEndpoint' then @item[:region_endpoint] = @text
601
+ when 'item' then @result << @item
1606
602
  end
1607
603
  end
1608
604
  def reset
@@ -1611,43 +607,27 @@ module RightAws
1611
607
  end
1612
608
 
1613
609
  #-----------------------------------------------------------------
1614
- # PARSERS: EBS - Snapshots
610
+ # PARSERS: Account
1615
611
  #-----------------------------------------------------------------
1616
-
1617
- class QEc2DescribeSnapshotsParser < RightAWSParser #:nodoc:
612
+
613
+ class QEc2DescribeAccountAttributesParser < RightAWSParser #:nodoc:
1618
614
  def tagstart(name, attributes)
1619
- @snapshot = {} if name == 'item'
1620
- end
1621
- def tagend(name)
1622
- case name
1623
- when 'volumeId' then @snapshot[:aws_volume_id] = @text
1624
- when 'snapshotId' then @snapshot[:aws_id] = @text
1625
- when 'status' then @snapshot[:aws_status] = @text
1626
- when 'startTime' then @snapshot[:aws_started_at] = Time.parse(@text)
1627
- when 'progress' then @snapshot[:aws_progress] = @text
1628
- when 'item' then @result << @snapshot
615
+ case name
616
+ when 'attributeValueSet' then @values = []
1629
617
  end
1630
618
  end
1631
- def reset
1632
- @result = []
1633
- end
1634
- end
1635
-
1636
- class QEc2CreateSnapshotParser < RightAWSParser #:nodoc:
1637
619
  def tagend(name)
1638
- case name
1639
- when 'volumeId' then @result[:aws_volume_id] = @text
1640
- when 'snapshotId' then @result[:aws_id] = @text
1641
- when 'status' then @result[:aws_status] = @text
1642
- when 'startTime' then @result[:aws_started_at] = Time.parse(@text)
1643
- when 'progress' then @result[:aws_progress] = @text
620
+ case name
621
+ when 'attributeName' then @name = @text
622
+ when 'attributeValue' then @values << @text
623
+ when 'attributeValueSet' then @result[@name] = (@values.size == 1) ? @values.first : @values
1644
624
  end
1645
625
  end
1646
626
  def reset
1647
627
  @result = {}
1648
628
  end
1649
629
  end
1650
-
630
+
1651
631
  end
1652
632
 
1653
633
  end