Experimenting with Cost Optimization Hub Boto3 API
In this article I share a Python 3 script used to programmatically retrieve status and recommendations from Cost Optimization Hub using the Boto3 APIs. Using these APIs to retrieve recommendations allows you to filter, categorize and incorporate them in your own task management systems. My goal with this script was to better understand what data the API provide for prioritizing cost optimization efforts.
This script was tested using AWS Cloud9 in a lab AWS organization with Cost Optimization Hub enabled for over 24 hours. Script goal is to experiment with the Boto3 APIs for Cost Optimization Hub. Script is not meant for production use as is.
I liked the ability of grouping summaries by implementation effort. That along with the ability to filter on actions allow you to identify quick wins in your AWS workloads. You can, for example, identify low to medium effort tasks that don't require a restart to complete. I am looking forward to experimenting further with the API and seeing what integrations and visualizations the community will build.
Cost Optimization Hub links:
- Announcement: https://aws.amazon.com/about-aws/whats-new/2023/11/cost-optimization-hub/
- FAQ: https://aws.amazon.com/aws-cost-management/cost-optimization-hub/faqs/
- API: https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_Operations_Cost_Optimization_Hub.html
- Boto3 API: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cost-optimization-hub.html
- Documentation: https://docs.aws.amazon.com/cost-management/latest/userguide/cost-optimization-hub.html
The prerequisites for the test code to run are Python 3 and Boto3. You will also need to provide AWS credentials with sufficient IAM permissions via one of the methods outlined here: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html . If you are using command line parameters instead of a configuration file don't forget to set the region with AWS_DEFAULT_REGION
. The IAM Policy Actions needed for the script to run are cost-optimization-hub:Get*
and cost-optimization-hub:List*
Save the code below in a file with .py extension. Use python scriptname.py
to run the script.
#!/usr/bin/python
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import boto3
# Experimenting with Cost Optimization Hub Boto3 API.
client = boto3.client('cost-optimization-hub')
print('=== Enrollment status for AWS accounts in the AWS Organization:')
list_enrollment_paginator = client.get_paginator('list_enrollment_statuses')
list_enrollment_page_iterator = list_enrollment_paginator.paginate(
includeOrganizationInfo=True
)
print('\tAccount ID \tStatus')
for page in list_enrollment_page_iterator:
if page.get('ResponseMetadata').get('HTTPStatusCode') == 200:
for item in page.get('items'):
print(f"\t{item.get('accountId')}\t{item.get('status')}")
print('=== Recommendation Summaries (unfiltered):')
for group in ['AccountId', 'Region', 'ActionType', 'ResourceType',
'RestartNeeded', 'RollbackPossible', 'ImplementationEffort']:
print(f'\tgroupBy {group}')
response = client.list_recommendation_summaries(groupBy=group)
print(f"\tEstimated Total Deduped Savings ({response.get('currencyCode')}): {response.get('estimatedTotalDedupedSavings')}")
# response.get('items')} has other details for review.
print('=== Recommendation (filtered):')
recommendations_filter = {
'actionTypes': ['Rightsize', 'Upgrade'],
'implementationEfforts': ['VeryLow', 'Low', 'Medium'],
'resourceTypes': ['Ec2Instance', 'EbsVolume'],
}
list_recommendations_paginator = client.get_paginator('list_recommendations')
list_recommendations_page_iterator = list_recommendations_paginator.paginate(
filter=recommendations_filter,
includeAllRecommendations=True,
maxResults=100
)
for page in list_recommendations_page_iterator:
if page.get('ResponseMetadata').get('HTTPStatusCode') == 200:
for item in page.get('items'):
print(f"\tAccount ID: {item.get('accountId')}", end='')
print(f"\tAction: {item.get('actionType')}", end='')
print(f"\tEffort: {item.get('implementationEffort')}", end='')
print(f"\tEstimated Monthly Savings: {item.get('estimatedMonthlySavings')}", end='')
print(f"\tResource Type: {item.get('currentResourceType')}")
Relevant content
- AWS OFFICIALUpdated 4 months ago
- AWS OFFICIALUpdated 19 days ago
- asked 5 months agolg...
- asked 3 months agolg...
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 3 months ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 4 months ago