Use boto3 to get current price for given EC2 instance type Use boto3 to get current price for given EC2 instance type python-3.x python-3.x

Use boto3 to get current price for given EC2 instance type


Here is the solution I ended up with. Using Boto3's own Pricing API with a filter for the instance type, region and operating system. The API still returns a lot of information, so I needed to do a bit of post-processing.

import boto3import jsonfrom pkg_resources import resource_filename# Search product filterFLT = '[{{"Field": "tenancy", "Value": "shared", "Type": "TERM_MATCH"}},'\      '{{"Field": "operatingSystem", "Value": "{o}", "Type": "TERM_MATCH"}},'\      '{{"Field": "preInstalledSw", "Value": "NA", "Type": "TERM_MATCH"}},'\      '{{"Field": "instanceType", "Value": "{t}", "Type": "TERM_MATCH"}},'\      '{{"Field": "location", "Value": "{r}", "Type": "TERM_MATCH"}},'\      '{{"Field": "capacitystatus", "Value": "Used", "Type": "TERM_MATCH"}}]'# Get current AWS price for an on-demand instancedef get_price(region, instance, os):    f = FLT.format(r=region, t=instance, o=os)    data = client.get_products(ServiceCode='AmazonEC2', Filters=json.loads(f))    od = json.loads(data['PriceList'][0])['terms']['OnDemand']    id1 = list(od)[0]    id2 = list(od[id1]['priceDimensions'])[0]    return od[id1]['priceDimensions'][id2]['pricePerUnit']['USD']# Translate region code to region namedef get_region_name(region_code):    default_region = 'EU (Ireland)'    endpoint_file = resource_filename('botocore', 'data/endpoints.json')    try:        with open(endpoint_file, 'r') as f:            data = json.load(f)        return data['partitions'][0]['regions'][region_code]['description']    except IOError:        return default_region# Use AWS Pricing API at US-East-1client = boto3.client('pricing', region_name='us-east-1')# Get current price for a given instance, region and osprice = get_price(get_region_name('eu-west-1'), 'c5.xlarge', 'Linux')print(price)

This example outputs 0.1920000000 (hourly price in USD) fairly quickly. But any further optimizations would indeed be appreciated.


If you don't like the native function, then look at Lyft's awspricing library for Python. Here's an example:

import awspricingec2_offer = awspricing.offer('AmazonEC2')p = ec2_offer.ondemand_hourly(  't2.micro',  operating_system='Linux',  region='eu-west-1')print(p) # 0.0126

I'd recommend enabling caching (see AWSPRICING_USE_CACHE) otherwise it will be slow.


I have updated toringe's solution a bit to handle different key errors

def price_information(self, instance_type, os, region):        # Search product filter        FLT = '[{{"Field": "operatingSystem", "Value": "{o}", "Type": "TERM_MATCH"}},' \              '{{"Field": "instanceType", "Value": "{t}", "Type": "TERM_MATCH"}}]'            f = FLT.format(t=instance_type, o=os)        try:            data = self.pricing_client.get_products(ServiceCode='AmazonEC2', Filters=json.loads(f))            instance_price = 0            for price in data['PriceList']:                try:                    first_id =  list(eval(price)['terms']['OnDemand'].keys())[0]                    price_data = eval(price)['terms']['OnDemand'][first_id]                    second_id = list(price_data['priceDimensions'].keys())[0]                    instance_price = price_data['priceDimensions'][second_id]['pricePerUnit']['USD']                    if float(price) > 0:                        break                except Exception as e:                    print(e)            print(instance_price)            return instance_price        except Exception as e:            print(e)            return 0