Skip to content

Instantly share code, notes, and snippets.

@noneal
Forked from corbinbs/aws_usage.py
Created August 9, 2011 22:52
Show Gist options
  • Select an option

  • Save noneal/1135411 to your computer and use it in GitHub Desktop.

Select an option

Save noneal/1135411 to your computer and use it in GitHub Desktop.

Revisions

  1. noneal revised this gist Aug 9, 2011. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion aws_usage.py
    Original file line number Diff line number Diff line change
    @@ -119,7 +119,8 @@ def get_report(service, date_from, date_to, username, password, format='csv', pe
    # report selector
    print >>sys.stderr, "Building report..."
    br.select_form(name="usageReportForm")
    br["timePeriod"] = ["Custom date range"]
    # update timePeriod to fix: mechanize._form.ItemNotFoundError: insufficient items with name 'Custom date range'
    br["timePeriod"] = ["aws-portal-custom-date-range"]
    br["startYear"] = [str(date_from.year)]
    br["startMonth"] = [str(date_from.month)]
    br["startDay"] = [str(date_from.day)]
  2. @corbinbs corbinbs revised this gist Feb 5, 2011. 1 changed file with 80 additions and 19 deletions.
    99 changes: 80 additions & 19 deletions aws_usage.py
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,7 @@
    Run with -h to see the available options.
    """

    import re
    import os
    import sys
    from datetime import date
    @@ -29,8 +30,51 @@
    PERIODS = ('hours', 'days', 'months')
    SERVICES = ('AmazonS3', 'AmazonEC2', 'AmazonCloudFront', 'AmazonSimpleDB', 'AWSQueueService', 'IngestionService', 'AmazonVPC',)

    ACCOUNT_SUMMARY_URL = "https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=activity-summary"
    FORM_URL = "https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=usage-report"

    def get_current(username, password, debug=False):
    br = mechanize.Browser()
    br.set_handle_robots(False)

    if debug:
    # Log information about HTTP redirects and Refreshes.
    br.set_debug_redirects(True)
    # Log HTTP response bodies (ie. the HTML, most of the time).
    br.set_debug_responses(True)
    # Print HTTP headers.
    br.set_debug_http(True)

    br.addheaders = [
    # the login process 404s if you leave Python's UA string
    ('User-Agent', 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4'),
    ('Accept', 'text/html, application/xml, */*'),
    ]

    # login
    print >>sys.stderr, "Logging in..."
    try:
    resp = br.open(ACCOUNT_SUMMARY_URL)
    #Some funkiness in DOCTYPE string. mechanize doesn't like
    #results in: mechanize._form.ParseError: unexpected '\\' char in declaration
    #if we don't strip out
    resp.set_data(re.sub('<!DOCTYPE(.*)>', '', resp.get_data()))
    br.set_response(resp)
    br.select_form(name="signIn")
    br["email"] = username
    br["password"] = password
    resp = br.submit() # submit current form
    except Exception, e:
    print >>sys.stderr, "Error logging in to AWS"
    raise

    cost = re.findall('Total Charges due on.*\$([0-9\,]+\.[0-9][0-9])', resp.get_data(), re.DOTALL)
    if len(cost) > 0:
    print "Total Charges due: %s" % cost[0]
    else:
    print "Current Charges Unknown"


    def get_report(service, date_from, date_to, username, password, format='csv', period='days', debug=False):
    br = mechanize.Browser()
    br.set_handle_robots(False)
    @@ -53,6 +97,11 @@ def get_report(service, date_from, date_to, username, password, format='csv', pe
    print >>sys.stderr, "Logging in..."
    try:
    resp = br.open(FORM_URL)
    #Some funkiness in DOCTYPE string. mechanize doesn't like
    #results in: mechanize._form.ParseError: unexpected '\\' char in declaration
    #if we don't strip out
    resp.set_data(re.sub('<!DOCTYPE(.*)>', '', resp.get_data()))
    br.set_response(resp)
    br.select_form(name="signIn")
    br["email"] = username
    br["password"] = password
    @@ -99,31 +148,43 @@ def get_report(service, date_from, date_to, username, password, format='csv', pe
    parser.add_option('-U', '--username', dest="username", metavar="USERNAME", help="Email address for your AWS account")
    parser.add_option('-P', '--password', dest="password", metavar="PASSWORD")
    parser.add_option('-d', '--debug', action="store_true", dest="debug", default=False)
    parser.add_option('-c', '--current', action="store_true", dest="current", default=False)

    opts, args = parser.parse_args()
    if len(args) < 2:
    parser.error("Missing date range")
    date_range = [date(*time.strptime(args[i], '%Y-%m-%d')[0:3]) for i in range(2)]
    if date_range[1] < date_range[0]:
    parser.error("End date < start date")

    if not opts.service:
    parser.error("Specify a service to query!")

    if not opts.username and not os.environ.get('AWS_USERNAME'):
    parser.error("Must specify username option or set AWS_USERNAME")
    if not opts.password and not os.environ.get('AWS_PASSWORD'):
    parser.error("Must specify password option or set AWS_PASSWORD")

    if opts.current:
    kwopts = {
    'username': opts.username or os.environ.get('AWS_USERNAME'),
    'password': opts.password or os.environ.get('AWS_PASSWORD'),
    'debug': opts.debug,
    }
    get_current(**kwopts)

    kwopts = {
    'service': opts.service,
    'date_from': date_range[0],
    'date_to': date_range[1],
    'format': opts.format,
    'period': opts.period,
    'username': opts.username or os.environ.get('AWS_USERNAME'),
    'password': opts.password or os.environ.get('AWS_PASSWORD'),
    'debug': opts.debug,
    }
    else:

    print get_report(**kwopts)
    if len(args) < 2:
    parser.error("Missing date range")
    date_range = [date(*time.strptime(args[i], '%Y-%m-%d')[0:3]) for i in range(2)]
    if date_range[1] < date_range[0]:
    parser.error("End date < start date")

    if not opts.service:
    parser.error("Specify a service to query!")

    kwopts = {
    'service': opts.service,
    'date_from': date_range[0],
    'date_to': date_range[1],
    'format': opts.format,
    'period': opts.period,
    'username': opts.username or os.environ.get('AWS_USERNAME'),
    'password': opts.password or os.environ.get('AWS_PASSWORD'),
    'debug': opts.debug,
    }

    print get_report(**kwopts)
  3. @rcoup rcoup created this gist Jun 1, 2010.
    129 changes: 129 additions & 0 deletions aws_usage.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,129 @@
    #!/usr/bin/env python

    """
    A script to query the Amazon Web Services usage reports programmatically.
    Ideally this wouldn't exist, and Amazon would provide an API we can use
    instead, but hey - that's life.
    Basically takes your AWS account username and password, logs into the
    website as you, and grabs the data out. Always gets the 'All Usage Types'
    report for the specified service.
    Requirements:
    * Mechanize: http://wwwsearch.sourceforge.net/mechanize/
    You can install this via pip/easy_install
    Run with -h to see the available options.
    """

    import os
    import sys
    from datetime import date
    import time

    import mechanize

    FORMATS = ('xml', 'csv')
    PERIODS = ('hours', 'days', 'months')
    SERVICES = ('AmazonS3', 'AmazonEC2', 'AmazonCloudFront', 'AmazonSimpleDB', 'AWSQueueService', 'IngestionService', 'AmazonVPC',)

    FORM_URL = "https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=usage-report"

    def get_report(service, date_from, date_to, username, password, format='csv', period='days', debug=False):
    br = mechanize.Browser()
    br.set_handle_robots(False)

    if debug:
    # Log information about HTTP redirects and Refreshes.
    br.set_debug_redirects(True)
    # Log HTTP response bodies (ie. the HTML, most of the time).
    br.set_debug_responses(True)
    # Print HTTP headers.
    br.set_debug_http(True)

    br.addheaders = [
    # the login process 404s if you leave Python's UA string
    ('User-Agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1) Gecko/20090701 Ubuntu/9.04 (jaunty) Firefox/3.5'),
    ('Accept', 'text/html, application/xml, */*'),
    ]

    # login
    print >>sys.stderr, "Logging in..."
    try:
    resp = br.open(FORM_URL)
    br.select_form(name="signIn")
    br["email"] = username
    br["password"] = password
    resp = br.submit() # submit current form
    except Exception, e:
    print >>sys.stderr, "Error logging in to AWS"
    raise

    # service selector
    print >>sys.stderr, "Selecting service %s..." % service
    br.select_form(name="usageReportForm")
    br["productCode"] = [service]
    resp = br.submit()

    # report selector
    print >>sys.stderr, "Building report..."
    br.select_form(name="usageReportForm")
    br["timePeriod"] = ["Custom date range"]
    br["startYear"] = [str(date_from.year)]
    br["startMonth"] = [str(date_from.month)]
    br["startDay"] = [str(date_from.day)]
    br["endYear"] = [str(date_to.year)]
    br["endMonth"] = [str(date_to.month)]
    br["endDay"] = [str(date_to.day)]
    br["periodType"] = [period]

    resp = br.submit("download-usage-report-%s" % format)
    return resp.read()

    if __name__ == "__main__":
    from optparse import OptionParser

    USAGE = (
    "Usage: %prog [options] -s SERVICE DATE_FROM DATE_TO\n\n"
    "DATE_FROM and DATE_TO should be in YYYY-MM-DD format (eg. 2009-01-31)\n"
    "Username and Password can also be specified via AWS_USERNAME and AWS_PASSWORD environment variables.\n"
    "\n"
    "Available Services: " + ', '.join(SERVICES)
    )
    parser = OptionParser(usage=USAGE)
    parser.add_option('-s', '--service', dest="service", type="choice", choices=SERVICES, help="The AWS service to query")
    parser.add_option('-p', '--period', dest="period", type="choice", choices=PERIODS, default='days', metavar="PERIOD", help="Period of report entries")
    parser.add_option('-f', '--format', dest="format", type="choice", choices=FORMATS, default='csv', metavar="FORMAT", help="Format of report")
    parser.add_option('-U', '--username', dest="username", metavar="USERNAME", help="Email address for your AWS account")
    parser.add_option('-P', '--password', dest="password", metavar="PASSWORD")
    parser.add_option('-d', '--debug', action="store_true", dest="debug", default=False)

    opts, args = parser.parse_args()
    if len(args) < 2:
    parser.error("Missing date range")
    date_range = [date(*time.strptime(args[i], '%Y-%m-%d')[0:3]) for i in range(2)]
    if date_range[1] < date_range[0]:
    parser.error("End date < start date")

    if not opts.service:
    parser.error("Specify a service to query!")

    if not opts.username and not os.environ.get('AWS_USERNAME'):
    parser.error("Must specify username option or set AWS_USERNAME")
    if not opts.password and not os.environ.get('AWS_PASSWORD'):
    parser.error("Must specify password option or set AWS_PASSWORD")

    kwopts = {
    'service': opts.service,
    'date_from': date_range[0],
    'date_to': date_range[1],
    'format': opts.format,
    'period': opts.period,
    'username': opts.username or os.environ.get('AWS_USERNAME'),
    'password': opts.password or os.environ.get('AWS_PASSWORD'),
    'debug': opts.debug,
    }

    print get_report(**kwopts)