Last active
June 1, 2021 15:28
-
-
Save AwsGeek/c7eb13cab85e797fd433f05b39ada096 to your computer and use it in GitHub Desktop.
AWS Price List API Sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>AWS Price List API</title> | |
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> | |
<script src="//code.jquery.com/jquery-1.10.2.js"></script> | |
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> | |
<style> | |
body { font-size: 62.5%; } | |
label, input { display:block; } | |
input.text { margin-bottom:12px; width:95%; padding: .4em; } | |
fieldset { padding:0; border:0; margin-top:25px; } | |
div#servers-container { float:left; margin: 20px 0; } | |
div#servers-container table { margin: 1em 0; border-collapse: collapse; width: 100%; } | |
div#servers-container table td, div#servers-container table th { border: 1px solid #eee; padding: .6em 10px; text-align: left; } | |
.ui-dialog .ui-state-error { padding: .3em; } | |
.validateTips { border: 1px solid transparent; padding: 0.3em; } | |
label { | |
display: block; | |
margin: 30px 0 0 0; | |
} | |
select { | |
width: 200px; | |
} | |
.overflow { | |
height: 200px; | |
} | |
</style> | |
<script> | |
region = "US West (Oregon)" | |
instances = {} | |
function update() { | |
c = $("#cores").val().trim(); | |
if (!c) { | |
return; | |
} | |
m = $("#memory").val().trim(); | |
if (!m) { | |
return; | |
} | |
region = $("#regions option:selected").text(); | |
scored = []; | |
max = 0.0 | |
// Score each instance | |
for(var i=0; i<instances[region].length; i++) { | |
instance = instances[region][i]; | |
dc = Math.log2(instance['vcpu']/c); | |
dm = Math.log2(instance['memory']/m); | |
if ((dc > -1) && (dm > -1)) { | |
score = Math.sqrt(dc*dc + dm*dm); | |
max = Math.max(max, score); | |
instance['score'] = score; | |
scored.push(instance); | |
} | |
} | |
// Normalize scores | |
for(var i=0; i<scored.length; i++) { | |
scored[i]['score'] = ((1.0 - scored[i]['score']/max) * 100).toFixed(2); | |
} | |
// Sort by score | |
sorted = scored.sort(function(a, b){return b['score']-a['score']}); | |
$("#instances tbody").empty(); | |
for(var i=0; i<sorted.length; i++) { | |
instance = scored[i]; | |
$( "#instances tbody" ).append( "<tr class=\"server\">" + | |
"<td>" + sorted[i]['score'] + "</td>" + | |
"<td>" + sorted[i]["type"] + "</td>" + | |
"<td>" + sorted[i]["vcpu"] + "</td>" + | |
"<td>" + sorted[i]["memory"] + "</td>" + | |
"<td>" + sorted[i]["cost"][0] + "</td>" + | |
"</tr>" ); | |
}; | |
} | |
$(function() { | |
$("#regions").selectmenu(); | |
$('#regions').on('selectmenuchange', function(e) { | |
update(); | |
}); | |
$('#cores, #memory').on('change', function(e) { | |
update(); | |
}); | |
$.ajax({ | |
url: "prices.json", | |
context: $(this) | |
}).success(function(resp) { | |
instances = resp["instances"]; | |
for (var key in instances) { | |
if (instances.hasOwnProperty(key)) { | |
$("#regions").append("<option>" + key + "</option>"); | |
} | |
} | |
$('#regions').val(region); | |
$("#regions").selectmenu("refresh"); | |
$('#published').text('AWS Price List API Example - Price date ' + resp["published"]); | |
$('#generated').text('Generated on ' + resp["created"]); | |
update(); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<h1 id="published">AWS Price List API Example</h1> | |
<h3 id="generated">AWS Price List API Example</h3> | |
<div id="servers-container" class="ui-widget"> | |
<table id="servers" class="ui-widget ui-widget-content"> | |
<thead> | |
<tr class="ui-widget-header "> | |
<th>Region</th> | |
<th>Cores</th> | |
<th>Memory (GB)</th> | |
</tr> | |
</thead> | |
<tbody> | |
<td><select name="regions" id="regions" class="text ui-widget-content ui-corner-all"></select></td> | |
<td><input type="text" name="cores" id="cores" class="text ui-widget-content ui-corner-all" value="1"></td> | |
<td><input type="text" name="memory" id="memory" class="text ui-widget-content ui-corner-all" value="2"></td> | |
</tbody> | |
</table> | |
<table id="instances" class="ui-widget ui-widget-content"> | |
<thead> | |
<tr class="ui-widget-header "> | |
<th>Score</th> | |
<th>Type</th> | |
<th>Cores</th> | |
<th>Memory (GB)</th> | |
<th>Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
</tbody> | |
</table> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json, boto3, time, requests | |
def lambda_handler(event, context): | |
if event['offerCode'] == 'AmazonEC2': | |
offer = download_offer(event) | |
prices = extract_prices(offer) | |
upload_prices(prices) | |
def download_offer(event): | |
response = requests.get(event['url']['json']) | |
return json.loads(response.text) | |
def filter_products(products): | |
filtered = [] | |
# Only interested in shared tenancy, linux instances | |
for sku, product in products: | |
a = product['attributes'] | |
if not ('locationType' in a and | |
'location' in a and | |
'tenancy' in a and | |
a['tenancy'] == "Shared" and | |
a['locationType'] == 'AWS Region' and | |
a['operatingSystem'] == 'Linux'): | |
continue | |
a['sku'] = sku | |
filtered.append(a) | |
return filtered | |
def extract_prices(offer): | |
terms = offer['terms'] | |
products = offer['products'].items() | |
instances = {} | |
for a in filter_products(products): | |
term = terms['OnDemand'][a['sku']].items()[0][1] | |
cost = [float(term['priceDimensions'].items()[0][1]['pricePerUnit']['USD'])] | |
info = {"type" : a['instanceType'], "vcpu" : a['vcpu'], | |
"memory" : a['memory'].split(" ")[0], "cost" : cost} | |
if not a['location'] in instances: | |
instances[a['location']] = [] | |
instances[a['location']].append(info) | |
return {'created': time.strftime("%c"), 'published': offer['publicationDate'], | |
'instances': instances} | |
def upload_prices(prices): | |
s3 = boto3.client('s3') | |
s3.put_object(ACL='public-read', Body=json.dumps(prices), ContentType='application/json', | |
Bucket='<bucket-name>', Key='prices.json') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"instances": {}, "published": "6/10/2016", "created": "6/10/2016"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks a lot Jerry for this useful tool.
I am trying to figure out to manually trigger execution of this Lambda function from Console to verify everything is working.
Appreciate.