right_aws 1.9.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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