amazon-pricing 0.0.8 → 0.0.9
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 +5 -7
- data/lib/amazon-pricing.rb +28 -30
- data/lib/amazon-pricing/ebs-price.rb +32 -0
- data/lib/amazon-pricing/instance-type.rb +1 -6
- data/lib/amazon-pricing/region.rb +2 -2
- data/lib/amazon-pricing/reserved-instance-type.rb +3 -2
- data/lib/amazon-pricing/version.rb +1 -1
- data/test/test-ec2-instance-types.rb +18 -2
- metadata +5 -4
data/Rakefile
CHANGED
@@ -32,15 +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
36
|
pricing.regions.each do |region|
|
36
|
-
|
37
|
-
|
38
|
-
region.ec2_on_demand_instance_types.each do |instance_type|
|
39
|
-
puts " #{instance_type.to_s}"
|
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}"
|
40
39
|
end
|
41
|
-
|
42
|
-
|
43
|
-
puts " #{instance_type.to_s}"
|
40
|
+
region.ec2_reserved_instance_types.each do |t|
|
41
|
+
puts "#{region.name},#{t.usage_type},#{t.api_name},#{t.linux_price_per_hour},#{t.windows_price_per_hour}"
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
data/lib/amazon-pricing.rb
CHANGED
@@ -26,6 +26,7 @@ module AwsPricing
|
|
26
26
|
@_regions = {}
|
27
27
|
get_ec2_on_demand_instance_pricing
|
28
28
|
get_ec2_reserved_instance_pricing
|
29
|
+
fetch_ec2_ebs_pricing
|
29
30
|
end
|
30
31
|
|
31
32
|
def get_region(name)
|
@@ -38,10 +39,9 @@ module AwsPricing
|
|
38
39
|
|
39
40
|
# Type = :on_demand or :reserved
|
40
41
|
# reserved_usage_type = :light, :medium, :heavy
|
41
|
-
def get_instance_type(
|
42
|
-
region_name = @@Availability_Zone_Lookup[availability_zone]
|
43
|
-
raise "Region not found for availability zone #{availability_zone}" if region_name.nil?
|
42
|
+
def get_instance_type(region_name, type, api_name, reserved_usage_type = :medium)
|
44
43
|
region = get_region(region_name)
|
44
|
+
raise "Region #{region_name} not found" if region.nil?
|
45
45
|
region.get_instance_type(type, api_name, reserved_usage_type)
|
46
46
|
end
|
47
47
|
|
@@ -66,9 +66,7 @@ module AwsPricing
|
|
66
66
|
|
67
67
|
# Retrieves the EC2 on-demand instance pricing.
|
68
68
|
def get_ec2_on_demand_instance_pricing
|
69
|
-
|
70
|
-
page = Net::HTTP.get_response(uri)
|
71
|
-
res = JSON.parse(page.body)
|
69
|
+
res = fetch_url(EC2_BASE_URL + "on-demand-instances.json")
|
72
70
|
@version_ec2_on_demand_instance = res['vers']
|
73
71
|
res['config']['regions'].each do |reg|
|
74
72
|
region_name = reg['region']
|
@@ -82,51 +80,51 @@ module AwsPricing
|
|
82
80
|
end
|
83
81
|
|
84
82
|
def get_ec2_reserved_instance_pricing
|
85
|
-
fetch_ec2_reserved_instance_pricing(
|
86
|
-
fetch_ec2_reserved_instance_pricing(
|
87
|
-
fetch_ec2_reserved_instance_pricing(
|
83
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "reserved-instances-low-utilization.json", :light)
|
84
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "reserved-instances.json", :medium)
|
85
|
+
fetch_ec2_reserved_instance_pricing(EC2_BASE_URL + "reserved-instances-high-utilization.json", :heavy)
|
88
86
|
end
|
89
87
|
|
90
88
|
# Retrieves the EC2 on-demand instance pricing.
|
91
89
|
# reserved_usage_type = :light, :medium, :heavy
|
92
90
|
def fetch_ec2_reserved_instance_pricing(url, reserved_usage_type)
|
93
|
-
|
94
|
-
page = Net::HTTP.get_response(uri)
|
95
|
-
res = JSON.parse(page.body)
|
91
|
+
res = fetch_url(url)
|
96
92
|
@version_ec2_reserved_instance = res['vers']
|
97
93
|
res['config']['regions'].each do |reg|
|
98
94
|
region_name = reg['region']
|
99
95
|
region = find_or_create_region(region_name)
|
100
96
|
reg['instanceTypes'].each do |type|
|
101
97
|
type['sizes'].each do |size|
|
102
|
-
region.add_instance_type(:reserved, ReservedInstanceType.new(region, type['type'], size), reserved_usage_type)
|
98
|
+
region.add_instance_type(:reserved, ReservedInstanceType.new(region, type['type'], size, reserved_usage_type), reserved_usage_type)
|
103
99
|
end
|
104
100
|
end
|
105
101
|
end
|
106
102
|
end
|
107
103
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
104
|
+
def fetch_ec2_ebs_pricing
|
105
|
+
res = fetch_url(EC2_BASE_URL + "ebs.json")
|
106
|
+
res["config"]["regions"].each do |ebs_types|
|
107
|
+
region = get_region(ebs_types["region"])
|
108
|
+
region.ebs_price = EbsPrice.new(region, ebs_types)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def fetch_url(url)
|
113
|
+
uri = URI.parse(url)
|
114
|
+
page = Net::HTTP.get_response(uri)
|
115
|
+
JSON.parse(page.body)
|
116
|
+
end
|
117
|
+
|
118
|
+
EC2_BASE_URL = "http://aws.amazon.com/ec2/pricing/pricing-"
|
119
|
+
|
120
|
+
# Lookup allows us to map to AWS API region names
|
123
121
|
@@Region_Lookup = {
|
124
122
|
'us-east-1' => 'us-east',
|
125
123
|
'us-west-1' => 'us-west',
|
126
124
|
'us-west-2' => 'us-west-2',
|
127
125
|
'eu-west-1' => 'eu-ireland',
|
128
|
-
'ap-southeast-1' => 'apac-sin',
|
129
|
-
'ap-northeast-1' => 'apac-tokyo',
|
126
|
+
'ap-southeast-1' => 'apac-sin',
|
127
|
+
'ap-northeast-1' => 'apac-tokyo',
|
130
128
|
'sa-east-1' => 'sa-east-1'
|
131
129
|
}
|
132
130
|
end
|
@@ -0,0 +1,32 @@
|
|
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 EbsPrice
|
13
|
+
attr_reader :standard_per_gb, :standard_per_million_io,
|
14
|
+
:preferred_per_gb, :preferred_per_iops, :s3_snaps_per_gb
|
15
|
+
|
16
|
+
def initialize(region, json)
|
17
|
+
json["types"].each do |t|
|
18
|
+
case t["name"]
|
19
|
+
when "ebsVols"
|
20
|
+
@standard_per_gb = t["values"].select{|v| v["rate"] == "perGBmoProvStorage" }.first["prices"].values.first.to_f
|
21
|
+
@standard_per_million_io = t["values"].select{|v| v["rate"] == "perMMIOreq" }.first["prices"].values.first.to_f
|
22
|
+
when "ebsPIOPSVols"
|
23
|
+
@preferred_per_gb = t["values"].select{|v| v["rate"] == "perGBmoProvStorage" }.first["prices"].values.first.to_f
|
24
|
+
@preferred_per_iops = t["values"].select{|v| v["rate"] == "perPIOPSreq" }.first["prices"].values.first.to_f
|
25
|
+
when "ebsSnapsToS3"
|
26
|
+
@s3_snaps_per_gb = t["values"].select{|v| v["rate"] == "perGBmoDataStored" }.first["prices"].values.first.to_f
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -16,7 +16,7 @@ module AwsPricing
|
|
16
16
|
# $0.48/hour for Windows.
|
17
17
|
#
|
18
18
|
class InstanceType
|
19
|
-
attr_accessor :
|
19
|
+
attr_accessor :name, :api_name, :linux_price_per_hour, :windows_price_per_hour,
|
20
20
|
:memory_in_mb, :disk_in_mb, :platform, :compute_units
|
21
21
|
|
22
22
|
# Initializes and InstanceType object given a region, the internal
|
@@ -25,7 +25,6 @@ module AwsPricing
|
|
25
25
|
def initialize(region, instance_type, json)
|
26
26
|
values = get_values(json)
|
27
27
|
|
28
|
-
@region = region
|
29
28
|
@size = json['size']
|
30
29
|
@linux_price_per_hour = values['linux'].to_f
|
31
30
|
@linux_price_per_hour = nil if @linux_price_per_hour == 0
|
@@ -50,10 +49,6 @@ module AwsPricing
|
|
50
49
|
return @linux_price_per_hour != nil || @windows_price_per_hour != nil
|
51
50
|
end
|
52
51
|
|
53
|
-
def to_s
|
54
|
-
"Instance Type: #{@region.name} #{@api_name}, Linux=$#{@linux_price_per_hour}/hour, Windows=$#{@windows_price_per_hour}/hour"
|
55
|
-
end
|
56
|
-
|
57
52
|
protected
|
58
53
|
|
59
54
|
attr_accessor :size, :instance_type
|
@@ -15,7 +15,7 @@ module AwsPricing
|
|
15
15
|
# e.g. us-east, us-west
|
16
16
|
#
|
17
17
|
class Region
|
18
|
-
attr_accessor :name
|
18
|
+
attr_accessor :name, :ebs_price
|
19
19
|
|
20
20
|
def initialize(name)
|
21
21
|
@name = name
|
@@ -39,7 +39,7 @@ module AwsPricing
|
|
39
39
|
when :heavy
|
40
40
|
@_ec2_reserved_instance_types_heavy.values
|
41
41
|
else
|
42
|
-
@_ec2_reserved_instance_types_light.values
|
42
|
+
@_ec2_reserved_instance_types_light.values + @_ec2_reserved_instance_types_medium.values + @_ec2_reserved_instance_types_heavy.values
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -15,12 +15,12 @@ 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
|
18
|
+
attr_accessor :prepay_1_year, :prepay_3_year, :usage_type
|
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)
|
23
|
+
def initialize(region, instance_type, json, usage_type)
|
24
24
|
super(region, instance_type, json)
|
25
25
|
|
26
26
|
# Fixme: calling twice, fix later
|
@@ -28,6 +28,7 @@ module AwsPricing
|
|
28
28
|
|
29
29
|
@prepay_1_year = values['yrTerm1'].to_f unless values['yrTerm1'].to_f == 0
|
30
30
|
@prepay_3_year = values['yrTerm3'].to_f unless values['yrTerm3'].to_f == 0
|
31
|
+
@usage_type = usage_type
|
31
32
|
end
|
32
33
|
|
33
34
|
def to_s
|
@@ -16,8 +16,7 @@ require 'test/unit'
|
|
16
16
|
class TestEc2InstanceTypes < Test::Unit::TestCase
|
17
17
|
def test_cc8xlarge_issue
|
18
18
|
pricing = AwsPricing::PriceList.new
|
19
|
-
obj = pricing.get_instance_type('us-east
|
20
|
-
puts obj.inspect
|
19
|
+
obj = pricing.get_instance_type('us-east', :reserved, 'cc2.8xlarge', :medium)
|
21
20
|
assert obj.api_name == 'cc2.8xlarge'
|
22
21
|
end
|
23
22
|
|
@@ -69,4 +68,21 @@ class TestEc2InstanceTypes < Test::Unit::TestCase
|
|
69
68
|
instance = region.get_instance_type(:on_demand, 'm1.large')
|
70
69
|
assert instance.memory_in_mb == 7500
|
71
70
|
end
|
71
|
+
|
72
|
+
def test_non_standard_region_name
|
73
|
+
pricing = AwsPricing::PriceList.new
|
74
|
+
region = pricing.get_region('eu-west-1')
|
75
|
+
instance = region.get_instance_type(:on_demand, 'm1.large')
|
76
|
+
assert instance.memory_in_mb == 7500
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_ebs
|
80
|
+
pricing = AwsPricing::PriceList.new
|
81
|
+
region = pricing.get_region('us-east')
|
82
|
+
assert region.ebs_price.standard_per_gb == 0.10
|
83
|
+
assert region.ebs_price.standard_per_million_io == 0.10
|
84
|
+
assert region.ebs_price.preferred_per_gb == 0.125
|
85
|
+
assert region.ebs_price.preferred_per_iops == 0.10
|
86
|
+
assert region.ebs_price.s3_snaps_per_gb == 0.125
|
87
|
+
end
|
72
88
|
end
|
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: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
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-08-
|
18
|
+
date: 2012-08-13 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- Rakefile
|
37
37
|
- amazon-pricing.gemspec
|
38
38
|
- lib/amazon-pricing.rb
|
39
|
+
- lib/amazon-pricing/ebs-price.rb
|
39
40
|
- lib/amazon-pricing/instance-type.rb
|
40
41
|
- lib/amazon-pricing/region.rb
|
41
42
|
- lib/amazon-pricing/reserved-instance-type.rb
|