right_aws 2.0.0 → 2.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 (50) hide show
  1. data/History.txt +22 -1
  2. data/Manifest.txt +11 -1
  3. data/README.txt +0 -4
  4. data/Rakefile +19 -25
  5. data/lib/acf/right_acf_interface.rb +199 -135
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +4 -4
  8. data/lib/acf/right_acf_streaming_interface.rb +19 -26
  9. data/lib/acw/right_acw_interface.rb +1 -2
  10. data/lib/as/right_as_interface.rb +6 -7
  11. data/lib/awsbase/right_awsbase.rb +287 -91
  12. data/lib/awsbase/support.rb +2 -82
  13. data/lib/awsbase/version.rb +9 -0
  14. data/lib/ec2/right_ec2.rb +101 -38
  15. data/lib/ec2/right_ec2_ebs.rb +71 -58
  16. data/lib/ec2/right_ec2_images.rb +82 -42
  17. data/lib/ec2/right_ec2_instances.rb +74 -44
  18. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  19. data/lib/ec2/right_ec2_reserved_instances.rb +50 -46
  20. data/lib/ec2/right_ec2_security_groups.rb +148 -32
  21. data/lib/ec2/right_ec2_spot_instances.rb +53 -27
  22. data/lib/ec2/right_ec2_tags.rb +139 -0
  23. data/lib/ec2/right_ec2_vpc.rb +151 -139
  24. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  25. data/lib/elb/right_elb_interface.rb +93 -18
  26. data/lib/iam/right_iam_access_keys.rb +71 -0
  27. data/lib/iam/right_iam_groups.rb +195 -0
  28. data/lib/iam/right_iam_interface.rb +341 -0
  29. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  30. data/lib/iam/right_iam_users.rb +251 -0
  31. data/lib/rds/right_rds_interface.rb +513 -202
  32. data/lib/right_aws.rb +12 -12
  33. data/lib/route_53/right_route_53_interface.rb +630 -0
  34. data/lib/s3/right_s3.rb +9 -12
  35. data/lib/s3/right_s3_interface.rb +10 -11
  36. data/lib/sdb/active_sdb.rb +18 -33
  37. data/lib/sdb/right_sdb_interface.rb +36 -4
  38. data/lib/sqs/right_sqs.rb +1 -2
  39. data/lib/sqs/right_sqs_gen2.rb +0 -1
  40. data/lib/sqs/right_sqs_gen2_interface.rb +4 -5
  41. data/lib/sqs/right_sqs_interface.rb +6 -7
  42. data/right_aws.gemspec +91 -0
  43. data/test/awsbase/test_helper.rb +2 -0
  44. data/test/awsbase/test_right_awsbase.rb +12 -0
  45. data/test/s3/test_right_s3.rb +1 -1
  46. data/test/sdb/test_active_sdb.rb +1 -1
  47. data/test/sdb/test_batch_put_attributes.rb +54 -0
  48. data/test/sqs/test_right_sqs.rb +0 -6
  49. data/test/sqs/test_right_sqs_gen2.rb +1 -1
  50. metadata +109 -58
@@ -30,7 +30,11 @@ module RightAws
30
30
  #-----------------------------------------------------------------
31
31
 
32
32
  # Retrieve reserved instances list.
33
- # Returns a list of Reserved Instances.
33
+ #
34
+ # Accepts a list of reserved instances and/or a set of filters as the last parameter.
35
+ #
36
+ # Filters: availability-zone, duration, fixed-price, instance-type, product-description,
37
+ # reserved-instances-id, start, state, tag-key, tag-value, tag:key, usage-price
34
38
  #
35
39
  # ec2.describe_reserved_instances #=>
36
40
  # [{:aws_id=>"1ba8e2e3-1c40-434c-a741-5ff16a4c542e",
@@ -44,21 +48,19 @@ module RightAws
44
48
  # :aws_start=>"2009-12-18T20:39:39.569Z"
45
49
  # :aws_instance_count=>1}]
46
50
  #
47
- def describe_reserved_instances(*reserved_instances)
48
- reserved_instances = reserved_instances.flatten
49
- link = generate_request("DescribeReservedInstances", amazonize_list('ReservedInstancesId', reserved_instances))
50
- request_cache_or_info(:describe_reserved_instances, link, QEc2DescribeReservedInstancesParser, @@bench, reserved_instances.blank?)
51
- rescue Exception
52
- on_exception
51
+ # ec2.describe_reserved_instances(:filters => {'availability-zone' => 'us-east-1a'})
52
+ #
53
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeReservedInstances.html
54
+ #
55
+ def describe_reserved_instances(*list_and_options)
56
+ describe_resources_with_list_and_options('DescribeReservedInstances', 'ReservedInstancesId', QEc2DescribeReservedInstancesParser, list_and_options)
53
57
  end
54
58
 
55
59
  # Retrieve reserved instances offerings.
56
- # Returns a set of available offerings.
60
+ #
61
+ # Accepts a list of reserved instances offerings and/or a set of filters as the last parameter.
57
62
  #
58
- # Optional params:
59
- # :aws_instance_type => String
60
- # :aws_availability_zone => String
61
- # :aws_product_description => String
63
+ # Filters: availability-zone, duration, fixed-price, instance-type, product-description, reserved-instances-offering-id, usage-price
62
64
  #
63
65
  # ec2.describe_reserved_instances_offerings #=>
64
66
  # [{:aws_instance_type=>"c1.medium",
@@ -77,19 +79,12 @@ module RightAws
77
79
  # :aws_usage_price=>0.24,
78
80
  # :aws_fixed_price=>2600.0}]
79
81
  #
80
- def describe_reserved_instances_offerings(*list_and_params)
81
- list, params = AwsUtils::split_items_and_params(list_and_params)
82
- # backward compartibility with the old way
83
- list ||= Array(params[:aws_ids])
84
- rparams = {}
85
- rparams.update(amazonize_list('ReservedInstancesOfferingId', list)) unless list.blank?
86
- rparams['InstanceType'] = params[:aws_instance_type] if params[:aws_instance_type]
87
- rparams['AvailabilityZone'] = params[:aws_availability_zone] if params[:aws_availability_zone]
88
- rparams['ProductDescription'] = params[:aws_product_description] if params[:aws_product_description]
89
- link = generate_request("DescribeReservedInstancesOfferings", rparams)
90
- request_cache_or_info(:describe_reserved_instances_offerings, link, QEc2DescribeReservedInstancesOfferingsParser, @@bench, list.blank?)
91
- rescue Exception
92
- on_exception
82
+ # ec2.describe_reserved_instances_offerings(:filters => {'availability-zone' => 'us-east-1c'})
83
+ #
84
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeReservedInstancesOfferings.html
85
+ #
86
+ def describe_reserved_instances_offerings(*list_and_options)
87
+ describe_resources_with_list_and_options('DescribeReservedInstancesOfferings', 'ReservedInstancesOfferingId', QEc2DescribeReservedInstancesOfferingsParser, list_and_options)
93
88
  end
94
89
 
95
90
  # Purchase a Reserved Instance.
@@ -111,21 +106,30 @@ module RightAws
111
106
 
112
107
  class QEc2DescribeReservedInstancesParser < RightAWSParser #:nodoc:
113
108
  def tagstart(name, attributes)
114
- @item = {} if name == 'item'
109
+ case full_tag_name
110
+ when %r{/reservedInstancesSet/item$} then @item = { :tags => {} }
111
+ when %r{/tagSet/item$} then @aws_tag = {}
112
+ end
115
113
  end
116
114
  def tagend(name)
117
115
  case name
118
- when 'reservedInstancesId' then @item[:aws_id] = @text
119
- when 'instanceType' then @item[:aws_instance_type] = @text
120
- when 'availabilityZone' then @item[:aws_availability_zone] = @text
121
- when 'duration' then @item[:aws_duration] = @text.to_i
122
- when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
123
- when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
124
- when 'instanceCount' then @item[:aws_instance_count] = @text.to_i
125
- when 'productDescription' then @item[:aws_product_description] = @text
126
- when 'state' then @item[:aws_state] = @text
127
- when 'start' then @item[:aws_start] = @text
128
- when 'item' then @result << @item
116
+ when 'reservedInstancesId' then @item[:aws_id] = @text
117
+ when 'instanceType' then @item[:aws_instance_type] = @text
118
+ when 'availabilityZone' then @item[:aws_availability_zone] = @text
119
+ when 'duration' then @item[:aws_duration] = @text.to_i
120
+ when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
121
+ when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
122
+ when 'instanceCount' then @item[:aws_instance_count] = @text.to_i
123
+ when 'productDescription' then @item[:aws_product_description] = @text
124
+ when 'state' then @item[:aws_state] = @text
125
+ when 'start' then @item[:aws_start] = @text
126
+ else
127
+ case full_tag_name
128
+ when %r{/tagSet/item/key$} then @aws_tag[:key] = @text
129
+ when %r{/tagSet/item/value$} then @aws_tag[:value] = @text
130
+ when %r{/tagSet/item$} then @item[:tags][@aws_tag[:key]] = @aws_tag[:value]
131
+ when %r{/reservedInstancesSet/item$} then @result << @item
132
+ end
129
133
  end
130
134
  end
131
135
  def reset
@@ -136,19 +140,19 @@ module RightAws
136
140
  class QEc2DescribeReservedInstancesOfferingsParser < RightAWSParser #:nodoc:
137
141
  def tagstart(name, attributes)
138
142
  @item = {} if name == 'item'
139
- end
143
+ end
140
144
  def tagend(name)
141
145
  case name
142
- when 'reservedInstancesOfferingId' then @item[:aws_id] = @text
143
- when 'instanceType' then @item[:aws_instance_type] = @text
144
- when 'availabilityZone' then @item[:aws_availability_zone] = @text
145
- when 'duration' then @item[:aws_duration] = @text.to_i
146
- when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
147
- when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
148
- when 'productDescription' then @item[:aws_product_description] = @text
146
+ when 'reservedInstancesOfferingId' then @item[:aws_id] = @text
147
+ when 'instanceType' then @item[:aws_instance_type] = @text
148
+ when 'availabilityZone' then @item[:aws_availability_zone] = @text
149
+ when 'duration' then @item[:aws_duration] = @text.to_i
150
+ when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
151
+ when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
152
+ when 'productDescription' then @item[:aws_product_description] = @text
149
153
  when 'item' then @result << @item
154
+ end
150
155
  end
151
- end
152
156
  def reset
153
157
  @result = []
154
158
  end
@@ -29,7 +29,12 @@ module RightAws
29
29
  # Security groups
30
30
  #-----------------------------------------------------------------
31
31
 
32
- # Retrieve Security Groups information. If +list+ is omitted the returns the whole list of groups.
32
+ # Retrieve Security Groups information.
33
+ #
34
+ # Accepts a list of security groups and/or a set of filters as the last parameter.
35
+ #
36
+ # Filters: description, group-name, ip-permission.cidr, ip-permission.from-port, ip-permission.group-name,
37
+ # ip-permission.protocol, ip-permission.to-port, ip-permission.user-id, owner-id
33
38
  #
34
39
  # # Amazon cloud:
35
40
  # ec2 = Rightscale::Ec2.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
@@ -79,10 +84,12 @@ module RightAws
79
84
  # :aws_description=>"default group",
80
85
  # :aws_owner=>"826693181925"}]
81
86
  #
82
- def describe_security_groups(list=[])
83
- link = generate_request("DescribeSecurityGroups", amazonize_list('GroupName', list))
84
-
85
- request_cache_or_info( :describe_security_groups, link, QEc2DescribeSecurityGroupsParser, @@bench, list.blank?) do |parser|
87
+ # ec2.describe_security_groups(:filters => {'ip-permission.from-port' => '22'})
88
+ #
89
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSecurityGroups.html
90
+ #
91
+ def describe_security_groups(*list_and_options)
92
+ describe_resources_with_list_and_options('DescribeSecurityGroups', 'GroupName', QEc2DescribeSecurityGroupsParser, list_and_options) do |parser|
86
93
  result = []
87
94
  parser.result.each do |item|
88
95
  result_item = { :aws_owner => item[:owner_id],
@@ -97,10 +104,7 @@ module RightAws
97
104
  # IP permissions
98
105
  Array(permission[:ip_ranges]).each do |ip_range|
99
106
  perm = result_perm.dup
100
- # Mhhh... For Eucalyptus we somehow get used to use ":cidr_ip" instead of ":cidr_ips"...
101
- if @params[:eucalyptus] then perm[:cidr_ip] = ip_range
102
- else perm[:cidr_ips] = ip_range
103
- end
107
+ perm[:cidr_ips] = ip_range
104
108
  aws_perms << perm
105
109
  end
106
110
  # Group permissions
@@ -108,12 +112,6 @@ module RightAws
108
112
  perm = result_perm.dup
109
113
  perm[:group] = group[:group_name]
110
114
  perm[:owner] = group[:user_id]
111
- # AWS does not support Port Based Group Permissions but Eucalyptus does
112
- unless @params[:port_based_group_ingress]
113
- perm.delete(:from_port)
114
- perm.delete(:to_port)
115
- perm.delete(:protocol)
116
- end
117
115
  aws_perms << perm
118
116
  end
119
117
  end
@@ -122,8 +120,6 @@ module RightAws
122
120
  end
123
121
  result
124
122
  end
125
- rescue Exception
126
- on_exception
127
123
  end
128
124
 
129
125
  # Create new Security Group. Returns +true+ or an exception.
@@ -132,7 +128,7 @@ module RightAws
132
128
  #
133
129
  def create_security_group(name, description=nil)
134
130
  # EC2 doesn't like an empty description...
135
- description = "-" if description.blank?
131
+ description = "-" if description.right_blank?
136
132
  link = generate_request("CreateSecurityGroup",
137
133
  'GroupName' => name.to_s,
138
134
  'GroupDescription' => description.to_s)
@@ -153,13 +149,14 @@ module RightAws
153
149
  on_exception
154
150
  end
155
151
 
156
- # Edit group permissions.
152
+ # Edit AWS/Eucaliptus security group permissions.
157
153
  #
158
- # action - :authorize (or :grant) | :revoke (or :remove)
159
- # group_name - security group name
160
- # params - a combination of options below:
161
- # :source_group_owner => grantee id
162
- # :source_group => grantee group name
154
+ # Options:
155
+ # action - :authorize (or :grant) | :revoke (or :remove)
156
+ # group_name - security group name
157
+ # permissions - a combination of options below:
158
+ # :source_group_owner => UserId
159
+ # :source_group => GroupName
163
160
  # :from_port => from port
164
161
  # :to_port => to port
165
162
  # :port => set both :from_port and to_port with the same value
@@ -174,7 +171,8 @@ module RightAws
174
171
  # :port => '80',
175
172
  # :cidr_ip => '127.0.0.1/32') #=> true
176
173
  #
177
- # P.S. setting both group based and port based ingresses is not supported by Amazon but by Eucalyptus.
174
+ # P.S. This method is deprecated for AWS and but still good for Eucaliptus clouds.
175
+ # Use +modify_security_group_ingress+ method for AWS clouds.
178
176
  #
179
177
  def edit_security_group(action, group_name, params)
180
178
  hash = {}
@@ -184,16 +182,134 @@ module RightAws
184
182
  else raise "Unknown action #{action.inspect}!"
185
183
  end
186
184
  hash['GroupName'] = group_name
187
- hash['SourceSecurityGroupName'] = params[:source_group] unless params[:source_group].blank?
188
- hash['SourceSecurityGroupOwnerId'] = params[:source_group_owner].to_s.gsub(/-/,'') unless params[:source_group_owner].blank?
189
- hash['IpProtocol'] = params[:protocol] unless params[:protocol].blank?
190
- unless params[:port].blank?
185
+ hash['SourceSecurityGroupName'] = params[:source_group] unless params[:source_group].right_blank?
186
+ hash['SourceSecurityGroupOwnerId'] = params[:source_group_owner].to_s.gsub(/-/,'') unless params[:source_group_owner].right_blank?
187
+ hash['IpProtocol'] = params[:protocol] unless params[:protocol].right_blank?
188
+ unless params[:port].right_blank?
191
189
  hash['FromPort'] = params[:port]
192
190
  hash['ToPort'] = params[:port]
193
191
  end
194
- hash['FromPort'] = params[:from_port] unless params[:from_port].blank?
195
- hash['ToPort'] = params[:to_port] unless params[:to_port].blank?
196
- hash['CidrIp'] = params[:cidr_ip] unless params[:cidr_ip].blank?
192
+ hash['FromPort'] = params[:from_port] unless params[:from_port].right_blank?
193
+ hash['ToPort'] = params[:to_port] unless params[:to_port].right_blank?
194
+ hash['CidrIp'] = params[:cidr_ip] unless params[:cidr_ip].right_blank?
195
+ #
196
+ link = generate_request(action, hash)
197
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
198
+ rescue Exception
199
+ on_exception
200
+ end
201
+
202
+ # Modify AWS security group permissions.
203
+ #
204
+ # Options:
205
+ # action - :authorize (or :grant) | :revoke (or :remove)
206
+ # group_name - security group name
207
+ # permissions - a combination of options below:
208
+ # # Ports:
209
+ # :from_port => from port
210
+ # :to_port => to port
211
+ # :port => set both :from_port and to_port with the same value
212
+ # # Protocol
213
+ # :protocol => :tcp | :udp | :icmp
214
+ # # Group(s)
215
+ # :source_group_owner => UserId
216
+ # :source_group => GroupName
217
+ # # or
218
+ # :source_groups => { UserId1 => GroupName1, UserName2 => GroupName2 }
219
+ # :source_groups => [ [ UserId1, GroupName1 ], [ UserName2 => GroupName2 ] ]
220
+ # # CidrIp(s)
221
+ # :cidr_ip => '0.0.0.0/0'
222
+ # :cidr_ips => ['1.1.1.1/1', '2.2.2.2/2']
223
+ #
224
+ # # CidrIP based permissions:
225
+ #
226
+ # ec2.modify_security_group_ingress(:authorize, 'my_cool_group',
227
+ # :cidr_ip => "127.0.0.0/31",
228
+ # :port => 811,
229
+ # :protocol => 'tcp' ) #=> true
230
+ #
231
+ # ec2.modify_security_group_ingress(:revoke, 'my_cool_group',
232
+ # :cidr_ips => ["127.0.0.1/32", "127.0.0.2/32"],
233
+ # :port => 812,
234
+ # :protocol => 'tcp' ) #=> true
235
+ #
236
+ # # Group based permissions:
237
+ #
238
+ # ec2.modify_security_group_ingress(:authorize, 'my_cool_group',
239
+ # :source_group_owner => "586789340000",
240
+ # :source_group => "sketchy-us",
241
+ # :port => 800,
242
+ # :protocol => 'tcp' ) #=> true
243
+ #
244
+ # ec2.modify_security_group_ingress(:authorize, 'my_cool_group',
245
+ # :source_groups => { "586789340000" => "sketchy-us",
246
+ # "635201710000" => "sketchy" },
247
+ # :port => 801,
248
+ # :protocol => 'tcp' ) #=> true
249
+ #
250
+ # ec2.modify_security_group_ingress(:revoke, 'my_cool_group',
251
+ # :source_groups => [[ "586789340000", "sketchy-us" ],
252
+ # [ "586789340000", "default" ]],
253
+ # :port => 809,
254
+ # :protocol => 'tcp' ) #=> true
255
+ #
256
+ # # +Permissions+ can be an array of permission hashes:
257
+ #
258
+ # ec2.modify_security_group_ingress(:authorize, 'my_cool_group',
259
+ # [{ :source_groups => { "586789340000" => "sketchy-us",
260
+ # "635201710000" => "sketchy" },
261
+ # :port => 803,
262
+ # :protocol => 'tcp'},
263
+ # { :cidr_ips => ["127.0.0.1/32", "127.0.0.2/32"],
264
+ # :port => 812,
265
+ # :protocol => 'tcp' }]) #=> true
266
+ #
267
+ def modify_security_group_ingress(action, group_name, permissions)
268
+ hash = {}
269
+ case action
270
+ when :authorize, :grant then action = "AuthorizeSecurityGroupIngress"
271
+ when :revoke, :remove then action = "RevokeSecurityGroupIngress"
272
+ else raise "Unknown action #{action.inspect}!"
273
+ end
274
+ # Group Name
275
+ hash["GroupName"] = group_name
276
+ #
277
+ permissions = [permissions] unless permissions.is_a?(Array)
278
+ permissions.each_with_index do |permission, idx|
279
+ pid = idx+1
280
+ # Protocol
281
+ hash["IpPermissions.#{pid}.IpProtocol"] = permission[:protocol]
282
+ # Port
283
+ unless permission[:port].right_blank?
284
+ hash["IpPermissions.#{pid}.FromPort"] = permission[:port]
285
+ hash["IpPermissions.#{pid}.ToPort"] = permission[:port]
286
+ else
287
+ hash["IpPermissions.#{pid}.FromPort"] = permission[:from_port]
288
+ hash["IpPermissions.#{pid}.ToPort"] = permission[:to_port]
289
+ end
290
+ # Source Group(s)
291
+ # Old way (if it is used):
292
+ # :source_group_owner => UserId, :source_group => GroupName
293
+ if !permission[:source_group].right_blank? && !permission[:source_group_owner].right_blank?
294
+ permission[:source_groups] = { permission[:source_group_owner] => permission[:source_group]}
295
+ end
296
+ # # Fix UserId(s): '0000-0000-0000' => '000000000000'
297
+ # permission[:source_groups] = Array(permission[:source_groups])
298
+ # permission[:source_groups].each do |item|
299
+ # item[0] = item[0].to_s.gsub(/-/,'')
300
+ # end
301
+ # New way:
302
+ # :source_groups => {UserId1 => GroupName1, ... UserIdN => GroupNameN}
303
+ # or (this allows using same UserId multiple times )
304
+ # :source_groups => [[UserId1, GroupName1], ... [UserIdN, GroupNameN]]
305
+ hash.merge!(amazonize_list( ["IpPermissions.#{pid}.Groups.?.UserId",
306
+ "IpPermissions.#{pid}.Groups.?.GroupName"],
307
+ permission[:source_groups] ))
308
+ # CidrIp(s)
309
+ cidr_ips = permission[:cidr_ips] unless permission[:cidr_ips].right_blank?
310
+ cidr_ips ||= permission[:cidr_ip] unless permission[:cidr_ip].right_blank?
311
+ hash.merge!(amazonize_list("IpPermissions.1.IpRanges.?.CidrIp", cidr_ips))
312
+ end
197
313
  #
198
314
  link = generate_request(action, hash)
199
315
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
@@ -30,7 +30,10 @@ module RightAws
30
30
  #-----------------------------------------------------------------
31
31
 
32
32
  # Describe Spot Price history.
33
+ #
33
34
  # Options: :start_time, :end_time, instance_types, product_description
35
+ #
36
+ # Filters: instance-type, product-description, spot-price, timestamp
34
37
  #
35
38
  # ec2.describe_spot_price_history #=>
36
39
  # [{:spot_price=>0.054,
@@ -63,13 +66,21 @@ module RightAws
63
66
  # :spot_price=>0.058,
64
67
  # :instance_type=>"c1.medium"}, ... ]
65
68
  #
69
+ # ec2.describe_spot_price_history(:filters => {'spot-price' => '0.2' })
70
+ #
71
+ # ec2.describe_spot_price_history(:instance_types => ["c1.medium"], :filters => {'spot-price' => '0.2' })
72
+ #
73
+ #
74
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeSpotPriceHistory.html
75
+ #
66
76
  def describe_spot_price_history(options={})
67
77
  options = options.dup
68
78
  request_hash = {}
69
- request_hash['StartTime'] = AwsUtils::utc_iso8601(options[:start_time]) unless options[:start_time].blank?
70
- request_hash['EndTime'] = AwsUtils::utc_iso8601(options[:end_time]) unless options[:end_time].blank?
71
- request_hash['ProductDescription'] = options[:product_description] unless options[:product_description].blank?
72
- request_hash.merge!(amazonize_list('InstanceType', Array(options[:instance_types]))) unless options[:instance_types].blank?
79
+ request_hash.merge!(amazonize_list(['Filter.?.Name', 'Filter.?.Value.?'], options[:filters])) unless options[:filters].right_blank?
80
+ request_hash['StartTime'] = AwsUtils::utc_iso8601(options[:start_time]) unless options[:start_time].right_blank?
81
+ request_hash['EndTime'] = AwsUtils::utc_iso8601(options[:end_time]) unless options[:end_time].right_blank?
82
+ request_hash['ProductDescription'] = options[:product_description] unless options[:product_description].right_blank?
83
+ request_hash.merge!(amazonize_list('InstanceType', Array(options[:instance_types]))) unless options[:instance_types].right_blank?
73
84
  link = generate_request("DescribeSpotPriceHistory", request_hash)
74
85
  request_info(link, QEc2DescribeSpotPriceHistoryParser.new)
75
86
  rescue Exception
@@ -78,6 +89,14 @@ module RightAws
78
89
 
79
90
  # Describe Spot Instance requests.
80
91
  #
92
+ # Accepts a list of requests and/or a set of filters as the last parameter.
93
+ #
94
+ # Filters: availability-zone-group, create-time, fault-code, fault-message, instance-id, launch-group,
95
+ # launch.block-device-mapping.delete-on-termination, launch.block-device-mapping.device-name,
96
+ # launch.block-device-mapping.snapshot-id, launch.group-id, launch.image-id, launch.instance-type,
97
+ # launch.kernel-id, launch.key-name, launch.monitoring-enabled, launch.ramdisk-id, product-description,
98
+ # spot-instance-request-id, spot-price, state, tag-key, tag-value, tag:key, type, valid-from, valid-until
99
+ #
81
100
  # ec2.describe_spot_instance_requests #=>
82
101
  # [{:type=>"one-time",
83
102
  # :create_time=>"2010-03-10T10:30:32.000Z",
@@ -113,9 +132,12 @@ module RightAws
113
132
  # :monitoring_enabled=>false,
114
133
  # :key_name=>"tim"}]
115
134
  #
116
- def describe_spot_instance_requests(*spot_instance_request_ids)
117
- link = generate_request("DescribeSpotInstanceRequests", amazonize_list('SpotInstanceRequestId', spot_instance_request_ids.flatten))
118
- request_info(link, QEc2DescribeSpotInstanceParser.new(:logger => @logger))
135
+ # ec2.describe_spot_instance_requests(:filters => {'type'=>"one-time", 'state'=>"open"})
136
+ #
137
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeSpotInstanceRequests.html
138
+ #
139
+ def describe_spot_instance_requests(*list_and_options)
140
+ describe_resources_with_list_and_options('DescribeSpotInstanceRequests', 'SpotInstanceRequestId', QEc2DescribeSpotInstanceParser, list_and_options)
119
141
  end
120
142
 
121
143
  # Create a Spot Instance request.
@@ -205,25 +227,25 @@ module RightAws
205
227
  request_hash = { 'SpotPrice' => options[:spot_price],
206
228
  'LaunchSpecification.ImageId' => options[:image_id],
207
229
  'LaunchSpecification.InstanceType' => options[:instance_type]}
208
- request_hash['ValidFrom'] = AwsUtils::utc_iso8601(options[:valid_from]) unless options[:valid_from].blank?
209
- request_hash['ValidUntil'] = AwsUtils::utc_iso8601(options[:valid_until]) unless options[:valid_until].blank?
210
- request_hash['InstanceCount'] = options[:instance_count] unless options[:instance_count].blank?
211
- request_hash['Type'] = options[:type] unless options[:type].blank?
212
- request_hash['LaunchGroup'] = options[:launch_group] unless options[:launch_group].blank?
213
- request_hash['AvailabilityZoneGroup'] = options[:availability_zone_group] unless options[:availability_zone_group].blank?
214
- request_hash['LaunchSpecification.KeyName'] = options[:key_name] unless options[:key_name].blank?
215
- request_hash['LaunchSpecification.AddressingType'] = options[:addressing_type] unless options[:addressing_type].blank?
216
- request_hash['LaunchSpecification.KernelId'] = options[:kernel_id] unless options[:kernel_id].blank?
217
- request_hash['LaunchSpecification.RamdiskId'] = options[:ramdisk_id] unless options[:ramdisk_id].blank?
218
- request_hash['LaunchSpecification.SubnetId'] = options[:subnet_id] unless options[:subnet_id].blank?
219
- request_hash['LaunchSpecification.Placement.AvailabilityZone'] = options[:availability_zone] unless options[:availability_zone].blank?
220
- request_hash['LaunchSpecification.Monitoring.Enabled'] = options[:monitoring_enabled] unless options[:monitoring_enabled].blank?
221
- request_hash.merge!(amazonize_list('LaunchSpecification.SecurityGroup', options[:groups])) unless options[:groups].blank?
230
+ request_hash['ValidFrom'] = AwsUtils::utc_iso8601(options[:valid_from]) unless options[:valid_from].right_blank?
231
+ request_hash['ValidUntil'] = AwsUtils::utc_iso8601(options[:valid_until]) unless options[:valid_until].right_blank?
232
+ request_hash['InstanceCount'] = options[:instance_count] unless options[:instance_count].right_blank?
233
+ request_hash['Type'] = options[:type] unless options[:type].right_blank?
234
+ request_hash['LaunchGroup'] = options[:launch_group] unless options[:launch_group].right_blank?
235
+ request_hash['AvailabilityZoneGroup'] = options[:availability_zone_group] unless options[:availability_zone_group].right_blank?
236
+ request_hash['LaunchSpecification.KeyName'] = options[:key_name] unless options[:key_name].right_blank?
237
+ request_hash['LaunchSpecification.AddressingType'] = options[:addressing_type] unless options[:addressing_type].right_blank?
238
+ request_hash['LaunchSpecification.KernelId'] = options[:kernel_id] unless options[:kernel_id].right_blank?
239
+ request_hash['LaunchSpecification.RamdiskId'] = options[:ramdisk_id] unless options[:ramdisk_id].right_blank?
240
+ request_hash['LaunchSpecification.SubnetId'] = options[:subnet_id] unless options[:subnet_id].right_blank?
241
+ request_hash['LaunchSpecification.Placement.AvailabilityZone'] = options[:availability_zone] unless options[:availability_zone].right_blank?
242
+ request_hash['LaunchSpecification.Monitoring.Enabled'] = options[:monitoring_enabled] unless options[:monitoring_enabled].right_blank?
243
+ request_hash.merge!(amazonize_list('LaunchSpecification.SecurityGroup', options[:groups])) unless options[:groups].right_blank?
222
244
  request_hash.merge!(amazonize_block_device_mappings(options[:block_device_mappings], 'LaunchSpecification.BlockDeviceMapping'))
223
- unless options[:user_data].blank?
245
+ unless options[:user_data].right_blank?
224
246
  # See RightAws::Ec2#run_instances
225
247
  options[:user_data].strip!
226
- request_hash['LaunchSpecification.UserData'] = Base64.encode64(options[:user_data]).delete("\n") unless options[:user_data].blank?
248
+ request_hash['LaunchSpecification.UserData'] = Base64.encode64(options[:user_data]).delete("\n") unless options[:user_data].right_blank?
227
249
  end
228
250
  link = generate_request("RequestSpotInstances", request_hash)
229
251
  request_info(link, QEc2DescribeSpotInstanceParser.new(:logger => @logger))
@@ -253,7 +275,7 @@ module RightAws
253
275
  #
254
276
  def create_spot_datafeed_subscription(bucket, prefix=nil)
255
277
  request_hash = { 'Bucket' => bucket }
256
- request_hash['Prefix'] = prefix unless prefix.blank?
278
+ request_hash['Prefix'] = prefix unless prefix.right_blank?
257
279
  link = generate_request("CreateSpotDatafeedSubscription", request_hash)
258
280
  request_info(link, QEc2DescribeSpotDatafeedSubscriptionParser.new(:logger => @logger))
259
281
  end
@@ -306,10 +328,12 @@ module RightAws
306
328
  def tagstart(name, attributes)
307
329
  case full_tag_name
308
330
  when %r{spotInstanceRequestSet/item$}
309
- @item = {}
331
+ @item = { :tags => {} }
310
332
  when %r{/blockDeviceMapping/item$}
311
333
  @item[:block_device_mappings] ||= []
312
334
  @block_device_mapping = {}
335
+ when %r{/tagSet/item$}
336
+ @aws_tag = {}
313
337
  end
314
338
  end
315
339
  def tagend(name)
@@ -351,8 +375,10 @@ module RightAws
351
375
  when 'deleteOnTermination' then @block_device_mapping[:ebs_delete_on_termination] = @text == 'true' ? true : false
352
376
  when 'item' then @item[:block_device_mappings] << @block_device_mapping
353
377
  end
354
- when %r{spotInstanceRequestSet/item$}
355
- @result << @item
378
+ when %r{/tagSet/item/key$} then @aws_tag[:key] = @text
379
+ when %r{/tagSet/item/value$} then @aws_tag[:value] = @text
380
+ when %r{/tagSet/item$} then @item[:tags][@aws_tag[:key]] = @aws_tag[:value]
381
+ when %r{spotInstanceRequestSet/item$} then @result << @item
356
382
  end
357
383
  end
358
384
  end