right_aws-yodal 1.10.7 → 1.10.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +46 -1
  2. data/Manifest.txt +4 -0
  3. data/README.txt +0 -0
  4. data/Rakefile +0 -0
  5. data/lib/acf/right_acf_interface.rb +105 -33
  6. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  7. data/lib/acf/right_acf_streaming_interface.rb +236 -0
  8. data/lib/acw/right_acw_interface.rb +3 -3
  9. data/lib/as/right_as_interface.rb +55 -46
  10. data/lib/awsbase/benchmark_fix.rb +0 -0
  11. data/lib/awsbase/right_awsbase.rb +71 -12
  12. data/lib/awsbase/support.rb +0 -0
  13. data/lib/ec2/right_ec2.rb +22 -244
  14. data/lib/ec2/right_ec2_ebs.rb +23 -22
  15. data/lib/ec2/right_ec2_images.rb +21 -21
  16. data/lib/ec2/right_ec2_instances.rb +49 -54
  17. data/lib/ec2/right_ec2_reserved_instances.rb +7 -4
  18. data/lib/ec2/right_ec2_security_groups.rb +277 -0
  19. data/lib/ec2/right_ec2_spot_instances.rb +399 -0
  20. data/lib/ec2/right_ec2_vpc.rb +4 -4
  21. data/lib/elb/right_elb_interface.rb +112 -23
  22. data/lib/rds/right_rds_interface.rb +4 -4
  23. data/lib/right_aws.rb +8 -4
  24. data/lib/s3/right_s3.rb +25 -1
  25. data/lib/s3/right_s3_interface.rb +6 -2
  26. data/lib/sdb/active_sdb.rb +202 -10
  27. data/lib/sdb/right_sdb_interface.rb +61 -11
  28. data/lib/sqs/right_sqs.rb +0 -0
  29. data/lib/sqs/right_sqs_gen2.rb +0 -0
  30. data/lib/sqs/right_sqs_gen2_interface.rb +5 -4
  31. data/lib/sqs/right_sqs_interface.rb +0 -0
  32. data/test/acf/test_helper.rb +0 -0
  33. data/test/acf/test_right_acf.rb +10 -18
  34. data/test/ec2/test_helper.rb +0 -0
  35. data/test/ec2/test_right_ec2.rb +0 -0
  36. data/test/http_connection.rb +0 -0
  37. data/test/s3/test_helper.rb +0 -0
  38. data/test/s3/test_right_s3.rb +10 -8
  39. data/test/s3/test_right_s3_stubbed.rb +6 -4
  40. data/test/sdb/test_active_sdb.rb +70 -12
  41. data/test/sdb/test_batch_put_attributes.rb +54 -0
  42. data/test/sdb/test_helper.rb +0 -0
  43. data/test/sdb/test_right_sdb.rb +13 -7
  44. data/test/sqs/test_helper.rb +0 -0
  45. data/test/sqs/test_right_sqs.rb +0 -0
  46. data/test/sqs/test_right_sqs_gen2.rb +21 -33
  47. data/test/test_credentials.rb +0 -0
  48. data/test/ts_right_aws.rb +0 -0
  49. metadata +16 -4
@@ -37,10 +37,10 @@ module RightAws
37
37
  # :aws_attachment_status => "attached",
38
38
  # :zone => "merlot",
39
39
  # :snapshot_id => nil,
40
- # :aws_attached_at => Wed Jun 18 08:19:28 UTC 2008,
40
+ # :aws_attached_at => "2008-06-18T08:19:28.000Z",
41
41
  # :aws_status => "in-use",
42
42
  # :aws_id => "vol-60957009",
43
- # :aws_created_at => Wed Jun 18 08:19:20s UTC 2008,
43
+ # :aws_created_at => "2008-06-18T08:19:20.000Z",
44
44
  # :aws_instance_id => "i-c014c0a9"},
45
45
  # {:aws_size => 1,
46
46
  # :zone => "merlot",
@@ -49,10 +49,10 @@ module RightAws
49
49
  # :aws_id => "vol-58957031",
50
50
  # :aws_created_at => Wed Jun 18 08:19:21 UTC 2008,}, ... ]
51
51
  #
52
- def describe_volumes(list=[])
53
- link = generate_request("DescribeVolumes",
54
- amazonize_list('VolumeId',list.to_a))
55
- request_cache_or_info :describe_volumes, link, QEc2DescribeVolumesParser, @@bench, list.blank?
52
+ def describe_volumes(*volumes)
53
+ volumes = volumes.flatten
54
+ link = generate_request("DescribeVolumes", amazonize_list('VolumeId', volumes))
55
+ request_cache_or_info :describe_volumes, link, QEc2DescribeVolumesParser, @@bench, volumes.blank?
56
56
  rescue Exception
57
57
  on_exception
58
58
  end
@@ -65,7 +65,7 @@ module RightAws
65
65
  # :aws_status => "creating",
66
66
  # :aws_id => "vol-fc9f7a95",
67
67
  # :zone => "merlot",
68
- # :aws_created_at => Tue Jun 24 18:13:32 UTC 2008,
68
+ # :aws_created_at => "2008-06-24T18:13:32.000Z",
69
69
  # :aws_size => 94}
70
70
  #
71
71
  def create_volume(snapshot_id, size, zone)
@@ -144,7 +144,7 @@ module RightAws
144
144
  # [ {:aws_volume_id=>"vol-545fac3d",
145
145
  # :aws_description=>"Wikipedia XML Backups (Linux)",
146
146
  # :aws_progress=>"100%",
147
- # :aws_started_at=>Mon Sep 28 23:49:50 UTC 2009,
147
+ # :aws_started_at=>"2009-09-28T23:49:50.000Z",
148
148
  # :aws_owner=>"amazon",
149
149
  # :aws_id=>"snap-8041f2e9",
150
150
  # :aws_volume_size=>500,
@@ -152,16 +152,16 @@ module RightAws
152
152
  # {:aws_volume_id=>"vol-185fac71",
153
153
  # :aws_description=>"Sloan Digital Sky Survey DR6 Subset (Linux)",
154
154
  # :aws_progress=>"100%",
155
- # :aws_started_at=>Mon Sep 28 23:56:10 UTC 2009,
155
+ # :aws_started_at=>"2009-09-28T23:56:10.000Z",
156
156
  # :aws_owner=>"amazon",
157
157
  # :aws_id=>"snap-3740f35e",
158
158
  # :aws_volume_size=>180,
159
159
  # :aws_status=>"completed"}, ...]
160
160
  #
161
- def describe_snapshots(list=[])
162
- link = generate_request("DescribeSnapshots",
163
- amazonize_list('SnapshotId',list.to_a))
164
- request_cache_or_info :describe_snapshots, link, QEc2DescribeSnapshotsParser, @@bench, list.blank?
161
+ def describe_snapshots(*snapshots)
162
+ snapshots = snapshots.flatten
163
+ link = generate_request("DescribeSnapshots", amazonize_list('SnapshotId', snapshots))
164
+ request_cache_or_info :describe_snapshots, link, QEc2DescribeSnapshotsParser, @@bench, snapshots.blank?
165
165
  rescue Exception
166
166
  on_exception
167
167
  end
@@ -170,7 +170,7 @@ module RightAws
170
170
  #
171
171
  # ec2.create_snapshot('vol-898a6fe0', 'KD: WooHoo!!') #=>
172
172
  # {:aws_volume_id=>"vol-e429db8d",
173
- # :aws_started_at=>Thu Oct 01 09:23:38 UTC 2009,
173
+ # :aws_started_at=>"2009-10-01T09:23:38.000Z",
174
174
  # :aws_description=>"KD: WooHoo!!",
175
175
  # :aws_owner=>"648770000000",
176
176
  # :aws_progress=>"",
@@ -194,7 +194,7 @@ module RightAws
194
194
  #
195
195
  # ec2.try_create_snapshot('vol-898a6fe0', 'KD: WooHoo!!') #=>
196
196
  # {:aws_volume_id=>"vol-e429db8d",
197
- # :aws_started_at=>Thu Oct 01 09:23:38 UTC 2009,
197
+ # :aws_started_at=>"2009-10-01T09:23:38.000Z",
198
198
  # :aws_description=>"KD: WooHoo!!",
199
199
  # :aws_owner=>"648770000000",
200
200
  # :aws_progress=>"",
@@ -270,8 +270,8 @@ module RightAws
270
270
  params = {'SnapshotId' => snapshot_id,
271
271
  'Attribute' => attribute,
272
272
  'OperationType' => operation_type}
273
- params.update(amazonize_list('UserId', vars[:user_id].to_a)) if vars[:user_id]
274
- params.update(amazonize_list('UserGroup', vars[:user_group].to_a)) if vars[:user_group]
273
+ params.update(amazonize_list('UserId', Array(vars[:user_id]))) if vars[:user_id]
274
+ params.update(amazonize_list('UserGroup', Array(vars[:user_group]))) if vars[:user_group]
275
275
  link = generate_request("ModifySnapshotAttribute", params)
276
276
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
277
277
  rescue Exception
@@ -335,7 +335,7 @@ module RightAws
335
335
  case name
336
336
  when 'volumeId' then @result[:aws_id] = @text
337
337
  when 'status' then @result[:aws_status] = @text
338
- when 'createTime' then @result[:aws_created_at] = Time.parse(@text)
338
+ when 'createTime' then @result[:aws_created_at] = @text
339
339
  when 'size' then @result[:aws_size] = @text.to_i ###
340
340
  when 'snapshotId' then @result[:snapshot_id] = @text.blank? ? nil : @text ###
341
341
  when 'availabilityZone' then @result[:zone] = @text ###
@@ -353,7 +353,7 @@ module RightAws
353
353
  when 'instanceId' then @result[:aws_instance_id] = @text
354
354
  when 'device' then @result[:aws_device] = @text
355
355
  when 'status' then @result[:aws_attachment_status] = @text
356
- when 'attachTime' then @result[:aws_attached_at] = Time.parse(@text)
356
+ when 'attachTime' then @result[:aws_attached_at] = @text
357
357
  end
358
358
  end
359
359
  def reset
@@ -382,12 +382,13 @@ module RightAws
382
382
  when 'DescribeVolumesResponse/volumeSet/item/attachmentSet/item' then @volume[:aws_attachment_status] = @text
383
383
  end
384
384
  when 'size' then @volume[:aws_size] = @text.to_i
385
- when 'createTime' then @volume[:aws_created_at] = Time.parse(@text)
385
+ when 'createTime' then @volume[:aws_created_at] = @text
386
386
  when 'instanceId' then @volume[:aws_instance_id] = @text
387
387
  when 'device' then @volume[:aws_device] = @text
388
- when 'attachTime' then @volume[:aws_attached_at] = Time.parse(@text)
388
+ when 'attachTime' then @volume[:aws_attached_at] = @text
389
389
  when 'snapshotId' then @volume[:snapshot_id] = @text.blank? ? nil : @text
390
390
  when 'availabilityZone' then @volume[:zone] = @text
391
+ when 'deleteOnTermination' then @volume[:delete_on_termination] = (@text == 'true')
391
392
  when 'item'
392
393
  case @xmlpath
393
394
  when 'DescribeVolumesResponse/volumeSet' then @result << @volume
@@ -414,7 +415,7 @@ module RightAws
414
415
  when 'volumeId' then @snapshot[:aws_volume_id] = @text
415
416
  when 'snapshotId' then @snapshot[:aws_id] = @text
416
417
  when 'status' then @snapshot[:aws_status] = @text
417
- when 'startTime' then @snapshot[:aws_started_at] = Time.parse(@text)
418
+ when 'startTime' then @snapshot[:aws_started_at] = @text
418
419
  when 'progress' then @snapshot[:aws_progress] = @text
419
420
  when 'description' then @snapshot[:aws_description] = @text
420
421
  when 'ownerId' then @snapshot[:aws_owner] = @text
@@ -38,7 +38,7 @@ module RightAws
38
38
  def ec2_describe_images(params={}, image_type=nil, cache_for=nil) #:nodoc:
39
39
  request_hash = {}
40
40
  params.each do |list_by, list|
41
- request_hash.merge! amazonize_list(list_by, list.to_a)
41
+ request_hash.merge! amazonize_list(list_by, Array(list))
42
42
  end
43
43
  request_hash['ImageType'] = image_type if image_type
44
44
  link = generate_request("DescribeImages", request_hash)
@@ -80,10 +80,10 @@ module RightAws
80
80
  #
81
81
  # ec2.describe_images(['ami-5aa1f74c'])
82
82
  #
83
- def describe_images(list=[], image_type=nil)
84
- list = list.to_a
85
- cache_for = list.empty? && !image_type ? :describe_images : nil
86
- ec2_describe_images({ 'ImageId' => list }, image_type, cache_for)
83
+ def describe_images(images=[], image_type=nil)
84
+ images = Array(images)
85
+ cache_for = images.empty? && !image_type ? :describe_images : nil
86
+ ec2_describe_images({ 'ImageId' => images }, image_type, cache_for)
87
87
  end
88
88
 
89
89
  # Example:
@@ -91,10 +91,10 @@ module RightAws
91
91
  # ec2.describe_images_by_owner('522821470517')
92
92
  # ec2.describe_images_by_owner('self')
93
93
  #
94
- def describe_images_by_owner(list=['self'], image_type=nil)
95
- list = list.to_a
96
- cache_for = list==['self'] && !image_type ? :describe_images_by_owner : nil
97
- ec2_describe_images({ 'Owner' => list }, image_type, cache_for)
94
+ def describe_images_by_owner(owners=['self'], image_type=nil)
95
+ owners = Array(owners)
96
+ cache_for = (owners == ['self']) && (!image_type ? :describe_images_by_owner : nil)
97
+ ec2_describe_images({ 'Owner' => owners }, image_type, cache_for)
98
98
  end
99
99
 
100
100
  # Example:
@@ -103,10 +103,10 @@ module RightAws
103
103
  # ec2.describe_images_by_executable_by('self')
104
104
  # ec2.describe_images_by_executable_by('all')
105
105
  #
106
- def describe_images_by_executable_by(list=['self'], image_type=nil)
107
- list = list.to_a
108
- cache_for = list==['self'] && !image_type ? :describe_images_by_executable_by : nil
109
- ec2_describe_images({ 'ExecutableBy' => list }, image_type, cache_for)
106
+ def describe_images_by_executable_by(executable_by=['self'], image_type=nil)
107
+ executable_by = Array(executable_by)
108
+ cache_for = (executable_by==['self']) && (!image_type ? :describe_images_by_executable_by : nil)
109
+ ec2_describe_images({ 'ExecutableBy' => executable_by }, image_type, cache_for)
110
110
  end
111
111
 
112
112
 
@@ -209,9 +209,9 @@ module RightAws
209
209
  params = {'ImageId' => image_id,
210
210
  'Attribute' => attribute}
211
211
  params['OperationType'] = operation_type if operation_type
212
- params.update(amazonize_list('UserId', vars[:user_id].to_a)) if vars[:user_id]
213
- params.update(amazonize_list('UserGroup', vars[:user_group].to_a)) if vars[:user_group]
214
- params.update(amazonize_list('ProductCode', vars[:product_code])) if vars[:product_code]
212
+ params.update(amazonize_list('UserId', vars[:user_id])) if vars[:user_id]
213
+ params.update(amazonize_list('UserGroup', vars[:user_group])) if vars[:user_group]
214
+ params.update(amazonize_list('ProductCode', vars[:product_code])) if vars[:product_code]
215
215
  link = generate_request("ModifyImageAttribute", params)
216
216
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
217
217
  rescue Exception
@@ -224,7 +224,7 @@ module RightAws
224
224
  #
225
225
  # ec2.modify_image_launch_perm_add_users('ami-e444444d',['000000000777','000000000778']) #=> true
226
226
  def modify_image_launch_perm_add_users(image_id, user_id=[])
227
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id.to_a)
227
+ modify_image_attribute(image_id, 'launchPermission', 'add', :user_id => user_id)
228
228
  end
229
229
 
230
230
  # Revokes image launch permissions for users. +user_id+ is a list of users AWS accounts ids. Returns +true+ or an exception.
@@ -232,7 +232,7 @@ module RightAws
232
232
  # ec2.modify_image_launch_perm_remove_users('ami-e444444d',['000000000777','000000000778']) #=> true
233
233
  #
234
234
  def modify_image_launch_perm_remove_users(image_id, user_id=[])
235
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id.to_a)
235
+ modify_image_attribute(image_id, 'launchPermission', 'remove', :user_id => user_id)
236
236
  end
237
237
 
238
238
  # Add image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
@@ -241,7 +241,7 @@ module RightAws
241
241
  # ec2.modify_image_launch_perm_add_groups('ami-e444444d') #=> true
242
242
  #
243
243
  def modify_image_launch_perm_add_groups(image_id, user_group=['all'])
244
- modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => user_group.to_a)
244
+ modify_image_attribute(image_id, 'launchPermission', 'add', :user_group => user_group)
245
245
  end
246
246
 
247
247
  # Remove image launch permissions for users groups (currently only 'all' is supported, which gives public launch permissions).
@@ -249,7 +249,7 @@ module RightAws
249
249
  # ec2.modify_image_launch_perm_remove_groups('ami-e444444d') #=> true
250
250
  #
251
251
  def modify_image_launch_perm_remove_groups(image_id, user_group=['all'])
252
- modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => user_group.to_a)
252
+ modify_image_attribute(image_id, 'launchPermission', 'remove', :user_group => user_group)
253
253
  end
254
254
 
255
255
  # Add product code to image
@@ -257,7 +257,7 @@ module RightAws
257
257
  # ec2.modify_image_product_code('ami-e444444d','0ABCDEF') #=> true
258
258
  #
259
259
  def modify_image_product_code(image_id, product_code=[])
260
- modify_image_attribute(image_id, 'productCodes', nil, :product_code => product_code.to_a)
260
+ modify_image_attribute(image_id, 'productCodes', nil, :product_code => product_code)
261
261
  end
262
262
 
263
263
  # Create a new image.
@@ -84,9 +84,10 @@ module RightAws
84
84
  # :ebs_volume_id=>"vol-f900f990"}],
85
85
  # :aws_instance_id=>"i-8ce84ae4"} , ... ]
86
86
  #
87
- def describe_instances(list=[])
88
- link = generate_request("DescribeInstances", amazonize_list('InstanceId',list.to_a))
89
- request_cache_or_info(:describe_instances, link, QEc2DescribeInstancesParser, @@bench, list.blank?) do |parser|
87
+ def describe_instances(*instances)
88
+ instances = instances.flatten
89
+ link = generate_request("DescribeInstances", amazonize_list('InstanceId', instances))
90
+ request_cache_or_info(:describe_instances, link, QEc2DescribeInstancesParser, @@bench, instances.blank?) do |parser|
90
91
  get_desc_instances(parser.result)
91
92
  end
92
93
  rescue Exception
@@ -191,7 +192,7 @@ module RightAws
191
192
  #
192
193
  def launch_instances(image_id, options={})
193
194
  @logger.info("Launching instance of image #{image_id} for #{@aws_access_key_id}, " +
194
- "key: #{options[:key_name]}, groups: #{(options[:group_ids]).to_a.join(',')}")
195
+ "key: #{options[:key_name]}, groups: #{Array(options[:group_ids]).join(',')}")
195
196
  options[:image_id] = image_id
196
197
  options[:min_count] ||= 1
197
198
  options[:max_count] ||= options[:min_count]
@@ -203,22 +204,8 @@ module RightAws
203
204
  on_exception
204
205
  end
205
206
 
206
- =begin
207
- # TODO: API does not support this call yet
208
- def create_instance(options={})
209
- @logger.info("Creating instance #{@aws_access_key_id}, " +
210
- "key: #{options[:key_name]}, groups: #{(options[:group_ids]).to_a.join(',')}")
211
- params = prepare_instance_launch_params(options)
212
- link = generate_request("CreateInstance", params)
213
- instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger))
214
- get_desc_instances(instances).first
215
- rescue Exception
216
- on_exception
217
- end
218
- =end
219
-
220
207
  def prepare_instance_launch_params(options={}) # :nodoc:
221
- params = amazonize_list('SecurityGroup', options[:group_ids].to_a)
208
+ params = amazonize_list('SecurityGroup', Array(options[:group_ids]))
222
209
  params['InstanceType'] = options[:instance_type] || DEFAULT_INSTANCE_TYPE
223
210
  params['ImageId'] = options[:image_id] unless options[:image_id].blank?
224
211
  params['AddressingType'] = options[:addressing_type] unless options[:addressing_type].blank?
@@ -313,8 +300,9 @@ module RightAws
313
300
  #
314
301
  # ec2.reboot_instances(['i-f222222d','i-f222222e']) #=> true
315
302
  #
316
- def reboot_instances(list)
317
- link = generate_request("RebootInstances", amazonize_list('InstanceId', list.to_a))
303
+ def reboot_instances(*instances)
304
+ instances = instances.flatten
305
+ link = generate_request("RebootInstances", amazonize_list('InstanceId', instances))
318
306
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
319
307
  rescue Exception
320
308
  on_exception
@@ -431,6 +419,25 @@ module RightAws
431
419
  on_exception
432
420
  end
433
421
 
422
+ # Get Initial windows instance password using Amazon API call GetPasswordData.
423
+ #
424
+ # puts ec2.get_initial_password_v2(my_awesome_instance[:aws_instance_id], my_awesome_key[:aws_material]) #=> "MhjWcgZuY6"
425
+ #
426
+ # P.S. To say the truth there is absolutely no any speedup if to compare to the old get_initial_password method... ;(
427
+ #
428
+ def get_initial_password_v2(instance_id, private_key)
429
+ link = generate_request('GetPasswordData',
430
+ 'InstanceId' => instance_id )
431
+ response = request_info(link, QEc2GetPasswordDataParser.new(:logger => @logger))
432
+ if response[:password_data].blank?
433
+ raise AwsError.new("Initial password is not yet created for #{instance_id}")
434
+ else
435
+ OpenSSL::PKey::RSA.new(private_key).private_decrypt(Base64.decode64(response[:password_data]))
436
+ end
437
+ rescue Exception
438
+ on_exception
439
+ end
440
+
434
441
  # Bundle a Windows image.
435
442
  # Internally, it queues the bundling task and shuts down the instance.
436
443
  # It then takes a snapshot of the Windows volume bundles it, and uploads it to
@@ -455,7 +462,7 @@ module RightAws
455
462
  s3_owner_aws_secret_access_key ||= @aws_secret_access_key
456
463
  s3_expires = Time.now.utc + s3_expires if s3_expires.is_a?(Fixnum) && (s3_expires < S3Interface::ONE_YEAR_IN_SECONDS)
457
464
  # policy
458
- policy = { 'expiration' => s3_expires.strftime('%Y-%m-%dT%H:%M:%SZ'),
465
+ policy = { 'expiration' => AwsUtils::utc_iso8601(s3_expires),
459
466
  'conditions' => [ { 'bucket' => s3_bucket },
460
467
  { 'acl' => s3_upload_policy },
461
468
  [ 'starts-with', '$key', s3_prefix ] ] }.to_json
@@ -490,8 +497,9 @@ module RightAws
490
497
  # :aws_state => "failed",
491
498
  # :aws_instance_id => "i-e3e24e8a"}]
492
499
  #
493
- def describe_bundle_tasks(list=[])
494
- link = generate_request("DescribeBundleTasks", amazonize_list('BundleId', list.to_a))
500
+ def describe_bundle_tasks(*tasks)
501
+ tasks = tasks.flatten
502
+ link = generate_request("DescribeBundleTasks", amazonize_list('BundleId', tasks))
495
503
  request_info(link, QEc2DescribeBundleTasksParser.new)
496
504
  rescue Exception
497
505
  on_exception
@@ -517,35 +525,6 @@ module RightAws
517
525
  on_exception
518
526
  end
519
527
 
520
- #-----------------------------------------------------------------
521
- # Helpers
522
- #-----------------------------------------------------------------
523
-
524
- BLOCK_DEVICE_KEY_MAPPING = { # :nodoc:
525
- :device_name => 'DeviceName',
526
- :virtual_name => 'VirtualName',
527
- :no_device => 'NoDevice',
528
- :ebs_snapshot_id => 'Ebs.SnapshotId',
529
- :ebs_volume_size => 'Ebs.VolumeSize',
530
- :ebs_delete_on_termination => 'Ebs.DeleteOnTermination' }
531
-
532
- def amazonize_block_device_mappings(block_device_mappings) # :nodoc:
533
- result = {}
534
- unless block_device_mappings.blank?
535
- block_device_mappings = [block_device_mappings] unless block_device_mappings.is_a?(Array)
536
- block_device_mappings.each_with_index do |b, idx|
537
- BLOCK_DEVICE_KEY_MAPPING.each do |local_name, remote_name|
538
- value = b[local_name]
539
- case local_name
540
- when :no_device then value = value ? '' : nil # allow to pass :no_device as boolean
541
- end
542
- result["BlockDeviceMapping.#{idx+1}.#{remote_name}"] = value unless value.nil?
543
- end
544
- end
545
- end
546
- result
547
- end
548
-
549
528
  #-----------------------------------------------------------------
550
529
  # PARSERS: Instances
551
530
  #-----------------------------------------------------------------
@@ -599,9 +578,12 @@ module RightAws
599
578
  when 'rootDeviceType' then @item[:root_device_type] = @text
600
579
  when 'rootDeviceName' then @item[:root_device_name] = @text
601
580
  when 'instanceClass' then @item[:instance_class] = @text
581
+ when 'instanceLifecycle' then @item[:instance_lifecycle] = @text
582
+ when 'spotInstanceRequestId' then @item[:spot_instance_request_id] = @text
583
+ when 'requesterId' then @item[:requester_id] = @text
602
584
  else
603
585
  case full_tag_name
604
- when %r{/stateReason/code$} then @item[:state_reason_code] = @text.to_i
586
+ when %r{/stateReason/code$} then @item[:state_reason_code] = @text
605
587
  when %r{/stateReason/message$} then @item[:state_reason_message] = @text
606
588
  when %r{/instanceState/code$} then @item[:aws_state_code] = @text.to_i
607
589
  when %r{/instanceState/name$} then @item[:aws_state] = @text
@@ -755,6 +737,19 @@ module RightAws
755
737
  end
756
738
  end
757
739
 
740
+ class QEc2GetPasswordDataParser < RightAWSParser #:nodoc:
741
+ def tagend(name)
742
+ case name
743
+ when 'instanceId' then @result[:aws_instance_id] = @text
744
+ when 'timestamp' then @result[:timestamp] = @text
745
+ when 'passwordData' then @result[:password_data] = @text
746
+ end
747
+ end
748
+ def reset
749
+ @result = {}
750
+ end
751
+ end
752
+
758
753
  end
759
754
 
760
755
  end
@@ -41,11 +41,13 @@ module RightAws
41
41
  # :aws_state=>"payment-pending",
42
42
  # :aws_product_description=>"Test",
43
43
  # :aws_fixed_price=>325.0,
44
+ # :aws_start=>"2009-12-18T20:39:39.569Z"
44
45
  # :aws_instance_count=>1}]
45
46
  #
46
- def describe_reserved_instances(list=[])
47
- link = generate_request("DescribeReservedInstances", amazonize_list('ReservedInstancesId',list.to_a))
48
- request_cache_or_info(:describe_reserved_instances, link, QEc2DescribeReservedInstancesParser, @@bench, list.blank?)
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?)
49
51
  rescue Exception
50
52
  on_exception
51
53
  end
@@ -78,7 +80,7 @@ module RightAws
78
80
  def describe_reserved_instances_offerings(*list_and_params)
79
81
  list, params = AwsUtils::split_items_and_params(list_and_params)
80
82
  # backward compartibility with the old way
81
- list ||= params[:aws_ids].to_a
83
+ list ||= Array(params[:aws_ids])
82
84
  rparams = {}
83
85
  rparams.update(amazonize_list('ReservedInstancesOfferingId', list)) unless list.blank?
84
86
  rparams['InstanceType'] = params[:aws_instance_type] if params[:aws_instance_type]
@@ -122,6 +124,7 @@ module RightAws
122
124
  when 'instanceCount' then @item[:aws_instance_count] = @text.to_i
123
125
  when 'productDescription' then @item[:aws_product_description] = @text
124
126
  when 'state' then @item[:aws_state] = @text
127
+ when 'start' then @item[:aws_start] = @text
125
128
  when 'item' then @result << @item
126
129
  end
127
130
  end
@@ -0,0 +1,277 @@
1
+ #
2
+ # Copyright (c) 2010 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ class Ec2
27
+
28
+ #-----------------------------------------------------------------
29
+ # Security groups
30
+ #-----------------------------------------------------------------
31
+
32
+ # Retrieve Security Groups information. If +list+ is omitted the returns the whole list of groups.
33
+ #
34
+ # # Amazon cloud:
35
+ # ec2 = Rightscale::Ec2.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
36
+ # ec2.describe_security_groups #=>
37
+ # [{:aws_perms=>
38
+ # [{:group=>"default", :owner=>"048291609141"},
39
+ # {:to_port=>"22",
40
+ # :protocol=>"tcp",
41
+ # :from_port=>"22",
42
+ # :cidr_ips=>"0.0.0.0/0"},
43
+ # {:to_port=>"9997",
44
+ # :protocol=>"tcp",
45
+ # :from_port=>"9997",
46
+ # :cidr_ips=>"0.0.0.0/0"}],
47
+ # :aws_group_name=>"photo_us",
48
+ # :aws_description=>"default group",
49
+ # :aws_owner=>"826693181925"}]
50
+ #
51
+ # # Eucalyptus cloud:
52
+ # ec2 = Rightscale::Ec2.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, :eucalyptus => true)
53
+ # ec2.describe_security_groups #=>
54
+ # [{:aws_perms=>
55
+ # [{:to_port=>"65535",
56
+ # :group=>"default",
57
+ # :protocol=>"tcp",
58
+ # :owner=>"048291609141",
59
+ # :from_port=>"1"},
60
+ # {:to_port=>"65535",
61
+ # :group=>"default",
62
+ # :protocol=>"udp",
63
+ # :owner=>"048291609141",
64
+ # :from_port=>"1"},
65
+ # {:to_port=>"-1",
66
+ # :group=>"default",
67
+ # :protocol=>"icmp",
68
+ # :owner=>"048291609141",
69
+ # :from_port=>"-1"},
70
+ # {:to_port=>"22",
71
+ # :protocol=>"tcp",
72
+ # :from_port=>"22",
73
+ # :cidr_ip=>"0.0.0.0/0"},
74
+ # {:to_port=>"9997",
75
+ # :protocol=>"tcp",
76
+ # :from_port=>"9997",
77
+ # :cidr_ip=>"0.0.0.0/0"}],
78
+ # :aws_group_name=>"photo_us",
79
+ # :aws_description=>"default group",
80
+ # :aws_owner=>"826693181925"}]
81
+ #
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|
86
+ result = []
87
+ parser.result.each do |item|
88
+ result_item = { :aws_owner => item[:owner_id],
89
+ :aws_group_name => item[:group_name],
90
+ :aws_description => item[:group_description] }
91
+ aws_perms = []
92
+ item[:ip_permissions].each do |permission|
93
+ result_perm = {}
94
+ result_perm[:from_port] = permission[:from_port]
95
+ result_perm[:to_port] = permission[:to_port]
96
+ result_perm[:protocol] = permission[:ip_protocol]
97
+ # IP permissions
98
+ Array(permission[:ip_ranges]).each do |ip_range|
99
+ perm = result_perm.dup
100
+ perm[:cidr_ips] = ip_range
101
+ aws_perms << perm
102
+ end
103
+ # Group permissions
104
+ Array(permission[:groups]).each do |group|
105
+ perm = result_perm.dup
106
+ perm[:group] = group[:group_name]
107
+ perm[:owner] = group[:user_id]
108
+ # AWS does not support Port Based Group Permissions but Eucalyptus does
109
+ unless @params[:port_based_group_ingress]
110
+ perm.delete(:from_port)
111
+ perm.delete(:to_port)
112
+ perm.delete(:protocol)
113
+ end
114
+ aws_perms << perm
115
+ end
116
+ end
117
+ result_item[:aws_perms] = aws_perms.uniq
118
+ result << result_item
119
+ end
120
+ result
121
+ end
122
+ rescue Exception
123
+ on_exception
124
+ end
125
+
126
+ # Create new Security Group. Returns +true+ or an exception.
127
+ #
128
+ # ec2.create_security_group('default-1',"Default allowing SSH, HTTP, and HTTPS ingress") #=> true
129
+ #
130
+ def create_security_group(name, description=nil)
131
+ # EC2 doesn't like an empty description...
132
+ description = "-" if description.blank?
133
+ link = generate_request("CreateSecurityGroup",
134
+ 'GroupName' => name.to_s,
135
+ 'GroupDescription' => description.to_s)
136
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
137
+ rescue Exception
138
+ on_exception
139
+ end
140
+
141
+ # Remove Security Group. Returns +true+ or an exception.
142
+ #
143
+ # ec2.delete_security_group('default-1') #=> true
144
+ #
145
+ def delete_security_group(name)
146
+ link = generate_request("DeleteSecurityGroup",
147
+ 'GroupName' => name.to_s)
148
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
149
+ rescue Exception
150
+ on_exception
151
+ end
152
+
153
+ # Edit group permissions.
154
+ #
155
+ # action - :authorize (or :grant) | :revoke (or :remove)
156
+ # group_name - security group name
157
+ # params - a combination of options below:
158
+ # :source_group_owner => grantee id
159
+ # :source_group => grantee group name
160
+ # :from_port => from port
161
+ # :to_port => to port
162
+ # :port => set both :from_port and to_port with the same value
163
+ # :protocol => :tcp | :udp | :icmp
164
+ # :cidr_ip => '0.0.0.0/0'
165
+ #
166
+ # ec2.edit_security_group( :grant,
167
+ # 'kd-sg-test',
168
+ # :source_group => "sketchy",
169
+ # :source_group_owner => "600000000006",
170
+ # :protocol => 'tcp',
171
+ # :port => '80',
172
+ # :cidr_ip => '127.0.0.1/32') #=> true
173
+ #
174
+ # P.S. setting both group based and port based ingresses is not supported by Amazon but by Eucalyptus.
175
+ #
176
+ def edit_security_group(action, group_name, params)
177
+ hash = {}
178
+ case action
179
+ when :authorize, :grant then action = "AuthorizeSecurityGroupIngress"
180
+ when :revoke, :remove then action = "RevokeSecurityGroupIngress"
181
+ else raise "Unknown action #{action.inspect}!"
182
+ end
183
+ hash['GroupName'] = group_name
184
+ hash['SourceSecurityGroupName'] = params[:source_group] unless params[:source_group].blank?
185
+ hash['SourceSecurityGroupOwnerId'] = params[:source_group_owner].to_s.gsub(/-/,'') unless params[:source_group_owner].blank?
186
+ hash['IpProtocol'] = params[:protocol] unless params[:protocol].blank?
187
+ unless params[:port].blank?
188
+ hash['FromPort'] = params[:port]
189
+ hash['ToPort'] = params[:port]
190
+ end
191
+ hash['FromPort'] = params[:from_port] unless params[:from_port].blank?
192
+ hash['ToPort'] = params[:to_port] unless params[:to_port].blank?
193
+ hash['CidrIp'] = params[:cidr_ip] unless params[:cidr_ip].blank?
194
+ #
195
+ link = generate_request(action, hash)
196
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
197
+ rescue Exception
198
+ on_exception
199
+ end
200
+
201
+ # Authorize named ingress for security group. Allows instances that are member of someone
202
+ # else's security group to open connections to instances in my group.
203
+ #
204
+ # ec2.authorize_security_group_named_ingress('my_awesome_group', '7011-0219-8268', 'their_group_name') #=> true
205
+ #
206
+ def authorize_security_group_named_ingress(name, owner, group)
207
+ edit_security_group( :authorize, name, :source_group_owner => owner, :source_group => group)
208
+ end
209
+
210
+ # Revoke named ingress for security group.
211
+ #
212
+ # ec2.revoke_security_group_named_ingress('my_awesome_group', aws_user_id, 'another_group_name') #=> true
213
+ #
214
+ def revoke_security_group_named_ingress(name, owner, group)
215
+ edit_security_group( :revoke, name, :source_group_owner => owner, :source_group => group)
216
+ end
217
+
218
+ # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp'.
219
+ #
220
+ # ec2.authorize_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
221
+ # ec2.authorize_security_group_IP_ingress('my_awesome_group', -1, -1, 'icmp') #=> true
222
+ #
223
+ def authorize_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
224
+ edit_security_group( :authorize, name, :from_port => from_port, :to_port => to_port, :protocol => protocol, :cidr_ip => cidr_ip )
225
+ end
226
+
227
+ # Remove permission from a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp' ('tcp' is default).
228
+ #
229
+ # ec2.revoke_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
230
+ #
231
+ def revoke_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
232
+ edit_security_group( :revoke, name, :from_port => from_port, :to_port => to_port, :protocol => protocol, :cidr_ip => cidr_ip )
233
+ end
234
+
235
+ #-----------------------------------------------------------------
236
+ # PARSERS: Security Groups
237
+ #-----------------------------------------------------------------
238
+
239
+ class QEc2DescribeSecurityGroupsParser < RightAWSParser #:nodoc:
240
+ def tagstart(name, attributes)
241
+ if name == 'item'
242
+ case
243
+ when @xmlpath[/securityGroupInfo$/] then @item = { :ip_permissions => [] }
244
+ when @xmlpath[/ipPermissions$/] then @ip_permission = { :groups => [], :ip_ranges => [] }
245
+ when @xmlpath[/groups$/] then @group = {}
246
+ end
247
+ end
248
+ end
249
+ def tagend(name)
250
+ case name
251
+ when 'ownerId' then @item[:owner_id] = @text
252
+ when 'groupDescription' then @item[:group_description] = @text
253
+ when 'ipProtocol' then @ip_permission[:ip_protocol] = @text
254
+ when 'fromPort' then @ip_permission[:from_port] = @text
255
+ when 'toPort' then @ip_permission[:to_port] = @text
256
+ when 'cidrIp' then @ip_permission[:ip_ranges] << @text
257
+ when 'userId' then @group[:user_id] = @text
258
+ when 'groupName'
259
+ case
260
+ when @xmlpath[/securityGroupInfo\/item$/] then @item[:group_name] = @text
261
+ when @xmlpath[/groups\/item$/] then @group[:group_name] = @text
262
+ end
263
+ when 'item'
264
+ case
265
+ when @xmlpath[/groups$/] then @ip_permission[:groups] << @group
266
+ when @xmlpath[/ipPermissions$/] then @item[:ip_permissions] << @ip_permission
267
+ when @xmlpath[/securityGroupInfo$/]then @result << @item
268
+ end
269
+ end
270
+ end
271
+ def reset
272
+ @result = []
273
+ end
274
+ end
275
+
276
+ end
277
+ end