amazon-pricing 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
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: