The original AWS Price List API, as described in New – AWS Price List API, gave you access to prices in JSON and CSV form by way of structured URLs. While this worked well for some types of cost management tools, the size and complexity of the files made them difficult to download and tedious to parse. Today we are updating the API by adding new functions that allow you to perform fine-grained price queries that return only the prices that you need. This will allow you to make use of the prices in mobile and browser-based applications.
New Functions
Here are the new functions:
DescribeServices
– Returns sets of attribute keys that are used to define products within a service. For example, the keys returned for EC2 will include physicalProcessor, memory, operatingSystem, location, and tenancy.
GetAttributeValues
– Returns all of the allowable values for a given attribute key. For example, values for the operatingSystem key include Windows, RHEL, Linux, and SUSE; values for the location key include US East (N. Virginia) and Asia Pacific (Mumbai).
GetProducts
-Returns all of the products, along with their public prices, that match a filter expression based on service name and attribute value.
You can access these functions from the AWS SDKs. In order to try them out I used Python and the AWS SDK for Python. I start by importing the SDK and creating a client:
import boto3
import json
import pprint
pricing = boto3.client('pricing')
Here’s how I list all of the services and attributes:
print("All Services")
print("============")
response = pricing.describe_services()
for service in response['Services']:
print(service['ServiceCode'] + ": " + ", ".join(service['AttributeNames']))
print()
The output starts like this:
All Services
============
SnowballExtraDays: productFamily, termType, usagetype, locationType, snowballType, feeDescription, servicecode, feeCode, location, operation
OpsWorks: productFamily, servicecode, termType, usagetype, locationType, location, operation, serverLocation, group
mobileanalytics: productFamily, servicecode, includedEvents, termType, usagetype, description, locationType, location, operation
IngestionServiceSnowball: productFamily, fromLocationType, termType, usagetype, locationType, toLocationType, toLocation, snowballType, servicecode, groupDescription, transferType, location, fromLocation, operation, group
IngestionService: productFamily, termType, usagetype, locationType, servicecode, groupDescription, dataAction, location, operation, group
ElasticMapReduce: productFamily, softwareType, instanceType, termType, usagetype, locationType, instanceFamily, servicecode, location, servicename, operation
datapipeline: productFamily, frequencyMode, termType, usagetype, locationType, description, executionFrequency, servicecode, location, operation, group, executionLocation
...
Here’s how I get all of the values for all of EC2’s pricing attributes:
print("Selected EC2 Attributes & Values")
print("================================")
response = pricing.describe_services(ServiceCode='AmazonEC2')
attrs = response['Services'][0]['AttributeNames']
for attr in attrs:
response = pricing.get_attribute_values(ServiceCode='AmazonEC2', AttributeName=attr)
values = []
for attr_value in response['AttributeValues']:
values.append(attr_value['Value'])
print(" " + attr + ": " + ", ".join(values))
The output starts like this:
Selected EC2 Attributes & Values
================================
volumeType: Throughput Optimized HDD, Provisioned IOPS, Magnetic, General Purpose, Cold HDD
maxIopsvolume: 500 - based on 1 MiB I/O size, 40 - 200, 250 - based on 1 MiB I/O size, 20000, 10000
instanceCapacity10xlarge: 1
locationType: AWS Region
instanceFamily: Storage optimized, Micro instances, Memory optimized, GPU instance, General purpose, Compute optimized
operatingSystem: Windows, SUSE, RHEL, NA, Linux
...
And here’s how I use the service name and attribute values to obtain price listings for EC2 instances with 64 vCPUs, 256 GiB of memory, pre-installed SQL Server Enterprise, in the Asia Pacific (Mumbai) Region. Each price is a JSON string:
print("Selected EC2 Products")
print("=====================")
response = pricing.get_products(
ServiceCode='AmazonEC2',
Filters = [
{'Type' :'TERM_MATCH', 'Field':'operatingSystem', 'Value':'Windows' },
{'Type' :'TERM_MATCH', 'Field':'vcpu', 'Value':'64' },
{'Type' :'TERM_MATCH', 'Field':'memory', 'Value':'256 GiB' },
{'Type' :'TERM_MATCH', 'Field':'preInstalledSw', 'Value':'SQL Ent' },
{'Type' :'TERM_MATCH', 'Field':'location', 'Value':'Asia Pacific (Mumbai)'}
],
MaxResults=100
)
for price in response['PriceList']:
pp = pprint.PrettyPrinter(indent=1, width=300)
pp.pprint(json.loads(price))
print()
The output starts like this (there’s a lot more):
Selected EC2 Products
=====================
{'product': {'attributes': {'clockSpeed': '2.3 GHz',
'currentGeneration': 'Yes',
'dedicatedEbsThroughput': '10000 Mbps',
'ecu': '188',
'enhancedNetworkingSupported': 'Yes',
'instanceFamily': 'General purpose',
'instanceType': 'm4.16xlarge',
'licenseModel': 'No License required',
'location': 'Asia Pacific (Mumbai)',
'locationType': 'AWS Region',
'memory': '256 GiB',
'networkPerformance': '20 Gigabit',
'normalizationSizeFactor': '128',
'operatingSystem': 'Windows',
'operation': 'RunInstances:0102',
'physicalProcessor': 'Intel Xeon E5-2686 v4 (Broadwell)',
'preInstalledSw': 'SQL Ent',
'processorArchitecture': '64-bit',
'processorFeatures': 'Intel AVX, Intel AVX2, Intel Turbo',
'servicecode': 'AmazonEC2',
'servicename': 'Amazon Elastic Compute Cloud',
'storage': 'EBS only',
'tenancy': 'Shared',
'usagetype': 'APS3-BoxUsage:m4.16xlarge',
'vcpu': '64'},
'productFamily': 'Compute Instance',
'sku': '24GRA8RB2KZ9NPCS'},
'publicationDate': '2017-10-07T00:26:55Z',
'serviceCode': 'AmazonEC2',
...
The next part of the response contains an array of terms, each describing a particular way to purchase the instance (On-Demand or various types of Reserved Instance):
'terms': {'OnDemand': {'24GRA8RB2KZ9NPCS.JRTCKXETXF': {'effectiveDate': '2017-09-01T00:00:00Z',
'offerTermCode': 'JRTCKXETXF',
'priceDimensions': {'24GRA8RB2KZ9NPCS.JRTCKXETXF.6YS6EN2CT7': {'appliesTo': [],
'beginRange': '0',
'description': '$30.88 per On Demand Windows with SQL Server Enterprise m4.16xlarge Instance Hour',
'endRange': 'Inf',
'pricePerUnit': {'USD': '30.8800000000'},
'rateCode': '24GRA8RB2KZ9NPCS.JRTCKXETXF.6YS6EN2CT7',
'unit': 'Hrs'}},
'sku': '24GRA8RB2KZ9NPCS',
'termAttributes': {}}},
'Reserved': {'24GRA8RB2KZ9NPCS.38NPMPTW36': {'effectiveDate': '2017-04-30T23:59:59Z',
'offerTermCode': '38NPMPTW36',
'priceDimensions': {'24GRA8RB2KZ9NPCS.38NPMPTW36.2TG2D8R56U': {'appliesTo': [], 'description': 'Upfront Fee', 'pricePerUnit': {'USD': '374227'}, 'rateCode': '24GRA8RB2KZ9NPCS.38NPMPTW36.2TG2D8R56U', 'unit': 'Quantity'},
'24GRA8RB2KZ9NPCS.38NPMPTW36.6YS6EN2CT7': {'appliesTo': [],
'beginRange': '0',
'description': 'Windows with SQL Server Enterprise (Amazon VPC), m4.16xlarge reserved instance applied',
'endRange': 'Inf',
'pricePerUnit': {'USD': '14.2400000000'},
'rateCode': '24GRA8RB2KZ9NPCS.38NPMPTW36.6YS6EN2CT7',
'unit': 'Hrs'}},
'sku': '24GRA8RB2KZ9NPCS',
'termAttributes': {'LeaseContractLength': '3yr', 'OfferingClass': 'standard', 'PurchaseOption': 'Partial Upfront'}},
...
Read Using the AWS Price List API to learn more about these functions and the data that they return.
Now Available
The new functions are available now and you can start using them today in the US East (N. Virginia) and Asia Pacific (Mumbai) Regions to access metadata and price listings for all public AWS Regions and AWS GovCloud (US), at no charge.
To see a real-world example of how to use these functions, take a look at the new post, Controlling Projected User Costs Through Monthly Budget Policies on the AWS Management Tools Blog.
— Jeff;