amazon-ec2 0.7.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,4 +5,5 @@ rdoc
5
5
  doc
6
6
  .yardoc
7
7
  pkg
8
+ .idea
8
9
 
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ === 0.9.0 2010-01-19
2
+ * Added EC2 Spot Instance Request Support (nirvdrum)
3
+ * Added EC2 describe_spot_price_history (tlossen)
4
+ * Added ELB describe_instance_health method (rubysolo)
5
+
1
6
  === 0.7.4 2009-12-05
2
7
  * Initial support for new EBS AMI's
3
8
  * Updated EC2 API version
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.9
1
+ 0.9.0
data/amazon-ec2.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{amazon-ec2}
8
- s.version = "0.7.9"
8
+ s.version = "0.9.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Glenn Rempe"]
12
- s.date = %q{2009-12-22}
12
+ s.date = %q{2010-01-19}
13
13
  s.description = %q{A Ruby library for accessing the Amazon Web Services EC2, ELB, RDS, Cloudwatch, and Autoscaling API's.}
14
14
  s.email = %q{glenn@rempe.us}
15
15
  s.executables = ["ec2-gem-example.rb", "ec2-gem-profile.rb", "ec2sh", "setup.rb"]
@@ -51,6 +51,8 @@ Gem::Specification.new do |s|
51
51
  "lib/AWS/EC2/products.rb",
52
52
  "lib/AWS/EC2/security_groups.rb",
53
53
  "lib/AWS/EC2/snapshots.rb",
54
+ "lib/AWS/EC2/spot_instance_requests.rb",
55
+ "lib/AWS/EC2/spot_prices.rb",
54
56
  "lib/AWS/EC2/volumes.rb",
55
57
  "lib/AWS/ELB.rb",
56
58
  "lib/AWS/ELB/load_balancers.rb",
@@ -76,6 +78,8 @@ Gem::Specification.new do |s|
76
78
  "test/test_EC2_s3_xmlsimple.rb",
77
79
  "test/test_EC2_security_groups.rb",
78
80
  "test/test_EC2_snapshots.rb",
81
+ "test/test_EC2_spot_instance_requests.rb",
82
+ "test/test_EC2_spot_prices.rb",
79
83
  "test/test_EC2_volumes.rb",
80
84
  "test/test_ELB_load_balancers.rb",
81
85
  "test/test_RDS.rb",
@@ -108,6 +112,8 @@ Gem::Specification.new do |s|
108
112
  "test/test_EC2_s3_xmlsimple.rb",
109
113
  "test/test_EC2_security_groups.rb",
110
114
  "test/test_EC2_snapshots.rb",
115
+ "test/test_EC2_spot_instance_requests.rb",
116
+ "test/test_EC2_spot_prices.rb",
111
117
  "test/test_EC2_volumes.rb",
112
118
  "test/test_ELB_load_balancers.rb",
113
119
  "test/test_helper.rb",
data/lib/AWS.rb CHANGED
@@ -29,6 +29,10 @@ class Hash
29
29
  end
30
30
  end
31
31
 
32
+ def type
33
+ self['type']
34
+ end
35
+
32
36
  def has?(key)
33
37
  self[key] && !self[key].to_s.empty?
34
38
  end
@@ -155,6 +159,20 @@ module AWS
155
159
 
156
160
  end
157
161
 
162
+ # If :user_data is passed in then URL escape and Base64 encode it
163
+ # as needed. Need for URL Escape + Base64 encoding is determined
164
+ # by :base64_encoded param.
165
+ def extract_user_data( options = {} )
166
+ return unless options[:user_data]
167
+ if options[:user_data]
168
+ if options[:base64_encoded]
169
+ Base64.encode64(options[:user_data]).gsub(/\n/, "").strip()
170
+ else
171
+ options[:user_data]
172
+ end
173
+ end
174
+ end
175
+
158
176
 
159
177
  protected
160
178
 
@@ -256,7 +274,6 @@ module AWS
256
274
  http_response = make_request(options[:action], options[:params])
257
275
  http_xml = http_response.body
258
276
  return Response.parse(:xml => http_xml)
259
-
260
277
  end
261
278
 
262
279
  # Raises the appropriate error if the specified Net::HTTPResponse object
@@ -36,7 +36,7 @@ module AWS
36
36
  raise ArgumentError, ":image_id must be provided" if options[:image_id].nil? || options[:image_id].empty?
37
37
  raise ArgumentError, ":min_count is not valid" unless options[:min_count].to_i > 0
38
38
  raise ArgumentError, ":max_count is not valid or must be >= :min_count" unless options[:max_count].to_i > 0 && options[:max_count].to_i >= options[:min_count].to_i
39
- raise ArgumentError, ":instance_type must specify a valid instance size" unless options[:instance_type].nil? || ["m1.small", "m1.large", "m1.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge"].include?(options[:instance_type])
39
+ raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["m1.small", "m1.large", "m1.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge"].include?(options[:instance_type])
40
40
  raise ArgumentError, ":monitoring_enabled must be 'true' or 'false'" unless options[:monitoring_enabled].nil? || [true, false].include?(options[:monitoring_enabled])
41
41
  raise ArgumentError, ":disable_api_termination must be 'true' or 'false'" unless options[:disable_api_termination].nil? || [true, false].include?(options[:disable_api_termination])
42
42
  raise ArgumentError, ":instance_initiated_shutdown_behavior must be 'stop' or 'terminate'" unless options[:instance_initiated_shutdown_behavior].nil? || ["stop", "terminate"].include?(options[:instance_initiated_shutdown_behavior])
@@ -72,21 +72,6 @@ module AWS
72
72
  return response_generator(:action => "RunInstances", :params => params)
73
73
  end
74
74
 
75
- # If :user_data is passed in then URL escape and Base64 encode it
76
- # as needed. Need for URL Escape + Base64 encoding is determined
77
- # by :base64_encoded param.
78
- def extract_user_data( options = {} )
79
- return unless options[:user_data]
80
- if options[:user_data]
81
- if options[:base64_encoded]
82
- Base64.encode64(options[:user_data]).gsub(/\n/,"").strip()
83
- else
84
- options[:user_data]
85
- end
86
- end
87
- end
88
-
89
-
90
75
  # The DescribeInstances operation returns information about instances owned by the user
91
76
  # making the request.
92
77
  #
@@ -0,0 +1,105 @@
1
+ module AWS
2
+ module EC2
3
+
4
+ class Base < AWS::Base
5
+
6
+ # Creates a Spot Instance request. Spot Instances are instances that Amazon EC2 starts on your behalf
7
+ # when the maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets
8
+ # the Spot Price based on available Spot Instance capacity and current spot instance requests. For conceptual
9
+ # information about Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic
10
+ # Compute Cloud User Guide.
11
+ #
12
+ # @option options [String] :spot_price (nil) Specifies the maximum hourly price for any Spot Instance launched to fulfill the request.
13
+ # @option options [optional,Integer] :instance_count (1) The maximum number of Spot Instances to launch.
14
+ # @option options [optional,String] :type (nil) Specifies the Spot Instance type.
15
+ # @option options [optional,Date] :valid_from (nil) Start date of the request. If this is a one-time request, the request becomes active at this date and time and remains active until all instances launch, the request expires, or the request is canceled. If the request is persistent, the request becomes active at this date and time and remains active until it expires or is canceled.
16
+ # @option options [optional,Date] :valid_until (nil) End date of the request. If this is a one-time request, the request remains active until all instances launch, the request is canceled, or this date is reached. If the request is persistent, it remains active until it is canceled or this date and time is reached.
17
+ # @option options [optional,String] :launch_group (nil) Specifies the instance launch group. Launch groups are Spot Instances that launch together and terminate together.
18
+ # @option options [optional,String] :availability_zone_group ("") Specifies the Availability Zone group. If you specify the same Availability Zone group for all Spot Instance requests, all Spot Instances are launched in the same Availability Zone.
19
+ # @option options [optional,String] :image_id (nil) The AMI ID.
20
+ # @option options [optional,String] :key_name (nil) The name of the key pair.
21
+ # @option options [optional,Array of Strings or String] :security_group (nil) Name of the security group(s).
22
+ # @option options [optional,String] :user_data (nil) MIME, Base64-encoded user data.
23
+ # @option options [optional,String] :instance_type ("m1.small") Specifies the instance type.
24
+ # @option options [optional,String] :kernel_id (nil) The ID of the kernel to select.
25
+ # @option options [optional,String] :ramdisk_id (nil) The ID of the RAM disk to select. Some kernels require additional drivers at launch. Check the kernel requirements for information on whether you need to specify a RAM disk and search for the kernel ID.
26
+ # @option options [optional,String] :subnet_id (nil) Specifies the Amazon VPC subnet ID within which to launch the instance(s) for Amazon Virtual Private Cloud.
27
+ # @option options [optional,String] :availability_zone (nil) Specifies the placement constraints (Availability Zones) for launching the instances.
28
+ # @option options [optional, Array] :block_device_mapping ([]) An array of Hashes representing the elements of the block device mapping. e.g. [{:device_name => '/dev/sdh', :virtual_name => '', :ebs_snapshot_id => '', :ebs_volume_size => '', :ebs_delete_on_termination => ''},{},...]
29
+ # @option options [optional, Boolean] :monitoring_enabled (false) Enables monitoring for the instance.
30
+ #
31
+ def request_spot_instances( options = {} )
32
+ options = { :instance_count => 1,
33
+ :instance_type => 'm1.small',
34
+ :base64_encoded => false }.merge(options)
35
+
36
+ raise ArgumentError, ":addressing_type has been deprecated." if options[:addressing_type]
37
+ raise ArgumentError, ":spot_price must be provided" if options[:spot_price].nil? || options[:spot_price].empty?
38
+
39
+ user_data = extract_user_data(options)
40
+
41
+ params = {}
42
+
43
+ if options[:security_group]
44
+ params.merge!(pathlist("LaunchSpecification.SecurityGroup", options[:security_group]))
45
+ end
46
+
47
+ if options[:block_device_mapping]
48
+ params.merge!(pathhashlist('LaunchSpecification.BlockDeviceMapping', options[:block_device_mapping].flatten, {:device_name => 'DeviceName', :virtual_name => 'VirtualName', :ebs_snapshot_id => 'Ebs.SnapshotId', :ebs_volume_size => 'Ebs.VolumeSize', :ebs_delete_on_termination => 'Ebs.DeleteOnTermination' }))
49
+ end
50
+
51
+ params["SpotPrice"] = options[:spot_price]
52
+ params["InstanceCount"] = options[:instance_count].to_s
53
+ params["Type"] = options[:type] unless options[:type].nil?
54
+ params["ValidFrom"] = options[:valid_from].to_s unless options[:valid_from].nil?
55
+ params["ValidUntil"] = options[:valid_until].to_s unless options[:valid_until].nil?
56
+ params["LaunchGroup"] = options[:launch_group] unless options[:launch_group].nil?
57
+ params["AvailabilityZoneGroup"] = options[:availability_zone_group] unless options[:availability_zone_group].nil?
58
+ params["LaunchSpecification.ImageId"] = options[:image_id] unless options[:image_id].nil?
59
+ params["LaunchSpecification.KeyName"] = options[:key_name] unless options[:key_name].nil?
60
+ params["LaunchSpecification.UserData"] = user_data unless user_data.nil?
61
+ params["LaunchSpecification.InstanceType"] = options[:instance_type] unless options[:instance_type].nil?
62
+ params["LaunchSpecification.KernelId"] = options[:kernel_id] unless options[:kernel_id].nil?
63
+ params["LaunchSpecification.RamdiskId"] = options[:ramdisk_id] unless options[:ramdisk_id].nil?
64
+ params["LaunchSpecification.SubnetId"] = options[:subnet_id] unless options[:subnet_id].nil?
65
+ params["LaunchSpecification.Placement.AvailabilityZone"] = options[:availability_zone] unless options[:availability_zone].nil?
66
+ params["LaunchSpecification.Monitoring.Enabled"] = options[:monitoring_enabled].to_s unless options[:monitoring_enabled].nil?
67
+
68
+ return response_generator(:action => "RequestSpotInstances", :params => params)
69
+ end
70
+
71
+ # Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your behalf when the
72
+ # maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets the Spot Price
73
+ # based on available Spot Instance capacity and current spot instance requests. For conceptual information about
74
+ # Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
75
+ #
76
+ # @option options [Array] :spot_instance_request_id ([])
77
+ #
78
+ def describe_spot_instance_requests( options = {} )
79
+ options = { :spot_instance_request_id => []}.merge(options)
80
+ params = pathlist( "SpotInstanceRequestId", options[:spot_instance_request_id] )
81
+
82
+ return response_generator(:action => "DescribeSpotInstanceRequests", :params => params)
83
+ end
84
+
85
+ # Cancels one or more Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your behalf
86
+ # when the maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets the Spot
87
+ # Price based on available Spot Instance capacity and current spot instance requests. For conceptual information
88
+ # about Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud
89
+ # User Guide.
90
+ #
91
+ # NB: Canceling a Spot Instance request does not terminate running Spot Instances associated with the request.
92
+ #
93
+ # @option options [Array] :spot_instance_request_id ([])
94
+ #
95
+ def cancel_spot_instance_requests( options = {} )
96
+ options = { :spot_instance_request_id => []}.merge(options)
97
+ params = pathlist( "SpotInstanceRequestId", options[:spot_instance_request_id] )
98
+
99
+ return response_generator(:action => "CancelSpotInstanceRequests", :params => params)
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+
@@ -0,0 +1,34 @@
1
+ module AWS
2
+ module EC2
3
+
4
+ class Base < AWS::Base
5
+
6
+ # This method returns historical information about spot prices.
7
+ #
8
+ # Amazon periodically sets the spot price for each instance type based on
9
+ # available capacity and current spot instance requests.
10
+ #
11
+ # @option options [Time] :start_time (nil)
12
+ # @option options [Time] :end_time (nil)
13
+ # @option options [String] :instance_type (nil)
14
+ # @option options [String] :product_description (nil)
15
+ #
16
+ def describe_spot_price_history( options = {} )
17
+ raise ArgumentError, ":start_time must be a Time object" unless options[:start_time].nil? || Time == options[:start_time].class
18
+ raise ArgumentError, ":end_time must be a Time object" unless options[:end_time].nil? || Time == options[:end_time].class
19
+ raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["m1.small", "m1.large", "m1.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge"].include?(options[:instance_type])
20
+ raise ArgumentError, ":product_description must be 'Linux/UNIX' or 'Windows'" unless options[:product_description].nil? || ["Linux/UNIX", "Windows"].include?(options[:product_description])
21
+
22
+ params = {}
23
+ params.merge!("StartTime" => options[:start_time].iso8601) if options[:start_time]
24
+ params.merge!("EndTime" => options[:end_time].iso8601) if options[:end_time]
25
+ params.merge!("InstanceType" => options[:instance_type]) if options[:instance_type]
26
+ params.merge!("ProductDescription" => options[:product_description]) if options[:product_description]
27
+
28
+ return response_generator(:action => "DescribeSpotPriceHistory", :params => params)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+
@@ -149,28 +149,69 @@ module AWS
149
149
  return response_generator(:action => "ConfigureHealthCheck", :params => params)
150
150
  end
151
151
 
152
- # Not yet implemented
152
+ # This API returns the current state of the instances of the specified LoadBalancer. If no instances are specified,
153
+ # the state of all the instances for the LoadBalancer is returned.
153
154
  #
154
- # @todo Implement this method
155
+ # You must have been the one who created in the LoadBalancer. In other words, in order to successfully call this API,
156
+ # you must provide the same account credentials as those that were used to create the LoadBalancer.
157
+ #
158
+ # @option options [Array<String>] :instances List of instances IDs whose state is being queried.
159
+ # @option options [String] :load_balancer_name The name of the load balancer
155
160
  #
156
161
  def describe_instance_health( options = {} )
157
- raise "Not yet implemented"
162
+ raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty?
163
+
164
+ params = {}
165
+
166
+ params['LoadBalancerName'] = options[:load_balancer_name]
167
+ params.merge!(pathlist('Instances.member', [options[:instances]].flatten)) if options.has_key?(:instances)
168
+
169
+ return response_generator(:action => "DescribeInstanceHealth", :params => params)
158
170
  end
159
171
 
160
- # Not yet implemented
172
+ # This API removes the specified EC2 Availability Zones from the set of configured Availability Zones for the
173
+ # LoadBalancer. Once an Availability Zone is removed, all the instances registered with the LoadBalancer that
174
+ # are in the removed Availability Zone go into the OutOfService state. Upon Availability Zone removal, the
175
+ # LoadBalancer attempts to equally balance the traffic among its remaining usable Availability Zones. Trying to
176
+ # remove an Availability Zone that was not associated with the LoadBalancer does nothing.
161
177
  #
162
- # @todo Implement this method
178
+ # There must be at least one Availability Zone registered with a LoadBalancer at all times. You cannot remove
179
+ # all the Availability Zones from a LoadBalancer.
180
+ #
181
+ # In order for this call to be successful, you must have created the LoadBalancer. In other words, in order to
182
+ # successfully call this API, you must provide the same account credentials as those that were used to create
183
+ # the LoadBalancer.
184
+ #
185
+ # @option options [Array<String>] :availability_zones List of Availability Zones to be removed from the LoadBalancer.
186
+ # @option options [String] :load_balancer_name The name of the load balancer
163
187
  #
164
188
  def disable_availability_zones_for_load_balancer( options = {} )
165
- raise "Not yet implemented"
189
+ raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty?
190
+ raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty?
191
+
192
+ params = {}
193
+
194
+ params['LoadBalancerName'] = options[:load_balancer_name]
195
+ params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten))
196
+
197
+ return response_generator(:action => "DisableAvailabilityZonesForLoadBalancer", :params => params)
166
198
  end
167
199
 
168
- # Not yet implemented
200
+ # This API is used to add one or more EC2 Availability Zones to the LoadBalancer.
169
201
  #
170
- # @todo Implement this method
202
+ # @option options [Array<String>] :availability_zones List of Availability Zones to be added to the LoadBalancer.
203
+ # @option options [String] :load_balancer_name The name of the load balancer
171
204
  #
172
205
  def enable_availability_zones_for_load_balancer( options = {} )
173
- raise "Not yet implemented"
206
+ raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty?
207
+ raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty?
208
+
209
+ params = {}
210
+
211
+ params['LoadBalancerName'] = options[:load_balancer_name]
212
+ params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten))
213
+
214
+ return response_generator(:action => "EnableAvailabilityZonesForLoadBalancer", :params => params)
174
215
  end
175
216
 
176
217
  end
@@ -0,0 +1,178 @@
1
+ #--
2
+ # Amazon Web Services EC2 Query API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2008 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ require File.dirname(__FILE__) + '/test_helper.rb'
12
+
13
+ context "An EC2 spot instances request " do
14
+
15
+ before do
16
+ @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
17
+
18
+ @create_spot_instances_request_response_body = <<-RESPONSE
19
+ <RequestSpotInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
20
+ <spotInstanceRequestSet>
21
+ <item>
22
+ <spotInstanceRequestId>sir-f102a405</spotInstanceRequestId>
23
+ <spotPrice>0.50</spotPrice>
24
+ <type>one-time</type>
25
+ <state>open</state>
26
+ <fault/>
27
+ <validFrom/>
28
+ <validUntil/>
29
+ <launchGroup/>
30
+ <availabilityZoneGroup>MyAzGroup</availabilityZoneGroup>
31
+ <launchSpecification>
32
+ <imageId> i-43a4412a</imageId>
33
+ <keyName>MyKeypair</keyName>
34
+ <groupSet>websrv</groupSet>
35
+ <instanceType>m1.small</instanceType>
36
+ </launchSpecification>
37
+ <instanceId>i-123345678</instanceId>
38
+ <createTime>2009-10-19T00:00:00+0000</createTime>
39
+ <productDescription/>
40
+ </item>
41
+ </spotInstanceRequestSet>
42
+ </RequestSpotInstancesResponse>
43
+ RESPONSE
44
+
45
+ @describe_spot_instance_requests_response_body = <<-RESPONSE
46
+ <DescribeSpotInstanceRequestsResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
47
+ <spotInstanceRequestSet>
48
+ <item>
49
+ <spotInstanceRequestId>sir-e95fae02</spotInstanceRequestId>
50
+ <spotPrice>0.01</spotPrice>
51
+ <type>one-time</type>
52
+ <state>open</state>
53
+ <createTime>2009-12-04T22:51:14.000Z</createTime>
54
+ <productDescription>Linux/UNIX</productDescription>
55
+ <launchSpecification>
56
+ <imageId>ami-235fba4a</imageId>
57
+ <groupSet>
58
+ <item>
59
+ <groupId>default</groupId>
60
+ </item>
61
+ </groupSet>
62
+ <instanceType>m1.small</instanceType>
63
+ <blockDeviceMapping/>
64
+ <monitoring>
65
+ <enabled>false</enabled>
66
+ </monitoring>
67
+ </launchSpecification>
68
+ <instanceId>i-2fd4ca67</instanceId>
69
+ </item>
70
+ <item>
71
+ <spotInstanceRequestId>sir-e95fae03</spotInstanceRequestId>
72
+ <spotPrice>0.10</spotPrice>
73
+ <type>persistent</type>
74
+ <state>open</state>
75
+ <createTime>2009-12-04T22:51:14.000Z</createTime>
76
+ <productDescription>Linux/UNIX</productDescription>
77
+ <launchSpecification>
78
+ <imageId>ami-235fba4a</imageId>
79
+ <groupSet>
80
+ <item>
81
+ <groupId>default</groupId>
82
+ </item>
83
+ </groupSet>
84
+ <instanceType>m1.medium</instanceType>
85
+ <blockDeviceMapping/>
86
+ <monitoring>
87
+ <enabled>false</enabled>
88
+ </monitoring>
89
+ </launchSpecification>
90
+ <instanceId>i-2fd4ca90</instanceId>
91
+ </item>
92
+ </spotInstanceRequestSet>
93
+ </DescribeSpotInstanceRequestsResponse>
94
+ RESPONSE
95
+
96
+ @cancel_spot_instance_requests_response_body = <<-RESPONSE
97
+ <CancelSpotInstanceRequestsResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
98
+ <requestId>59dbff89-35bd-4eac-99ed-be587ed81825</requestId>
99
+ <spotInstanceRequestSet>
100
+ <item>
101
+ <spotInstanceRequestId>sir-e95fae02</spotInstanceRequestId>
102
+ <state>cancelled</state>
103
+ </item>
104
+ </spotInstanceRequestSet>
105
+ </CancelSpotInstanceRequestsResponse>
106
+ RESPONSE
107
+
108
+ end
109
+
110
+
111
+ specify "should be able to be created" do
112
+ @ec2.stubs(:make_request).with('RequestSpotInstances', {"SpotPrice"=>"0.50", 'LaunchSpecification.InstanceType' => 'm1.small', "InstanceCount"=>"1"}).
113
+ returns stub(:body => @create_spot_instances_request_response_body, :is_a? => true)
114
+ @ec2.request_spot_instances(:spot_price => "0.50").should.be.an.instance_of Hash
115
+ @ec2.request_spot_instances(:spot_price => "0.50").spotInstanceRequestSet.item[0].spotInstanceRequestId.should.equal "sir-f102a405"
116
+ end
117
+
118
+
119
+ specify "method create_spot_instances_request should raise an exception when called with nil/empty string arguments" do
120
+ lambda { @ec2.request_spot_instances() }.should.raise(AWS::ArgumentError)
121
+ lambda { @ec2.request_spot_instances(:spot_price => "") }.should.raise(AWS::ArgumentError)
122
+ lambda { @ec2.request_spot_instances(:spot_price => nil) }.should.raise(AWS::ArgumentError)
123
+ end
124
+
125
+
126
+ specify "should be able to be described and return the correct Ruby response class for parent and members" do
127
+ @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {}).
128
+ returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true)
129
+ @ec2.describe_spot_instance_requests.should.be.an.instance_of Hash
130
+ response = @ec2.describe_spot_instance_requests
131
+ response.should.be.an.instance_of Hash
132
+ end
133
+
134
+
135
+ specify "should be able to be described with no params and return a spotInstanceRequestSet" do
136
+ @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {}).
137
+ returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true)
138
+ @ec2.describe_spot_instance_requests.spotInstanceRequestSet.item.length.should.equal 2
139
+ end
140
+
141
+ specify "should be able to be described by an Array of SpotInstanceRequestId.N ID's and return an array of Items" do
142
+ @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {"SpotInstanceRequestId.1"=>"sir-e95fae02", "SpotInstanceRequestId.2"=>"sir-e95fae03"}).
143
+ returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true)
144
+ @ec2.describe_spot_instance_requests( :spot_instance_request_id => ["sir-e95fae02", "sir-e95fae03"] ).spotInstanceRequestSet.item.length.should.equal 2
145
+
146
+ response = @ec2.describe_spot_instance_requests( :spot_instance_request_id => ["sir-e95fae02", "sir-e95fae03"] )
147
+
148
+ # test first 'Item' object returned
149
+ response.spotInstanceRequestSet.item[0].spotInstanceRequestId.should.equal "sir-e95fae02"
150
+ response.spotInstanceRequestSet.item[0].spotPrice.should.equal "0.01"
151
+ response.spotInstanceRequestSet.item[0].type.should.equal "one-time"
152
+ response.spotInstanceRequestSet.item[0].state.should.equal "open"
153
+ response.spotInstanceRequestSet.item[0].createTime.should.equal "2009-12-04T22:51:14.000Z"
154
+ response.spotInstanceRequestSet.item[0].productDescription.should.equal "Linux/UNIX"
155
+ response.spotInstanceRequestSet.item[0].launchSpecification.imageId.should.equal "ami-235fba4a"
156
+ response.spotInstanceRequestSet.item[0].launchSpecification.instanceType.should.equal "m1.small"
157
+ response.spotInstanceRequestSet.item[0].instanceId.should.equal "i-2fd4ca67"
158
+
159
+ # test second 'Item' object returned
160
+ response.spotInstanceRequestSet.item[1].spotInstanceRequestId.should.equal "sir-e95fae03"
161
+ response.spotInstanceRequestSet.item[1].spotPrice.should.equal "0.10"
162
+ response.spotInstanceRequestSet.item[1].type.should.equal "persistent"
163
+ response.spotInstanceRequestSet.item[1].state.should.equal "open"
164
+ response.spotInstanceRequestSet.item[1].createTime.should.equal "2009-12-04T22:51:14.000Z"
165
+ response.spotInstanceRequestSet.item[1].productDescription.should.equal "Linux/UNIX"
166
+ response.spotInstanceRequestSet.item[1].launchSpecification.imageId.should.equal "ami-235fba4a"
167
+ response.spotInstanceRequestSet.item[1].launchSpecification.instanceType.should.equal "m1.medium"
168
+ response.spotInstanceRequestSet.item[1].instanceId.should.equal "i-2fd4ca90"
169
+ end
170
+
171
+ specify "should be able to be destroyed" do
172
+ @ec2.stubs(:make_request).with('CancelSpotInstanceRequests', {"SpotInstanceRequestId.1"=>"sir-e95fae02"}).
173
+ returns stub(:body => @cancel_spot_instance_requests_response_body, :is_a? => true)
174
+ @ec2.cancel_spot_instance_requests(:spot_instance_request_id => "sir-e95fae02" ).should.be.an.instance_of Hash
175
+ @ec2.cancel_spot_instance_requests(:spot_instance_request_id => "sir-e95fae02" ).spotInstanceRequestSet.item[0].state.should.equal "cancelled"
176
+ end
177
+
178
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "Spot price history " do
4
+
5
+ before do
6
+ @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" )
7
+
8
+ @describe_spot_price_history_response_body = <<-RESPONSE
9
+ <DescribeSpotPriceHistoryResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
10
+ <spotPriceHistorySet>
11
+ <item>
12
+ <instanceType>m1.small</instanceType>
13
+ <productDescription>Linux/UNIX</productDescription>
14
+ <spotPrice>0.287</spotPrice>
15
+ <timestamp>2009-12-04T20:56:05.000Z</timestamp>
16
+ </item>
17
+ <item>
18
+ <instanceType>m1.small</instanceType>
19
+ <productDescription>Windows</productDescription>
20
+ <spotPrice>0.033</spotPrice>
21
+ <timestamp>2009-12-04T22:33:47.000Z</timestamp>
22
+ </item>
23
+ </spotPriceHistorySet>
24
+ </DescribeSpotPriceHistoryResponse>
25
+ RESPONSE
26
+ end
27
+
28
+ specify "should be able to be listed" do
29
+ @ec2.stubs(:make_request).with('DescribeSpotPriceHistory', {}).
30
+ returns stub(:body => @describe_spot_price_history_response_body, :is_a? => true)
31
+ @ec2.describe_spot_price_history().should.be.an.instance_of Hash
32
+ @ec2.describe_spot_price_history().spotPriceHistorySet.item.should.be.an.instance_of Array
33
+ end
34
+
35
+ specify "should reject a start_time which is not a Time object" do
36
+ lambda { @ec2.describe_spot_price_history(:start_time => "foo") }.should.raise(AWS::ArgumentError)
37
+ end
38
+
39
+ specify "should reject an end_time which is not a Time object" do
40
+ lambda { @ec2.describe_spot_price_history(:end_time => 42) }.should.raise(AWS::ArgumentError)
41
+ end
42
+
43
+ specify "should reject an invalid instance type" do
44
+ lambda { @ec2.describe_spot_price_history(:instance_type => 'm1.tiny') }.should.raise(AWS::ArgumentError)
45
+ end
46
+
47
+ specify "should reject an invalid product description" do
48
+ lambda { @ec2.describe_spot_price_history(:product_description => 'Solaris') }.should.raise(AWS::ArgumentError)
49
+ end
50
+
51
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amazon-ec2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.9
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glenn Rempe
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-22 00:00:00 -08:00
12
+ date: 2010-01-19 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -108,6 +108,8 @@ files:
108
108
  - lib/AWS/EC2/products.rb
109
109
  - lib/AWS/EC2/security_groups.rb
110
110
  - lib/AWS/EC2/snapshots.rb
111
+ - lib/AWS/EC2/spot_instance_requests.rb
112
+ - lib/AWS/EC2/spot_prices.rb
111
113
  - lib/AWS/EC2/volumes.rb
112
114
  - lib/AWS/ELB.rb
113
115
  - lib/AWS/ELB/load_balancers.rb
@@ -133,6 +135,8 @@ files:
133
135
  - test/test_EC2_s3_xmlsimple.rb
134
136
  - test/test_EC2_security_groups.rb
135
137
  - test/test_EC2_snapshots.rb
138
+ - test/test_EC2_spot_instance_requests.rb
139
+ - test/test_EC2_spot_prices.rb
136
140
  - test/test_EC2_volumes.rb
137
141
  - test/test_ELB_load_balancers.rb
138
142
  - test/test_RDS.rb
@@ -190,6 +194,8 @@ test_files:
190
194
  - test/test_EC2_s3_xmlsimple.rb
191
195
  - test/test_EC2_security_groups.rb
192
196
  - test/test_EC2_snapshots.rb
197
+ - test/test_EC2_spot_instance_requests.rb
198
+ - test/test_EC2_spot_prices.rb
193
199
  - test/test_EC2_volumes.rb
194
200
  - test/test_ELB_load_balancers.rb
195
201
  - test/test_helper.rb