amazon-pricing 0.1.9 → 0.1.10

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/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake/testtask'
3
3
 
4
4
  $: << File.expand_path(File.dirname(__FILE__), 'lib')
5
5
 
6
- require 'amazon-pricing/version'
6
+ require File.join('amazon-pricing','version')
7
7
 
8
8
  Rake::TestTask.new(:test) do |test|
9
9
  test.libs << 'lib' << 'test'
@@ -32,10 +32,10 @@ task :test do
32
32
  end
33
33
 
34
34
  desc "Prints current EC2 pricing in CSV format"
35
- task :print_price_list do
36
- require 'lib/amazon-pricing'
37
- pricing = AwsPricing::PriceList.new
38
- line = "Region,Instance Type,API Name,Memory (MB),Disk (MB),Compute Units, Virtual Cores,OD Linux PPH,OD Windows PPH,OD RHEL PPH,OD SLES PPH,OD MsWinSQL PPH,OD MsWinSQLWeb PPH,"
35
+ task :print_ec2_price_list do
36
+ require 'amazon-pricing'
37
+ pricing = AwsPricing::Ec2PriceList.new
38
+ line = "Region,Instance Type,API Name,Memory (MB),Disk (GB),Compute Units,Virtual Cores,Disk Type,OD Linux PPH,OD Windows PPH,OD RHEL PPH,OD SLES PPH,OD MsWinSQL PPH,OD MsWinSQLWeb PPH,"
39
39
  [:year1, :year3].each do |term|
40
40
  [:light, :medium, :heavy].each do |res_type|
41
41
  [:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb].each do |os|
@@ -45,8 +45,8 @@ task :print_price_list do
45
45
  end
46
46
  puts line.chop
47
47
  pricing.regions.each do |region|
48
- region.instance_types.each do |t|
49
- line = "#{region.name},#{t.name},#{t.api_name},#{t.memory_in_mb},#{t.disk_in_mb},#{t.compute_units},#{t.virtual_cores},"
48
+ region.ec2_instance_types.each do |t|
49
+ line = "#{region.name},#{t.name},#{t.api_name},#{t.memory_in_mb},#{t.disk_in_gb},#{t.compute_units},#{t.virtual_cores},#{t.disk_type},"
50
50
  [:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb].each do |os|
51
51
  line += "#{t.price_per_hour(os, :ondemand)},"
52
52
  end
@@ -62,4 +62,72 @@ task :print_price_list do
62
62
  end
63
63
  end
64
64
 
65
+
66
+ desc "Prints current RDS pricing in CSV format"
67
+ task :print_rds_price_list do
68
+ require 'amazon-pricing'
69
+ pricing = AwsPricing::RdsPriceList.new
70
+
71
+ line = "Region,Instance Type,API Name,Memory (MB),Disk (GB),Compute Units,Virtual Cores,Disk Type,"
72
+
73
+
74
+ [:mysql, :oracle, :oracle_byol, :sqlserver, :sqlserver_express, :sqlserver_web, :sqlserver_byol].each do |db|
75
+ if [:mysql, :oracle, :oracle_byol].include? db
76
+ [:standard,:multiAZ].each do |deploy_type|
77
+ line += "OD #{db} #{deploy_type} PPH,"
78
+ end
79
+ else
80
+ line += "OD #{db} PPH,"
81
+ end
82
+ end
83
+
84
+
85
+ [:year1, :year3].each do |term|
86
+ [:light, :medium, :heavy].each do |res_type|
87
+ [:mysql, :oracle, :oracle_byol, :sqlserver, :sqlserver_express, :sqlserver_web, :sqlserver_byol].each do |db|
88
+ if [:mysql, :oracle, :oracle_byol].include? db
89
+ [:standard,:multiAZ].each do |deploy_type|
90
+ line += "#{term} #{res_type} #{deploy_type} #{db} Prepay,#{term} #{res_type} #{deploy_type} #{db} PPH,"
91
+ end
92
+ else
93
+ line += "#{term} #{res_type} #{db} Prepay,#{term} #{res_type} #{db} PPH,"
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ puts line.chop
101
+
102
+ pricing.regions.each do |region|
103
+ region.rds_instance_types.each do |t|
104
+ line = "#{region.name},#{t.name},#{t.api_name},#{t.memory_in_mb},#{t.disk_in_gb},#{t.compute_units},#{t.virtual_cores},#{t.disk_type},"
105
+ [:mysql, :oracle, :oracle_byol, :sqlserver, :sqlserver_express, :sqlserver_web, :sqlserver_byol].each do |db|
106
+ if [:mysql, :oracle, :oracle_byol].include? db
107
+ [:standard,:multiAZ].each do |deploy_type|
108
+ line += "#{t.price_per_hour(db, :ondemand, nil, deploy_type == :multiAZ)},"
109
+ end
110
+ else
111
+ line += "#{t.price_per_hour(db, :ondemand, nil, false)},"
112
+ end
113
+ end
114
+
115
+ [:year1, :year3].each do |term|
116
+ [:light, :medium, :heavy].each do |res_type|
117
+ [:mysql, :oracle, :oracle_byol, :sqlserver, :sqlserver_express, :sqlserver_web, :sqlserver_byol].each do |db|
118
+ if [:mysql, :oracle, :oracle_byol].include? db
119
+ [:standard,:multiAZ].each do |deploy_type|
120
+ line += "#{t.prepay(db, res_type, term, deploy_type == :multiAZ)},#{t.price_per_hour(db, res_type, term, deploy_type == :multiAZ)},"
121
+ end
122
+ else
123
+ line += "#{t.prepay(db, res_type, term, false)},#{t.price_per_hour(db, res_type, term, false)},"
124
+ end
125
+ end
126
+ end
127
+ end
128
+ puts line.chop
129
+ end
130
+ end
131
+ end
132
+
65
133
  task :default => [:test]
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
2
+ $:.push File.expand_path(File.join("..","lib"), __FILE__)
3
3
  require "amazon-pricing/version"
4
4
 
5
5
  Gem::Specification.new do |s|
@@ -18,16 +18,9 @@ module AwsPricing
18
18
  # Upon instantiating a PriceList object, all the corresponding pricing
19
19
  # information will be retrieved from Amazon via currently undocumented
20
20
  # json APIs.
21
- class PriceList
21
+ class PriceList
22
22
  attr_accessor :regions
23
23
 
24
- def initialize
25
- @_regions = {}
26
- get_ec2_on_demand_instance_pricing
27
- get_ec2_reserved_instance_pricing
28
- fetch_ec2_ebs_pricing
29
- end
30
-
31
24
  def get_region(name)
32
25
  @_regions[@@Region_Lookup[name] || name]
33
26
  end
@@ -42,6 +35,12 @@ module AwsPricing
42
35
  region.get_instance_type(api_name)
43
36
  end
44
37
 
38
+ def fetch_url(url)
39
+ uri = URI.parse(url)
40
+ page = Net::HTTP.get_response(uri)
41
+ JSON.parse(page.body)
42
+ end
43
+
45
44
  protected
46
45
 
47
46
  attr_accessor :_regions
@@ -59,6 +58,33 @@ module AwsPricing
59
58
  region
60
59
  end
61
60
 
61
+ EC2_BASE_URL = "http://aws.amazon.com/ec2/pricing/"
62
+ RDS_BASE_URL = "http://aws.amazon.com/rds/pricing/"
63
+
64
+ # Lookup allows us to map to AWS API region names
65
+ @@Region_Lookup = {
66
+ 'us-east-1' => 'us-east',
67
+ 'us-west-1' => 'us-west',
68
+ 'us-west-2' => 'us-west-2',
69
+ 'eu-west-1' => 'eu-ireland',
70
+ 'ap-southeast-1' => 'apac-sin',
71
+ 'ap-southeast-2' => 'apac-syd',
72
+ 'ap-northeast-1' => 'apac-tokyo',
73
+ 'sa-east-1' => 'sa-east-1'
74
+ }
75
+
76
+ end
77
+
78
+
79
+ class Ec2PriceList < PriceList
80
+
81
+ def initialize
82
+ @_regions = {}
83
+ get_ec2_on_demand_instance_pricing
84
+ get_ec2_reserved_instance_pricing
85
+ fetch_ec2_ebs_pricing
86
+ end
87
+
62
88
  protected
63
89
 
64
90
  @@OS_TYPES = [:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb]
@@ -90,9 +116,9 @@ module AwsPricing
90
116
  # e.g. size = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
91
117
  type['sizes'].each do |size|
92
118
  begin
93
- api_name, name = InstanceType.get_name(type["type"], size["size"], type_of_instance != :ondemand)
94
-
95
- region.add_or_update_instance_type(api_name, name, operating_system, type_of_instance, size)
119
+ api_name, name = Ec2InstanceType.get_name(type["type"], size["size"], type_of_instance != :ondemand)
120
+
121
+ region.add_or_update_ec2_instance_type(api_name, name, operating_system, type_of_instance, size)
96
122
  rescue UnknownTypeError
97
123
  $stderr.puts "WARNING: encountered #{$!.message}"
98
124
  end
@@ -109,24 +135,118 @@ module AwsPricing
109
135
  end
110
136
  end
111
137
 
112
- def fetch_url(url)
113
- uri = URI.parse(url)
114
- page = Net::HTTP.get_response(uri)
115
- JSON.parse(page.body)
138
+ end
139
+
140
+
141
+
142
+ class RdsPriceList < PriceList
143
+
144
+ def initialize
145
+ @_regions = {}
146
+ get_rds_on_demand_instance_pricing
147
+ get_rds_reserved_instance_pricing
116
148
  end
117
149
 
118
- EC2_BASE_URL = "http://aws.amazon.com/ec2/pricing/"
150
+ protected
119
151
 
120
- # Lookup allows us to map to AWS API region names
121
- @@Region_Lookup = {
122
- 'us-east-1' => 'us-east',
123
- 'us-west-1' => 'us-west',
124
- 'us-west-2' => 'us-west-2',
125
- 'eu-west-1' => 'eu-ireland',
126
- 'ap-southeast-1' => 'apac-sin',
127
- 'ap-southeast-2' => 'apac-syd',
128
- 'ap-northeast-1' => 'apac-tokyo',
129
- 'sa-east-1' => 'sa-east-1'
130
- }
152
+ @@DB_TYPE = [:mysql, :oracle, :sqlserver]
153
+ @@RES_TYPES = [:light, :medium, :heavy]
154
+
155
+ @@OD_DB_DEPLOY_TYPE = {
156
+ :mysql=> {:mysql=>["standard","multiAZ"]},
157
+ :oracle=> {:oracle=>["li-standard","li-multiAZ"], :oracle_byol=>["byol-standard","byol-multiAZ"]},
158
+ :sqlserver=> {:sqlserver=>["li-se"], :sqlserver_express=>["li-ex"], :sqlserver_web=>["li-web"], :sqlserver_byol=>["byol"]}
159
+ }
160
+
161
+
162
+ @@RESERVED_DB_DEPLOY_TYPE = {
163
+ :oracle=> {:oracle=>"li", :oracle_byol=>"byol"},
164
+ :sqlserver=> {:sqlserver=>"li-se", :sqlserver_express=>"li-ex", :sqlserver_web=>"li-web", :sqlserver_byol=>"byol"}
165
+ }
166
+
167
+
168
+ def is_multi_az?(type)
169
+ return true if type.match("multiAZ")
170
+ false
171
+ end
172
+
173
+ def get_rds_on_demand_instance_pricing
174
+ @@DB_TYPE.each do |db|
175
+ @@OD_DB_DEPLOY_TYPE[db].each {|db_type, db_instances|
176
+ db_instances.each do |dp_type|
177
+ if db == :mysql or db == :oracle
178
+ fetch_on_demand_rds_instance_pricing(RDS_BASE_URL+"#{db}/pricing-#{dp_type}-deployments.json",:ondemand, db_type)
179
+ elsif db == :sqlserver
180
+ fetch_on_demand_rds_instance_pricing(RDS_BASE_URL+"#{db}/sqlserver-#{dp_type}-ondemand.json",:ondemand, db_type)
181
+ end
182
+ end
183
+ }
184
+ end
185
+ end
186
+
187
+ def get_rds_reserved_instance_pricing
188
+ @@DB_TYPE.each do |db|
189
+ if db == :mysql
190
+ @@RES_TYPES.each do |res_type|
191
+ fetch_reserved_rds_instance_pricing(RDS_BASE_URL+"#{db}/pricing-#{res_type}-utilization-reserved-instances.json", res_type, db)
192
+ end
193
+ else
194
+ @@RESERVED_DB_DEPLOY_TYPE[db].each {|db_type, db_instance|
195
+ @@RES_TYPES.each do |res_type|
196
+ fetch_reserved_rds_instance_pricing(RDS_BASE_URL+"#{db}/pricing-#{db_instance}-#{res_type}-utilization-reserved-instances.json", res_type, db_type) if db == :oracle
197
+ fetch_reserved_rds_instance_pricing(RDS_BASE_URL+"#{db}/sqlserver-#{db_instance}-#{res_type}-ri.json", res_type, db_type) if db == :sqlserver
198
+ end
199
+ }
200
+ end
201
+ end
202
+ end
203
+
204
+ def fetch_on_demand_rds_instance_pricing(url, type_of_rds_instance, db_type)
205
+ res = fetch_url(url)
206
+ res['config']['regions'].each do |reg|
207
+ region_name = reg['region']
208
+ region = find_or_create_region(region_name)
209
+ reg['types'].each do |type|
210
+ type['tiers'].each do |tier|
211
+ begin
212
+ #
213
+ # this is special case URL, it is oracle - multiAZ type of deployment but it doesn't have mutliAZ attributes in json.
214
+ if url == "http://aws.amazon.com/rds/pricing/oracle/pricing-li-multiAZ-deployments.json"
215
+ isMultiAz = true
216
+ else
217
+ isMultiAz = is_multi_az? type["name"]
218
+ end
219
+ api_name, name = RdsInstanceType.get_name(type["name"], tier["name"], type_of_rds_instance != :ondemand)
220
+
221
+ region.add_or_update_rds_instance_type(api_name, name, db_type, type_of_rds_instance, tier, isMultiAz)
222
+ rescue UnknownTypeError
223
+ $stderr.puts "WARNING: encountered #{$!.message}"
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ def fetch_reserved_rds_instance_pricing(url, type_of_rds_instance, db_type)
231
+ res = fetch_url(url)
232
+ res['config']['regions'].each do |reg|
233
+ region_name = reg['region']
234
+ region = find_or_create_region(region_name)
235
+ reg['instanceTypes'].each do |type|
236
+ type['tiers'].each do |tier|
237
+ begin
238
+ isMultiAz = is_multi_az? type["type"]
239
+ api_name, name = RdsInstanceType.get_name(type["type"], tier["size"], true)
240
+
241
+ region.add_or_update_rds_instance_type(api_name, name, db_type, type_of_rds_instance, tier, isMultiAz)
242
+ rescue UnknownTypeError
243
+ $stderr.puts "WARNING: encountered #{$!.message}"
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
131
249
  end
250
+
251
+
132
252
  end
@@ -0,0 +1,154 @@
1
+ #--
2
+ # Amazon Web Services Pricing Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-pricing
5
+ # Author:: Joe Kinsella (mailto:joe.kinsella@gmail.com)
6
+ # Copyright:: Copyright (c) 2011-2013 CloudHealth
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/CloudHealth/amazon-pricing
9
+ #++
10
+ module AwsPricing
11
+
12
+ class CategoryType
13
+ attr_accessor :instance_type, :name,
14
+ :ondemand_price_per_hour, :light_price_per_hour_1_year, :medium_price_per_hour_1_year, :heavy_price_per_hour_1_year,
15
+ :light_price_per_hour_3_year, :medium_price_per_hour_3_year, :heavy_price_per_hour_3_year,
16
+ :light_prepay_1_year, :light_prepay_3_year, :medium_prepay_1_year, :medium_prepay_3_year, :heavy_prepay_1_year, :heavy_prepay_3_year
17
+
18
+
19
+ def initialize(instance_type, name)
20
+ @instance_type = instance_type
21
+ @name = name
22
+ end
23
+
24
+ # Returns whether an instance_type is available.
25
+ # type_of_instance = :ondemand, :light, :medium, :heavy
26
+ def available?(type_of_instance = :ondemand)
27
+ not price_per_hour(type_of_instance).nil?
28
+ end
29
+
30
+ # type_of_instance = :ondemand, :light, :medium, :heavy
31
+ # term = :year_1, :year_3, nil
32
+ def prepay(type_of_instance = :ondemand, term = nil)
33
+ case type_of_instance
34
+ when :ondemand
35
+ 0
36
+ when :light
37
+ if term == :year1
38
+ @light_prepay_1_year
39
+ elsif term == :year3
40
+ @light_prepay_3_year
41
+ end
42
+ when :medium
43
+ if term == :year1
44
+ @medium_prepay_1_year
45
+ elsif term == :year3
46
+ @medium_prepay_3_year
47
+ end
48
+ when :heavy
49
+ if term == :year1
50
+ @heavy_prepay_1_year
51
+ elsif term == :year3
52
+ @heavy_prepay_3_year
53
+ end
54
+ end
55
+ end
56
+
57
+ # type_of_instance = :ondemand, :light, :medium, :heavy
58
+ # term = :year_1, :year_3, nil
59
+ def set_prepay(type_of_instance, term, price)
60
+ case type_of_instance
61
+ when :light
62
+ if term == :year1
63
+ @light_prepay_1_year = price
64
+ elsif term == :year3
65
+ @light_prepay_3_year = price
66
+ end
67
+ when :medium
68
+ if term == :year1
69
+ @medium_prepay_1_year = price
70
+ elsif term == :year3
71
+ @medium_prepay_3_year = price
72
+ end
73
+ when :heavy
74
+ if term == :year1
75
+ @heavy_prepay_1_year = price
76
+ elsif term == :year3
77
+ @heavy_prepay_3_year = price
78
+ end
79
+ end
80
+ end
81
+
82
+ # type_of_instance = :ondemand, :light, :medium, :heavy
83
+ # term = :year_1, :year_3, nil
84
+ def price_per_hour(type_of_instance = :ondemand, term = nil)
85
+ case type_of_instance
86
+ when :ondemand
87
+ @ondemand_price_per_hour
88
+ when :light
89
+ if term == :year1
90
+ @light_price_per_hour_1_year
91
+ elsif term == :year3
92
+ @light_price_per_hour_3_year
93
+ end
94
+ when :medium
95
+ if term == :year1
96
+ @medium_price_per_hour_1_year
97
+ elsif term == :year3
98
+ @medium_price_per_hour_3_year
99
+ end
100
+ when :heavy
101
+ if term == :year1
102
+ @heavy_price_per_hour_1_year
103
+ elsif term == :year3
104
+ @heavy_price_per_hour_3_year
105
+ end
106
+ end
107
+ end
108
+
109
+ # type_of_instance = :ondemand, :light, :medium, :heavy
110
+ # term = :year_1, :year_3, nil
111
+ def set_price_per_hour(type_of_instance, term, price_per_hour)
112
+ case type_of_instance
113
+ when :ondemand
114
+ @ondemand_price_per_hour = price_per_hour
115
+ when :light
116
+ if term == :year1
117
+ @light_price_per_hour_1_year = price_per_hour
118
+ elsif term == :year3
119
+ @light_price_per_hour_3_year = price_per_hour
120
+ end
121
+ when :medium
122
+ if term == :year1
123
+ @medium_price_per_hour_1_year = price_per_hour
124
+ elsif term == :year3
125
+ @medium_price_per_hour_3_year = price_per_hour
126
+ end
127
+ when :heavy
128
+ if term == :year1
129
+ @heavy_price_per_hour_1_year = price_per_hour
130
+ elsif term == :year3
131
+ @heavy_price_per_hour_3_year = price_per_hour
132
+ end
133
+ end
134
+ end
135
+
136
+ # type_of_instance = :ondemand, :light, :medium, :heavy
137
+ # term = :year_1, :year_3, nil
138
+ def get_breakeven_month(type_of_instance, term)
139
+ # Some regions and types do not have reserved available
140
+ ondemand_pph = price_per_hour(:ondemand)
141
+ reserved_pph = price_per_hour(type_of_instance, term)
142
+ return nil if ondemand_pph.nil? || reserved_pph.nil?
143
+
144
+ on_demand = 0
145
+ reserved = prepay(type_of_instance, term)
146
+ for i in 1..36 do
147
+ on_demand += ondemand_pph * 24 * 30.4
148
+ reserved += reserved_pph * 24 * 30.4
149
+ return i if reserved < on_demand
150
+ end
151
+ nil
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,13 @@
1
+ #--
2
+ # Amazon Web Services Pricing Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-pricing
5
+ # Author:: Joe Kinsella (mailto:joe.kinsella@gmail.com)
6
+ # Copyright:: Copyright (c) 2011-2013 CloudHealth
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/CloudHealth/amazon-pricing
9
+ #++
10
+ module AwsPricing
11
+ class DatabaseType < CategoryType
12
+ end
13
+ end
@@ -0,0 +1,79 @@
1
+ require 'amazon-pricing/instance-type'
2
+ module AwsPricing
3
+ class Ec2InstanceType < InstanceType
4
+
5
+ # Returns whether an instance_type is available.
6
+ # operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
7
+ # type_of_instance = :ondemand, :light, :medium, :heavy
8
+ def available?(type_of_instance = :ondemand, operating_system = :linux)
9
+ os = get_category_type(operating_system)
10
+ return false if os.nil?
11
+ os.available?(type_of_instance)
12
+ end
13
+
14
+ # operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
15
+ # type_of_instance = :ondemand, :light, :medium, :heavy
16
+ def update_pricing(operating_system, type_of_instance, json)
17
+ os = get_category_type(operating_system)
18
+ if os.nil?
19
+ os = OperatingSystem.new(self, operating_system)
20
+ @category_types[operating_system] = os
21
+ end
22
+
23
+ if type_of_instance == :ondemand
24
+ # e.g. {"size"=>"sm", "valueColumns"=>[{"name"=>"linux", "prices"=>{"USD"=>"0.060"}}]}
25
+ values = Ec2InstanceType::get_values(json, operating_system)
26
+ price = coerce_price(values[operating_system.to_s])
27
+ os.set_price_per_hour(type_of_instance, nil, price)
28
+ else
29
+ json['valueColumns'].each do |val|
30
+ price = coerce_price(val['prices']['USD'])
31
+
32
+ case val["name"]
33
+ when "yrTerm1"
34
+ os.set_prepay(type_of_instance, :year1, price)
35
+ when "yrTerm3"
36
+ os.set_prepay(type_of_instance, :year3, price)
37
+ when "yrTerm1Hourly"
38
+ os.set_price_per_hour(type_of_instance, :year1, price)
39
+ when "yrTerm3Hourly"
40
+ os.set_price_per_hour(type_of_instance, :year3, price)
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # Maintained for backward compatibility reasons
47
+ def operating_systems
48
+ category_types
49
+ end
50
+
51
+ protected
52
+ # Returns [api_name, name]
53
+ def self.get_name(instance_type, api_name, is_reserved = false)
54
+ # Let's handle new instances more gracefully
55
+ unless @@Memory_Lookup.has_key? api_name
56
+ raise UnknownTypeError, "Unknown instance type #{instance_type} #{api_name}", caller
57
+ end
58
+
59
+ name = @@Name_Lookup[api_name]
60
+
61
+ [api_name, name]
62
+ end
63
+
64
+
65
+ @@Name_Lookup = {
66
+ 'm1.small' => 'Standard Small', 'm1.medium' => 'Standard Medium', 'm1.large' => 'Standard Large', 'm1.xlarge' => 'Standard Extra Large',
67
+ 'm2.xlarge' => 'Hi-Memory Extra Large', 'm2.2xlarge' => 'Hi-Memory Double Extra Large', 'm2.4xlarge' => 'Hi-Memory Quadruple Extra Large',
68
+ 'm3.xlarge' => 'M3 Extra Large Instance', 'm3.2xlarge' => 'M3 Double Extra Large Instance',
69
+ 'c1.medium' => 'High-CPU Medium', 'c1.xlarge' => 'High-CPU Extra Large',
70
+ 'hi1.4xlarge' => 'High I/O Quadruple Extra Large',
71
+ 'cg1.4xlarge' => 'Cluster GPU Quadruple Extra Large',
72
+ 'cc1.4xlarge' => 'Cluster Compute Quadruple Extra Large', 'cc2.8xlarge' => 'Cluster Compute Eight Extra Large',
73
+ 't1.micro' => 'Micro',
74
+ 'cr1.8xlarge' => 'High-Memory Cluster Eight Extra Large',
75
+ 'hs1.8xlarge' => 'High-Storage Eight Extra Large',
76
+ 'g2.2xlarge' => 'Cluster GPU Double Extra Large',
77
+ }
78
+ end
79
+ end
@@ -19,93 +19,62 @@ module AwsPricing
19
19
  # $0.48/hour for Windows.
20
20
  #
21
21
  class InstanceType
22
- attr_accessor :name, :api_name, :memory_in_mb, :disk_in_mb, :platform, :compute_units, :virtual_cores
23
-
24
- # Initializes and InstanceType object given a region, the internal
25
- # type (e.g. stdODI) and the json for the specific instance. The json is
26
- # based on the current undocumented AWS pricing API.
22
+ attr_accessor :name, :api_name, :memory_in_mb, :platform, :compute_units, :virtual_cores, :disk_type, :disk_in_gb
23
+
27
24
  def initialize(region, api_name, name)
28
- @operating_systems = {}
25
+ @category_types = {}
29
26
 
30
27
  @region = region
31
28
  @name = name
32
29
  @api_name = api_name
33
30
 
34
31
  @memory_in_mb = @@Memory_Lookup[@api_name]
35
- @disk_in_mb = @@Disk_Lookup[@api_name]
32
+ @disk_in_gb = @@Disk_Lookup[@api_name]
36
33
  @platform = @@Platform_Lookup[@api_name]
37
34
  @compute_units = @@Compute_Units_Lookup[@api_name]
38
35
  @virtual_cores = @@Virtual_Cores_Lookup[@api_name]
36
+ @disk_type = @@Disk_Type_Lookup[@api_name]
39
37
  end
40
38
 
41
- def operating_systems
42
- @operating_systems.values
39
+ # Keep this in for backwards compatibility within current major version of gem
40
+ def disk_in_mb
41
+ @disk_in_gb * 1000
43
42
  end
44
43
 
45
- def get_operating_system(name)
46
- @operating_systems[name]
44
+ def memory_in_gb
45
+ @memory_in_mb / 1000
47
46
  end
48
47
 
49
- # Returns whether an instance_type is available.
50
- # operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
51
- # type_of_instance = :ondemand, :light, :medium, :heavy
52
- def available?(type_of_instance = :ondemand, operating_system = :linux)
53
- os = get_operating_system(operating_system)
54
- return false if os.nil?
55
- os.available?(type_of_instance)
48
+ def category_types
49
+ @category_types.values
56
50
  end
57
51
 
58
- # type_of_instance = :ondemand, :light, :medium, :heavy
59
- # term = :year_1, :year_3, nil
60
- def price_per_hour(operating_system, type_of_instance, term = nil)
61
- os = get_operating_system(operating_system)
62
- os.price_per_hour(type_of_instance, term)
52
+ def get_category_type(name, multiAz = false)
53
+ if multiAz
54
+ db = @category_types["#{name}_multiAz"]
55
+ else
56
+ db = @category_types[name]
57
+ end
63
58
  end
64
59
 
65
60
  # type_of_instance = :ondemand, :light, :medium, :heavy
66
61
  # term = :year_1, :year_3, nil
67
- def prepay(operating_system, type_of_instance, term = nil)
68
- os = get_operating_system(operating_system)
69
- os.prepay(type_of_instance, term)
62
+ def price_per_hour(category_type, type_of_instance, term = nil, isMultiAz = false)
63
+ cat = get_category_type(category_type, isMultiAz)
64
+ cat.price_per_hour(type_of_instance, term) unless cat.nil?
70
65
  end
71
66
 
72
- # operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
73
67
  # type_of_instance = :ondemand, :light, :medium, :heavy
74
- def update_pricing(operating_system, type_of_instance, json)
75
- os = get_operating_system(operating_system)
76
- if os.nil?
77
- os = OperatingSystem.new(self, operating_system)
78
- @operating_systems[operating_system] = os
79
- end
80
-
81
- if type_of_instance == :ondemand
82
- # e.g. {"size"=>"sm", "valueColumns"=>[{"name"=>"linux", "prices"=>{"USD"=>"0.060"}}]}
83
- values = InstanceType::get_values(json)
84
- price = coerce_price(values[operating_system.to_s])
85
-
86
- os.set_price_per_hour(type_of_instance, nil, price)
87
- else
88
- json['valueColumns'].each do |val|
89
- price = coerce_price(val['prices']['USD'])
90
-
91
- case val["name"]
92
- when "yrTerm1"
93
- os.set_prepay(type_of_instance, :year1, price)
94
- when "yrTerm3"
95
- os.set_prepay(type_of_instance, :year3, price)
96
- when "yrTerm1Hourly"
97
- os.set_price_per_hour(type_of_instance, :year1, price)
98
- when "yrTerm3Hourly"
99
- os.set_price_per_hour(type_of_instance, :year3, price)
100
- end
101
- end
102
- end
68
+ # term = :year_1, :year_3, nil
69
+ def prepay(category_type, type_of_instance, term = nil, isMultiAz = false)
70
+ cat = get_category_type(category_type, isMultiAz)
71
+ cat.prepay(type_of_instance, term) unless cat.nil?
103
72
  end
104
73
 
105
74
  # type_of_instance = :ondemand, :light, :medium, :heavy
106
75
  # term = :year_1, :year_3, nil
107
- def get_breakeven_month(operating_system, type_of_instance, term)
108
- os = get_operating_system(operating_system)
76
+ def get_breakeven_month(category_types, type_of_instance, term)
77
+ os = get_category_type(category_types)
109
78
  os.get_breakeven_month(type_of_instance, term)
110
79
  end
111
80
 
@@ -113,46 +82,21 @@ module AwsPricing
113
82
 
114
83
  def coerce_price(price)
115
84
  return nil if price.nil? || price == "N/A"
116
- price.to_f
117
- end
118
-
119
- #attr_accessor :size, :instance_type
120
-
121
- # Returns [api_name, name]
122
- def self.get_name(instance_type, api_name, is_reserved = false)
123
- # Let's handle new instances more gracefully
124
- unless @@Memory_Lookup.has_key? api_name
125
- raise UnknownTypeError, "Unknown instance type #{instance_type} #{api_name}", caller
126
- end
127
-
128
- name = @@Name_Lookup[api_name]
129
-
130
- [api_name, name]
85
+ price.gsub(",","").to_f
131
86
  end
132
87
 
133
- # Turn json into hash table for parsing
134
- def self.get_values(json)
135
- # e.g. json = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
88
+ def self.get_values(json, category_type)
136
89
  values = {}
137
- json['valueColumns'].each do |val|
138
- values[val['name']] = val['prices']['USD']
90
+ unless json['valueColumns'].nil?
91
+ json['valueColumns'].each do |val|
92
+ values[val['name']] = val['prices']['USD']
93
+ end
94
+ else
95
+ values[category_type.to_s] = json['prices']['USD']
139
96
  end
140
97
  values
141
98
  end
142
99
 
143
- @@Name_Lookup = {
144
- 'm1.small' => 'Standard Small', 'm1.medium' => 'Standard Medium', 'm1.large' => 'Standard Large', 'm1.xlarge' => 'Standard Extra Large',
145
- 'm2.xlarge' => 'Hi-Memory Extra Large', 'm2.2xlarge' => 'Hi-Memory Double Extra Large', 'm2.4xlarge' => 'Hi-Memory Quadruple Extra Large',
146
- 'm3.xlarge' => 'M3 Extra Large Instance', 'm3.2xlarge' => 'M3 Double Extra Large Instance',
147
- 'c1.medium' => 'High-CPU Medium', 'c1.xlarge' => 'High-CPU Extra Large',
148
- 'hi1.4xlarge' => 'High I/O Quadruple Extra Large',
149
- 'cg1.4xlarge' => 'Cluster GPU Quadruple Extra Large',
150
- 'cc1.4xlarge' => 'Cluster Compute Quadruple Extra Large', 'cc2.8xlarge' => 'Cluster Compute Eight Extra Large',
151
- 't1.micro' => 'Micro',
152
- 'cr1.8xlarge' => 'High-Memory Cluster Eight Extra Large',
153
- 'hs1.8xlarge' => 'High-Storage Eight Extra Large',
154
- 'g2.2xlarge' => 'Cluster GPU Double Extra Large',
155
- }
156
100
  @@Memory_Lookup = {
157
101
  'm1.small' => 1700, 'm1.medium' => 3750, 'm1.large' => 7500, 'm1.xlarge' => 15000,
158
102
  'm2.xlarge' => 17100, 'm2.2xlarge' => 34200, 'm2.4xlarge' => 68400,
@@ -166,6 +110,8 @@ module AwsPricing
166
110
  'cr1.8xlarge' => 244000,
167
111
  'hs1.8xlarge' => 117000,
168
112
  'g2.2xlarge' => 15000,
113
+ 'db.m1.small' => 1700, 'db.m1.medium' => 3750, 'db.m1.large' => 7500, 'db.m1.xlarge' => 15000,
114
+ 'db.m2.xlarge' => 17100, 'db.m2.2xlarge' => 34200, 'db.m2.4xlarge' => 68400, 'db.m2.8xlarge' => 136800
169
115
  }
170
116
  @@Disk_Lookup = {
171
117
  'm1.small' => 160, 'm1.medium' => 410, 'm1.large' =>850, 'm1.xlarge' => 1690,
@@ -180,6 +126,8 @@ module AwsPricing
180
126
  'cr1.8xlarge' => 240,
181
127
  'hs1.8xlarge' => 48000,
182
128
  'g2.2xlarge' => 60,
129
+ 'db.m1.small' => 160, 'db.m1.medium' => 410, 'db.m1.large' =>850, 'db.m1.xlarge' => 1690,
130
+ 'db.m2.xlarge' => 420, 'db.m2.2xlarge' => 850, 'db.m2.4xlarge' => 1690, 'db.m2.8xlarge' => 0
183
131
  }
184
132
  @@Platform_Lookup = {
185
133
  'm1.small' => 32, 'm1.medium' => 32, 'm1.large' => 64, 'm1.xlarge' => 64,
@@ -194,6 +142,8 @@ module AwsPricing
194
142
  'cr1.8xlarge' => 64,
195
143
  'hs1.8xlarge' => 64,
196
144
  'g2.2xlarge' => 64,
145
+ 'db.m1.small' => 32, 'db.m1.medium' => 32, 'db.m1.large' => 64, 'db.m1.xlarge' => 64,
146
+ 'db.m2.xlarge' => 64, 'db.m2.2xlarge' => 64, 'db.m2.4xlarge' => 64, 'db.m2.8xlarge' => 64
197
147
  }
198
148
  @@Compute_Units_Lookup = {
199
149
  'm1.small' => 1, 'm1.medium' => 2, 'm1.large' => 4, 'm1.xlarge' => 8,
@@ -208,6 +158,8 @@ module AwsPricing
208
158
  'hs1.8xlarge' => 35,
209
159
  'g2.2xlarge' => 26,
210
160
  'unknown' => 0,
161
+ 'db.m1.small' => 1, 'db.m1.medium' => 2, 'db.m1.large' => 4, 'db.m1.xlarge' => 8,
162
+ 'db.m2.xlarge' => 6, 'db.m2.2xlarge' => 13, 'db.m2.4xlarge' => 26, 'db.m2.8xlarge' => 52
211
163
  }
212
164
  @@Virtual_Cores_Lookup = {
213
165
  'm1.small' => 1, 'm1.medium' => 1, 'm1.large' => 2, 'm1.xlarge' => 4,
@@ -222,6 +174,24 @@ module AwsPricing
222
174
  'hs1.8xlarge' => 16,
223
175
  'g2.2xlarge' => 8,
224
176
  'unknown' => 0,
177
+ 'db.m1.small' => 1, 'db.m1.medium' => 1, 'db.m1.large' => 2, 'db.m1.xlarge' => 4,
178
+ 'db.m2.xlarge' => 2, 'db.m2.2xlarge' => 4, 'db.m2.4xlarge' => 8, 'db.m2.8xlarge' => 16
179
+ }
180
+ @@Disk_Type_Lookup = {
181
+ 'm1.small' => :ephemeral, 'm1.medium' => :ephemeral, 'm1.large' => :ephemeral, 'm1.xlarge' => :ephemeral,
182
+ 'm2.xlarge' => :ephemeral, 'm2.2xlarge' => :ephemeral, 'm2.4xlarge' => :ephemeral,
183
+ 'm3.xlarge' => :ephemeral, 'm3.2xlarge' => :ephemeral,
184
+ 'c1.medium' => :ephemeral, 'c1.xlarge' => :ephemeral,
185
+ 'hi1.4xlarge' => :ssd,
186
+ 'cg1.4xlarge' => :ephemeral,
187
+ 'cc1.4xlarge' => :ephemeral, 'cc2.8xlarge' => :ephemeral,
188
+ 't1.micro' => :ebs,
189
+ 'cr1.8xlarge' => :ssd,
190
+ 'hs1.8xlarge' => :ephemeral,
191
+ 'g2.2xlarge' => :ssd,
192
+ 'unknown' => :ephemeral,
193
+ 'db.m1.small' => :ephemeral, 'db.m1.medium' => :ephemeral, 'db.m1.large' => :ephemeral, 'db.m1.xlarge' => :ephemeral,
194
+ 'db.m2.xlarge' => :ephemeral, 'db.m2.2xlarge' => :ephemeral, 'db.m2.4xlarge' => :ephemeral, 'db.m2.8xlarge' => :ephemeral
225
195
  }
226
196
  end
227
197
 
@@ -8,149 +8,6 @@
8
8
  # Home:: http://github.com/CloudHealth/amazon-pricing
9
9
  #++
10
10
  module AwsPricing
11
-
12
- class OperatingSystem
13
- attr_accessor :instance_type, :name,
14
- :ondemand_price_per_hour, :light_price_per_hour_1_year, :medium_price_per_hour_1_year, :heavy_price_per_hour_1_year,
15
- :light_price_per_hour_3_year, :medium_price_per_hour_3_year, :heavy_price_per_hour_3_year,
16
- :light_prepay_1_year, :light_prepay_3_year, :medium_prepay_1_year, :medium_prepay_3_year, :heavy_prepay_1_year, :heavy_prepay_3_year
17
-
18
-
19
- def initialize(instance_type, name)
20
- @instance_type = instance_type
21
- @name = name
22
- end
23
-
24
- # Returns whether an instance_type is available.
25
- # type_of_instance = :ondemand, :light, :medium, :heavy
26
- def available?(type_of_instance = :ondemand)
27
- not price_per_hour(type_of_instance).nil?
28
- end
29
-
30
- # type_of_instance = :ondemand, :light, :medium, :heavy
31
- # term = :year_1, :year_3, nil
32
- def prepay(type_of_instance = :ondemand, term = nil)
33
- case type_of_instance
34
- when :ondemand
35
- 0
36
- when :light
37
- if term == :year1
38
- @light_prepay_1_year
39
- elsif term == :year3
40
- @light_prepay_3_year
41
- end
42
- when :medium
43
- if term == :year1
44
- @medium_prepay_1_year
45
- elsif term == :year3
46
- @medium_prepay_3_year
47
- end
48
- when :heavy
49
- if term == :year1
50
- @heavy_prepay_1_year
51
- elsif term == :year3
52
- @heavy_prepay_3_year
53
- end
54
- end
55
- end
56
-
57
- # type_of_instance = :ondemand, :light, :medium, :heavy
58
- # term = :year_1, :year_3, nil
59
- def set_prepay(type_of_instance, term, price)
60
- case type_of_instance
61
- when :light
62
- if term == :year1
63
- @light_prepay_1_year = price
64
- elsif term == :year3
65
- @light_prepay_3_year = price
66
- end
67
- when :medium
68
- if term == :year1
69
- @medium_prepay_1_year = price
70
- elsif term == :year3
71
- @medium_prepay_3_year = price
72
- end
73
- when :heavy
74
- if term == :year1
75
- @heavy_prepay_1_year = price
76
- elsif term == :year3
77
- @heavy_prepay_3_year = price
78
- end
79
- end
80
- end
81
-
82
- # type_of_instance = :ondemand, :light, :medium, :heavy
83
- # term = :year_1, :year_3, nil
84
- def price_per_hour(type_of_instance = :ondemand, term = nil)
85
- case type_of_instance
86
- when :ondemand
87
- @ondemand_price_per_hour
88
- when :light
89
- if term == :year1
90
- @light_price_per_hour_1_year
91
- elsif term == :year3
92
- @light_price_per_hour_3_year
93
- end
94
- when :medium
95
- if term == :year1
96
- @medium_price_per_hour_1_year
97
- elsif term == :year3
98
- @medium_price_per_hour_3_year
99
- end
100
- when :heavy
101
- if term == :year1
102
- @heavy_price_per_hour_1_year
103
- elsif term == :year3
104
- @heavy_price_per_hour_3_year
105
- end
106
- end
107
- end
108
-
109
- # type_of_instance = :ondemand, :light, :medium, :heavy
110
- # term = :year_1, :year_3, nil
111
- def set_price_per_hour(type_of_instance, term, price_per_hour)
112
- case type_of_instance
113
- when :ondemand
114
- @ondemand_price_per_hour = price_per_hour
115
- when :light
116
- if term == :year1
117
- @light_price_per_hour_1_year = price_per_hour
118
- elsif term == :year3
119
- @light_price_per_hour_3_year = price_per_hour
120
- end
121
- when :medium
122
- if term == :year1
123
- @medium_price_per_hour_1_year = price_per_hour
124
- elsif term == :year3
125
- @medium_price_per_hour_3_year = price_per_hour
126
- end
127
- when :heavy
128
- if term == :year1
129
- @heavy_price_per_hour_1_year = price_per_hour
130
- elsif term == :year3
131
- @heavy_price_per_hour_3_year = price_per_hour
132
- end
133
- end
134
- end
135
-
136
- # type_of_instance = :ondemand, :light, :medium, :heavy
137
- # term = :year_1, :year_3, nil
138
- def get_breakeven_month(type_of_instance, term)
139
- # Some regions and types do not have reserved available
140
- ondemand_pph = price_per_hour(:ondemand)
141
- reserved_pph = price_per_hour(type_of_instance, term)
142
- return nil if ondemand_pph.nil? || reserved_pph.nil?
143
-
144
- on_demand = 0
145
- reserved = prepay(type_of_instance, term)
146
- for i in 1..36 do
147
- on_demand += ondemand_pph * 24 * 30.4
148
- reserved += reserved_pph * 24 * 30.4
149
- return i if reserved < on_demand
150
- end
151
- nil
152
- end
153
-
11
+ class OperatingSystem < CategoryType
154
12
  end
155
-
156
13
  end
@@ -0,0 +1,89 @@
1
+ require 'amazon-pricing/instance-type'
2
+ module AwsPricing
3
+ class RdsInstanceType < InstanceType
4
+ # database_type = :mysql, :oracle, :sqlserver
5
+ # type_of_instance = :ondemand, :light, :medium, :heavy
6
+ def update_pricing(database_type, type_of_instance, json, isMultiAz)
7
+ db = get_category_type(database_type, isMultiAz)
8
+ if db.nil?
9
+ db = DatabaseType.new(self, database_type)
10
+ if isMultiAz
11
+ @category_types["#{database_type}_multiAz"] = db
12
+ else
13
+ @category_types[database_type] = db
14
+ end
15
+ end
16
+
17
+ if type_of_instance == :ondemand
18
+ values = RdsInstanceType::get_values(json, database_type)
19
+ price = coerce_price(values[database_type.to_s])
20
+ db.set_price_per_hour(type_of_instance, nil, price)
21
+ else
22
+ json['valueColumns'].each do |val|
23
+ price = coerce_price(val['prices']['USD'])
24
+
25
+ case val["name"]
26
+ when "yrTerm1"
27
+ db.set_prepay(type_of_instance, :year1, price)
28
+ when "yrTerm3"
29
+ db.set_prepay(type_of_instance, :year3, price)
30
+ when "yrTerm1Hourly"
31
+ db.set_price_per_hour(type_of_instance, :year1, price)
32
+ when "yrTerm3Hourly"
33
+ db.set_price_per_hour(type_of_instance, :year3, price)
34
+ when "yearTerm1Hourly"
35
+ db.set_price_per_hour(type_of_instance, :year1, price)
36
+ when "yearTerm3Hourly"
37
+ db.set_price_per_hour(type_of_instance, :year3, price)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ protected
44
+
45
+ # Returns [api_name, name]
46
+ def self.get_name(instance_type, size, is_reserved = false)
47
+ lookup = @@Api_Name_Lookup
48
+ lookup = @@Api_Name_Lookup_Reserved if is_reserved
49
+
50
+ # Let's handle new instances more gracefully
51
+ unless lookup.has_key? instance_type
52
+ raise UnknownTypeError, "Unknown instance type #{instance_type}", caller
53
+ else
54
+ api_name = lookup[instance_type][size]
55
+ end
56
+
57
+ lookup = @@Name_Lookup
58
+ lookup = @@Name_Lookup_Reserved if is_reserved
59
+ name = lookup[instance_type][size]
60
+
61
+ [api_name, name]
62
+ end
63
+
64
+ @@Api_Name_Lookup = {
65
+ 'udbInstClass' => {'uDBInst'=>'db.t1.micro'},
66
+ 'dbInstClass'=> {'uDBInst' => 'db.t1.micro', 'smDBInst' => 'db.m1.small', 'medDBInst' => 'db.m1.medium', 'lgDBInst' => 'db.m1.large', 'xlDBInst' => 'db.m1.xlarge'},
67
+ 'hiMemDBInstClass'=> {'xlDBInst' => 'db.m2.xlarge', 'xxlDBInst' => 'db.m2.2xlarge', 'xxxxDBInst' => 'db.m2.4xlarge'},
68
+ 'clusterHiMemDB' => {'xxxxxxxxl' => 'db.m2.8xlarge'},
69
+ 'multiAZDBInstClass'=> {'uDBInst' => 'db.t1.micro', 'smDBInst' => 'db.m1.small', 'medDBInst' => 'db.m1.medium', 'lgDBInst' => 'db.m1.large', 'xlDBInst' => 'db.m1.xlarge'},
70
+ 'multiAZHiMemInstClass'=> {'xlDBInst' => 'db.m2.xlarge', 'xxlDBInst' => 'db.m2.2xlarge', 'xxxxDBInst' => 'db.m2.4xlarge'},
71
+ }
72
+ @@Name_Lookup = {
73
+ 'udbInstClass' => {'uDBInst'=>'Standard Micro'},
74
+ 'dbInstClass'=> {'uDBInst' => 'Standard Micro', 'smDBInst' => 'Standard Small', 'medDBInst' => 'Standard Medium', 'lgDBInst' => 'Standard Large', 'xlDBInst' => 'Standard Extra Large'},
75
+ 'hiMemDBInstClass'=> {'xlDBInst' => 'Standard High-Memory Extra Large', 'xxlDBInst' => 'Standard High-Memory Double Extra Large', 'xxxxDBInst' => 'Standard High-Memory Quadruple Extra Large'},
76
+ 'clusterHiMemDB' => {'xxxxxxxxl' => 'Standard High-Memory Cluster Eight Extra Large'},
77
+ 'multiAZDBInstClass'=> {'uDBInst' => 'Multi-AZ Micro', 'smDBInst' => 'Multi-AZ Small', 'medDBInst' => 'Multi-AZ Medium', 'lgDBInst' => 'Multi-AZ Large', 'xlDBInst' => 'Multi-AZ Extra Large'},
78
+ 'multiAZHiMemInstClass'=> {'xlDBInst' => 'Multi-AZ High-Memory Extra Large', 'xxlDBInst' => 'Multi-AZ High-Memory Double Extra Large', 'xxxxDBInst' => 'Multi-AZ High-Memory Quadruple Extra Large'},
79
+ }
80
+ @@Api_Name_Lookup_Reserved = {
81
+ 'stdDeployRes' => {'u' => 'db.t1.micro', 'micro' => 'db.t1.micro', 'sm' => 'db.m1.small', 'med' => 'db.m1.medium', 'lg' => 'db.m1.large', 'xl' => 'db.m1.xlarge', 'xlHiMem' => 'db.m2.xlarge', 'xxlHiMem' => 'db.m2.2xlarge', 'xxxxlHiMem' => 'db.m2.4xlarge', 'xxxxxxxxl' => 'db.m2.8xlarge'},
82
+ 'multiAZdeployRes' => {'u' => 'db.t1.micro', 'micro' => 'db.t1.micro', 'sm' => 'db.m1.small', 'med' => 'db.m1.medium', 'lg' => 'db.m1.large', 'xl' => 'db.m1.xlarge', 'xlHiMem' => 'db.m2.xlarge', 'xxlHiMem' => 'db.m2.2xlarge', 'xxxxlHiMem' => 'db.m2.4xlarge', 'xxxxxxxxl' => 'db.m2.8xlarge'},
83
+ }
84
+ @@Name_Lookup_Reserved = {
85
+ 'stdDeployRes' => {'u' => 'Standard Micro', 'micro' => 'Standard Micro', 'sm' => 'Standard Small', 'med' => 'Standard Medium', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large', 'xlHiMem' => 'Standard Extra Large High-Memory', 'xxlHiMem' => 'Standard Double Extra Large High-Memory', 'xxxxlHiMem' => 'Standard Quadruple Extra Large High-Memory', 'xxxxxxxxl' => 'Standard Eight Extra Large'} ,
86
+ 'multiAZdeployRes' => {'u' => 'Multi-AZ Micro', 'micro' => 'Multi-AZ Micro', 'sm' => 'Multi-AZ Small', 'med' => 'Multi-AZ Medium', 'lg' => 'Multi-AZ Large', 'xl' => 'Multi-AZ Extra Large', 'xlHiMem' => 'Multi-AZ Extra Large High-Memory', 'xxlHiMem' => 'Multi-AZ Double Extra Large High-Memory', 'xxxxlHiMem' => 'Multi-AZ Quadruple Extra Large High-Memory', 'xxxxxxxxl' => 'Multi-AZ Eight Extra Large'},
87
+ }
88
+ end
89
+ end
@@ -19,35 +19,59 @@ module AwsPricing
19
19
 
20
20
  def initialize(name)
21
21
  @name = name
22
- @instance_types = {}
22
+ @ec2_instance_types = {}
23
+ @rds_instance_types = {}
23
24
  end
24
25
 
25
- def instance_types
26
- @instance_types.values
26
+ def ec2_instance_types
27
+ @ec2_instance_types.values
28
+ end
29
+
30
+ def rds_instance_types
31
+ @rds_instance_types.values
27
32
  end
28
33
 
29
34
  # Returns whether an instance_type is available.
30
35
  # operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
31
36
  # type_of_instance = :ondemand, :light, :medium, :heavy
32
37
  def instance_type_available?(api_name, type_of_instance = :ondemand, operating_system = :linux)
33
- instance = @instance_types[api_name]
38
+ instance = @ec2_instance_types[api_name]
34
39
  return false if instance.nil?
35
40
  instance.available?(type_of_instance, operating_system)
36
41
  end
37
42
 
38
43
  # type_of_instance = :ondemand, :light, :medium, :heavy
39
- def add_or_update_instance_type(api_name, name, operating_system, type_of_instance, json)
40
- current = get_instance_type(api_name)
44
+ def add_or_update_ec2_instance_type(api_name, name, operating_system, type_of_instance, json)
45
+ current = get_ec2_instance_type(api_name)
41
46
  if current.nil?
42
- current = InstanceType.new(self, api_name, name)
43
- @instance_types[api_name] = current
47
+ current = Ec2InstanceType.new(self, api_name, name)
48
+ @ec2_instance_types[api_name] = current
44
49
  end
45
50
  current.update_pricing(operating_system, type_of_instance, json)
46
51
  current
47
52
  end
48
53
 
54
+ def add_or_update_rds_instance_type(api_name, name, db_type, type_of_instance, json, isMultiAz)
55
+ current = get_rds_instance_type(api_name)
56
+ if current.nil?
57
+ current = RdsInstanceType.new(self, api_name, name)
58
+ @rds_instance_types[api_name] = current
59
+ end
60
+ current.update_pricing(db_type, type_of_instance, json, isMultiAz)
61
+ current
62
+ end
63
+
64
+ # Maintained for backward compatibility reasons (retrieves EC2 instance type)
49
65
  def get_instance_type(api_name)
50
- @instance_types[api_name]
66
+ get_ec2_instance_type(api_name)
67
+ end
68
+
69
+ def get_ec2_instance_type(api_name)
70
+ @ec2_instance_types[api_name]
71
+ end
72
+
73
+ def get_rds_instance_type(api_name)
74
+ @rds_instance_types[api_name]
51
75
  end
52
76
 
53
77
  end
@@ -8,5 +8,5 @@
8
8
  # Home:: http://github.com/CloudHealth/amazon-pricing
9
9
  #++
10
10
  module AwsPricing
11
- VERSION = '0.1.9'
11
+ VERSION = '0.1.10'
12
12
  end
@@ -0,0 +1,34 @@
1
+ require 'amazon-pricing'
2
+
3
+ describe AwsPricing::RdsPriceList do
4
+
5
+ before do
6
+ @region_name = ['us-east', 'us-west', 'us-west-2', 'eu-ireland', 'apac-sin', 'apac-syd', 'apac-tokyo', 'sa-east-1']
7
+ @db_types = [:mysql, :oracle, :oracle_byol, :sqlserver, :sqlserver_express, :sqlserver_web, :sqlserver_byol]
8
+ end
9
+
10
+ describe 'new' do
11
+ it 'RdsPriceList.new should return the valid response' do
12
+ result = AwsPricing::RdsPriceList.new
13
+ result.regions.each do |region|
14
+ # response should have valid region
15
+ expect(@region_name).to include(region.name)
16
+ # Result have valid db name
17
+ expect(@db_types).to include(region.rds_instance_types.first.category_types.first.name)
18
+ # values should not be nil
19
+ region.rds_instance_types.first.category_types.first.ondemand_price_per_hour.should_not be_nil
20
+ region.rds_instance_types.first.category_types.first.light_price_per_hour_1_year.should_not be_nil
21
+ region.rds_instance_types.first.category_types.first.medium_price_per_hour_1_year.should_not be_nil
22
+ region.rds_instance_types.first.category_types.first.heavy_price_per_hour_1_year.should_not be_nil
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '::get_api_name' do
28
+ it "raises an UnknownTypeError on an unexpected instance type" do
29
+ expect {
30
+ AwsPricing::InstanceType::get_name 'QuantumODI', 'huge'
31
+ }.to raise_error(AwsPricing::UnknownTypeError)
32
+ end
33
+ end
34
+ end
@@ -16,17 +16,17 @@ require 'test/unit'
16
16
 
17
17
  class TestEc2InstanceTypes < Test::Unit::TestCase
18
18
  def test_cc8xlarge_issue
19
- pricing = AwsPricing::PriceList.new
19
+ pricing = AwsPricing::Ec2PriceList.new
20
20
  obj = pricing.get_instance_type('us-east', 'cc2.8xlarge')
21
21
  assert obj.api_name == 'cc2.8xlarge'
22
22
  end
23
23
 
24
24
  def test_name_lookup
25
- pricing = AwsPricing::PriceList.new
25
+ pricing = AwsPricing::Ec2PriceList.new
26
26
  pricing.regions.each do |region|
27
27
  assert_not_nil region.name
28
28
 
29
- region.instance_types.each do |instance|
29
+ region.ec2_instance_types.each do |instance|
30
30
  assert_not_nil(instance.api_name)
31
31
  assert_not_nil(instance.name)
32
32
  end
@@ -43,15 +43,15 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
43
43
 
44
44
  def test_available
45
45
  # Validate instance types in specific regions are available
46
- pricing = AwsPricing::PriceList.new
46
+ pricing = AwsPricing::Ec2PriceList.new
47
47
  region = pricing.get_region('us-east')
48
48
  assert region.instance_type_available?('m1.large')
49
49
  end
50
50
 
51
51
  def test_fetch_all_breakeven_months
52
- pricing = AwsPricing::PriceList.new
52
+ pricing = AwsPricing::Ec2PriceList.new
53
53
  pricing.regions.each do |region|
54
- region.instance_types.each do |instance|
54
+ region.ec2_instance_types.each do |instance|
55
55
  instance.operating_systems.each do |os|
56
56
  [:light, :medium, :heavy].each do |res_type|
57
57
  next if not instance.available?(res_type)
@@ -64,30 +64,30 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
64
64
  end
65
65
 
66
66
  def test_breakeven_month
67
- pricing = AwsPricing::PriceList.new
67
+ pricing = AwsPricing::Ec2PriceList.new
68
68
  region = pricing.get_region('us-east')
69
- instance = region.get_instance_type('m1.large')
69
+ instance = region.get_ec2_instance_type('m1.large')
70
70
  bem = instance.get_breakeven_month(:linux, :heavy, :year1)
71
71
  assert bem == 6
72
72
  end
73
73
 
74
74
  def test_memory
75
75
  # Validate instance types in specific regions are available
76
- pricing = AwsPricing::PriceList.new
76
+ pricing = AwsPricing::Ec2PriceList.new
77
77
  region = pricing.get_region('us-east')
78
- instance = region.get_instance_type('m1.large')
78
+ instance = region.get_ec2_instance_type('m1.large')
79
79
  assert instance.memory_in_mb == 7500
80
80
  end
81
81
 
82
82
  def test_non_standard_region_name
83
- pricing = AwsPricing::PriceList.new
83
+ pricing = AwsPricing::Ec2PriceList.new
84
84
  region = pricing.get_region('eu-west-1')
85
- instance = region.get_instance_type('m1.large')
85
+ instance = region.get_ec2_instance_type('m1.large')
86
86
  assert instance.memory_in_mb == 7500
87
87
  end
88
88
 
89
89
  def test_ebs
90
- pricing = AwsPricing::PriceList.new
90
+ pricing = AwsPricing::Ec2PriceList.new
91
91
  region = pricing.get_region('us-east')
92
92
  assert region.ebs_price.standard_per_gb == 0.10
93
93
  assert region.ebs_price.standard_per_million_io == 0.10
@@ -97,7 +97,7 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
97
97
  end
98
98
 
99
99
  def test_ebs_not_null
100
- pricing = AwsPricing::PriceList.new
100
+ pricing = AwsPricing::Ec2PriceList.new
101
101
  pricing.regions.each do |region|
102
102
  # Everyone should have standard pricing
103
103
  assert_not_nil region.ebs_price.standard_per_gb
@@ -107,9 +107,9 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
107
107
  end
108
108
 
109
109
  def test_virtual_cores
110
- pricing = AwsPricing::PriceList.new
110
+ pricing = AwsPricing::Ec2PriceList.new
111
111
  region = pricing.get_region('us-east')
112
- instance = region.get_instance_type('m1.large')
112
+ instance = region.get_ec2_instance_type('m1.large')
113
113
  assert instance.virtual_cores == 2
114
114
  end
115
115
 
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.9
4
+ version: 0.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,13 +27,18 @@ files:
27
27
  - Rakefile
28
28
  - amazon-pricing.gemspec
29
29
  - lib/amazon-pricing.rb
30
+ - lib/amazon-pricing/category-type.rb
31
+ - lib/amazon-pricing/database-type.rb
30
32
  - lib/amazon-pricing/ebs-price.rb
33
+ - lib/amazon-pricing/ec2-instance-type.rb
31
34
  - lib/amazon-pricing/instance-type.rb
32
35
  - lib/amazon-pricing/operating-system.rb
36
+ - lib/amazon-pricing/rds-instance-type.rb
33
37
  - lib/amazon-pricing/region.rb
34
38
  - lib/amazon-pricing/version.rb
35
39
  - spec/instance_type_spec.rb
36
40
  - spec/price_list_spec.rb
41
+ - spec/rds-amazon-pricing-spec.rb
37
42
  - test/helper.rb
38
43
  - test/test-ec2-instance-types.rb
39
44
  homepage: http://github.com/CloudHealth/amazon-pricing
@@ -69,6 +74,7 @@ summary: Amazon Web Services Pricing Ruby gem
69
74
  test_files:
70
75
  - spec/instance_type_spec.rb
71
76
  - spec/price_list_spec.rb
77
+ - spec/rds-amazon-pricing-spec.rb
72
78
  - test/helper.rb
73
79
  - test/test-ec2-instance-types.rb
74
80
  has_rdoc: