Programmatically Retrieving AWS Pricing

Amazon Web Services pricing can make a Wall Street derivatives algorithm look simple. Each service has its own unique pricing scheme with sophisticated multi-variable equations and in some cases price tiering. To make matters worse, the pricing varies by region and is subject to change with little or no advance notice.

For a moderate user of AWS, the published pricing on the web or a third party cost management service will be enough to get by. But sometimes you want programmatic access to Amazon pricing. To help expedite this process, I wrapped the undocumented internal APIs used on the Amazon web site into a small Ruby gem called amazon-pricing. This gem provides users the ability to programmatically retrieve AWS pricing for all EC2 instance types in all regions.

Our example will use both the amazon-pricing and fog gems, which can be retrieved as follows:

$ gem install fog  
Successfully installed fog-1.1.2  
1 gem installed  
Installing ri documentation for fog-1.1.2...  
Building YARD (yri) index for fog-1.1.2...  
Installing RDoc documentation for fog-1.1.2...  

$ gem install amazon-pricing  
Successfully installed amazon-pricing-0.0.3  
1 gem installed  
Installing ri documentation for amazon-pricing-0.0.3...  
Building YARD (yri) index for amazon-pricing-0.0.3...  
Installing RDoc documentation for amazon-pricing-0.0.3...

To demonstrate the amazon-pricing gem, we have written a simple script that retrieves the on-demand price per month for all of your instances in an AWS account and exports it in CSV format.

#!/usr/bin/env ruby  

require 'rubygems'  
require 'fog'  
require 'amazon-pricing'  

ACCESS_KEY = "YOUR_AWS_KEY"  
SECRET_KEY = "YOUR_AWS_SECRET_KEY"  

compute = Fog::Compute.new(  
:provider => :aws,  
:aws_secret_access_key => ACCESS_SECRET,  
:aws_access_key_id => SECRET_KEY  
)  

# Retrieve pricing  
price_list = AwsPricing::PriceList.new  

puts "Region,Availability Zone,Instance Id,Instance IP,Instance Type,On-Demand Price Per Month"  
compute.servers.each do |server|  
  instance_type = price_list.get_instance_type(server.availability_zone, :on_demand, server.flavor_id)  
  if instance_type.platform == 'windows'  
    price_per_month = instance_type.windows_price_per_hour*24*30.4  
  else  
    price_per_month = instance_type.linux_price_per_hour*24*30.4  
  end  
  puts "#{instance_type.region.name},#{server.availability_zone},#{server.id},#{server.public_ip_address},#{server.flavor_id},$#{price_per_month}"  
end

Here is a sample run of the script:

us-east,us-east-1d,i-10301a75,0.0.0.0,c1.medium,$124.032  
us-east,us-east-1d,i-fb313e9f,0.0.0.0,c1.medium,$124.032  
us-east,us-east-1d,i-22e222f1,0.0.0.0,m1.xlarge,$496.128

I am currently using this gem in an internal cloud asset management tool at Sonian. It is integrated to retrieve and historically retain daily pricing, allowing us to not only project the real-time cost of our infrastructure, but also to analyze potential cost savings (e.g. comparing on-demand to reserved instances).

It's a pretty simple gem at this point, with much left to add. Let me know if you have features you’d like to see in a future version.