amazon-pricing 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +3 -3
- data/lib/amazon-pricing.rb +12 -9
- data/lib/amazon-pricing/instance-type.rb +10 -0
- data/lib/amazon-pricing/region.rb +16 -12
- data/lib/amazon-pricing/reserved-instance-type.rb +45 -8
- data/lib/amazon-pricing/version.rb +1 -1
- metadata +4 -4
data/Rakefile
CHANGED
@@ -32,13 +32,13 @@ desc "Prints current EC2 pricing to console"
|
|
32
32
|
task :print_price_list do
|
33
33
|
require 'lib/amazon-pricing'
|
34
34
|
pricing = AwsPricing::PriceList.new
|
35
|
-
puts "Region,Instance Type,Linux PPH,Windows PPH"
|
35
|
+
puts "Region,Instance Type,Linux PPH,Windows PPH,Prepay 1 Year,Prepay 3 Year"
|
36
36
|
pricing.regions.each do |region|
|
37
37
|
region.ec2_on_demand_instance_types.each do |t|
|
38
|
-
puts "#{region.name},on-demand,#{t.api_name},#{t.linux_price_per_hour},#{t.windows_price_per_hour}"
|
38
|
+
puts "#{region.name},on-demand,#{t.api_name},#{t.linux_price_per_hour},#{t.windows_price_per_hour},,,,"
|
39
39
|
end
|
40
40
|
region.ec2_reserved_instance_types.each do |t|
|
41
|
-
puts "#{region.name},#{t.usage_type},#{t.api_name},#{t.
|
41
|
+
puts "#{region.name},#{t.usage_type},#{t.api_name},#{t.linux_price_per_hour_1_year},#{t.windows_price_per_hour_1_year},#{t.linux_price_per_hour_3_year},#{t.windows_price_per_hour_3_year}#{t.prepay_1_year},#{t.prepay_3_year}"
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/amazon-pricing.rb
CHANGED
@@ -66,28 +66,31 @@ module AwsPricing
|
|
66
66
|
|
67
67
|
# Retrieves the EC2 on-demand instance pricing.
|
68
68
|
def get_ec2_on_demand_instance_pricing
|
69
|
-
res = fetch_url(EC2_BASE_URL + "on-demand-instances.json")
|
69
|
+
res = fetch_url(EC2_BASE_URL + "pricing-on-demand-instances.json")
|
70
70
|
@version_ec2_on_demand_instance = res['vers']
|
71
71
|
res['config']['regions'].each do |reg|
|
72
72
|
region_name = reg['region']
|
73
73
|
region = find_or_create_region(region_name)
|
74
74
|
reg['instanceTypes'].each do |type|
|
75
75
|
type['sizes'].each do |size|
|
76
|
-
region.
|
76
|
+
region.add_or_update_instance_type(:on_demand, InstanceType.new(region, type['type'], size))
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
82
|
def get_ec2_reserved_instance_pricing
|
83
|
-
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "
|
84
|
-
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "
|
85
|
-
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "
|
83
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-light-linux.json", :light, :linux)
|
84
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-light-mswin.json", :light, :windows)
|
85
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-medium-linux.json", :medium, :linux)
|
86
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-medium-mswin.json", :medium, :windows)
|
87
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-heavy-linux.json", :heavy, :linux)
|
88
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "ri-heavy-mswin.json", :heavy, :windows)
|
86
89
|
end
|
87
90
|
|
88
91
|
# Retrieves the EC2 on-demand instance pricing.
|
89
92
|
# reserved_usage_type = :light, :medium, :heavy
|
90
|
-
def fetch_ec2_reserved_instance_pricing(url, reserved_usage_type)
|
93
|
+
def fetch_ec2_reserved_instance_pricing(url, reserved_usage_type, platform)
|
91
94
|
res = fetch_url(url)
|
92
95
|
@version_ec2_reserved_instance = res['vers']
|
93
96
|
res['config']['regions'].each do |reg|
|
@@ -95,14 +98,14 @@ module AwsPricing
|
|
95
98
|
region = find_or_create_region(region_name)
|
96
99
|
reg['instanceTypes'].each do |type|
|
97
100
|
type['sizes'].each do |size|
|
98
|
-
region.
|
101
|
+
region.add_or_update_instance_type(:reserved, ReservedInstanceType.new(region, type['type'], size, reserved_usage_type, platform), reserved_usage_type)
|
99
102
|
end
|
100
103
|
end
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
104
107
|
def fetch_ec2_ebs_pricing
|
105
|
-
res = fetch_url(EC2_BASE_URL + "ebs.json")
|
108
|
+
res = fetch_url(EC2_BASE_URL + "pricing-ebs.json")
|
106
109
|
res["config"]["regions"].each do |ebs_types|
|
107
110
|
region = get_region(ebs_types["region"])
|
108
111
|
region.ebs_price = EbsPrice.new(region, ebs_types)
|
@@ -115,7 +118,7 @@ module AwsPricing
|
|
115
118
|
JSON.parse(page.body)
|
116
119
|
end
|
117
120
|
|
118
|
-
EC2_BASE_URL = "http://aws.amazon.com/ec2/pricing/
|
121
|
+
EC2_BASE_URL = "http://aws.amazon.com/ec2/pricing/"
|
119
122
|
|
120
123
|
# Lookup allows us to map to AWS API region names
|
121
124
|
@@Region_Lookup = {
|
@@ -49,6 +49,16 @@ module AwsPricing
|
|
49
49
|
return @linux_price_per_hour != nil || @windows_price_per_hour != nil
|
50
50
|
end
|
51
51
|
|
52
|
+
def is_reserved?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def update(instance_type)
|
57
|
+
# Due to new AWS json we have to make two passes through to populate an instance
|
58
|
+
@windows_price_per_hour = instance_type.windows_price_per_hour if @windows_price_per_hour.nil?
|
59
|
+
@linux_price_per_hour = instance_type.linux_price_per_hour if @linux_price_per_hour.nil?
|
60
|
+
end
|
61
|
+
|
52
62
|
protected
|
53
63
|
|
54
64
|
attr_accessor :size, :instance_type
|
@@ -52,19 +52,23 @@ module AwsPricing
|
|
52
52
|
|
53
53
|
# instance_type = :on_demand or :reserved
|
54
54
|
# reserved_usage_type = :light, :medium, :heavy
|
55
|
-
def
|
56
|
-
|
57
|
-
if
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
55
|
+
def add_or_update_instance_type(type, instance_type, reserved_usage_type = :medium)
|
56
|
+
current = get_instance_type(type, instance_type.api_name, reserved_usage_type)
|
57
|
+
if current.nil?
|
58
|
+
if type == :on_demand
|
59
|
+
@_ec2_on_demand_instance_types[instance_type.api_name] = instance_type
|
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
|
67
69
|
end
|
70
|
+
else
|
71
|
+
current.update(instance_type)
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
@@ -15,26 +15,61 @@ module AwsPricing
|
|
15
15
|
# reserved instances have three usage types: light, medium and heavy.
|
16
16
|
#
|
17
17
|
class ReservedInstanceType < InstanceType
|
18
|
-
attr_accessor :prepay_1_year, :prepay_3_year, :usage_type
|
18
|
+
attr_accessor :prepay_1_year, :prepay_3_year, :usage_type, :linux_price_per_hour_3_year, :windows_price_per_hour_3_year
|
19
19
|
|
20
20
|
# Initializes and InstanceType object given a region, the internal
|
21
21
|
# type (e.g. stdODI) and the json for the specific instance. The json is
|
22
22
|
# based on the current undocumented AWS pricing API.
|
23
|
-
def initialize(region, instance_type, json, usage_type)
|
23
|
+
def initialize(region, instance_type, json, usage_type, platform)
|
24
24
|
super(region, instance_type, json)
|
25
25
|
|
26
26
|
# Fixme: calling twice, fix later
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
json['valueColumns'].each do |val|
|
28
|
+
case val["name"]
|
29
|
+
when "yrTerm1"
|
30
|
+
@prepay_1_year = val['prices']['USD'].to_f unless val['prices']['USD'].to_f == 0
|
31
|
+
when "yrTerm1Hourly"
|
32
|
+
if platform == :windows
|
33
|
+
@windows_price_per_hour = val['prices']['USD']
|
34
|
+
elsif platform == :linux
|
35
|
+
@linux_price_per_hour = val['prices']['USD']
|
36
|
+
end
|
37
|
+
when "yrTerm3"
|
38
|
+
@prepay_3_year = val['prices']['USD'].to_f unless val['prices']['USD'].to_f == 0
|
39
|
+
when "yrTerm3Hourly"
|
40
|
+
if platform == :windows
|
41
|
+
@windows_price_per_hour_3_year = val['prices']['USD']
|
42
|
+
elsif platform == :linux
|
43
|
+
@linux_price_per_hour_3_year = val['prices']['USD']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
31
47
|
@usage_type = usage_type
|
32
48
|
end
|
33
49
|
|
50
|
+
def linux_price_per_hour_1_year
|
51
|
+
self.linux_price_per_hour
|
52
|
+
end
|
53
|
+
|
54
|
+
def windows_price_per_hour_1_year
|
55
|
+
self.windows_price_per_hour
|
56
|
+
end
|
57
|
+
|
34
58
|
def to_s
|
35
59
|
"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"
|
36
60
|
end
|
37
61
|
|
62
|
+
def is_reserved?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def update(instance_type)
|
67
|
+
super
|
68
|
+
# Due to new AWS json we have to make two passes through to populate an instance
|
69
|
+
@linux_price_per_hour_3_year = instance_type.linux_price_per_hour_3_year if @linux_price_per_hour_3_year.nil?
|
70
|
+
@windows_price_per_hour_3_year = instance_type.windows_price_per_hour_3_year if @windows_price_per_hour_3_year.nil?
|
71
|
+
end
|
72
|
+
|
38
73
|
protected
|
39
74
|
attr_accessor :size, :instance_type
|
40
75
|
|
@@ -47,20 +82,22 @@ module AwsPricing
|
|
47
82
|
end
|
48
83
|
|
49
84
|
@@Api_Name_Lookup_Reserved = {
|
50
|
-
'stdResI' => {'sm' => 'm1.small', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
85
|
+
'stdResI' => {'sm' => 'm1.small', 'med' => 'm1.medium', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
51
86
|
'hiMemResI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
52
87
|
'hiCPUResI' => {'med' => 'c1.medium', 'xl' => 'c1.xlarge'},
|
53
88
|
'clusterGPUResI' => {'xxxxl' => 'cg1.4xlarge'},
|
54
89
|
'clusterCompResI' => {'xxxxl' => 'cc1.4xlarge', 'xxxxxxxxl' => 'cc2.8xlarge'},
|
55
90
|
'uResI' => {'u' => 't1.micro'},
|
91
|
+
'hiIoResI' => {'xxxxl' => 'hi1.4xlarge'},
|
56
92
|
}
|
57
93
|
@@Name_Lookup_Reserved = {
|
58
|
-
'stdResI' => {'sm' => 'Standard Small', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
94
|
+
'stdResI' => {'sm' => 'Standard Small', 'med' => 'Standard Medium', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
59
95
|
'hiMemResI' => {'xl' => 'Hi-Memory Extra Large', 'xxl' => 'Hi-Memory Double Extra Large', 'xxxxl' => 'Hi-Memory Quadruple Extra Large'},
|
60
96
|
'hiCPUResI' => {'med' => 'High-CPU Medium', 'xl' => 'High-CPU Extra Large'},
|
61
97
|
'clusterGPUResI' => {'xxxxl' => 'Cluster GPU Quadruple Extra Large'},
|
62
98
|
'clusterCompResI' => {'xxxxl' => 'Cluster Compute Quadruple Extra Large', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
63
99
|
'uResI' => {'u' => 'Micro'},
|
100
|
+
'hiIoResI' => {'xxxxl' => 'High I/O Quadruple Extra Large Instance'},
|
64
101
|
}
|
65
102
|
end
|
66
103
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amazon-pricing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.9
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joe Kinsella
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-10-21 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|