amazon-pricing 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,4 @@
1
+ = Version 0.0.1
2
+
3
+ * Created basic framework for dynamically retrieving pricing information
4
+ on EC2 on-demand and reserved instances.
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