10
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AWSの料金表を自動作成したい

Last updated at Posted at 2018-02-02

AWS の料金一覧画面から Google スプレッドシートに値をコピペするのに疲れたので、なんとか EC2 の料金表を自動生成できないかと思いました。試行錯誤の結果、ようやくデータ構造までは把握できました。

AWS Price List Service API

AWS Price List Service API (AWS Price List Service)で AWS の料金データを取得できます。今回は取っ掛かりとして AWS CLI を使うので、Pricing サブコマンドでやることになります。

この API は、使えるエンドポイントが以下に限られます。

このため、.aws/config は以下のようにしています。

$ cat .aws/config
[default]
output = json
region = us-east-1

Pricing で使えるサブコマンドは、以下の3種類です。

サブコマンド名 機能
describe-services サービスとその属性名の一覧
get-attribute-values サービス毎の属性値の一覧
get-products 価格の一覧

describe-services

describe-services を何も指定せずに呼び出すと、サービスとその属性名の一覧がずらずらと表示されます。なお便宜上、(JSONではなく)テキスト形式で出力しています。

$ aws pricing describe-services --output=text | head -5
SERVICES        AWSBudgets
ATTRIBUTENAMES  productFamily
ATTRIBUTENAMES  servicecode
ATTRIBUTENAMES  groupDescription
ATTRIBUTENAMES  termType

いろんなサービスがありますね。。

$ aws pricing describe-services --output=text | grep ^SERVICES | wc -l
92
$ aws pricing describe-services --output=text | grep ^SERVICES | head -5
SERVICES        AWSBudgets
SERVICES        AWSCloudTrail
SERVICES        AWSCodeCommit
SERVICES        AWSCodeDeploy
SERVICES        AWSCodePipeline

今回目的とするサービス(EC2)の正式なサービス名を調べます。

$ aws pricing describe-services --output=text | grep -i ec2
SERVICES        AmazonEC2

これ以降は、コマンドを発行する際にサービスコードを明示することで、なるべくデータ量を減らすようにします。

AmazonEC2 サービスで使えそうな属性名の候補を調べます。

$ aws pricing describe-services --output=text --service-code AmazonEC2 | wc -l
62
$ aws pricing describe-services --output=text --service-code AmazonEC2 | \
  grep -Ei '(type|cpu|ecu|memory)'
ATTRIBUTENAMES  volumeType
ATTRIBUTENAMES  locationType
ATTRIBUTENAMES  ecu
ATTRIBUTENAMES  gpuMemory
ATTRIBUTENAMES  elasticGpuType
ATTRIBUTENAMES  memory
ATTRIBUTENAMES  vcpu
ATTRIBUTENAMES  termType
ATTRIBUTENAMES  instanceType
ATTRIBUTENAMES  usagetype

AmazonEC2 に限っても、ATTRIBUTENAME(属性名)だけで 62 個もある…。

get-attribute-values

次に "instanceType" という属性名に着目して、その属性値の候補を取得します。

$ aws pricing get-attribute-values --output=text --service-code AmazonEC2 \
  --attribute-name instanceType | wc -l
122
$ aws pricing get-attribute-values --output=text --service-code AmazonEC2 \
    --attribute-name instanceType | grep -E 't[12]'
ATTRIBUTEVALUES t1.micro
ATTRIBUTEVALUES t2.2xlarge
ATTRIBUTEVALUES t2.large
ATTRIBUTEVALUES t2.medium
ATTRIBUTEVALUES t2.micro
ATTRIBUTEVALUES t2.nano
ATTRIBUTEVALUES t2.small
ATTRIBUTEVALUES t2.xlarge

インスタンスタイプだけで 122 個…。この調子ですべての組み合わせを表示しようとすると、表のサイズが爆発するのは明白です。API サーバにも無意味に負荷をかけそうなので、最初はとりあえず t1.micro の Linux インスタンス(かつ東京リージョンのみ)に絞ってやってみています。

get-products

このサブコマンドで価格の値が取れるのですが、そのままでは使い勝手がよくありません。

$ aws pricing get-products --service-code AmazonEC2  \
  --filters Type=TERM_MATCH,Field=instanceType,Value=t1.micro \
            Type=TERM_MATCH,Field=operatingSystem,Value=Linux \
            'Type=TERM_MATCH,Field=location,Value=Asia Pacific (Tokyo)' \
  > t1-micro-linux-tokyo.txt
$ cat t1-micro-linux-tokyo.txt
{
    "PriceList": [
        "{\"product\":{\"productFamily\":\"Compute Instance\",\"attributes\":{\"memory(以下、死ぬほど長い文字列)...

jq というコマンドを通すといい感じに整形してくれるらしいのですが、どうもうまくパースしてくれません。いろいろと試してみたところ、配列の中身全体が "" で囲まれているのが問題のようです。ということで、この引用符を外してやると、うまく見えるようになりました。ついでにバックスラッシュも外します。

$ cat t1-micro-linux-tokyo.txt | \
  sed -e 's/\\//g' -e 's/"{/{/g' -e 's/}"/}/g' | \
  jq
{
  "PriceList": [
    {
      "product": {
        "productFamily": "Compute Instance",
        "attributes": {
          "memory": "0.613 GiB",
          "vcpu": "1",
          "instanceType": "t1.micro",
          "tenancy": "Shared",
          "usagetype": "APN1-BoxUsage:t1.micro",
          "locationType": "AWS Region",
          "storage": "EBS only",
          "normalizationSizeFactor": "0.5",
          "instanceFamily": "Micro instances",
          "operatingSystem": "Linux",
          "servicecode": "AmazonEC2",
          "physicalProcessor": "Variable",
          "licenseModel": "No License required",
          "ecu": "Variable",
          "currentGeneration": "No",
          "preInstalledSw": "NA",
          "networkPerformance": "Very Low",
          "location": "Asia Pacific (Tokyo)",
          "servicename": "Amazon Elastic Compute Cloud",
          "processorArchitecture": "32-bit or 64-bit",
          "operation": "RunInstances"
        },
        "sku": "ERVWZ4V3UBYH4NQH"
      },
      "serviceCode": "AmazonEC2",
      "terms": {
        "OnDemand": {
          "ERVWZ4V3UBYH4NQH.JRTCKXETXF": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.JRTCKXETXF.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "$0.026 per On Demand Linux t1.micro Instance Hour",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.JRTCKXETXF.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0260000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2017-12-01T00:00:00Z",
            "offerTermCode": "JRTCKXETXF",
            "termAttributes": {}
          }
        },
        "Reserved": {
          "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "316"
                }
              },
              "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "USD 0.0 per Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0000000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "NQ3QZPMQV9",
            "termAttributes": {
              "LeaseContractLength": "3yr",
              "OfferingClass": "standard",
              "PurchaseOption": "All Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.6QCMYABX3D": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.6QCMYABX3D.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.6QCMYABX3D.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "138"
                }
              },
              "ERVWZ4V3UBYH4NQH.6QCMYABX3D.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "USD 0.0 per Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.6QCMYABX3D.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0000000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "6QCMYABX3D",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "All Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.38NPMPTW36": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.38NPMPTW36.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.38NPMPTW36.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "100"
                }
              },
              "ERVWZ4V3UBYH4NQH.38NPMPTW36.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.38NPMPTW36.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0090000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2016-10-31T23:59:59Z",
            "offerTermCode": "38NPMPTW36",
            "termAttributes": {
              "LeaseContractLength": "3yr",
              "OfferingClass": "standard",
              "PurchaseOption": "Partial Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.HU7G6KETJZ": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "62"
                }
              },
              "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0090000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "HU7G6KETJZ",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "Partial Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.4NA7Y494T4": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.4NA7Y494T4.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.4NA7Y494T4.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0180000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2016-08-31T23:59:59Z",
            "offerTermCode": "4NA7Y494T4",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "No Upfront"
            }
          }
        }
      },
      "version": "20180131042456",
      "publicationDate": "2018-01-31T04:24:56Z"
    }
  ],
  "FormatVersion": "aws_v1"
}

返されるデータの構造がわかったので、後は必要な項目だけを抜き出して CSV で出力してやれば、Google スプレッドシートにインポートで取り込めそうです。ということで、今日はここまでです。


っと、ここまで書いてから投稿しようとしたら、AWS Price List API の使用 とかいうよさげなページがあるのに気づいたのでこれから読みます。。。

(参照)

10
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?