amazon-pricing 0.1.63 → 0.1.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|