AWS Price List APIから欲しい情報だけ抜き取るAPIをAPI Gateway + Lambdaで作った
この記事はAWS Advent Calendar 2015の11日の記事です。
経緯
それは昨日(2015-12-10)の出来事でした。
全世界待望(?)の料金を取得するための公式APIが公開されました。
過去にこんなのやこんなのを作って、公式HPで使っているデータソースのJSONのURLやフォーマットが変わる度に(´・ω・`)ショボーンとしてきた身としては、「これは!!」となったわけです。
で、喜び勇んで試しに叩いてみたら
@marcy_terui RDSで26MB。。でけぇよ!
— Michael H. Oshita (@ijin) 2015, 12月 10
100万行超えのJSONやばすぎでしょw
— Masashi Terui (@marcy_terui) 2015, 12月 10
そんなこんなで
@ayakomuro たしかに。ほしいやつだけ返してくれる簡易APIでラップするの良いですね!
— Masashi Terui (@marcy_terui) 2015, 12月 10
みたいな話になったので勢いで作ってみましたよと。
成果物
ソース
APIドキュメント(swagger-ui)
フィードバックはGitHubの方からお願いします :-)
エラー処理とか雑なんでエラー時に普通にスタックトレースとか返ってくるので、Issueに貼り付けてやってくださいw
使い方
APIドキュメント見れば大枠はわかると思うので、ここでは各属性の指定方法を説明したいと思います。
とりあえずコマンドからのサンプルを貼っておきます。これをベースに説明したいと思います。
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '[{ "key": "instanceType", "value": "m4.4xlarge" }, { "key": "location", "value": "US West (Oregon)" }, { "key": "operatingSystem", "value": "Linux" }] ' 'https://eaoftu7rfi.execute-api.us-east-1.amazonaws.com/public/v1/offer/AmazonEC2?term=OnDemand'
Method
POSTのみに対応します(CORS対応のためにOPTIONも叩くことはできます)
URL
まず、ベースとなるのが以下の部分です。
https://eaoftu7rfi.execute-api.us-east-1.amazonaws.com/public/v1/offer/
次に、その後の AmazonEC2 の部分がサービスを示します。それぞれ何が使えるかは本家のAPIに準拠します。
なので、以下の offerCode で何が使えるか確認できます。
https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json
そして、クエリストリングの term で購入方式を指定します。ここは、確認した範囲では OnDemand or Reserved しかないようです。EC2やRDS等以外の Reserved の概念が存在しないサービスについては OnDemand を指定してください。
Body
JSONフォーマットで各プロダクトの属性名が key 、その内容を valueで指定します。それぞれの内容は公式APIのデータが以下のようになっており、その中の attributes の内容がそのまま該当します。
{
"formatVersion" : "v1.0",
"disclaimer" : "This pricing list is for informational purposes only. All prices are subject to the additional terms included in the pricing pages on http://aws.amazon.com. All Free Tier prices are also subject to the terms included at https://aws.amazon.com/free/",
"offerCode" : "AmazonRDS",
"version" : "20151001000000",
"publicationDate" : "2015-11-15T04:02:20Z",
"products" : {
"FNR4GZ675EW5UXJW" : {
"sku" : "FNR4GZ675EW5UXJW",
"productFamily" : "Database Instance",
"attributes" : {
"servicecode" : "AmazonRDS",
"location" : "US West (Oregon)",
"locationType" : "AWS Region",
"instanceType" : "db.t2.small",
"currentGeneration" : "Yes",
"instanceClass" : "Burstable performance instances",
"vcpu" : "1",
"memory" : "2",
"piopsOptimized" : "No",
"networkPerformance" : "Low",
"engineCode" : "10",
"databaseEngine" : "SQL Server",
"databaseEdition" : "Express",
"deploymentOption" : "Single-AZ",
"usagetype" : "USW2-InstanceUsage:db.t2.small",
"operation" : "CreateDBInstance:0010"
}
},
複数の条件は全て AND で繋がります。指定された条件を全て満たすデータが返却されます。
結果
上記コマンドの結果は以下のようになります。
[
{
"product": {
"sku": "8YGPZRQEKSSY8VWV",
"productFamily": "Compute Instance",
"attributes": {
"enhancedNetworkingSupported": "Yes",
"currentGeneration": "Yes",
"operation": "RunInstances",
"instanceType": "m4.4xlarge",
"vcpu": "16",
"storage": "EBS only",
"location": "US West (Oregon)",
"memory": "64 GiB",
"processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo",
"networkPerformance": "High",
"usagetype": "USW2-HostBoxUsage:m4.4xlarge",
"processorArchitecture": "64-bit",
"tenancy": "Host",
"servicecode": "AmazonEC2",
"dedicatedEbsThroughput": "2000 Mbps",
"instanceFamily": "General purpose",
"locationType": "AWS Region",
"licenseModel": "No License required",
"preInstalledSw": "NA",
"clockSpeed": "2.4 GHz",
"physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)",
"operatingSystem": "Linux"
}
},
"price": [
{
"sku": "8YGPZRQEKSSY8VWV",
"termAttributes": {},
"effectiveDate": "2015-12-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"8YGPZRQEKSSY8VWV.JRTCKXETXF.6YS6EN2CT7": {
"description": "$0.000 per Linux m4.4xlarge Dedicated Host Instance hour",
"pricePerUnit": {
"USD": "0.0000000000"
},
"rateCode": "8YGPZRQEKSSY8VWV.JRTCKXETXF.6YS6EN2CT7",
"endRange": "Inf",
"beginRange": "0",
"appliesTo": [],
"unit": "Hrs"
}
}
}
]
},
{
"product": {
"sku": "ZPAH28S2QQZ64QB5",
"productFamily": "Compute Instance",
"attributes": {
"enhancedNetworkingSupported": "Yes",
"currentGeneration": "Yes",
"operation": "RunInstances",
"instanceType": "m4.4xlarge",
"vcpu": "16",
"storage": "EBS only",
"location": "US West (Oregon)",
"memory": "64 GiB",
"processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo",
"networkPerformance": "High",
"usagetype": "USW2-DedicatedUsage:m4.4xlarge",
"processorArchitecture": "64-bit",
"tenancy": "Dedicated",
"servicecode": "AmazonEC2",
"dedicatedEbsThroughput": "2000 Mbps",
"instanceFamily": "General purpose",
"locationType": "AWS Region",
"licenseModel": "No License required",
"preInstalledSw": "NA",
"clockSpeed": "2.4 GHz",
"physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)",
"operatingSystem": "Linux"
}
},
"price": [
{
"sku": "ZPAH28S2QQZ64QB5",
"termAttributes": {},
"effectiveDate": "2015-12-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"ZPAH28S2QQZ64QB5.JRTCKXETXF.6YS6EN2CT7": {
"description": "$1.109 per Dedicated Usage Linux m4.4xlarge Instance Hour",
"pricePerUnit": {
"USD": "1.1090000000"
},
"rateCode": "ZPAH28S2QQZ64QB5.JRTCKXETXF.6YS6EN2CT7",
"endRange": "Inf",
"beginRange": "0",
"appliesTo": [],
"unit": "Hrs"
}
}
}
]
},
{
"product": {
"sku": "BMEYUTP658QKQRTP",
"productFamily": "Compute Instance",
"attributes": {
"enhancedNetworkingSupported": "Yes",
"currentGeneration": "Yes",
"operation": "RunInstances",
"instanceType": "m4.4xlarge",
"vcpu": "16",
"storage": "EBS only",
"location": "US West (Oregon)",
"memory": "64 GiB",
"processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo",
"networkPerformance": "High",
"usagetype": "USW2-BoxUsage:m4.4xlarge",
"processorArchitecture": "64-bit",
"tenancy": "Shared",
"servicecode": "AmazonEC2",
"dedicatedEbsThroughput": "2000 Mbps",
"instanceFamily": "General purpose",
"locationType": "AWS Region",
"licenseModel": "No License required",
"preInstalledSw": "NA",
"clockSpeed": "2.4 GHz",
"physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)",
"operatingSystem": "Linux"
}
},
"price": [
{
"sku": "BMEYUTP658QKQRTP",
"termAttributes": {},
"effectiveDate": "2015-12-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"BMEYUTP658QKQRTP.JRTCKXETXF.6YS6EN2CT7": {
"description": "$1.008 per On Demand Linux m4.4xlarge Instance Hour",
"pricePerUnit": {
"USD": "1.0080000000"
},
"rateCode": "BMEYUTP658QKQRTP.JRTCKXETXF.6YS6EN2CT7",
"endRange": "Inf",
"beginRange": "0",
"appliesTo": [],
"unit": "Hrs"
}
}
}
]
}
]
制限事項
ざっくり構築方法
1. ソースを取得
git clone git@github.com:willyworks/aws-price-api.git
2. Lambda functionをデプロイ
virtualenv -p /path/to/python2.7 .venv . .venv/bin/activate pip install -r requirements.txt lamvery deploy
デプロイは拙作のこちらを使ってます。詳しくはLambda縛り Advent Calendar 2015の16日で書きたいと思ってます。
3. Amazon API Gateway Swagger ImporterでAPIを定義する
Amazon API Gateway Swagger ImporterでAPIを一発で定義する | Developers.IO
4. Lambda functionの紐付けとMapping Templates設定
こんな感じ。

Mapping Templates↓
{
"offer" : "$input.params('offer')",
"term": "$input.params('term')",
"condition": $input.json('$')
}
4. CORS設定
5. Deploy API!!
所感など
- Price List API生で使うのツラい
- 変更通知がSNSで受けれるらしいし、データストアに突っ込んで通知をトリガーに更新させることを想定してる?
- LambdaもAPIのデータ受け取るのに一番時間かかってる。Lambdaから叩ける低レイテンシなキャッシュほしい。*2
- Reservedで期間指定できるようにしたり、もうちょっとAPIの改善もしたいかも
というわけで
以上です!当初は以下のどちらかにしようと思ってましたが、予定を変更してお送りしました!
この辺はまたの機会に!