4

I want to programatically retrieve a list of prices for given instance IDs for AWS EC2 instances. I'm trying to do this via plain REST API calls (ie. without a framework).

I want to provide a list of instance IDs:

i-12345   
i-45678
...

and ultimately retrieve their price per hour:

i-12345 = $0.032
i-45678 = $0.56
...

I'm trying to use Postman with my AccessKey and SecretKey but getting a 401 Unauthorized when I use: https://ec2.amazonaws.com/?Action=DescribeInstances&Filter.1.Name=instance-id&Filter.1.Value=i-12345

It may well be that I need multiple REST calls:

  1. Describe instances to get the instance size and region.
  2. Call the pricing endpoint https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/Welcome.html

Any ideas?

Notes:

  • I'm aware of the price list JSON https://aws.amazon.com/blogs/aws/new-aws-price-list-api/ but this post was from 2015.

  • I'm aware of the JSON downloads https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/us-east-1/index.json but this would require that I first know which region each of my instances is running in & then download the entire +20MB JSON for each region.

  • I'm aware of the pricing page: https://aws.amazon.com/ec2/pricing/ which highlights another complication - how was the instance created.

Perhaps I'm going about this the wrong way. Perhaps I should be querying the cost explorer API to see how much the instances have cost over the last X days and thus extrapolate from that?

A. Gardner
  • 571
  • 2
  • 7
  • 17
  • 1
    I feel that your approach won't work as is. The AWS Rest API's authentication [is pretty involved](https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader) and will require code to calculate the SHA1 hashes. Then, at best you can access **your** instance information. Now you have to join that with pricing info. You can get worldwide info from [here](https://raw.githubusercontent.com/powdahound/ec2instances.info/master/www/instances.json) (warning - 9MB) but now you have to find the region and instance type. You really need some code. – stdunbar Aug 15 '18 at 17:33

1 Answers1

1

There's an pricing API, see Jeff Barr's Blog: https://aws.amazon.com/blogs/aws/aws-price-list-api-update-new-query-and-metadata-functions/

Note that pricing records are for multiple services, so a good filter can really help you zoom in on the records you get back and the number of pagination API calls needed (which translate to speed...).

Example:

b3session = boto3.Session(region_name="us-east-1") # pricing API not supported in all regions, I default to us-east-1
pricing_client = b3session.client('pricing')

# Filter to only on-demand, no pre-isntalled SW, and Linux (to avoid adding OS cost in this example)
region_name = 'eu-west-1'
query_parameters =  {           

        'ServiceCode': 'AmazonEC2',
        'FormatVersion': 'aws_v1',
        'Filters': [
                {"Type": "TERM_MATCH", "Field": "regionCode", "Value": region_name},
                {"Type": "TERM_MATCH", "Field": "marketoption", "Value": "OnDemand"},
                {"Type": "TERM_MATCH", "Field": "preInstalledSw", "Value": "NA"},
                {"Type": "TERM_MATCH", "Field": "operatingSystem", "Value": "Linux"},
                {"Type": "TERM_MATCH", "Field": "productFamily", "Value": "Compute Instance"},
                {"Type": "TERM_MATCH", "Field": "tenancy", "Value": "Shared"},
        ]
    }   

next_token = True
while next_token:
        try:
            prices = pricing_client.get_products(**query_parameters)
        except Exception as e:
            print("Some thing went wrong)
            exit(1)
        if 'NextToken' in prices.keys():
            query_parameters['NextToken'] = prices['NextToken']
        else:
            next_token = False
        for p in prices["PriceList"]:
            price = json.loads(p).   # (This API returns strings, not dicts)

            ## DO SOMETHING WITH THIS PRICING RECORD

ouflak
  • 2,458
  • 10
  • 44
  • 49
Eran Brown
  • 11
  • 1