amazon-pricing 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/LICENSE +66 -0
- data/README +84 -0
- data/Rakefile +42 -0
- data/amazon-pricing.gemspec +27 -0
- data/lib/amazon-pricing/instance-type.rb +129 -0
- data/lib/amazon-pricing/region.rb +94 -0
- data/lib/amazon-pricing/reserved-instance-type.rb +66 -0
- data/lib/amazon-pricing/version.rb +12 -0
- data/lib/amazon-pricing.rb +105 -0
- data/test/helper.rb +12 -0
- data/test/test-ec2-instance-types.rb +61 -0
- metadata +85 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
Copyright (c) 2007-2009 Glenn Rempe
|
2
|
+
|
3
|
+
This software is distributed under the Ruby License. A copy of which is
|
4
|
+
provided below.
|
5
|
+
|
6
|
+
RUBY LICENSE
|
7
|
+
|
8
|
+
http://www.ruby-lang.org/en/LICENSE.txt
|
9
|
+
|
10
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
11
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
12
|
+
(see COPYING.txt file), or the conditions below:
|
13
|
+
|
14
|
+
1. You may make and give away verbatim copies of the source form of the
|
15
|
+
software without restriction, provided that you duplicate all of the
|
16
|
+
original copyright notices and associated disclaimers.
|
17
|
+
|
18
|
+
2. You may modify your copy of the software in any way, provided that
|
19
|
+
you do at least ONE of the following:
|
20
|
+
|
21
|
+
a) place your modifications in the Public Domain or otherwise
|
22
|
+
make them Freely Available, such as by posting said
|
23
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
24
|
+
the author to include your modifications in the software.
|
25
|
+
|
26
|
+
b) use the modified software only within your corporation or
|
27
|
+
organization.
|
28
|
+
|
29
|
+
c) rename any non-standard executables so the names do not conflict
|
30
|
+
with standard executables, which must also be provided.
|
31
|
+
|
32
|
+
d) make other distribution arrangements with the author.
|
33
|
+
|
34
|
+
3. You may distribute the software in object code or executable
|
35
|
+
form, provided that you do at least ONE of the following:
|
36
|
+
|
37
|
+
a) distribute the executables and library files of the software,
|
38
|
+
together with instructions (in the manual page or equivalent)
|
39
|
+
on where to get the original distribution.
|
40
|
+
|
41
|
+
b) accompany the distribution with the machine-readable source of
|
42
|
+
the software.
|
43
|
+
|
44
|
+
c) give non-standard executables non-standard names, with
|
45
|
+
instructions on where to get the original software distribution.
|
46
|
+
|
47
|
+
d) make other distribution arrangements with the author.
|
48
|
+
|
49
|
+
4. You may modify and include the part of the software into any other
|
50
|
+
software (possibly commercial). But some files in the distribution
|
51
|
+
are not written by the author, so that they are not under this terms.
|
52
|
+
|
53
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
54
|
+
files under the ./missing directory. See each file for the copying
|
55
|
+
condition.
|
56
|
+
|
57
|
+
5. The scripts and library files supplied as input to or produced as
|
58
|
+
output from the software do not automatically fall under the
|
59
|
+
copyright of the software, but belong to whomever generated them,
|
60
|
+
and may be sold commercially, and may be aggregated with this
|
61
|
+
software.
|
62
|
+
|
63
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
64
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
65
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
66
|
+
PURPOSE.
|
data/README
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
= Amazon Web Services Pricing Ruby Gem
|
2
|
+
|
3
|
+
== About amazon-pricing
|
4
|
+
|
5
|
+
Amazon Web Services offers cloud-based on demand compute, storage and application services. Due to the number of services, and the number of pricing variables in each service, the pricing model is very complex. In addition, this pricing changes periodically. The amazon-pricing Ruby Gem is an interface library that simplifies the real-time retrieval of pricing information from Amazon.
|
6
|
+
|
7
|
+
|
8
|
+
For the most complete and up-to date README information please visit the project homepage at:
|
9
|
+
|
10
|
+
http://github.com/sonian/amazon-pricing/tree/master
|
11
|
+
|
12
|
+
|
13
|
+
== Installation
|
14
|
+
|
15
|
+
This gem follows the standard conventions for installation on any system with Ruby and RubyGems installed and uses Bundler for gem installation and build management.
|
16
|
+
|
17
|
+
=== Get an AWS account
|
18
|
+
|
19
|
+
Before you can make use of this gem you will need an Amazon Web Services account.
|
20
|
+
|
21
|
+
=== Install the amazon-pricing gem (Canonical Release)
|
22
|
+
|
23
|
+
This is the standard install for stable releases from RubyGems.
|
24
|
+
|
25
|
+
# Install the gem
|
26
|
+
[sudo] gem install amazon-pricing
|
27
|
+
|
28
|
+
=== Install from local Git clone (for amazon-pricing developers)
|
29
|
+
|
30
|
+
To install from git for adding features or fixing bugs, you'll need to clone and build.
|
31
|
+
|
32
|
+
git clone git://github.com/sonian/amazon-pricing.git
|
33
|
+
cd amazon-pricing
|
34
|
+
bundle install
|
35
|
+
rake test
|
36
|
+
rake build
|
37
|
+
rake install
|
38
|
+
|
39
|
+
|
40
|
+
== Using amazon-pricing
|
41
|
+
|
42
|
+
The library exposes one main interface class AwsPricing::PriceList that allows you to retrieve pricing information from Amazon. The information is retrieved using undocumented json APIs - so has the potential to undergo change from time to time.
|
43
|
+
|
44
|
+
=== The Basics
|
45
|
+
|
46
|
+
The library exposes one main interface module
|
47
|
+
|
48
|
+
AwsPricing::PriceList
|
49
|
+
|
50
|
+
== Additional Resources
|
51
|
+
|
52
|
+
=== Project Websites
|
53
|
+
|
54
|
+
* Project Home : http://github.com/sonian/amazon-pricing/tree/master
|
55
|
+
* API Documentation : http://rdoc.info/projects/sonian/amazon-pricing
|
56
|
+
* Report Bugs / Request Features : http://github.com/sonian/amazon-pricing/issues
|
57
|
+
* Amazon Web Services : http://aws.amazon.com
|
58
|
+
|
59
|
+
== Credits
|
60
|
+
|
61
|
+
Thanks for Amazon developers for provided Json APIs to the pricing data (albeit undocumented).
|
62
|
+
|
63
|
+
== Contact
|
64
|
+
|
65
|
+
Comments, patches, Git pull requests and bug reports are welcome. Send an email to mailto:joe.kinsella@gmail.com.
|
66
|
+
|
67
|
+
== Patches & Pull Requests
|
68
|
+
|
69
|
+
Please follow these steps if you want to send a patch or a GitHub pull request:
|
70
|
+
|
71
|
+
* Fork sonian/amazon-pricing
|
72
|
+
* Create a topic branch: `git checkout -b my_fix`
|
73
|
+
* Make sure you add tests for your changes and that they all pass with 'rake test'
|
74
|
+
* Don't change files that you don't own like the gemspec or version.rb
|
75
|
+
* Commit your changes, one change/fix per commit
|
76
|
+
* Push your fixes branch: `git push origin my_fix`
|
77
|
+
* Open an Issue on GitHub referencing your branch and send a pull request.
|
78
|
+
* Please do not push to `master` on your fork. Using a feature/bugfix branch will make everyone’s life easier.
|
79
|
+
|
80
|
+
|
81
|
+
Enjoy!
|
82
|
+
|
83
|
+
Sonian
|
84
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |test|
|
5
|
+
test.libs << 'lib' << 'test'
|
6
|
+
test.pattern = 'test/**/test_*.rb'
|
7
|
+
test.verbose = true
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
desc "Build the gem"
|
12
|
+
task :gem do
|
13
|
+
sh 'gem build *.gemspec'
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Installs the gem"
|
17
|
+
task :install => :gem do
|
18
|
+
sh "#{SUDO} gem install amazon-pricing.gem --no-rdoc --no-ri"
|
19
|
+
end
|
20
|
+
|
21
|
+
task :test do
|
22
|
+
ruby "test/test-ec2-instance-types.rb"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Prints current EC2 pricing to console"
|
26
|
+
task :print_price_list do
|
27
|
+
require 'lib/amazon-pricing'
|
28
|
+
pricing = AwsPricing::PriceList.new
|
29
|
+
pricing.regions.each do |region|
|
30
|
+
puts "Region: #{region.name}"
|
31
|
+
puts " On-demand instances"
|
32
|
+
region.ec2_on_demand_instance_types.each do |instance_type|
|
33
|
+
puts " #{instance_type.to_s}"
|
34
|
+
end
|
35
|
+
puts " Reserved instances"
|
36
|
+
region.ec2_reserved_instance_types.each do |instance_type|
|
37
|
+
puts " #{instance_type.to_s}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default => [:test]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "amazon-pricing/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "amazon-pricing"
|
7
|
+
s.version = AwsPricing::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Joe Kinsella"]
|
10
|
+
s.email = ["joe.kinsella@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/sonian/amazon-pricing"
|
12
|
+
s.summary = "Amazon Web Services Pricing Ruby gem"
|
13
|
+
s.description = "A Ruby library for retrieving pricing for Amazon Web Services"
|
14
|
+
|
15
|
+
s.rubyforge_project = "amazon-pricing"
|
16
|
+
|
17
|
+
s.rdoc_options = ["--title", "amazon-pricing documentation", "--line-numbers", "--main", "README"]
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE",
|
20
|
+
"README"
|
21
|
+
]
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
@@ -0,0 +1,129 @@
|
|
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
|
+
# InstanceType is a specific type of instance in a region with a defined
|
13
|
+
# price per hour. The price will vary by platform (Linux, Windows).
|
14
|
+
#
|
15
|
+
# e.g. m1.large instance in US-East region will cost $0.34/hour for Linux and
|
16
|
+
# $0.48/hour for Windows.
|
17
|
+
#
|
18
|
+
class InstanceType
|
19
|
+
attr_accessor :region, :name, :api_name, :linux_price_per_hour, :windows_price_per_hour,
|
20
|
+
:memory_in_mb, :disk_in_mb, :platform, :compute_units
|
21
|
+
|
22
|
+
# Initializes and InstanceType object given a region, the internal
|
23
|
+
# type (e.g. stdODI) and the json for the specific instance. The json is
|
24
|
+
# based on the current undocumented AWS pricing API.
|
25
|
+
def initialize(region, instance_type, json)
|
26
|
+
values = get_values(json)
|
27
|
+
|
28
|
+
@region = region
|
29
|
+
@size = json['size']
|
30
|
+
@linux_price_per_hour = values['linux'].to_f
|
31
|
+
@linux_price_per_hour = nil if @linux_price_per_hour == 0
|
32
|
+
@windows_price_per_hour = values['mswin'].to_f
|
33
|
+
@windows_price_per_hour = nil if @windows_price_per_hour == 0
|
34
|
+
@instance_type = instance_type
|
35
|
+
|
36
|
+
@api_name = get_api_name(@instance_type, @size)
|
37
|
+
@name = get_name(@instance_type, @size)
|
38
|
+
|
39
|
+
@memory_in_mb = @@Memory_Lookup[@api_name]
|
40
|
+
@disk_in_mb = @@Disk_Lookup[@api_name]
|
41
|
+
@platform = @@Platform_Lookup[@api_name]
|
42
|
+
@compute_units = @@Compute_Units_Lookup[@api_name]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns whether an instance_type is available.
|
46
|
+
# Optionally can specify the specific platform (:linix or :windows).
|
47
|
+
def available?(platform = nil)
|
48
|
+
return @linux_price_per_hour != nil if platform == :linux
|
49
|
+
return @windows_price_per_hour != nil if platform == :windows
|
50
|
+
return @linux_price_per_hour != nil || @windows_price_per_hour != nil
|
51
|
+
end
|
52
|
+
|
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
|
+
protected
|
58
|
+
|
59
|
+
attr_accessor :size, :instance_type
|
60
|
+
|
61
|
+
def get_api_name(instance_type, size)
|
62
|
+
@@Api_Name_Lookup[instance_type][size]
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_name(instance_type, size)
|
66
|
+
@@Name_Lookup[instance_type][size]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Turn json into hash table for parsing
|
70
|
+
def get_values(json)
|
71
|
+
values = {}
|
72
|
+
json['valueColumns'].each do |val|
|
73
|
+
values[val['name']] = val['prices']['USD']
|
74
|
+
end
|
75
|
+
values
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
@@Api_Name_Lookup = {
|
80
|
+
'stdODI' => {'sm' => 'm1.small', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
81
|
+
'hiMemODI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
82
|
+
'hiCPUODI' => {'med' => 'c1.medium', 'xl' => 'c1.xlarge'},
|
83
|
+
'clusterGPUI' => {'xxxxl' => 'cg1.4xlarge'},
|
84
|
+
'clusterComputeI' => {'xxxxl' => 'cc1.4xlarge','xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
85
|
+
'uODI' => {'u' => 't1.micro'},
|
86
|
+
}
|
87
|
+
@@Name_Lookup = {
|
88
|
+
'stdODI' => {'sm' => 'Standard Small', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
89
|
+
'hiMemODI' => {'xl' => 'Hi-Memory Extra Large', 'xxl' => 'Hi-Memory Double Extra Large', 'xxxxl' => 'Hi-Memory Quadruple Extra Large'},
|
90
|
+
'hiCPUODI' => {'med' => 'High-CPU Medium', 'xl' => 'High-CPU Extra Large'},
|
91
|
+
'clusterGPUI' => {'xxxxl' => 'Cluster GPU Quadruple Extra Large'},
|
92
|
+
'clusterComputeI' => {'xxxxl' => 'Cluster Compute Quadruple Extra Large', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
93
|
+
'uODI' => {'u' => 'Micro'},
|
94
|
+
}
|
95
|
+
@@Memory_Lookup = {
|
96
|
+
'm1.small' => 1700, 'm1.large' => 7500, 'm1.xlarge' => 15000,
|
97
|
+
'm2.xlarge' => 17100, 'm2.2xlarge' => 34200, 'm2.4xlarge' => 68400,
|
98
|
+
'c1.medium' => 1700, 'c1.xlarge' => 7000,
|
99
|
+
'cg1.4xlarge' => 22000,
|
100
|
+
'cc1.4xlarge' => 23000,
|
101
|
+
't1.micro' => 1700,
|
102
|
+
}
|
103
|
+
@@Disk_Lookup = {
|
104
|
+
'm1.small' => 160, 'm1.large' =>850, 'm1.xlarge' => 1690,
|
105
|
+
'm2.xlarge' => 420, 'm2.2xlarge' => 850, 'm2.4xlarge' => 1690,
|
106
|
+
'c1.medium' => 350, 'c1.xlarge' => 1690,
|
107
|
+
'cg1.4xlarge' => 1690,
|
108
|
+
'cc1.4xlarge' => 1690,
|
109
|
+
't1.micro' => 160,
|
110
|
+
}
|
111
|
+
@@Platform_Lookup = {
|
112
|
+
'm1.small' => 32, 'm1.large' => 64, 'm1.xlarge' => 64,
|
113
|
+
'm2.xlarge' => 64, 'm2.2xlarge' => 64, 'm2.4xlarge' => 64,
|
114
|
+
'c1.medium' => 32, 'c1.xlarge' => 64,
|
115
|
+
'cg1.4xlarge' => 64,
|
116
|
+
'cc1.4xlarge' => 64,
|
117
|
+
't1.micro' => 32,
|
118
|
+
}
|
119
|
+
@@Compute_Units_Lookup = {
|
120
|
+
'm1.small' => 1, 'm1.large' => 4, 'm1.xlarge' => 8,
|
121
|
+
'm2.xlarge' => 6, 'm2.2xlarge' => 13, 'm2.4xlarge' => 26,
|
122
|
+
'c1.medium' => 5, 'c1.xlarge' => 20,
|
123
|
+
'cg1.4xlarge' => 34,
|
124
|
+
'cc1.4xlarge' => 34,
|
125
|
+
't1.micro' => 2,
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,94 @@
|
|
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
|
+
# Region represents a geographic area in which Amazon Web Services has
|
12
|
+
# one or more data centers. Different regions will offer difference services
|
13
|
+
# and pricing.
|
14
|
+
#
|
15
|
+
# e.g. us-east, us-west
|
16
|
+
#
|
17
|
+
class Region
|
18
|
+
attr_accessor :name
|
19
|
+
|
20
|
+
def initialize(name)
|
21
|
+
@name = name
|
22
|
+
@_ec2_on_demand_instance_types = {}
|
23
|
+
@_ec2_reserved_instance_types_light = {}
|
24
|
+
@_ec2_reserved_instance_types_medium = {}
|
25
|
+
@_ec2_reserved_instance_types_heavy = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def ec2_on_demand_instance_types
|
29
|
+
@_ec2_on_demand_instance_types.values
|
30
|
+
end
|
31
|
+
|
32
|
+
# reserved_usage_type = :light, :medium, :heavy
|
33
|
+
def ec2_reserved_instance_types(reserved_usage_type)
|
34
|
+
case reserved_usage_type
|
35
|
+
when :light
|
36
|
+
@_ec2_reserved_instance_types_light.values
|
37
|
+
when :medium
|
38
|
+
@_ec2_reserved_instance_types_medium.values
|
39
|
+
when :heavy
|
40
|
+
@_ec2_reserved_instance_types_heavy.values
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns whether an instance_type is available. Must specify the type
|
45
|
+
# (:on_demand or :reserved) and instance type (m1.large). Optionally can
|
46
|
+
# specify the specific platform (:linix or :windows).
|
47
|
+
def instance_type_available?(type, api_name, platform = nil)
|
48
|
+
get_instance_type(type, api_name).available?(platform)
|
49
|
+
end
|
50
|
+
|
51
|
+
# instance_type = :on_demand or :reserved
|
52
|
+
# reserved_usage_type = :light, :medium, :heavy
|
53
|
+
def add_instance_type(type, instance_type, reserved_usage_type = :medium)
|
54
|
+
raise "Instance type #{instance_type.api_name} in region #{@name} already exists" if get_instance_type(type, instance_type.api_name, reserved_usage_type)
|
55
|
+
if type == :on_demand
|
56
|
+
@_ec2_on_demand_instance_types[instance_type.api_name] = instance_type
|
57
|
+
elsif type == :reserved
|
58
|
+
case reserved_usage_type
|
59
|
+
when :light
|
60
|
+
@_ec2_reserved_instance_types_light[instance_type.api_name] = instance_type
|
61
|
+
when :medium
|
62
|
+
@_ec2_reserved_instance_types_medium[instance_type.api_name] = instance_type
|
63
|
+
when :heavy
|
64
|
+
@_ec2_reserved_instance_types_heavy[instance_type.api_name] = instance_type
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Type = :on_demand or :reserved
|
70
|
+
# reserved_usage_type = :light, :medium, :heavy
|
71
|
+
def get_instance_type(type, api_name, reserved_usage_type = :medium)
|
72
|
+
if type == :on_demand
|
73
|
+
@_ec2_on_demand_instance_types[api_name]
|
74
|
+
elsif type == :reserved
|
75
|
+
case reserved_usage_type
|
76
|
+
when :light
|
77
|
+
@_ec2_reserved_instance_types_light[api_name]
|
78
|
+
when :medium
|
79
|
+
@_ec2_reserved_instance_types_medium[api_name]
|
80
|
+
when :heavy
|
81
|
+
@_ec2_reserved_instance_types_heavy[api_name]
|
82
|
+
end
|
83
|
+
else
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
attr_accessor :_ec2_on_demand_instance_types, :_ec2_reserved_instance_types_light, :_ec2_reserved_instance_types_medium, :_ec2_reserved_instance_types_heavy
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,66 @@
|
|
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
|
19
|
+
|
20
|
+
# Initializes and InstanceType object given a region, the internal
|
21
|
+
# type (e.g. stdODI) and the json for the specific instance. The json is
|
22
|
+
# based on the current undocumented AWS pricing API.
|
23
|
+
def initialize(region, instance_type, json)
|
24
|
+
super(region, instance_type, json)
|
25
|
+
|
26
|
+
# Fixme: calling twice, fix later
|
27
|
+
values = get_values(json)
|
28
|
+
|
29
|
+
@prepay_1_year = values['yrTerm1'].to_f unless values['yrTerm1'].to_f == 0
|
30
|
+
@prepay_3_year = values['yrTerm3'].to_f unless values['yrTerm3'].to_f == 0
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"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"
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
attr_accessor :size, :instance_type
|
39
|
+
|
40
|
+
def get_api_name(instance_type, size)
|
41
|
+
@@Api_Name_Lookup_Reserved[instance_type][size]
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_name(instance_type, size)
|
45
|
+
@@Name_Lookup_Reserved[instance_type][size]
|
46
|
+
end
|
47
|
+
|
48
|
+
@@Api_Name_Lookup_Reserved = {
|
49
|
+
'stdResI' => {'sm' => 'm1.small', 'lg' => 'm1.large', 'xl' => 'm1.xlarge'},
|
50
|
+
'hiMemResI' => {'xl' => 'm2.xlarge', 'xxl' => 'm2.2xlarge', 'xxxxl' => 'm2.4xlarge'},
|
51
|
+
'hiCPUResI' => {'med' => 'c1.medium', 'xl' => 'c1.xlarge'},
|
52
|
+
'clusterGPUResI' => {'xxxxl' => 'cg1.4xlarge'},
|
53
|
+
'clusterCompResI' => {'xxxxl' => 'cc1.4xlarge', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
54
|
+
'uResI' => {'u' => 't1.micro'},
|
55
|
+
}
|
56
|
+
@@Name_Lookup_Reserved = {
|
57
|
+
'stdResI' => {'sm' => 'Standard Small', 'lg' => 'Standard Large', 'xl' => 'Standard Extra Large'},
|
58
|
+
'hiMemResI' => {'xl' => 'Hi-Memory Extra Large', 'xxl' => 'Hi-Memory Double Extra Large', 'xxxxl' => 'Hi-Memory Quadruple Extra Large'},
|
59
|
+
'hiCPUResI' => {'med' => 'High-CPU Medium', 'xl' => 'High-CPU Extra Large'},
|
60
|
+
'clusterGPUResI' => {'xxxxl' => 'Cluster GPU Quadruple Extra Large'},
|
61
|
+
'clusterCompResI' => {'xxxxl' => 'Cluster Compute Quadruple Extra Large', 'xxxxxxxxl' => 'Cluster Compute Eight Extra Large'},
|
62
|
+
'uResI' => {'u' => 'Micro'},
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,12 @@
|
|
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
|
+
VERSION = '0.0.2'
|
12
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
Dir[File.join(File.dirname(__FILE__), 'amazon-pricing/*.rb')].sort.each { |lib| require lib }
|
5
|
+
|
6
|
+
#--
|
7
|
+
# Amazon Web Services Pricing Ruby library
|
8
|
+
#
|
9
|
+
# Ruby Gem Name:: amazon-pricing
|
10
|
+
# Author:: Joe Kinsella (mailto:joe.kinsella@gmail.com)
|
11
|
+
# Copyright:: Copyright (c) 2011-2012 Sonian
|
12
|
+
# License:: Distributes under the same terms as Ruby
|
13
|
+
# Home:: http://github.com/sonian/amazon-pricing
|
14
|
+
#++
|
15
|
+
module AwsPricing
|
16
|
+
|
17
|
+
# PriceList provides the primary interface for retrieving AWS pricing.
|
18
|
+
# Upon instantiating a PriceList object, all the corresponding pricing
|
19
|
+
# information will be retrieved from Amazon via currently undocumented
|
20
|
+
# json APIs.
|
21
|
+
class PriceList
|
22
|
+
attr_accessor :regions, :version_ec2_on_demand_instance,
|
23
|
+
:version_ec2_reserved_instance
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@_regions = {}
|
27
|
+
get_ec2_on_demand_instance_pricing
|
28
|
+
get_ec2_reserved_instance_pricing
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_region(name)
|
32
|
+
@_regions[name]
|
33
|
+
end
|
34
|
+
|
35
|
+
def regions
|
36
|
+
@_regions.values
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
attr_accessor :_regions
|
42
|
+
|
43
|
+
def add_region(region)
|
44
|
+
@_regions[region.name] = region
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_or_create_region(name)
|
48
|
+
region = get_region(name)
|
49
|
+
if region.nil?
|
50
|
+
region = Region.new(name)
|
51
|
+
add_region(region)
|
52
|
+
end
|
53
|
+
region
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
# Retrieves the EC2 on-demand instance pricing.
|
59
|
+
def get_ec2_on_demand_instance_pricing
|
60
|
+
uri = URI.parse(EC2_STANDARD_INSTANCE_PRICING_URL)
|
61
|
+
page = Net::HTTP.get_response(uri)
|
62
|
+
res = JSON.parse(page.body)
|
63
|
+
@version_ec2_on_demand_instance = res['vers']
|
64
|
+
res['config']['regions'].each do |reg|
|
65
|
+
region_name = reg['region']
|
66
|
+
region = find_or_create_region(region_name)
|
67
|
+
reg['instanceTypes'].each do |type|
|
68
|
+
type['sizes'].each do |size|
|
69
|
+
region.add_instance_type(:on_demand, InstanceType.new(region, type['type'], size))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_ec2_reserved_instance_pricing
|
76
|
+
fetch_ec2_reserved_instance_pricing(EC2_RESERVED_INSTANCE_LIGHT_PRICING_URL, :low)
|
77
|
+
fetch_ec2_reserved_instance_pricing(EC2_RESERVED_INSTANCE_MEDIUM_PRICING_URL, :medium)
|
78
|
+
fetch_ec2_reserved_instance_pricing(EC2_RESERVED_INSTANCE_HEAVY_PRICING_URL, :heavy)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Retrieves the EC2 on-demand instance pricing.
|
82
|
+
# reserved_usage_type = :light, :medium, :heavy
|
83
|
+
def fetch_ec2_reserved_instance_pricing(url, reserved_usage_type)
|
84
|
+
uri = URI.parse(url)
|
85
|
+
page = Net::HTTP.get_response(uri)
|
86
|
+
res = JSON.parse(page.body)
|
87
|
+
@version_ec2_reserved_instance = res['vers']
|
88
|
+
res['config']['regions'].each do |reg|
|
89
|
+
region_name = reg['region']
|
90
|
+
region = find_or_create_region(region_name)
|
91
|
+
reg['instanceTypes'].each do |type|
|
92
|
+
type['sizes'].each do |size|
|
93
|
+
region.add_instance_type(:reserved, ReservedInstanceType.new(region, type['type'], size), reserved_usage_type)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
EC2_STANDARD_INSTANCE_PRICING_URL = 'http://aws.amazon.com/ec2/pricing/pricing-on-demand-instances.json'
|
100
|
+
EC2_RESERVED_INSTANCE_LIGHT_PRICING_URL = 'http://aws.amazon.com/ec2/pricing/pricing-reserved-instances-low-utilization.json'
|
101
|
+
EC2_RESERVED_INSTANCE_MEDIUM_PRICING_URL = 'http://aws.amazon.com/ec2/pricing/pricing-reserved-instances.json'
|
102
|
+
EC2_RESERVED_INSTANCE_HEAVY_PRICING_URL = 'http://aws.amazon.com/ec2/pricing/pricing-reserved-instances-high-utilization.json'
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#--
|
2
|
+
# IBM SmartCloud 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
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require File.dirname(__FILE__) + '/../lib/amazon-pricing'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Amazon Web Services Pricing Ruby library
|
5
|
+
#
|
6
|
+
# Ruby Gem Name:: amazon-pricing
|
7
|
+
# Author:: Joe Kinsella (mailto:joe.kinsella@gmail.com)
|
8
|
+
# Copyright:: Copyright (c) 2011-2012 Sonian
|
9
|
+
# License:: Distributes under the same terms as Ruby
|
10
|
+
# Home:: http://github.com/sonian/amazon-pricing
|
11
|
+
#++
|
12
|
+
|
13
|
+
require File.dirname(__FILE__) + '/helper.rb'
|
14
|
+
require 'test/unit'
|
15
|
+
|
16
|
+
class TestEc2InstanceTypes < Test::Unit::TestCase
|
17
|
+
def test_name_lookup
|
18
|
+
pricing = AwsPricing::PriceList.new
|
19
|
+
pricing.regions.each do |region|
|
20
|
+
assert_not_nil region.name
|
21
|
+
region.ec2_on_demand_instance_types.each do |instance_type|
|
22
|
+
assert_not_nil instance_type.api_name
|
23
|
+
assert_not_nil instance_type.name
|
24
|
+
end
|
25
|
+
region.ec2_reserved_instance_types(:light).each do |instance_type|
|
26
|
+
assert_not_nil instance_type.api_name
|
27
|
+
assert_not_nil instance_type.name
|
28
|
+
end
|
29
|
+
region.ec2_reserved_instance_types(:medium).each do |instance_type|
|
30
|
+
assert_not_nil instance_type.api_name
|
31
|
+
assert_not_nil instance_type.name
|
32
|
+
end
|
33
|
+
region.ec2_reserved_instance_types(:heavy).each do |instance_type|
|
34
|
+
assert_not_nil instance_type.api_name
|
35
|
+
assert_not_nil instance_type.name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_unavailable
|
41
|
+
# Validate instance types in specific regions are not available
|
42
|
+
pricing = AwsPricing::PriceList.new
|
43
|
+
region = pricing.get_region('apac-tokyo')
|
44
|
+
assert !region.instance_type_available?(:on_demand, 'cc1.4xlarge')
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_available
|
48
|
+
# Validate instance types in specific regions are available
|
49
|
+
pricing = AwsPricing::PriceList.new
|
50
|
+
region = pricing.get_region('us-east')
|
51
|
+
assert region.instance_type_available?(:on_demand, 'm1.large')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_memory
|
55
|
+
# Validate instance types in specific regions are available
|
56
|
+
pricing = AwsPricing::PriceList.new
|
57
|
+
region = pricing.get_region('us-east')
|
58
|
+
instance = region.get_instance_type(:on_demand, 'm1.large')
|
59
|
+
assert instance.memory_in_mb == 7500
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: amazon-pricing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joe Kinsella
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-03-03 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: A Ruby library for retrieving pricing for Amazon Web Services
|
23
|
+
email:
|
24
|
+
- joe.kinsella@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files:
|
30
|
+
- LICENSE
|
31
|
+
- README
|
32
|
+
files:
|
33
|
+
- CHANGELOG
|
34
|
+
- LICENSE
|
35
|
+
- README
|
36
|
+
- Rakefile
|
37
|
+
- amazon-pricing.gemspec
|
38
|
+
- lib/amazon-pricing.rb
|
39
|
+
- lib/amazon-pricing/instance-type.rb
|
40
|
+
- lib/amazon-pricing/region.rb
|
41
|
+
- lib/amazon-pricing/reserved-instance-type.rb
|
42
|
+
- lib/amazon-pricing/version.rb
|
43
|
+
- test/helper.rb
|
44
|
+
- test/test-ec2-instance-types.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/sonian/amazon-pricing
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --title
|
52
|
+
- amazon-pricing documentation
|
53
|
+
- --line-numbers
|
54
|
+
- --main
|
55
|
+
- README
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: amazon-pricing
|
79
|
+
rubygems_version: 1.3.7
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Amazon Web Services Pricing Ruby gem
|
83
|
+
test_files:
|
84
|
+
- test/helper.rb
|
85
|
+
- test/test-ec2-instance-types.rb
|