現在のインスタンス料金を取得する script: Redshift 編

今までリザーブド購入のために料金をいちいち AWS の料金ページまでアクセスして料金を確認してたんだけど AWS Price List API (http://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/price-changes.html) を利用して現在の料金の取得を自動化したかったので現在のインスタンス料金を取得する script を書いてみた

![1111111料金_-_Amazon_Redshift___AWS.png](https://qiita-image-store.s3.amazonaws.com/0/13148/e66692c6-8c25-5eea-4942-45333e48ae66.png)

とりあえずインスタンスの種類が少なくて楽そうだったので今回は Redshift のものを対象に取得


前提条件として

- Tokyo リージョンだけわかればよかったので Tokyo リージョンだけに絞ってる
- 時間あたりの料金がわかる
- リザーブドインスタンスの時の料金がわかる
- インスタンスのスペックがわかる

あたりがわかるように書いた


とりあえず動いたものを貼ってるのでコードはきれいじゃない

```ruby:redshift.rb
require 'json'
require 'bigdecimal'

results = {}
json_data = open(ARGV[0]) {|io| JSON.load(io) }

# product 情報を取得
json_data['products'].keys.each do |skuNo|
	product = json_data['products'][skuNo]

	if (product['productFamily'] == 'Compute Instance' and
		  product['attributes']['locationType'] == 'AWS Region' and
		  product['attributes']['location'] == 'Asia Pacific (Tokyo)')

		results[product['sku']] = {
			sku: product['sku'],
			location: product['attributes']['location'],
			instanceType: product['attributes']['instanceType'],
			instanceFamily: product['attributes']['instanceType'].split('.')[0],
			vcpu: product['attributes']['vcpu'],
			memory: product['attributes']['memory'],
			storage: product['attributes']['storage'],
			io: product['attributes']['io'],
			ecu: product['attributes']['ecu'],
			currentGeneration: product['attributes']['currentGeneration'],
			price_unit: 'USD'
		}

	end
end


# price

## on demand
json_data['terms']['OnDemand'].keys.each do |skuNo|
	if (results[skuNo])
		results[skuNo][:price_per_hour] = Proc.new {
			skuTerm = json_data['terms']['OnDemand'][skuNo][json_data['terms']['OnDemand'][skuNo].keys[0]]
			priceInfo = skuTerm['priceDimensions'][skuTerm['priceDimensions'].keys[0]]
			sprintf('%.3f', BigDecimal(priceInfo['pricePerUnit']['USD']).floor(2).to_f.to_s)
		}.call
		results[skuNo][:price_per_day] = sprintf('%.3f', (BigDecimal(results[skuNo][:price_per_hour]) * BigDecimal("24")).floor(2).to_f.to_s)
		results[skuNo][:price_per_month] = sprintf('%.3f', (BigDecimal(results[skuNo][:price_per_day]) * BigDecimal("30")).floor(2).to_f.to_s)
	end
end

## reserved 
json_data['terms']['Reserved'].keys.each do |skuNo|
	if (results[skuNo])

		plans = json_data['terms']['Reserved'][skuNo].values.select do |plan|
			plan['termAttributes']['PurchaseOption'] == "All Upfront" # "All Upfront" のものだけ取得したい
		end

		results[skuNo][:price_reserved_1year_purchased_all_upfront] = sprintf('%.3f', plans.find { |plan|
			plan['termAttributes']['LeaseContractLength'] == '1yr'
		}['priceDimensions'].values.find {|priceDimension|
			priceDimension['description'] == "Upfront Fee"
		}['pricePerUnit']['USD'])

		results[skuNo][:price_reserved_3year_purchased_all_upfront] = sprintf('%.3f', plans.find { |plan|
			plan['termAttributes']['LeaseContractLength'] == '3yr'
		}['priceDimensions'].values.find {|priceDimension|
			priceDimension['description'] == "Upfront Fee"
		}['pricePerUnit']['USD'])

	end
end


# sort
sorted_result = {}
results.values.each do |row|
	sorted_result[row[:currentGeneration]] ||= {}
	sorted_result[row[:currentGeneration]][row[:instanceFamily]] ||= []
	sorted_result[row[:currentGeneration]][row[:instanceFamily]].push row
end

results = []
['Yes', 'No'].each do |currentGeneration| # 現行世代のものから並べる
	sorted_result[currentGeneration].keys.sort.each do |instanceFamily| # インスタンスファミリー毎に並べる
		results.concat sorted_result[currentGeneration][instanceFamily].sort_by { |row| row[:price_per_hour] }
	end
end

p results.to_json
```

上記を保存して以下のように実行する

```shell-session
curl https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonRedshift/current/index.json > price-AmazonRedshift.json
ruby redshift.rb price-AmazonRedshift.json | sed -e s/^\"// | sed -e s/\"$// | sed -e 's/\\"/"/g' | jq .
```

以下のような結果が取れる

```json
[
  {
    "sku": "6REDMMEE7FXXH5Y6",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "dc1.large",
    "instanceFamily": "dc1",
    "vcpu": "2",
    "memory": "15 GiB",
    "storage": "0.16TB SSD",
    "io": "0.20 GB/s",
    "ecu": "7",
    "currentGeneration": "Yes",
    "price_unit": "USD",
    "price_per_hour": "0.310",
    "price_per_day": "7.440",
    "price_per_month": "223.200",
    "price_reserved_1year_purchased_all_upfront": "1645.000",
    "price_reserved_3year_purchased_all_upfront": "2885.000"
  },
  {
    "sku": "CNP4R2XZ8N7RJJA8",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "dc1.8xlarge",
    "instanceFamily": "dc1",
    "vcpu": "32",
    "memory": "244 GiB",
    "storage": "2.56TB SSD",
    "io": "3.70 GB/s",
    "ecu": "104",
    "currentGeneration": "Yes",
    "price_unit": "USD",
    "price_per_hour": "6.090",
    "price_per_day": "146.160",
    "price_per_month": "4384.800",
    "price_reserved_1year_purchased_all_upfront": "33180.000",
    "price_reserved_3year_purchased_all_upfront": "46160.000"
  },
  {
    "sku": "YWHTRJBA2KAFS857",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "ds2.xlarge",
    "instanceFamily": "ds2",
    "vcpu": "4",
    "memory": "31 GiB",
    "storage": "2TB HDD",
    "io": "0.40 GB/s",
    "ecu": "14",
    "currentGeneration": "Yes",
    "price_unit": "USD",
    "price_per_hour": "1.190",
    "price_per_day": "28.560",
    "price_per_month": "856.800",
    "price_reserved_1year_purchased_all_upfront": "6125.000",
    "price_reserved_3year_purchased_all_upfront": "7585.000"
  },
  {
    "sku": "Q8X9U7UKTJV2VGY8",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "ds2.8xlarge",
    "instanceFamily": "ds2",
    "vcpu": "36",
    "memory": "244 GiB",
    "storage": "16TB HDD",
    "io": "3.30 GB/s",
    "ecu": "116",
    "currentGeneration": "Yes",
    "price_unit": "USD",
    "price_per_hour": "9.520",
    "price_per_day": "228.480",
    "price_per_month": "6854.400",
    "price_reserved_1year_purchased_all_upfront": "49020.000",
    "price_reserved_3year_purchased_all_upfront": "60630.000"
  },
  {
    "sku": "ZURKE2HZ3JZC6F2U",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "ds1.xlarge",
    "instanceFamily": "ds1",
    "vcpu": "2",
    "memory": "15 GiB",
    "storage": "2TB HDD",
    "io": "0.30 GB/s",
    "ecu": "4.4",
    "currentGeneration": "No",
    "price_unit": "USD",
    "price_per_hour": "1.190",
    "price_per_day": "28.560",
    "price_per_month": "856.800",
    "price_reserved_1year_purchased_all_upfront": "6125.000",
    "price_reserved_3year_purchased_all_upfront": "7585.000"
  },
  {
    "sku": "PDMPNVN5SPA5HWHH",
    "location": "Asia Pacific (Tokyo)",
    "instanceType": "ds1.8xlarge",
    "instanceFamily": "ds1",
    "vcpu": "16",
    "memory": "120 GiB",
    "storage": "16TB HDD",
    "io": "2.40 GB/s",
    "ecu": "35",
    "currentGeneration": "No",
    "price_unit": "USD",
    "price_per_hour": "9.520",
    "price_per_day": "228.480",
    "price_per_month": "6854.400",
    "price_reserved_1year_purchased_all_upfront": "49020.000",
    "price_reserved_3year_purchased_all_upfront": "60630.000"
  }
]
```