amazon-pricing 0.1.63 → 0.1.64
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/amazon-pricing.rb +3 -0
- data/lib/amazon-pricing/aws-price-list.rb +4 -0
- data/lib/amazon-pricing/common/ec2_common.rb +77 -0
- data/lib/amazon-pricing/ec2-di-price-list.rb +48 -0
- data/lib/amazon-pricing/ec2-price-list.rb +2 -76
- data/lib/amazon-pricing/version.rb +1 -1
- metadata +4 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -73,7 +73,7 @@ Additional Resources
|
|
73
73
|
Credits
|
74
74
|
-------
|
75
75
|
|
76
|
-
Thanks for Amazon developers for provided
|
76
|
+
Thanks for Amazon developers for provided JSON APIs to the pricing data (albeit undocumented).
|
77
77
|
|
78
78
|
Contact
|
79
79
|
-------
|
data/lib/amazon-pricing.rb
CHANGED
@@ -4,7 +4,10 @@ require 'mechanize'
|
|
4
4
|
|
5
5
|
Dir[File.join(File.dirname(__FILE__), 'amazon-pricing/definitions/*.rb')].sort.each { |lib| require lib }
|
6
6
|
|
7
|
+
require 'amazon-pricing/common/ec2_common'
|
8
|
+
|
7
9
|
require 'amazon-pricing/aws-price-list'
|
8
10
|
require 'amazon-pricing/ec2-price-list'
|
11
|
+
require 'amazon-pricing/ec2-di-price-list'
|
9
12
|
require 'amazon-pricing/rds-price-list'
|
10
13
|
require 'amazon-pricing/dynamo-db-price-list'
|
@@ -101,6 +101,10 @@ module AwsPricing
|
|
101
101
|
EBS_BASE_URL = "http://a0.awsstatic.com/pricing/1/ebs/"
|
102
102
|
RDS_BASE_URL = "http://a0.awsstatic.com/pricing/1/rds/"
|
103
103
|
|
104
|
+
DI_OD_BASE_URL = "http://a0.awsstatic.com/pricing/1/dedicated-instances/"
|
105
|
+
RESERVED_DI_BASE_URL = "http://a0.awsstatic.com/pricing/1/ec2/ri-v2/"
|
106
|
+
RESERVED_DI_PREV_GEN_BASE_URL = "http://a0.awsstatic.com/pricing/1/ec2/previous-generation/ri-v2/"
|
107
|
+
|
104
108
|
def convert_region(name)
|
105
109
|
case name
|
106
110
|
when "us-east"
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module AwsPricing
|
2
|
+
module Ec2Common
|
3
|
+
# Retrieves the EC2 on-demand instance pricing.
|
4
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
5
|
+
def fetch_ec2_instance_pricing(url, type_of_instance, operating_system)
|
6
|
+
res = PriceList.fetch_url(url)
|
7
|
+
res['config']['regions'].each do |reg|
|
8
|
+
region_name = reg['region']
|
9
|
+
region = get_region(region_name)
|
10
|
+
if region.nil?
|
11
|
+
$stderr.puts "[fetch_ec2_instance_pricing] WARNING: unable to find region #{region_name}"
|
12
|
+
next
|
13
|
+
end
|
14
|
+
# e.g. type = {"type"=>"hiCPUODI", "sizes"=>[{"size"=>"med", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"N/A"}}]}, {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}]}
|
15
|
+
reg['instanceTypes'].each do |type|
|
16
|
+
# e.g. size = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
|
17
|
+
# Amazon now can return array or hash here (hash = only 1 item)
|
18
|
+
items = type['sizes']
|
19
|
+
items = [type] if items.nil?
|
20
|
+
items.each do |size|
|
21
|
+
begin
|
22
|
+
api_name, name = Ec2InstanceType.get_name(type["type"], size["size"], type_of_instance != :ondemand)
|
23
|
+
instance_type = region.add_or_update_ec2_instance_type(api_name, name)
|
24
|
+
instance_type.update_pricing(operating_system, type_of_instance, size)
|
25
|
+
rescue UnknownTypeError
|
26
|
+
$stderr.puts "[fetch_ec2_instance_pricing] WARNING: encountered #{$!.message}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# With v2 of RIs they have an entirely new format that needs to be parsed
|
34
|
+
def fetch_ec2_instance_pricing_ri_v2(url, operating_system)
|
35
|
+
res = PriceList.fetch_url(url)
|
36
|
+
res['config']['regions'].each do |reg|
|
37
|
+
region_name = reg['region']
|
38
|
+
region = get_region(region_name)
|
39
|
+
if region.nil?
|
40
|
+
$stderr.puts "[fetch_ec2_instance_pricing_ri_v2] WARNING: unable to find region #{region_name}"
|
41
|
+
next
|
42
|
+
end
|
43
|
+
reg['instanceTypes'].each do |type|
|
44
|
+
api_name = type["type"]
|
45
|
+
instance_type = region.get_instance_type(api_name)
|
46
|
+
if instance_type.nil?
|
47
|
+
$stderr.puts "[fetch_ec2_instance_pricing_ri_v2] WARNING: new reserved instances not found for #{api_name} in #{region_name}"
|
48
|
+
next
|
49
|
+
end
|
50
|
+
|
51
|
+
type["terms"].each do |term|
|
52
|
+
term["purchaseOptions"].each do |option|
|
53
|
+
case option["purchaseOption"]
|
54
|
+
when "noUpfront"
|
55
|
+
reservation_type = :noupfront
|
56
|
+
when "allUpfront"
|
57
|
+
reservation_type = :allupfront
|
58
|
+
when "partialUpfront"
|
59
|
+
reservation_type = :partialupfront
|
60
|
+
end
|
61
|
+
|
62
|
+
duration = term["term"]
|
63
|
+
prices = option["valueColumns"]
|
64
|
+
upfront = prices.select{|i| i["name"] == "upfront"}.first
|
65
|
+
price = upfront["prices"]["USD"]
|
66
|
+
instance_type.update_pricing_new(operating_system, reservation_type, price.to_f, duration, true) unless reservation_type == :noupfront || price == "N/A"
|
67
|
+
hourly = prices.select{|i| i["name"] == "monthlyStar"}.first
|
68
|
+
price = hourly["prices"]["USD"]
|
69
|
+
instance_type.update_pricing_new(operating_system, reservation_type, price.to_f * 12 / 365 / 24, duration, false) unless reservation_type == :allupfront || price == "N/A"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module AwsPricing
|
2
|
+
class Ec2DiPriceList < PriceList
|
3
|
+
include AwsPricing::Ec2Common
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
InstanceType.populate_lookups
|
8
|
+
get_ec2_di_od_pricing
|
9
|
+
get_ec2_reserved_di_pricing
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
@@OS_TYPES = [
|
15
|
+
['linux', 'linux-unix'],
|
16
|
+
['rhel', 'red-hat-enterprise-linux'],
|
17
|
+
['sles', 'suse-linux'],
|
18
|
+
['mswin', 'windows'],
|
19
|
+
['mswinSQL', 'windows-with-sql-server-standard'],
|
20
|
+
['mswinSQLWeb', 'windows-with-sql-server-web'],
|
21
|
+
['mswinSQLEnterprise', 'windows-with-sql-server-enterprise']
|
22
|
+
]
|
23
|
+
|
24
|
+
OS_INDEX = 0
|
25
|
+
OD_OS_INDEX = 0
|
26
|
+
RI_OS_INDEX = 1
|
27
|
+
|
28
|
+
def get_ec2_di_od_pricing
|
29
|
+
for_each_os_and_name(OS_INDEX, OD_OS_INDEX) do |os, os_name|
|
30
|
+
fetch_ec2_instance_pricing(DI_OD_BASE_URL + "di-#{os_name}-od.min.js", :ondemand, os.to_sym)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_ec2_reserved_di_pricing
|
35
|
+
for_each_os_and_name(OS_INDEX, RI_OS_INDEX) do |os, os_name|
|
36
|
+
fetch_ec2_instance_pricing_ri_v2(RESERVED_DI_BASE_URL + "#{os_name}-dedicated.min.js", os.to_sym)
|
37
|
+
next if os == 'mswinSQLEnterprise' # No SQL Enterprise for previous generation
|
38
|
+
fetch_ec2_instance_pricing_ri_v2(RESERVED_DI_PREV_GEN_BASE_URL + "#{os_name}-dedicated.min.js", os.to_sym)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def for_each_os_and_name os_index, os_name_index
|
43
|
+
@@OS_TYPES.inject({}) {|h,o| h[o[os_index]]=o[os_name_index];h}.each do |os, os_name|
|
44
|
+
yield os, os_name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module AwsPricing
|
2
2
|
class Ec2PriceList < PriceList
|
3
|
-
|
3
|
+
include AwsPricing::Ec2Common
|
4
|
+
|
4
5
|
def initialize
|
5
6
|
super
|
6
7
|
InstanceType.populate_lookups
|
@@ -56,81 +57,6 @@ module AwsPricing
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
# Retrieves the EC2 on-demand instance pricing.
|
60
|
-
# type_of_instance = :ondemand, :light, :medium, :heavy
|
61
|
-
def fetch_ec2_instance_pricing(url, type_of_instance, operating_system)
|
62
|
-
res = PriceList.fetch_url(url)
|
63
|
-
res['config']['regions'].each do |reg|
|
64
|
-
region_name = reg['region']
|
65
|
-
region = get_region(region_name)
|
66
|
-
if region.nil?
|
67
|
-
$stderr.puts "[fetch_ec2_instance_pricing] WARNING: unable to find region #{region_name}"
|
68
|
-
next
|
69
|
-
end
|
70
|
-
# e.g. type = {"type"=>"hiCPUODI", "sizes"=>[{"size"=>"med", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"N/A"}}]}, {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}]}
|
71
|
-
reg['instanceTypes'].each do |type|
|
72
|
-
# e.g. size = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
|
73
|
-
# Amazon now can return array or hash here (hash = only 1 item)
|
74
|
-
items = type['sizes']
|
75
|
-
items = [type] if items.nil?
|
76
|
-
items.each do |size|
|
77
|
-
begin
|
78
|
-
api_name, name = Ec2InstanceType.get_name(type["type"], size["size"], type_of_instance != :ondemand)
|
79
|
-
instance_type = region.add_or_update_ec2_instance_type(api_name, name)
|
80
|
-
instance_type.update_pricing(operating_system, type_of_instance, size)
|
81
|
-
rescue UnknownTypeError
|
82
|
-
$stderr.puts "[fetch_ec2_instance_pricing] WARNING: encountered #{$!.message}"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# With v2 of RIs they have an entirely new format that needs to be parsed
|
90
|
-
def fetch_ec2_instance_pricing_ri_v2(url, operating_system)
|
91
|
-
res = PriceList.fetch_url(url)
|
92
|
-
res['config']['regions'].each do |reg|
|
93
|
-
region_name = reg['region']
|
94
|
-
region = get_region(region_name)
|
95
|
-
if region.nil?
|
96
|
-
$stderr.puts "[fetch_ec2_instance_pricing_ri_v2] WARNING: unable to find region #{region_name}"
|
97
|
-
next
|
98
|
-
end
|
99
|
-
reg['instanceTypes'].each do |type|
|
100
|
-
api_name = type["type"]
|
101
|
-
instance_type = region.get_instance_type(api_name)
|
102
|
-
if instance_type.nil?
|
103
|
-
$stderr.puts "[fetch_ec2_instance_pricing_ri_v2] WARNING: new reserved instances not found for #{api_name} in #{region_name}"
|
104
|
-
next
|
105
|
-
end
|
106
|
-
|
107
|
-
type["terms"].each do |term|
|
108
|
-
term["purchaseOptions"].each do |option|
|
109
|
-
case option["purchaseOption"]
|
110
|
-
when "noUpfront"
|
111
|
-
reservation_type = :noupfront
|
112
|
-
when "allUpfront"
|
113
|
-
reservation_type = :allupfront
|
114
|
-
when "partialUpfront"
|
115
|
-
reservation_type = :partialupfront
|
116
|
-
end
|
117
|
-
|
118
|
-
duration = term["term"]
|
119
|
-
prices = option["valueColumns"]
|
120
|
-
upfront = prices.select{|i| i["name"] == "upfront"}.first
|
121
|
-
price = upfront["prices"]["USD"]
|
122
|
-
instance_type.update_pricing_new(operating_system, reservation_type, price.to_f, duration, true) unless reservation_type == :noupfront || price == "N/A"
|
123
|
-
hourly = prices.select{|i| i["name"] == "monthlyStar"}.first
|
124
|
-
price = hourly["prices"]["USD"]
|
125
|
-
instance_type.update_pricing_new(operating_system, reservation_type, price.to_f * 12 / 365 / 24, duration, false) unless reservation_type == :allupfront || price == "N/A"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
|
134
60
|
def fetch_ec2_ebs_pricing
|
135
61
|
res = PriceList.fetch_url(EBS_BASE_URL + "pricing-ebs.min.js")
|
136
62
|
res["config"]["regions"].each do |ebs_types|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amazon-pricing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.64
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-08-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mechanize
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/.DS_Store
|
52
52
|
- lib/amazon-pricing.rb
|
53
53
|
- lib/amazon-pricing/aws-price-list.rb
|
54
|
+
- lib/amazon-pricing/common/ec2_common.rb
|
54
55
|
- lib/amazon-pricing/definitions/category-type.rb
|
55
56
|
- lib/amazon-pricing/definitions/database-type.rb
|
56
57
|
- lib/amazon-pricing/definitions/ebs-price.rb
|
@@ -60,6 +61,7 @@ files:
|
|
60
61
|
- lib/amazon-pricing/definitions/rds-instance-type.rb
|
61
62
|
- lib/amazon-pricing/definitions/region.rb
|
62
63
|
- lib/amazon-pricing/dynamo-db-price-list.rb
|
64
|
+
- lib/amazon-pricing/ec2-di-price-list.rb
|
63
65
|
- lib/amazon-pricing/ec2-price-list.rb
|
64
66
|
- lib/amazon-pricing/helpers/instance-type.rb
|
65
67
|
- lib/amazon-pricing/rds-price-list.rb
|