icehouse-right_aws 1.11.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/History.txt +93 -15
  2. data/Manifest.txt +15 -1
  3. data/README.txt +0 -4
  4. data/Rakefile +34 -17
  5. data/lib/acf/right_acf_interface.rb +260 -124
  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 +4 -5
  10. data/lib/as/right_as_interface.rb +59 -51
  11. data/lib/awsbase/benchmark_fix.rb +0 -0
  12. data/lib/awsbase/right_awsbase.rb +351 -104
  13. data/lib/awsbase/support.rb +2 -82
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +97 -246
  16. data/lib/ec2/right_ec2_ebs.rb +88 -68
  17. data/lib/ec2/right_ec2_images.rb +90 -50
  18. data/lib/ec2/right_ec2_instances.rb +118 -89
  19. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  20. data/lib/ec2/right_ec2_reserved_instances.rb +51 -44
  21. data/lib/ec2/right_ec2_security_groups.rb +396 -0
  22. data/lib/ec2/right_ec2_spot_instances.rb +425 -0
  23. data/lib/ec2/right_ec2_tags.rb +139 -0
  24. data/lib/ec2/right_ec2_vpc.rb +152 -140
  25. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  26. data/lib/elb/right_elb_interface.rb +205 -39
  27. data/lib/iam/right_iam_access_keys.rb +71 -0
  28. data/lib/iam/right_iam_groups.rb +195 -0
  29. data/lib/iam/right_iam_interface.rb +341 -0
  30. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  31. data/lib/iam/right_iam_users.rb +251 -0
  32. data/lib/rds/right_rds_interface.rb +591 -205
  33. data/lib/right_aws.rb +16 -12
  34. data/lib/route_53/right_route_53_interface.rb +640 -0
  35. data/lib/s3/right_s3.rb +34 -13
  36. data/lib/s3/right_s3_interface.rb +17 -14
  37. data/lib/sdb/active_sdb.rb +215 -38
  38. data/lib/sdb/right_sdb_interface.rb +93 -12
  39. data/lib/sqs/right_sqs.rb +1 -2
  40. data/lib/sqs/right_sqs_gen2.rb +0 -1
  41. data/lib/sqs/right_sqs_gen2_interface.rb +9 -9
  42. data/lib/sqs/right_sqs_interface.rb +6 -7
  43. data/right_aws.gemspec +91 -0
  44. data/test/README.mdown +39 -0
  45. data/test/acf/test_helper.rb +0 -0
  46. data/test/acf/test_right_acf.rb +10 -18
  47. data/test/awsbase/test_helper.rb +0 -0
  48. data/test/awsbase/test_right_awsbase.rb +0 -1
  49. data/test/ec2/test_helper.rb +0 -0
  50. data/test/ec2/test_right_ec2.rb +0 -1
  51. data/test/elb/test_helper.rb +2 -0
  52. data/test/elb/test_right_elb.rb +43 -0
  53. data/test/http_connection.rb +0 -0
  54. data/test/route_53/fixtures/a_record.xml +18 -0
  55. data/test/route_53/fixtures/alias_record.xml +18 -0
  56. data/test/route_53/test_helper.rb +2 -0
  57. data/test/route_53/test_right_route_53.rb +141 -0
  58. data/test/s3/test_helper.rb +0 -0
  59. data/test/s3/test_right_s3.rb +11 -9
  60. data/test/s3/test_right_s3_stubbed.rb +6 -4
  61. data/test/sdb/test_active_sdb.rb +71 -13
  62. data/test/sdb/test_batch_put_attributes.rb +54 -0
  63. data/test/sdb/test_helper.rb +0 -0
  64. data/test/sdb/test_right_sdb.rb +13 -7
  65. data/test/sqs/test_helper.rb +0 -0
  66. data/test/sqs/test_right_sqs.rb +0 -6
  67. data/test/sqs/test_right_sqs_gen2.rb +22 -34
  68. data/test/test_credentials.rb +0 -0
  69. data/test/ts_right_aws.rb +0 -0
  70. metadata +146 -16
  71. data/VERSION +0 -1
@@ -47,8 +47,18 @@ module RightAws
47
47
  on_exception
48
48
  end
49
49
 
50
- # Retrieve information about EC2 instances. If +list+ is omitted then returns the
51
- # list of all instances.
50
+ # Retrieve information about EC2 instances.
51
+ #
52
+ # Accepts a list of instances and/or a set of filters as the last parameter.
53
+ #
54
+ # Filters: architecture, availability-zone, block-device-mapping.attach-time, block-device-mapping.delete-on-termination,
55
+ # block-device-mapping.device-name, block-device-mapping.status, block-device-mapping.volume-id, client-token, dns-name,
56
+ # group-id, image-id, instance-id, instance-lifecycle, instance-state-code, instance-state-name, instance-type, ip-address,
57
+ # kernel-id, key-name, launch-index, launch-time, monitoring-state, owner-id, placement-group-name, platform,
58
+ # private-dns-name, private-ip-address, product-code, ramdisk-id, reason, requester-id, reservation-id, root-device-name,
59
+ # root-device-type, spot-instance-request-id, state-reason-code, state-reason-message, subnet-id, tag-key, tag-value,
60
+ # tag:key, virtualization-type, vpc-id,
61
+ #
52
62
  #
53
63
  # ec2.describe_instances #=>
54
64
  # [{:private_ip_address=>"10.240.7.99",
@@ -84,13 +94,15 @@ module RightAws
84
94
  # :ebs_volume_id=>"vol-f900f990"}],
85
95
  # :aws_instance_id=>"i-8ce84ae4"} , ... ]
86
96
  #
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|
97
+ # ec2.describe_instances("i-8ce84ae6", "i-8ce84ae8", "i-8ce84ae0")
98
+ # ec2.describe_instances(:filters => { 'availability-zone' => 'us-east-1a', 'instance-type' => 'c1.medium' })
99
+ #
100
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeInstances.html
101
+ #
102
+ def describe_instances(*list_and_options)
103
+ describe_resources_with_list_and_options('DescribeInstances', 'InstanceId', QEc2DescribeInstancesParser, list_and_options) do |parser|
90
104
  get_desc_instances(parser.result)
91
105
  end
92
- rescue Exception
93
- on_exception
94
106
  end
95
107
 
96
108
  # Return the product code attached to instance or +nil+ otherwise.
@@ -130,7 +142,8 @@ module RightAws
130
142
  addressing_type = nil, instance_type = nil,
131
143
  kernel_id = nil, ramdisk_id = nil, availability_zone = nil,
132
144
  monitoring_enabled = nil, subnet_id = nil, disable_api_termination = nil,
133
- instance_initiated_shutdown_behavior = nil, block_device_mappings = nil)
145
+ instance_initiated_shutdown_behavior = nil, block_device_mappings = nil,
146
+ placement_group_name = nil, client_token = nil)
134
147
  launch_instances(image_id, { :min_count => min_count,
135
148
  :max_count => max_count,
136
149
  :user_data => user_data,
@@ -145,14 +158,16 @@ module RightAws
145
158
  :subnet_id => subnet_id,
146
159
  :disable_api_termination => disable_api_termination,
147
160
  :instance_initiated_shutdown_behavior => instance_initiated_shutdown_behavior,
148
- :block_device_mappings => block_device_mappings
161
+ :block_device_mappings => block_device_mappings,
162
+ :placement_group_name => placement_group_name,
163
+ :client_token => client_token
149
164
  })
150
165
  end
151
166
 
152
167
  # Launch new EC2 instances.
153
168
  # Options: :image_id, :addressing_type, :min_count, max_count, :key_name, :kernel_id, :ramdisk_id,
154
169
  # :availability_zone, :monitoring_enabled, :subnet_id, :disable_api_termination, :instance_initiated_shutdown_behavior,
155
- # :block_device_mappings
170
+ # :block_device_mappings, :placement_group_name, :license_pool
156
171
  #
157
172
  # Returns a list of launched instances or an exception.
158
173
  #
@@ -190,12 +205,12 @@ module RightAws
190
205
  # :aws_instance_id=>"i-8ce84ae4"}]
191
206
  #
192
207
  def launch_instances(image_id, options={})
193
- @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
208
  options[:image_id] = image_id
196
209
  options[:min_count] ||= 1
197
210
  options[:max_count] ||= options[:min_count]
198
211
  params = prepare_instance_launch_params(options)
212
+ # Log debug information
213
+ @logger.info("Launching instance of image #{image_id}. Options: #{params.inspect}")
199
214
  link = generate_request("RunInstances", params)
200
215
  instances = request_info(link, QEc2DescribeInstancesParser.new(:logger => @logger))
201
216
  get_desc_instances(instances)
@@ -203,47 +218,39 @@ module RightAws
203
218
  on_exception
204
219
  end
205
220
 
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
221
  def prepare_instance_launch_params(options={}) # :nodoc:
221
- params = amazonize_list('SecurityGroup', options[:group_ids].to_a)
222
+ params = amazonize_list('SecurityGroup', Array(options[:group_ids]))
222
223
  params['InstanceType'] = options[:instance_type] || DEFAULT_INSTANCE_TYPE
223
- params['ImageId'] = options[:image_id] unless options[:image_id].blank?
224
- params['AddressingType'] = options[:addressing_type] unless options[:addressing_type].blank?
225
- params['MinCount'] = options[:min_count] unless options[:min_count].blank?
226
- params['MaxCount'] = options[:max_count] unless options[:max_count].blank?
227
- params['KeyName'] = options[:key_name] unless options[:key_name].blank?
228
- params['KernelId'] = options[:kernel_id] unless options[:kernel_id].blank?
229
- params['RamdiskId'] = options[:ramdisk_id] unless options[:ramdisk_id].blank?
230
- params['Placement.AvailabilityZone'] = options[:availability_zone] unless options[:availability_zone].blank?
224
+ params['ImageId'] = options[:image_id] unless options[:image_id].right_blank?
225
+ params['AddressingType'] = options[:addressing_type] unless options[:addressing_type].right_blank?
226
+ params['MinCount'] = options[:min_count] unless options[:min_count].right_blank?
227
+ params['MaxCount'] = options[:max_count] unless options[:max_count].right_blank?
228
+ params['KeyName'] = options[:key_name] unless options[:key_name].right_blank?
229
+ params['KernelId'] = options[:kernel_id] unless options[:kernel_id].right_blank?
230
+ params['RamdiskId'] = options[:ramdisk_id] unless options[:ramdisk_id].right_blank?
231
+ params['Placement.AvailabilityZone'] = options[:availability_zone] unless options[:availability_zone].right_blank?
231
232
  params['Monitoring.Enabled'] = options[:monitoring_enabled].to_s if options[:monitoring_enabled]
232
- params['SubnetId'] = options[:subnet_id] unless options[:subnet_id].blank?
233
- params['AdditionalInfo'] = options[:additional_info] unless options[:additional_info].blank?
233
+ params['SubnetId'] = options[:subnet_id] unless options[:subnet_id].right_blank?
234
+ params['AdditionalInfo'] = options[:additional_info] unless options[:additional_info].right_blank?
234
235
  params['DisableApiTermination'] = options[:disable_api_termination].to_s unless options[:disable_api_termination].nil?
235
- params['InstanceInitiatedShutdownBehavior'] = options[:instance_initiated_shutdown_behavior] unless options[:instance_initiated_shutdown_behavior].blank?
236
- # params['VolumeId'] = options[:volume_id] unless options[:volume_id].blank?
237
- # params['RootDeviceName'] = options[:root_device_name] unless options[:root_device_name].blank?
238
- # params['RootDeviceType'] = options[:root_device_type] unless options[:root_device_type].blank?
236
+ params['InstanceInitiatedShutdownBehavior'] = options[:instance_initiated_shutdown_behavior] unless options[:instance_initiated_shutdown_behavior].right_blank?
237
+ params['Placement.GroupName'] = options[:placement_group_name] unless options[:placement_group_name].right_blank?
238
+ params['License.Pool'] = options[:license_pool] unless options[:license_pool].right_blank?
239
+ # Client token: do not set it automatically for Euca clouds (but let it go if it was set by a user)
240
+ client_token = options[:client_token]
241
+ client_token ||= AwsUtils::generate_unique_token unless @params[:eucalyptus]
242
+ params['ClientToken'] = client_token if client_token
243
+ #
239
244
  params.merge!(amazonize_block_device_mappings(options[:block_device_mappings]))
240
- unless options[:user_data].blank?
241
- options[:user_data].strip!
242
- # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library.
243
- # Amazon 169.254.169.254 does not like escaped symbols!
244
- # And it doesn't like "\n" inside of encoded string! Grrr....
245
- # Otherwise, some of UserData symbols will be lost...
246
- params['UserData'] = Base64.encode64(options[:user_data]).delete("\n") unless options[:user_data].blank?
245
+ # KD: https://github.com/rightscale/right_aws/issues#issue/11
246
+ # Do not modify user data and pass it as is: one may pass there a hex-binary data
247
+ options[:user_data] = options[:user_data].to_s
248
+ unless options[:user_data].empty?
249
+ # Do not use CGI::escape(encode64(...)) as it is done in Amazons EC2 library.
250
+ # Amazon 169.254.169.254 does not like escaped symbols!
251
+ # And it doesn't like "\n" inside of encoded string! Grrr....
252
+ # Otherwise, some of UserData symbols will be lost...
253
+ params['UserData'] = Base64.encode64(options[:user_data]).delete("\n")
247
254
  end
248
255
  params
249
256
  end
@@ -313,8 +320,9 @@ module RightAws
313
320
  #
314
321
  # ec2.reboot_instances(['i-f222222d','i-f222222e']) #=> true
315
322
  #
316
- def reboot_instances(list)
317
- link = generate_request("RebootInstances", amazonize_list('InstanceId', list.to_a))
323
+ def reboot_instances(*instances)
324
+ instances = instances.flatten
325
+ link = generate_request("RebootInstances", amazonize_list('InstanceId', instances))
318
326
  request_info(link, RightBoolResponseParser.new(:logger => @logger))
319
327
  rescue Exception
320
328
  on_exception
@@ -431,6 +439,25 @@ module RightAws
431
439
  on_exception
432
440
  end
433
441
 
442
+ # Get Initial windows instance password using Amazon API call GetPasswordData.
443
+ #
444
+ # puts ec2.get_initial_password_v2(my_awesome_instance[:aws_instance_id], my_awesome_key[:aws_material]) #=> "MhjWcgZuY6"
445
+ #
446
+ # P.S. To say the truth there is absolutely no any speedup if to compare to the old get_initial_password method... ;(
447
+ #
448
+ def get_initial_password_v2(instance_id, private_key)
449
+ link = generate_request('GetPasswordData',
450
+ 'InstanceId' => instance_id )
451
+ response = request_info(link, QEc2GetPasswordDataParser.new(:logger => @logger))
452
+ if response[:password_data].right_blank?
453
+ raise AwsError.new("Initial password is not yet created for #{instance_id}")
454
+ else
455
+ OpenSSL::PKey::RSA.new(private_key).private_decrypt(Base64.decode64(response[:password_data]))
456
+ end
457
+ rescue Exception
458
+ on_exception
459
+ end
460
+
434
461
  # Bundle a Windows image.
435
462
  # Internally, it queues the bundling task and shuts down the instance.
436
463
  # It then takes a snapshot of the Windows volume bundles it, and uploads it to
@@ -455,7 +482,7 @@ module RightAws
455
482
  s3_owner_aws_secret_access_key ||= @aws_secret_access_key
456
483
  s3_expires = Time.now.utc + s3_expires if s3_expires.is_a?(Fixnum) && (s3_expires < S3Interface::ONE_YEAR_IN_SECONDS)
457
484
  # policy
458
- policy = { 'expiration' => s3_expires.strftime('%Y-%m-%dT%H:%M:%SZ'),
485
+ policy = { 'expiration' => AwsUtils::utc_iso8601(s3_expires),
459
486
  'conditions' => [ { 'bucket' => s3_bucket },
460
487
  { 'acl' => s3_upload_policy },
461
488
  [ 'starts-with', '$key', s3_prefix ] ] }.to_json
@@ -476,9 +503,13 @@ module RightAws
476
503
  end
477
504
 
478
505
  # Describe the status of the Windows AMI bundlings.
479
- # If +list+ is omitted the returns the whole list of tasks.
480
506
  #
481
- # ec2.describe_bundle_tasks(['bun-4fa74226']) #=>
507
+ # Accepts a list of tasks and/or a set of filters as the last parameter.
508
+ #
509
+ # Filters" bundle-id, error-code, error-message, instance-id, progress, s3-aws-access-key-id, s3-bucket, s3-prefix,
510
+ # start-time, state, update-time
511
+ #
512
+ # ec2.describe_bundle_tasks('bun-4fa74226') #=>
482
513
  # [{:s3_bucket => "my-awesome-bucket"
483
514
  # :aws_id => "bun-0fa70206",
484
515
  # :s3_prefix => "win1pr",
@@ -490,11 +521,12 @@ module RightAws
490
521
  # :aws_state => "failed",
491
522
  # :aws_instance_id => "i-e3e24e8a"}]
492
523
  #
493
- def describe_bundle_tasks(list=[])
494
- link = generate_request("DescribeBundleTasks", amazonize_list('BundleId', list.to_a))
495
- request_info(link, QEc2DescribeBundleTasksParser.new)
496
- rescue Exception
497
- on_exception
524
+ # ec2.describe_bundle_tasks(:filters => { 'state' => 'pending' })
525
+ #
526
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeBundleTasks.html
527
+ #
528
+ def describe_bundle_tasks(*list_and_options)
529
+ describe_resources_with_list_and_options('DescribeBundleTasks', 'BundleId', QEc2DescribeBundleTasksParser, list_and_options)
498
530
  end
499
531
 
500
532
  # Cancel an in‐progress or pending bundle task by id.
@@ -517,35 +549,6 @@ module RightAws
517
549
  on_exception
518
550
  end
519
551
 
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
552
  #-----------------------------------------------------------------
550
553
  # PARSERS: Instances
551
554
  #-----------------------------------------------------------------
@@ -566,10 +569,13 @@ module RightAws
566
569
  :ami_launch_index => '',
567
570
  :ssh_key_name => '',
568
571
  :aws_state => '',
569
- :aws_product_codes => [] }
572
+ :aws_product_codes => [],
573
+ :tags => {} }
570
574
  when %r{blockDeviceMapping/item$}
571
575
  @item[:block_device_mappings] ||= []
572
576
  @block_device_mapping = {}
577
+ when %r{/tagSet/item$}
578
+ @aws_tag = {}
573
579
  end
574
580
  end
575
581
  def tagend(name)
@@ -599,13 +605,20 @@ module RightAws
599
605
  when 'rootDeviceType' then @item[:root_device_type] = @text
600
606
  when 'rootDeviceName' then @item[:root_device_name] = @text
601
607
  when 'instanceClass' then @item[:instance_class] = @text
608
+ when 'instanceLifecycle' then @item[:instance_lifecycle] = @text
609
+ when 'spotInstanceRequestId' then @item[:spot_instance_request_id] = @text
610
+ when 'requesterId' then @item[:requester_id] = @text
611
+ when 'groupName' then @item[:placement_group_name] = @text
612
+ when 'virtualizationType' then @item[:virtualization_type] = @text
613
+ when 'clientToken' then @item[:client_token] = @text
602
614
  else
603
615
  case full_tag_name
604
- when %r{/stateReason/code$} then @item[:state_reason_code] = @text.to_i
616
+ when %r{/stateReason/code$} then @item[:state_reason_code] = @text
605
617
  when %r{/stateReason/message$} then @item[:state_reason_message] = @text
606
618
  when %r{/instanceState/code$} then @item[:aws_state_code] = @text.to_i
607
619
  when %r{/instanceState/name$} then @item[:aws_state] = @text
608
620
  when %r{/monitoring/state$} then @item[:monitoring_state] = @text
621
+ when %r{/license/pool$} then @item[:license_pool] = @text
609
622
  when %r{/blockDeviceMapping/item} # no trailing $
610
623
  case name
611
624
  when 'deviceName' then @block_device_mapping[:device_name] = @text
@@ -617,6 +630,9 @@ module RightAws
617
630
  when 'item' then @item[:block_device_mappings] << @block_device_mapping
618
631
  end
619
632
  when %r{/instancesSet/item$} then @reservation[:instances_set] << @item
633
+ when %r{/tagSet/item/key$} then @aws_tag[:key] = @text
634
+ when %r{/tagSet/item/value$} then @aws_tag[:value] = @text
635
+ when %r{/tagSet/item$} then @item[:tags][@aws_tag[:key]] = @aws_tag[:value]
620
636
  when 'DescribeInstancesResponse/reservationSet/item',
621
637
  'RunInstancesResponse'
622
638
  @result << @reservation
@@ -755,6 +771,19 @@ module RightAws
755
771
  end
756
772
  end
757
773
 
774
+ class QEc2GetPasswordDataParser < RightAWSParser #:nodoc:
775
+ def tagend(name)
776
+ case name
777
+ when 'instanceId' then @result[:aws_instance_id] = @text
778
+ when 'timestamp' then @result[:timestamp] = @text
779
+ when 'passwordData' then @result[:password_data] = @text
780
+ end
781
+ end
782
+ def reset
783
+ @result = {}
784
+ end
785
+ end
786
+
758
787
  end
759
788
 
760
789
  end
@@ -0,0 +1,108 @@
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
+ # Placement Groups
30
+ #-----------------------------------------------------------------
31
+
32
+ # Describe placement groups.
33
+ #
34
+ # Accepts a list of placement groups and/or a set of filters as the last parameter.
35
+ #
36
+ # Filters: group-name, state, strategy
37
+ #
38
+ # If you don’t specify a particular placement group, the response includes
39
+ # information about all of them. The information includes the group name, the strategy,
40
+ # and the group state (e.g., pending, available, etc.).
41
+ #
42
+ # ec2.describe_placement_groups #=>
43
+ # [{:state=>"available", :strategy=>"cluster", :group_name=>"kd_first"},
44
+ # {:state=>"available", :strategy=>"cluster", :group_name=>"kd_second"}]
45
+ #
46
+ # ec2.describe_placement_groups('kd_second') #=>
47
+ # [{:strategy=>"cluster", :group_name=>"kd_second", :state=>"available"}]
48
+ #
49
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference_query_DescribePlacementGroups.html
50
+ #
51
+ def describe_placement_groups(*list_and_options)
52
+ describe_resources_with_list_and_options('DescribePlacementGroups', 'GroupName', QEc2DescribePlacementGroupsParser, list_and_options)
53
+ end
54
+
55
+ # Create placement group creates a placement group (i.e. logical cluster group)
56
+ # into which you can then launch instances. You must provide a name for the group
57
+ # that is unique within the scope of your account. You must also provide a strategy
58
+ # value. Currently the only value accepted is cluster.
59
+ #
60
+ # ec2.create_placement_group('kd_second') #=> true
61
+ #
62
+ def create_placement_group(placement_group_name, strategy = 'cluster')
63
+ link = generate_request('CreatePlacementGroup',
64
+ 'GroupName' => placement_group_name.to_s,
65
+ 'Strategy' => strategy.to_s)
66
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
67
+ rescue Exception
68
+ on_exception
69
+ end
70
+
71
+ # Delete placement group deletes a placement group that you own. The group must not
72
+ # contain any instances.
73
+ #
74
+ # ec2.delete_placement_group('kd_second') #=> true
75
+ #
76
+ def delete_placement_group(placement_group_name)
77
+ link = generate_request('DeletePlacementGroup',
78
+ 'GroupName' => placement_group_name.to_s)
79
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
80
+ rescue Exception
81
+ on_exception
82
+ end
83
+
84
+ #-----------------------------------------------------------------
85
+ # PARSERS: Placement Groups
86
+ #-----------------------------------------------------------------
87
+
88
+ class QEc2DescribePlacementGroupsParser < RightAWSParser #:nodoc:
89
+ def tagstart(name, attributes)
90
+ case name
91
+ when 'item' then @item = {}
92
+ end
93
+ end
94
+ def tagend(name)
95
+ case name
96
+ when 'groupName' then @item[:group_name] = @text
97
+ when 'strategy' then @item[:strategy] = @text
98
+ when 'state' then @item[:state] = @text
99
+ when 'item' then @result << @item
100
+ end
101
+ end
102
+ def reset
103
+ @result = []
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -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",
@@ -41,22 +45,22 @@ module RightAws
41
45
  # :aws_state=>"payment-pending",
42
46
  # :aws_product_description=>"Test",
43
47
  # :aws_fixed_price=>325.0,
48
+ # :aws_start=>"2009-12-18T20:39:39.569Z"
44
49
  # :aws_instance_count=>1}]
45
50
  #
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?)
49
- rescue Exception
50
- 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)
51
57
  end
52
58
 
53
59
  # Retrieve reserved instances offerings.
54
- # 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.
55
62
  #
56
- # Optional params:
57
- # :aws_instance_type => String
58
- # :aws_availability_zone => String
59
- # :aws_product_description => String
63
+ # Filters: availability-zone, duration, fixed-price, instance-type, product-description, reserved-instances-offering-id, usage-price
60
64
  #
61
65
  # ec2.describe_reserved_instances_offerings #=>
62
66
  # [{:aws_instance_type=>"c1.medium",
@@ -75,19 +79,12 @@ module RightAws
75
79
  # :aws_usage_price=>0.24,
76
80
  # :aws_fixed_price=>2600.0}]
77
81
  #
78
- def describe_reserved_instances_offerings(*list_and_params)
79
- list, params = AwsUtils::split_items_and_params(list_and_params)
80
- # backward compartibility with the old way
81
- list ||= params[:aws_ids].to_a
82
- rparams = {}
83
- rparams.update(amazonize_list('ReservedInstancesOfferingId', list)) unless list.blank?
84
- rparams['InstanceType'] = params[:aws_instance_type] if params[:aws_instance_type]
85
- rparams['AvailabilityZone'] = params[:aws_availability_zone] if params[:aws_availability_zone]
86
- rparams['ProductDescription'] = params[:aws_product_description] if params[:aws_product_description]
87
- link = generate_request("DescribeReservedInstancesOfferings", rparams)
88
- request_cache_or_info(:describe_reserved_instances_offerings, link, QEc2DescribeReservedInstancesOfferingsParser, @@bench, list.blank?)
89
- rescue Exception
90
- 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)
91
88
  end
92
89
 
93
90
  # Purchase a Reserved Instance.
@@ -109,20 +106,30 @@ module RightAws
109
106
 
110
107
  class QEc2DescribeReservedInstancesParser < RightAWSParser #:nodoc:
111
108
  def tagstart(name, attributes)
112
- @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
113
113
  end
114
114
  def tagend(name)
115
115
  case name
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 '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
126
133
  end
127
134
  end
128
135
  def reset
@@ -133,19 +140,19 @@ module RightAws
133
140
  class QEc2DescribeReservedInstancesOfferingsParser < RightAWSParser #:nodoc:
134
141
  def tagstart(name, attributes)
135
142
  @item = {} if name == 'item'
136
- end
143
+ end
137
144
  def tagend(name)
138
145
  case name
139
- when 'reservedInstancesOfferingId' then @item[:aws_id] = @text
140
- when 'instanceType' then @item[:aws_instance_type] = @text
141
- when 'availabilityZone' then @item[:aws_availability_zone] = @text
142
- when 'duration' then @item[:aws_duration] = @text.to_i
143
- when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
144
- when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
145
- 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
146
153
  when 'item' then @result << @item
154
+ end
147
155
  end
148
- end
149
156
  def reset
150
157
  @result = []
151
158
  end