diff --git a/lib/fog/compute/aws.rb b/lib/fog/compute/aws.rb index 42cd940da..304b6d347 100644 --- a/lib/fog/compute/aws.rb +++ b/lib/fog/compute/aws.rb @@ -70,6 +70,7 @@ module Fog request :import_key_pair request :modify_image_attributes request :modify_snapshot_attribute + request :purchase_reserved_instances_offering request :reboot_instances request :release_address request :register_image @@ -93,6 +94,7 @@ module Fog :addresses => {}, :images => {}, :instances => {}, + :reserved_instances => {}, :key_pairs => {}, :limits => { :addresses => 5 }, :owner_id => owner_id, diff --git a/lib/fog/compute/parsers/aws/describe_reserved_instances.rb b/lib/fog/compute/parsers/aws/describe_reserved_instances.rb index a0ed56d62..7f21033d3 100644 --- a/lib/fog/compute/parsers/aws/describe_reserved_instances.rb +++ b/lib/fog/compute/parsers/aws/describe_reserved_instances.rb @@ -24,7 +24,7 @@ module Fog when 'requestId' @response[name] = value when 'start' - @response[name] = Time.parse(value) + @reserved_instance[name] = Time.parse(value) end end diff --git a/lib/fog/compute/parsers/aws/describe_reserved_instances_offerings.rb b/lib/fog/compute/parsers/aws/describe_reserved_instances_offerings.rb index 32b2132d6..8e7ea7023 100644 --- a/lib/fog/compute/parsers/aws/describe_reserved_instances_offerings.rb +++ b/lib/fog/compute/parsers/aws/describe_reserved_instances_offerings.rb @@ -12,7 +12,7 @@ module Fog def end_element(name) case name - when 'availabilityZone', 'instanceType', 'productDescription', 'reservedInstancesOfferingId' + when 'availabilityZone', 'currencyCode', 'instanceType', 'instanceTenancy', 'productDescription', 'reservedInstancesOfferingId' @reserved_instances_offering[name] = value when 'duration' @reserved_instances_offering[name] = value.to_i @@ -31,4 +31,4 @@ module Fog end end end -end \ No newline at end of file +end diff --git a/lib/fog/compute/parsers/aws/purchase_reserved_instances_offering.rb b/lib/fog/compute/parsers/aws/purchase_reserved_instances_offering.rb new file mode 100644 index 000000000..09c42a18d --- /dev/null +++ b/lib/fog/compute/parsers/aws/purchase_reserved_instances_offering.rb @@ -0,0 +1,24 @@ +module Fog + module Parsers + module Compute + module AWS + + class PurchaseReservedInstancesOffering < Fog::Parsers::Base + + def reset + @response = {} + end + + def end_element(name) + case name + when 'reservedInstancesId', 'requestId' + @response[name] = value + end + end + + end + + end + end + end +end diff --git a/lib/fog/compute/requests/aws/describe_reserved_instances.rb b/lib/fog/compute/requests/aws/describe_reserved_instances.rb index 565b9fe2d..06923193b 100644 --- a/lib/fog/compute/requests/aws/describe_reserved_instances.rb +++ b/lib/fog/compute/requests/aws/describe_reserved_instances.rb @@ -41,6 +41,20 @@ module Fog end end + + class Mock + def describe_reserved_instances(filters = {}) + response = Excon::Response.new + response.status = 200 + + response.body = { + 'reservedInstancesSet' => self.data[:reserved_instances].values, + 'requestId' => Fog::AWS::Mock.request_id + } + + response + end + end end end end diff --git a/lib/fog/compute/requests/aws/describe_reserved_instances_offerings.rb b/lib/fog/compute/requests/aws/describe_reserved_instances_offerings.rb index d4cadeecf..f54bfe0e4 100644 --- a/lib/fog/compute/requests/aws/describe_reserved_instances_offerings.rb +++ b/lib/fog/compute/requests/aws/describe_reserved_instances_offerings.rb @@ -32,7 +32,32 @@ module Fog :parser => Fog::Parsers::Compute::AWS::DescribeReservedInstancesOfferings.new }.merge!(params)) end + end + class Mock + def describe_reserved_instances_offerings(filters = {}) + response = Excon::Response.new + response.status = 200 + + self.data[:reserved_instances_offerings] ||= [{ + 'reservedInstancesOfferingId' => Fog::AWS::Mock.reserved_instances_offering_id, + 'instanceType' => 'm1.small', + 'availabilityZone' => 'us-east-1d', + 'duration' => 31536000, + 'fixedPrice' => 350.0, + 'usagePrice' => 0.03, + 'productDescription' => 'Linux/UNIX', + 'instanceTenancy' => 'default', + 'currencyCode' => 'USD' + }] + + response.body = { + 'reservedInstancesOfferingsSet' => self.data[:reserved_instances_offerings], + 'requestId' => Fog::AWS::Mock.request_id + } + + response + end end end end diff --git a/lib/fog/compute/requests/aws/purchase_reserved_instances_offering.rb b/lib/fog/compute/requests/aws/purchase_reserved_instances_offering.rb new file mode 100644 index 000000000..198e35558 --- /dev/null +++ b/lib/fog/compute/requests/aws/purchase_reserved_instances_offering.rb @@ -0,0 +1,63 @@ +module Fog + module Compute + class AWS + class Real + + require 'fog/compute/parsers/aws/purchase_reserved_instances_offering' + + # Purchases a Reserved Instance for use with your account. + # + # ==== Parameters + # * reserved_instances_offering_id<~String> - ID of the Reserved Instance offering you want to purchase. + # * instance_count<~Integer> - The number of Reserved Instances to purchase. + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'requestId'<~String> - Id of request + # * 'reservedInstancesId'<~String> - Id of the purchased reserved instances. + # + # {Amazon API Reference}[http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-PurchaseReservedInstancesOffering.html] + def purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count = 1) + request({ + 'Action' => 'PurchaseReservedInstancesOffering', + 'ReservedInstancesOfferingId' => reserved_instances_offering_id, + 'InstanceCount' => instance_count, + :idempotent => true, + :parser => Fog::Parsers::Compute::AWS::PurchaseReservedInstancesOffering.new + }) + end + + end + + class Mock + def purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count) + response = Excon::Response.new + response.status = 200 + + # Need to implement filters in the mock to find this there instead of here + # Also there's no information about what to do when the specified reserved_instances_offering_id doesn't exist + raise unless reserved_instance_offering = Compute[:aws].describe_reserved_instances_offerings.body["reservedInstancesOfferingsSet"].find { |offering| offering["reservedInstancesOfferingId"] == reserved_instances_offering_id } + + reserved_instances_id = Fog::AWS::Mock.reserved_instances_id + reserved_instance_offering.delete('reservedInstancesOfferingId') + + self.data[:reserved_instances][reserved_instances_id] = reserved_instance_offering.merge({ + 'reservedInstancesId' => reserved_instances_id, + 'start' => Time.now, + 'instanceCount' => instance_count, + 'state' => 'payment-pending', + 'tagSet' => [] + }) + + response.body = { + 'reservedInstancesId' => reserved_instances_id, + 'requestId' => Fog::AWS::Mock.request_id + } + + response + end + end + end + end +end diff --git a/lib/fog/providers/aws.rb b/lib/fog/providers/aws.rb index 7ef39795c..fa804e483 100644 --- a/lib/fog/providers/aws.rb +++ b/lib/fog/providers/aws.rb @@ -175,6 +175,10 @@ module Fog request_id << Fog::Mock.random_hex(12) request_id.join('-') end + class << self + alias :reserved_instances_id :request_id + alias :reserved_instances_offering_id :request_id + end def self.reservation_id "r-#{Fog::Mock.random_hex(8)}" diff --git a/tests/compute/requests/aws/instance_tests.rb b/tests/compute/requests/aws/instance_tests.rb index 8e0e5d2c1..81b71ac41 100644 --- a/tests/compute/requests/aws/instance_tests.rb +++ b/tests/compute/requests/aws/instance_tests.rb @@ -79,6 +79,48 @@ Shindo.tests('Fog::Compute[:aws] | instance requests', ['aws']) do 'requestId' => String } + @describe_reserved_instances_offerings_format = { + 'reservedInstancesOfferingsSet' => [{ + 'reservedInstancesOfferingId' => String, + 'instanceType' => String, + 'availabilityZone' => String, + 'duration' => Integer, + 'fixedPrice' => Float, + 'usagePrice' => Float, + 'productDescription' => String, + 'instanceTenancy' => String, + 'currencyCode' => String + }], + 'requestId' => String + } + + @purchase_reserved_instances_offering_format = { + 'reservedInstancesId' => String, + 'requestId' => String + } + + @describe_reserved_instances_format = { + 'reservedInstancesSet' => [{ + 'reservedInstancesId' => String, + 'instanceType' => String, + 'availabilityZone' => String, + 'start' => Time, + 'duration' => Integer, + 'fixedPrice' => Float, + 'usagePrice' => Float, + 'instanceCount' => Integer, + 'productDescription' => String, + 'state' => String, + 'tagSet' => [{ + 'key' => String, + 'value' => String + }], + 'instanceTenancy' => String, + 'currencyCode' => String + }], + 'requestId' => String + } + tests('success') do @instance_id = nil @@ -151,6 +193,21 @@ Shindo.tests('Fog::Compute[:aws] | instance requests', ['aws']) do Fog::Compute[:aws].terminate_instances(@instance_id).body end + tests("#describe_reserved_instances_offerings").formats(@describe_reserved_instances_offerings_format) do + @reserved_instances = Fog::Compute[:aws].describe_reserved_instances_offerings.body + @reserved_instances + end + + if Fog.mocking? + @reserved_instance_offering_id = @reserved_instances["reservedInstancesOfferingsSet"].first["reservedInstancesOfferingId"] + tests("#purchase_reserved_instances_offering('#{@reserved_instance_offering_id}')").formats(@purchase_reserved_instances_offering_format) do + Fog::Compute[:aws].purchase_reserved_instances_offering(@reserved_instance_offering_id, 1).body + end + + tests("#describe_reserved_instances").formats(@describe_reserved_instances_format) do + Fog::Compute[:aws].describe_reserved_instances.body + end + end end tests('failure') do