amazon-pricing 0.1.6 → 0.1.7
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 +24 -8
- data/lib/amazon-pricing.rb +12 -30
- data/lib/amazon-pricing/instance-type.rb +106 -60
- data/lib/amazon-pricing/operating-system.rb +150 -0
- data/lib/amazon-pricing/region.rb +22 -64
- data/lib/amazon-pricing/version.rb +1 -1
- data/spec/instance_type_spec.rb +1 -1
- data/spec/price_list_spec.rb +4 -0
- data/test/test-ec2-instance-types.rb +17 -24
- metadata +18 -17
- data/lib/amazon-pricing/reserved-instance-type.rb +0 -131
data/Rakefile
CHANGED
@@ -19,12 +19,12 @@ end
|
|
19
19
|
|
20
20
|
desc "Publish the gem"
|
21
21
|
task :publish do
|
22
|
-
sh "gem push amazon-pricing-#{
|
22
|
+
sh "gem push amazon-pricing-#{AwsPricing::VERSION}.gem"
|
23
23
|
end
|
24
24
|
|
25
25
|
desc "Installs the gem"
|
26
26
|
task :install => :gem do
|
27
|
-
sh "
|
27
|
+
sh "sudo gem install amazon-pricing-#{AwsPricing::VERSION}.gem --no-rdoc --no-ri"
|
28
28
|
end
|
29
29
|
|
30
30
|
task :test do
|
@@ -35,13 +35,29 @@ desc "Prints current EC2 pricing to console"
|
|
35
35
|
task :print_price_list do
|
36
36
|
require 'lib/amazon-pricing'
|
37
37
|
pricing = AwsPricing::PriceList.new
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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,"
|
39
|
+
[:year1, :year3].each do |term|
|
40
|
+
[:light, :medium, :heavy].each do |res_type|
|
41
|
+
[:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb].each do |os|
|
42
|
+
line += "#{term} #{res_type} #{os} Prepay,#{term} #{res_type} #{os} PPH,"
|
43
|
+
end
|
42
44
|
end
|
43
|
-
|
44
|
-
|
45
|
+
end
|
46
|
+
puts line.chop
|
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},"
|
50
|
+
[:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb].each do |os|
|
51
|
+
line += "#{t.price_per_hour(os, :ondemand)},"
|
52
|
+
end
|
53
|
+
[:year1, :year3].each do |term|
|
54
|
+
[:light, :medium, :heavy].each do |res_type|
|
55
|
+
[:linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb].each do |os|
|
56
|
+
line += "#{t.prepay(os, res_type, term)},#{t.price_per_hour(os, res_type, term)},"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
puts line.chop
|
45
61
|
end
|
46
62
|
end
|
47
63
|
end
|
data/lib/amazon-pricing.rb
CHANGED
@@ -19,8 +19,7 @@ module AwsPricing
|
|
19
19
|
# information will be retrieved from Amazon via currently undocumented
|
20
20
|
# json APIs.
|
21
21
|
class PriceList
|
22
|
-
attr_accessor :regions
|
23
|
-
:version_ec2_reserved_instance
|
22
|
+
attr_accessor :regions
|
24
23
|
|
25
24
|
def initialize
|
26
25
|
@_regions = {}
|
@@ -37,12 +36,10 @@ module AwsPricing
|
|
37
36
|
@_regions.values
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
# reserved_usage_type = :light, :medium, :heavy
|
42
|
-
def get_instance_type(region_name, type, api_name, reserved_usage_type = :medium)
|
39
|
+
def get_instance_type(region_name, api_name)
|
43
40
|
region = get_region(region_name)
|
44
41
|
raise "Region #{region_name} not found" if region.nil?
|
45
|
-
region.get_instance_type(
|
42
|
+
region.get_instance_type(api_name)
|
46
43
|
end
|
47
44
|
|
48
45
|
protected
|
@@ -69,48 +66,33 @@ module AwsPricing
|
|
69
66
|
|
70
67
|
def get_ec2_on_demand_instance_pricing
|
71
68
|
@@OS_TYPES.each do |os|
|
72
|
-
|
69
|
+
fetch_ec2_instance_pricing(EC2_BASE_URL + "json/#{os}-od.json", :ondemand, os)
|
73
70
|
end
|
74
71
|
end
|
75
72
|
|
76
73
|
def get_ec2_reserved_instance_pricing
|
77
74
|
@@OS_TYPES.each do |os|
|
78
75
|
@@RES_TYPES.each do |res_type|
|
79
|
-
|
76
|
+
fetch_ec2_instance_pricing(EC2_BASE_URL + "json/#{os}-ri-#{res_type}.json", res_type, os)
|
80
77
|
end
|
81
78
|
end
|
82
79
|
end
|
83
80
|
|
84
81
|
# Retrieves the EC2 on-demand instance pricing.
|
85
|
-
|
82
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
83
|
+
def fetch_ec2_instance_pricing(url, type_of_instance, operating_system)
|
86
84
|
res = fetch_url(url)
|
87
|
-
@version_ec2_on_demand_instance = res['vers']
|
88
85
|
res['config']['regions'].each do |reg|
|
89
86
|
region_name = reg['region']
|
90
87
|
region = find_or_create_region(region_name)
|
88
|
+
# e.g. type = {"type"=>"hiCPUODI", "sizes"=>[{"size"=>"med", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"N/A"}}]}, {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}]}
|
91
89
|
reg['instanceTypes'].each do |type|
|
90
|
+
# e.g. size = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
|
92
91
|
type['sizes'].each do |size|
|
93
92
|
begin
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
# Retrieves the EC2 on-demand instance pricing.
|
103
|
-
# reserved_usage_type = :light, :medium, :heavy
|
104
|
-
def fetch_ec2_reserved_instance_pricing(url, reserved_usage_type, platform)
|
105
|
-
res = fetch_url(url)
|
106
|
-
@version_ec2_reserved_instance = res['vers']
|
107
|
-
res['config']['regions'].each do |reg|
|
108
|
-
region_name = reg['region']
|
109
|
-
region = find_or_create_region(region_name)
|
110
|
-
reg['instanceTypes'].each do |type|
|
111
|
-
type['sizes'].each do |size|
|
112
|
-
begin
|
113
|
-
region.add_or_update_instance_type(:reserved, ReservedInstanceType.new(region, type['type'], size, reserved_usage_type, platform), reserved_usage_type)
|
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)
|
114
96
|
rescue UnknownTypeError
|
115
97
|
$stderr.puts "WARNING: encountered #{$!.message}"
|
116
98
|
end
|
@@ -19,42 +19,17 @@ module AwsPricing
|
|
19
19
|
# $0.48/hour for Windows.
|
20
20
|
#
|
21
21
|
class InstanceType
|
22
|
-
attr_accessor :name, :api_name, :
|
23
|
-
:memory_in_mb, :disk_in_mb, :platform, :compute_units, :virtual_cores,
|
24
|
-
:rhel_price_per_hour, :sles_price_per_hour, :mswinSQL_price_per_hour, :mswinSQLWeb_price_per_hour
|
22
|
+
attr_accessor :name, :api_name, :memory_in_mb, :disk_in_mb, :platform, :compute_units, :virtual_cores
|
25
23
|
|
26
24
|
# Initializes and InstanceType object given a region, the internal
|
27
25
|
# type (e.g. stdODI) and the json for the specific instance. The json is
|
28
26
|
# based on the current undocumented AWS pricing API.
|
29
|
-
def initialize(region,
|
30
|
-
|
31
|
-
|
32
|
-
# e.g. {"linux"=>"0.060"}
|
33
|
-
values = InstanceType::get_values(json)
|
34
|
-
|
35
|
-
@size = json['size']
|
36
|
-
|
37
|
-
pph = values[platform.to_s]
|
38
|
-
pph = nil if pph == "N/A"
|
39
|
-
|
40
|
-
if platform == :mswin
|
41
|
-
@windows_price_per_hour = pph
|
42
|
-
elsif platform == :linux
|
43
|
-
@linux_price_per_hour = pph
|
44
|
-
elsif platform == :rhel
|
45
|
-
@rhel_price_per_hour = pph
|
46
|
-
elsif platform == :sles
|
47
|
-
@sles_price_per_hour = pph
|
48
|
-
elsif platform == :mswinSQL
|
49
|
-
@mswinSQL_price_per_hour = pph
|
50
|
-
elsif platform == :mswinSQLWeb
|
51
|
-
@mswinSQLWeb_price_per_hour = pph
|
52
|
-
end
|
53
|
-
|
54
|
-
@instance_type = instance_type
|
27
|
+
def initialize(region, api_name, name)
|
28
|
+
@operating_systems = {}
|
55
29
|
|
56
|
-
@
|
57
|
-
@name =
|
30
|
+
@region = region
|
31
|
+
@name = name
|
32
|
+
@api_name = api_name
|
58
33
|
|
59
34
|
@memory_in_mb = @@Memory_Lookup[@api_name]
|
60
35
|
@disk_in_mb = @@Disk_Lookup[@api_name]
|
@@ -63,52 +38,99 @@ module AwsPricing
|
|
63
38
|
@virtual_cores = @@Virtual_Cores_Lookup[@api_name]
|
64
39
|
end
|
65
40
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
41
|
+
def operating_systems
|
42
|
+
@operating_systems.values
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_operating_system(name)
|
46
|
+
@operating_systems[name]
|
47
|
+
end
|
48
|
+
|
49
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
50
|
+
# term = :year_1, :year_3, nil
|
51
|
+
def price_per_hour(operating_system, type_of_instance, term = nil)
|
52
|
+
os = get_operating_system(operating_system)
|
53
|
+
os.price_per_hour(type_of_instance, term)
|
77
54
|
end
|
78
55
|
|
79
|
-
|
80
|
-
|
56
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
57
|
+
# term = :year_1, :year_3, nil
|
58
|
+
def prepay(operating_system, type_of_instance, term = nil)
|
59
|
+
os = get_operating_system(operating_system)
|
60
|
+
os.prepay(type_of_instance, term)
|
81
61
|
end
|
82
62
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
63
|
+
# operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
|
64
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
65
|
+
def update_pricing(operating_system, type_of_instance, json)
|
66
|
+
os = get_operating_system(operating_system)
|
67
|
+
if os.nil?
|
68
|
+
os = OperatingSystem.new(self, operating_system)
|
69
|
+
@operating_systems[operating_system] = os
|
70
|
+
end
|
71
|
+
|
72
|
+
if type_of_instance == :ondemand
|
73
|
+
# e.g. {"size"=>"sm", "valueColumns"=>[{"name"=>"linux", "prices"=>{"USD"=>"0.060"}}]}
|
74
|
+
values = InstanceType::get_values(json)
|
75
|
+
price = coerce_price(values[operating_system.to_s])
|
76
|
+
|
77
|
+
os.set_price_per_hour(type_of_instance, nil, price)
|
78
|
+
else
|
79
|
+
json['valueColumns'].each do |val|
|
80
|
+
price = coerce_price(val['prices']['USD'])
|
81
|
+
|
82
|
+
case val["name"]
|
83
|
+
when "yrTerm1"
|
84
|
+
os.set_prepay(type_of_instance, :year1, price)
|
85
|
+
when "yrTerm3"
|
86
|
+
os.set_prepay(type_of_instance, :year3, price)
|
87
|
+
when "yrTerm1Hourly"
|
88
|
+
os.set_price_per_hour(type_of_instance, :year1, price)
|
89
|
+
when "yrTerm3Hourly"
|
90
|
+
os.set_price_per_hour(type_of_instance, :year3, price)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
97
|
+
# term = :year_1, :year_3, nil
|
98
|
+
def get_breakeven_month(operating_system, type_of_instance, term)
|
99
|
+
os = get_operating_system(operating_system)
|
100
|
+
os.get_breakeven_month(type_of_instance, term)
|
91
101
|
end
|
92
102
|
|
93
103
|
protected
|
94
104
|
|
95
|
-
|
105
|
+
def coerce_price(price)
|
106
|
+
return nil if price.nil? || price == "N/A"
|
107
|
+
price.to_f
|
108
|
+
end
|
109
|
+
|
110
|
+
#attr_accessor :size, :instance_type
|
111
|
+
|
112
|
+
# Returns [api_name, name]
|
113
|
+
def self.get_name(instance_type, size, is_reserved = false)
|
114
|
+
lookup = @@Api_Name_Lookup
|
115
|
+
lookup = @@Api_Name_Lookup_Reserved if is_reserved
|
96
116
|
|
97
|
-
def self.get_api_name(instance_type, size)
|
98
117
|
# Let's handle new instances more gracefully
|
99
|
-
unless
|
118
|
+
unless lookup.has_key? instance_type
|
100
119
|
raise UnknownTypeError, "Unknown instance type #{instance_type}", caller
|
101
120
|
else
|
102
|
-
|
121
|
+
api_name = lookup[instance_type][size]
|
103
122
|
end
|
104
|
-
end
|
105
123
|
|
106
|
-
|
107
|
-
@@
|
124
|
+
lookup = @@Name_Lookup
|
125
|
+
lookup = @@Name_Lookup_Reserved if is_reserved
|
126
|
+
name = lookup[instance_type][size]
|
127
|
+
|
128
|
+
[api_name, name]
|
108
129
|
end
|
109
130
|
|
110
131
|
# Turn json into hash table for parsing
|
111
132
|
def self.get_values(json)
|
133
|
+
# e.g. json = {"size"=>"xl", "valueColumns"=>[{"name"=>"mswinSQL", "prices"=>{"USD"=>"2.427"}}]}
|
112
134
|
values = {}
|
113
135
|
json['valueColumns'].each do |val|
|
114
136
|
values[val['name']] = val['prices']['USD']
|
@@ -116,7 +138,6 @@ module AwsPricing
|
|
116
138
|
values
|
117
139
|
end
|
118
140
|
|
119
|
-
|
120
141
|
@@Api_Name_Lookup = {
|
121
142
|
'stdODI' => {'sm' => 'm1.small', 'med' => 'm1.medium', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
122
143
|
'hiMemODI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
@@ -141,6 +162,31 @@ module AwsPricing
|
|
141
162
|
'clusterHiMemODI' => {'xxxxxxxxl' => 'High-Memory Cluster Eight Extra Large'},
|
142
163
|
'hiStoreODI' => {'xxxxxxxxl' => 'High-Storage Eight Extra Large'},
|
143
164
|
}
|
165
|
+
@@Api_Name_Lookup_Reserved = {
|
166
|
+
'stdResI' => {'sm' => 'm1.small', 'med' => 'm1.medium', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
167
|
+
'hiMemResI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
168
|
+
'hiCPUResI' => {'med' => 'c1.medium', 'xl' => 'c1.xlarge'},
|
169
|
+
'clusterGPUResI' => {'xxxxl' => 'cg1.4xlarge'},
|
170
|
+
'clusterCompResI' => {'xxxxl' => 'cc1.4xlarge', 'xxxxxxxxl' => 'cc2.8xlarge'},
|
171
|
+
'uResI' => {'u' => 't1.micro'},
|
172
|
+
'hiIoResI' => {'xxxxl' => 'hi1.4xlarge'},
|
173
|
+
'secgenstdResI' => {'xl' => 'm3.xlarge', 'xxl' => 'm3.2xlarge'},
|
174
|
+
'clusterHiMemResI' => {'xxxxxxxxl' => 'cr1.8xlarge'},
|
175
|
+
'hiStoreResI' => {'xxxxxxxxl' => 'hs1.8xlarge'},
|
176
|
+
}
|
177
|
+
@@Name_Lookup_Reserved = {
|
178
|
+
'stdResI' => {'sm' => 'Standard Small', 'med' => 'Standard Medium', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
179
|
+
'hiMemResI' => {'xl' => 'Hi-Memory Extra Large', 'xxl' => 'Hi-Memory Double Extra Large', 'xxxxl' => 'Hi-Memory Quadruple Extra Large'},
|
180
|
+
'hiCPUResI' => {'med' => 'High-CPU Medium', 'xl' => 'High-CPU Extra Large'},
|
181
|
+
'clusterGPUResI' => {'xxxxl' => 'Cluster GPU Quadruple Extra Large'},
|
182
|
+
'clusterCompResI' => {'xxxxl' => 'Cluster Compute Quadruple Extra Large', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
183
|
+
'uResI' => {'u' => 'Micro'},
|
184
|
+
'hiIoResI' => {'xxxxl' => 'High I/O Quadruple Extra Large Instance'},
|
185
|
+
'secgenstdResI' => {'xl' => 'M3 Extra Large Instance', 'xxl' => 'M3 Double Extra Large Instance'},
|
186
|
+
'clusterHiMemResI' => {'xxxxxxxxl' => 'High-Memory Cluster Eight Extra Large'},
|
187
|
+
'hiStoreResI' => {'xxxxxxxxl' => 'High-Storage Eight Extra Large'},
|
188
|
+
}
|
189
|
+
|
144
190
|
@@Memory_Lookup = {
|
145
191
|
'm1.small' => 1700, 'm1.medium' => 3750, 'm1.large' => 7500, 'm1.xlarge' => 15000,
|
146
192
|
'm2.xlarge' => 17100, 'm2.2xlarge' => 34200, 'm2.4xlarge' => 68400,
|
@@ -0,0 +1,150 @@
|
|
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-2012 Sonian
|
7
|
+
# License:: Distributes under the same terms as Ruby
|
8
|
+
# Home:: http://github.com/sonian/amazon-pricing
|
9
|
+
#++
|
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
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
25
|
+
# term = :year_1, :year_3, nil
|
26
|
+
def prepay(type_of_instance = :ondemand, term = nil)
|
27
|
+
case type_of_instance
|
28
|
+
when :ondemand
|
29
|
+
0
|
30
|
+
when :light
|
31
|
+
if term == :year1
|
32
|
+
@light_prepay_1_year
|
33
|
+
elsif term == :year3
|
34
|
+
@light_prepay_3_year
|
35
|
+
end
|
36
|
+
when :medium
|
37
|
+
if term == :year1
|
38
|
+
@medium_prepay_1_year
|
39
|
+
elsif term == :year3
|
40
|
+
@medium_prepay_3_year
|
41
|
+
end
|
42
|
+
when :heavy
|
43
|
+
if term == :year1
|
44
|
+
@heavy_prepay_1_year
|
45
|
+
elsif term == :year3
|
46
|
+
@heavy_prepay_3_year
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
52
|
+
# term = :year_1, :year_3, nil
|
53
|
+
def set_prepay(type_of_instance, term, price)
|
54
|
+
case type_of_instance
|
55
|
+
when :light
|
56
|
+
if term == :year1
|
57
|
+
@light_prepay_1_year = price
|
58
|
+
elsif term == :year3
|
59
|
+
@light_prepay_3_year = price
|
60
|
+
end
|
61
|
+
when :medium
|
62
|
+
if term == :year1
|
63
|
+
@medium_prepay_1_year = price
|
64
|
+
elsif term == :year3
|
65
|
+
@medium_prepay_3_year = price
|
66
|
+
end
|
67
|
+
when :heavy
|
68
|
+
if term == :year1
|
69
|
+
@heavy_prepay_1_year = price
|
70
|
+
elsif term == :year3
|
71
|
+
@heavy_prepay_3_year = price
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
77
|
+
# term = :year_1, :year_3, nil
|
78
|
+
def price_per_hour(type_of_instance = :ondemand, term = nil)
|
79
|
+
case type_of_instance
|
80
|
+
when :ondemand
|
81
|
+
@ondemand_price_per_hour
|
82
|
+
when :light
|
83
|
+
if term == :year1
|
84
|
+
@light_price_per_hour_1_year
|
85
|
+
elsif term == :year3
|
86
|
+
@light_price_per_hour_3_year
|
87
|
+
end
|
88
|
+
when :medium
|
89
|
+
if term == :year1
|
90
|
+
@medium_price_per_hour_1_year
|
91
|
+
elsif term == :year3
|
92
|
+
@medium_price_per_hour_3_year
|
93
|
+
end
|
94
|
+
when :heavy
|
95
|
+
if term == :year1
|
96
|
+
@heavy_price_per_hour_1_year
|
97
|
+
elsif term == :year3
|
98
|
+
@heavy_price_per_hour_3_year
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
104
|
+
# term = :year_1, :year_3, nil
|
105
|
+
def set_price_per_hour(type_of_instance, term, price_per_hour)
|
106
|
+
case type_of_instance
|
107
|
+
when :ondemand
|
108
|
+
@ondemand_price_per_hour = price_per_hour
|
109
|
+
when :light
|
110
|
+
if term == :year1
|
111
|
+
@light_price_per_hour_1_year = price_per_hour
|
112
|
+
elsif term == :year3
|
113
|
+
@light_price_per_hour_3_year = price_per_hour
|
114
|
+
end
|
115
|
+
when :medium
|
116
|
+
if term == :year1
|
117
|
+
@medium_price_per_hour_1_year = price_per_hour
|
118
|
+
elsif term == :year3
|
119
|
+
@medium_price_per_hour_3_year = price_per_hour
|
120
|
+
end
|
121
|
+
when :heavy
|
122
|
+
if term == :year1
|
123
|
+
@heavy_price_per_hour_1_year = price_per_hour
|
124
|
+
elsif term == :year3
|
125
|
+
@heavy_price_per_hour_3_year = price_per_hour
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
131
|
+
# term = :year_1, :year_3, nil
|
132
|
+
def get_breakeven_month(type_of_instance, term)
|
133
|
+
# Some regions and types do not have reserved available
|
134
|
+
ondemand_pph = price_per_hour(:ondemand)
|
135
|
+
reserved_pph = price_per_hour(type_of_instance, term)
|
136
|
+
return nil if ondemand_pph.nil? || reserved_pph.nil?
|
137
|
+
|
138
|
+
on_demand = 0
|
139
|
+
reserved = prepay(type_of_instance, term)
|
140
|
+
for i in 1..36 do
|
141
|
+
on_demand += ondemand_pph * 24 * 30.4
|
142
|
+
reserved += reserved_pph * 24 * 30.4
|
143
|
+
return i if reserved < on_demand
|
144
|
+
end
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -19,82 +19,40 @@ module AwsPricing
|
|
19
19
|
|
20
20
|
def initialize(name)
|
21
21
|
@name = name
|
22
|
-
@
|
23
|
-
@_ec2_reserved_instance_types_light = {}
|
24
|
-
@_ec2_reserved_instance_types_medium = {}
|
25
|
-
@_ec2_reserved_instance_types_heavy = {}
|
22
|
+
@instance_types = {}
|
26
23
|
end
|
27
24
|
|
28
|
-
def
|
29
|
-
@
|
25
|
+
def instance_types
|
26
|
+
@instance_types.values
|
30
27
|
end
|
31
28
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@_ec2_reserved_instance_types_light.values + @_ec2_reserved_instance_types_medium.values + @_ec2_reserved_instance_types_heavy.values
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Returns whether an instance_type is available. Must specify the type
|
47
|
-
# (:on_demand or :reserved) and instance type (m1.large). Optionally can
|
48
|
-
# specify the specific platform (:linix or :windows).
|
49
|
-
def instance_type_available?(type, api_name, platform = nil)
|
50
|
-
get_instance_type(type, api_name).available?(platform)
|
29
|
+
# Returns whether an instance_type is available.
|
30
|
+
# operating_system = :linux, :mswin, :rhel, :sles, :mswinSQL, :mswinSQLWeb
|
31
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
32
|
+
def instance_type_available?(api_name, type_of_instance = :ondemand, operating_system = :linux)
|
33
|
+
instance = @instance_types[api_name]
|
34
|
+
return false if instance.nil?
|
35
|
+
os = instance.get_operating_system(operating_system)
|
36
|
+
return false if os.nil?
|
37
|
+
pph = os.price_per_hour(type_of_instance)
|
38
|
+
not pph.nil?
|
51
39
|
end
|
52
40
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
current = get_instance_type(type, instance_type.api_name, reserved_usage_type)
|
41
|
+
# type_of_instance = :ondemand, :light, :medium, :heavy
|
42
|
+
def add_or_update_instance_type(api_name, name, operating_system, type_of_instance, json)
|
43
|
+
current = get_instance_type(api_name)
|
57
44
|
if current.nil?
|
58
|
-
|
59
|
-
|
60
|
-
elsif type == :reserved
|
61
|
-
case reserved_usage_type
|
62
|
-
when :light
|
63
|
-
@_ec2_reserved_instance_types_light[instance_type.api_name] = instance_type
|
64
|
-
when :medium
|
65
|
-
@_ec2_reserved_instance_types_medium[instance_type.api_name] = instance_type
|
66
|
-
when :heavy
|
67
|
-
@_ec2_reserved_instance_types_heavy[instance_type.api_name] = instance_type
|
68
|
-
end
|
69
|
-
end
|
70
|
-
else
|
71
|
-
current.update(instance_type)
|
45
|
+
current = InstanceType.new(self, api_name, name)
|
46
|
+
@instance_types[api_name] = current
|
72
47
|
end
|
48
|
+
current.update_pricing(operating_system, type_of_instance, json)
|
49
|
+
current
|
73
50
|
end
|
74
51
|
|
75
|
-
|
76
|
-
|
77
|
-
def get_instance_type(type, api_name, reserved_usage_type = :medium)
|
78
|
-
if type == :on_demand
|
79
|
-
@_ec2_on_demand_instance_types[api_name]
|
80
|
-
elsif type == :reserved
|
81
|
-
case reserved_usage_type
|
82
|
-
when :light
|
83
|
-
@_ec2_reserved_instance_types_light[api_name]
|
84
|
-
when :medium
|
85
|
-
@_ec2_reserved_instance_types_medium[api_name]
|
86
|
-
when :heavy
|
87
|
-
@_ec2_reserved_instance_types_heavy[api_name]
|
88
|
-
end
|
89
|
-
else
|
90
|
-
nil
|
91
|
-
end
|
52
|
+
def get_instance_type(api_name)
|
53
|
+
@instance_types[api_name]
|
92
54
|
end
|
93
55
|
|
94
|
-
protected
|
95
|
-
|
96
|
-
attr_accessor :_ec2_on_demand_instance_types, :_ec2_reserved_instance_types_light, :_ec2_reserved_instance_types_medium, :_ec2_reserved_instance_types_heavy
|
97
|
-
|
98
56
|
end
|
99
57
|
|
100
58
|
end
|
data/spec/instance_type_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe AwsPricing::InstanceType do
|
|
4
4
|
describe '::get_api_name' do
|
5
5
|
it "raises an UnknownTypeError on an unexpected instance type" do
|
6
6
|
expect {
|
7
|
-
AwsPricing::InstanceType::
|
7
|
+
AwsPricing::InstanceType::get_name 'QuantumODI', 'huge'
|
8
8
|
}.to raise_error(AwsPricing::UnknownTypeError)
|
9
9
|
end
|
10
10
|
end
|
data/spec/price_list_spec.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'amazon-pricing'
|
2
2
|
|
3
3
|
describe AwsPricing::PriceList do
|
4
|
+
|
5
|
+
# Need to update below based on 2013-07 changes
|
6
|
+
=begin
|
4
7
|
describe "#get_ec2_on_demand_instance_pricing" do
|
5
8
|
let(:price_list) {
|
6
9
|
{
|
@@ -36,4 +39,5 @@ describe AwsPricing::PriceList do
|
|
36
39
|
}.to_not raise_error
|
37
40
|
end
|
38
41
|
end
|
42
|
+
=end
|
39
43
|
end
|
@@ -17,7 +17,7 @@ require 'test/unit'
|
|
17
17
|
class TestEc2InstanceTypes < Test::Unit::TestCase
|
18
18
|
def test_cc8xlarge_issue
|
19
19
|
pricing = AwsPricing::PriceList.new
|
20
|
-
obj = pricing.get_instance_type('us-east',
|
20
|
+
obj = pricing.get_instance_type('us-east', 'cc2.8xlarge')
|
21
21
|
assert obj.api_name == 'cc2.8xlarge'
|
22
22
|
end
|
23
23
|
|
@@ -25,25 +25,10 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
|
|
25
25
|
pricing = AwsPricing::PriceList.new
|
26
26
|
pricing.regions.each do |region|
|
27
27
|
assert_not_nil region.name
|
28
|
-
|
29
|
-
|
30
|
-
assert_not_nil
|
31
|
-
|
32
|
-
end
|
33
|
-
region.ec2_reserved_instance_types(:light).each do |instance_type|
|
34
|
-
assert_not_nil instance_type.api_name
|
35
|
-
assert_not_nil instance_type.name
|
36
|
-
assert instance_type.api_name != instance_type.name
|
37
|
-
end
|
38
|
-
region.ec2_reserved_instance_types(:medium).each do |instance_type|
|
39
|
-
assert_not_nil instance_type.api_name
|
40
|
-
assert_not_nil instance_type.name
|
41
|
-
assert instance_type.api_name != instance_type.name
|
42
|
-
end
|
43
|
-
region.ec2_reserved_instance_types(:heavy).each do |instance_type|
|
44
|
-
assert_not_nil instance_type.api_name
|
45
|
-
assert_not_nil instance_type.name
|
46
|
-
assert instance_type.api_name != instance_type.name
|
28
|
+
|
29
|
+
region.instance_types.each do |instance|
|
30
|
+
assert_not_nil(instance.api_name)
|
31
|
+
assert_not_nil(instance.name)
|
47
32
|
end
|
48
33
|
end
|
49
34
|
end
|
@@ -60,21 +45,29 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
|
|
60
45
|
# Validate instance types in specific regions are available
|
61
46
|
pricing = AwsPricing::PriceList.new
|
62
47
|
region = pricing.get_region('us-east')
|
63
|
-
assert region.instance_type_available?(
|
48
|
+
assert region.instance_type_available?('m1.large')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_breakeven_month
|
52
|
+
pricing = AwsPricing::PriceList.new
|
53
|
+
region = pricing.get_region('us-east')
|
54
|
+
instance = region.get_instance_type('m1.large')
|
55
|
+
bem = instance.get_breakeven_month(:linux, :heavy, :year1)
|
56
|
+
assert bem == 6
|
64
57
|
end
|
65
58
|
|
66
59
|
def test_memory
|
67
60
|
# Validate instance types in specific regions are available
|
68
61
|
pricing = AwsPricing::PriceList.new
|
69
62
|
region = pricing.get_region('us-east')
|
70
|
-
instance = region.get_instance_type(
|
63
|
+
instance = region.get_instance_type('m1.large')
|
71
64
|
assert instance.memory_in_mb == 7500
|
72
65
|
end
|
73
66
|
|
74
67
|
def test_non_standard_region_name
|
75
68
|
pricing = AwsPricing::PriceList.new
|
76
69
|
region = pricing.get_region('eu-west-1')
|
77
|
-
instance = region.get_instance_type(
|
70
|
+
instance = region.get_instance_type('m1.large')
|
78
71
|
assert instance.memory_in_mb == 7500
|
79
72
|
end
|
80
73
|
|
@@ -101,7 +94,7 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
|
|
101
94
|
def test_virtual_cores
|
102
95
|
pricing = AwsPricing::PriceList.new
|
103
96
|
region = pricing.get_region('us-east')
|
104
|
-
instance = region.get_instance_type(
|
97
|
+
instance = region.get_instance_type('m1.large')
|
105
98
|
assert instance.virtual_cores == 2
|
106
99
|
end
|
107
100
|
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amazon-pricing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Joe Kinsella
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
date: 2013-07-19 00:00:00.000000000 Z
|
@@ -29,8 +29,8 @@ files:
|
|
29
29
|
- lib/amazon-pricing.rb
|
30
30
|
- lib/amazon-pricing/ebs-price.rb
|
31
31
|
- lib/amazon-pricing/instance-type.rb
|
32
|
+
- lib/amazon-pricing/operating-system.rb
|
32
33
|
- lib/amazon-pricing/region.rb
|
33
|
-
- lib/amazon-pricing/reserved-instance-type.rb
|
34
34
|
- lib/amazon-pricing/version.rb
|
35
35
|
- spec/instance_type_spec.rb
|
36
36
|
- spec/price_list_spec.rb
|
@@ -38,31 +38,33 @@ files:
|
|
38
38
|
- test/test-ec2-instance-types.rb
|
39
39
|
homepage: http://github.com/sonian/amazon-pricing
|
40
40
|
licenses: []
|
41
|
-
post_install_message:
|
41
|
+
post_install_message:
|
42
42
|
rdoc_options:
|
43
|
-
- --title
|
43
|
+
- "--title"
|
44
44
|
- amazon-pricing documentation
|
45
|
-
- --line-numbers
|
46
|
-
- --main
|
45
|
+
- "--line-numbers"
|
46
|
+
- "--main"
|
47
47
|
- README
|
48
48
|
require_paths:
|
49
49
|
- lib
|
50
50
|
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
51
|
requirements:
|
53
|
-
- -
|
52
|
+
- - ">="
|
54
53
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
56
|
-
|
54
|
+
version: !binary |-
|
55
|
+
MA==
|
57
56
|
none: false
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: !binary |-
|
62
|
+
MA==
|
63
|
+
none: false
|
62
64
|
requirements: []
|
63
65
|
rubyforge_project: amazon-pricing
|
64
|
-
rubygems_version: 1.8.
|
65
|
-
signing_key:
|
66
|
+
rubygems_version: 1.8.24
|
67
|
+
signing_key:
|
66
68
|
specification_version: 3
|
67
69
|
summary: Amazon Web Services Pricing Ruby gem
|
68
70
|
test_files:
|
@@ -70,4 +72,3 @@ test_files:
|
|
70
72
|
- spec/price_list_spec.rb
|
71
73
|
- test/helper.rb
|
72
74
|
- test/test-ec2-instance-types.rb
|
73
|
-
has_rdoc:
|
@@ -1,131 +0,0 @@
|
|
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-2012 Sonian
|
7
|
-
# License:: Distributes under the same terms as Ruby
|
8
|
-
# Home:: http://github.com/sonian/amazon-pricing
|
9
|
-
#++
|
10
|
-
module AwsPricing
|
11
|
-
|
12
|
-
# ReservedInstanceType is a specific type of instance reservation in a region
|
13
|
-
# with a defined price per hour, and a reservation term of 1 or 3 years. The
|
14
|
-
# price will vary by platform (Linux, Windows), and as of December 2012,
|
15
|
-
# reserved instances have three usage types: light, medium and heavy.
|
16
|
-
#
|
17
|
-
class ReservedInstanceType < InstanceType
|
18
|
-
attr_accessor :prepay_1_year, :prepay_3_year, :usage_type,
|
19
|
-
:linux_price_per_hour_3_year, :windows_price_per_hour_3_year, :rhel_price_per_hour_3_year, :sles_price_per_hour_3_year, :mswinSQL_price_per_hour_3_year, :mswinSQLWeb_price_per_hour_3_year
|
20
|
-
|
21
|
-
# Initializes and InstanceType object given a region, the internal
|
22
|
-
# type (e.g. stdODI) and the json for the specific instance. The json is
|
23
|
-
# based on the current undocumented AWS pricing API.
|
24
|
-
def initialize(region, instance_type, json, usage_type, platform)
|
25
|
-
super(region, instance_type, json, platform)
|
26
|
-
|
27
|
-
# Fixme: calling twice, fix later
|
28
|
-
json['valueColumns'].each do |val|
|
29
|
-
price = val['prices']['USD']
|
30
|
-
price = nil if price == "N/A"
|
31
|
-
|
32
|
-
case val["name"]
|
33
|
-
when "yrTerm1"
|
34
|
-
@prepay_1_year ||= price
|
35
|
-
when "yrTerm1Hourly"
|
36
|
-
if platform == :mswin
|
37
|
-
@windows_price_per_hour = price
|
38
|
-
elsif platform == :linux
|
39
|
-
@linux_price_per_hour = price
|
40
|
-
elsif platform == :rhel
|
41
|
-
@rhel_price_per_hour = price
|
42
|
-
elsif platform == :sles
|
43
|
-
@sles_price_per_hour = price
|
44
|
-
elsif platform == :mswinSQL
|
45
|
-
@mswinSQL_price_per_hour = price
|
46
|
-
elsif platform == :mswinSQLWeb
|
47
|
-
@mswinSQLWeb_price_per_hour = price
|
48
|
-
end
|
49
|
-
when "yrTerm3"
|
50
|
-
@prepay_3_year ||= price
|
51
|
-
when "yrTerm3Hourly"
|
52
|
-
if platform == :mswin
|
53
|
-
@windows_price_per_hour_3_year = price
|
54
|
-
elsif platform == :linux
|
55
|
-
@linux_price_per_hour_3_year = price
|
56
|
-
elsif platform == :rhel
|
57
|
-
@rhel_price_per_hour_3_year = price
|
58
|
-
elsif platform == :sles
|
59
|
-
@sles_price_per_hour_3_year = price
|
60
|
-
elsif platform == :mswinSQL
|
61
|
-
@mswinSQL_price_per_hour_3_year = price
|
62
|
-
elsif platform == :mswinSQLWeb
|
63
|
-
@mswinSQLWeb_price_per_hour_3_year = price
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
@usage_type = usage_type
|
68
|
-
end
|
69
|
-
|
70
|
-
def to_s
|
71
|
-
"Reserved Instance Type: #{@region.name} #{@api_name}, 1 Year Prepay=#{@prepay_1_year}, 3 Year Prepay=#{@prepay_3_year}, Linux=$#{@linux_price_per_hour}/hour, Windows=$#{@windows_price_per_hour}/hour"
|
72
|
-
end
|
73
|
-
|
74
|
-
def is_reserved?
|
75
|
-
true
|
76
|
-
end
|
77
|
-
|
78
|
-
def update(instance_type)
|
79
|
-
super
|
80
|
-
# Due to new AWS json we have to make two passes through to populate an instance
|
81
|
-
@linux_price_per_hour_3_year ||= instance_type.linux_price_per_hour_3_year
|
82
|
-
@windows_price_per_hour_3_year ||= instance_type.windows_price_per_hour_3_year
|
83
|
-
@rhel_price_per_hour_3_year ||= instance_type.rhel_price_per_hour_3_year
|
84
|
-
@sles_price_per_hour_3_year ||= instance_type.sles_price_per_hour_3_year
|
85
|
-
@mswinSQL_price_per_hour_3_year ||= instance_type.mswinSQL_price_per_hour_3_year
|
86
|
-
@mswinSQLWeb_price_per_hour_3_year ||= instance_type.mswinSQLWeb_price_per_hour_3_year
|
87
|
-
end
|
88
|
-
|
89
|
-
protected
|
90
|
-
attr_accessor :size, :instance_type
|
91
|
-
|
92
|
-
def self.get_api_name(instance_type, size)
|
93
|
-
# Let's handle new instances more gracefully
|
94
|
-
unless @@Api_Name_Lookup_Reserved.has_key? instance_type
|
95
|
-
raise UnknownTypeError, "Unknown instance type #{instance_type}", caller
|
96
|
-
else
|
97
|
-
@@Api_Name_Lookup_Reserved[instance_type][size]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.get_name(instance_type, size)
|
102
|
-
@@Name_Lookup_Reserved[instance_type][size]
|
103
|
-
end
|
104
|
-
|
105
|
-
@@Api_Name_Lookup_Reserved = {
|
106
|
-
'stdResI' => {'sm' => 'm1.small', 'med' => 'm1.medium', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
107
|
-
'hiMemResI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
108
|
-
'hiCPUResI' => {'med' => 'c1.medium', 'xl' => 'c1.xlarge'},
|
109
|
-
'clusterGPUResI' => {'xxxxl' => 'cg1.4xlarge'},
|
110
|
-
'clusterCompResI' => {'xxxxl' => 'cc1.4xlarge', 'xxxxxxxxl' => 'cc2.8xlarge'},
|
111
|
-
'uResI' => {'u' => 't1.micro'},
|
112
|
-
'hiIoResI' => {'xxxxl' => 'hi1.4xlarge'},
|
113
|
-
'secgenstdResI' => {'xl' => 'm3.xlarge', 'xxl' => 'm3.2xlarge'},
|
114
|
-
'clusterHiMemResI' => {'xxxxxxxxl' => 'cr1.8xlarge'},
|
115
|
-
'hiStoreResI' => {'xxxxxxxxl' => 'hs1.8xlarge'},
|
116
|
-
}
|
117
|
-
@@Name_Lookup_Reserved = {
|
118
|
-
'stdResI' => {'sm' => 'Standard Small', 'med' => 'Standard Medium', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
119
|
-
'hiMemResI' => {'xl' => 'Hi-Memory Extra Large', 'xxl' => 'Hi-Memory Double Extra Large', 'xxxxl' => 'Hi-Memory Quadruple Extra Large'},
|
120
|
-
'hiCPUResI' => {'med' => 'High-CPU Medium', 'xl' => 'High-CPU Extra Large'},
|
121
|
-
'clusterGPUResI' => {'xxxxl' => 'Cluster GPU Quadruple Extra Large'},
|
122
|
-
'clusterCompResI' => {'xxxxl' => 'Cluster Compute Quadruple Extra Large', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
123
|
-
'uResI' => {'u' => 'Micro'},
|
124
|
-
'hiIoResI' => {'xxxxl' => 'High I/O Quadruple Extra Large Instance'},
|
125
|
-
'secgenstdResI' => {'xl' => 'M3 Extra Large Instance', 'xxl' => 'M3 Double Extra Large Instance'},
|
126
|
-
'clusterHiMemResI' => {'xxxxxxxxl' => 'High-Memory Cluster Eight Extra Large'},
|
127
|
-
'hiStoreResI' => {'xxxxxxxxl' => 'High-Storage Eight Extra Large'},
|
128
|
-
}
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|