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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- amazon-pricing (0.1.63)
4
+ amazon-pricing (0.1.64)
5
5
  mechanize (~> 2.7.2)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -73,7 +73,7 @@ Additional Resources
73
73
  Credits
74
74
  -------
75
75
 
76
- Thanks for Amazon developers for provided Json APIs to the pricing data (albeit undocumented).
76
+ Thanks for Amazon developers for provided JSON APIs to the pricing data (albeit undocumented).
77
77
 
78
78
  Contact
79
79
  -------
@@ -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|
@@ -8,5 +8,5 @@
8
8
  # Home:: http://github.com/CloudHealth/amazon-pricing
9
9
  #++
10
10
  module AwsPricing
11
- VERSION = '0.1.63'
11
+ VERSION = '0.1.64'
12
12
  end
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.63
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-06-29 00:00:00.000000000 Z
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