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の改善もしたいかも
というわけで
以上です!当初は以下のどちらかにしようと思ってましたが、予定を変更してお送りしました!
この辺はまたの機会に!