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 +1 -0
- data/ChangeLog +5 -0
- data/VERSION +1 -1
- data/amazon-ec2.gemspec +8 -2
- data/lib/AWS.rb +18 -1
- data/lib/AWS/EC2/instances.rb +1 -16
- data/lib/AWS/EC2/spot_instance_requests.rb +105 -0
- data/lib/AWS/EC2/spot_prices.rb +34 -0
- data/lib/AWS/ELB/load_balancers.rb +50 -9
- data/test/test_EC2_spot_instance_requests.rb +178 -0
- data/test/test_EC2_spot_prices.rb +51 -0
- metadata +8 -2
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.
|
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.
|
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{
|
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
|
data/lib/AWS/EC2/instances.rb
CHANGED
@@ -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
|
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
|
-
#
|
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
|
-
#
|
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 "
|
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
|
-
#
|
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
|
-
#
|
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 "
|
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
|
-
#
|
200
|
+
# This API is used to add one or more EC2 Availability Zones to the LoadBalancer.
|
169
201
|
#
|
170
|
-
# @
|
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 "
|
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.
|
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:
|
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
|