Skip to content
This repository was archived by the owner on Jan 20, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ce557e2
依存gemを更新した。
juno May 7, 2011
581dbdb
added error handling for Cloudwatch.
juno May 7, 2011
0c60552
add NextToken support to Cloudwatch ListMetrics API.
juno May 7, 2011
605cd38
update ChangeLog.
juno May 7, 2011
2d71964
added Filters for instances and volumes.
juno May 7, 2011
b0d6495
add ImportKeyPair API.
juno May 7, 2011
3b932e9
update EC2 API Version to 2011-02-28.
juno May 7, 2011
066b9ea
ドキュメントを更新した。
juno May 10, 2011
54a53e2
update.
juno May 10, 2011
631c2a1
updated
juno May 10, 2011
fc863d3
HTTP リクエストの Content-Type ヘッダーに charset=utf-8 を付加した。
May 25, 2011
97ab6a6
Fix a require problem in the Ruby 1.9.
May 26, 2011
525e71d
Implement the filterlist method.
May 26, 2011
75aede1
Implement the describe_regions method.
May 26, 2011
0369045
Support filter arguments for the describe_images method.
May 26, 2011
22f260e
Support filter arguments for the describe_volumes method.
May 26, 2011
65702b4
Support filter arguments for the describe_instances method.
May 26, 2011
90e597c
Support filter arguments for the describe_snapshots method.
May 26, 2011
fa39445
Bump the version number to 0.9.18.
May 26, 2011
8185bf2
Fix a bug that the describe_snapshots rewrites the argument.
May 26, 2011
a40e5f0
DeleteSecurityGroup API の引数に :group_id を受け付けるように修正した。
May 31, 2011
9921005
CloudWatch APIの対応バージョンを2010-05-15から2010-08-01に変更した。
juno Jul 8, 2011
5bc3621
add m1.medium instance type
Jun 8, 2012
b0552c6
add m1.medium EC2 instance type
Jun 8, 2012
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
=== x.x.x 2011-06-08
* add EC2 instance_type "m1.medium". (mitsuharu_odagiri)

=== x.x.x 2011-05-08
* add NextToken support to Cloudwatch ListMetrics API. (juno)
* added error handling for Cloudwatch. (juno)
* added Filters for instances and volumes. (skade)
* add EC2 ImportKeyPair API. (juno)
* EC2#describe_security_groups : add :group_id option (juno)
* Update EC2 API Version to 2011-02-28 (juno)
* EC2#authorize_security_group_ingress : support API Version 2011-02-28 (juno)
* EC2#revoke_security_group_ingress : support API Version 2011-02-28 (juno)

=== 0.9.17 2010-11-21
* Converted from Jeweler to Bundler, 'bundle install' to install dependencies
Expand Down
17 changes: 8 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
PATH
remote: .
specs:
amazon-ec2 (0.9.17)
amazon-ec2 (0.9.19)
xml-simple (>= 1.0.12)

GEM
remote: http://rubygems.org/
specs:
mocha (0.9.9)
rake
perftools.rb (0.5.4)
rake (0.8.7)
awesome_print (0.3.2)
mocha (0.9.12)
perftools.rb (0.5.6)
rcov (0.9.9)
test-spec (0.10.0)
test-unit (2.1.2)
xml-simple (1.0.12)
yard (0.6.2)
test-unit (2.3.0)
xml-simple (1.1.0)
yard (0.6.8)

PLATFORMS
ruby

DEPENDENCIES
amazon-ec2!
awesome_print
mocha (>= 0.9.9)
perftools.rb (>= 0.5.4)
rcov (>= 0.9.9)
test-spec (>= 0.10.0)
test-unit (>= 2.1.2)
xml-simple (>= 1.0.12)
yard (>= 0.6.2)
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
amazon-ec2カスタマイズ版
====

コードに変更を加えた場合は`ChangeLog`の最上部に以下のようなエントリを追加します(バージョン番号は`x.x.x`のままでよい)。

=== x.x.x 2011-05-08
* add NextToken support to Cloudwatch ListMetrics API. (juno)

変更した`amazon-ec2`をRailsアプリケーションに含める場合は、以下のような手順で行います。

$ rake build # => pkg/amazon-ec2-0.9.15.gemが生成される

$ cd /path/to/rails-app
$ rm -rf vendor/gems/amazon-ec2-0.9.15 # => 古いamazon-ec2ライブラリを削除する
$ gem /path/to/amazon-ec2-0.9.15.gem --target vendor/gems # => 新しいamazon-ec2ライブラリを展開する
$ ls vendor/gems
amazon-ec2-0.9.15

`Gemfile`に以下の記述を追加する。

gem 'amazon-ec2', :path => 'vendor/gems/amazon-ec2-0.9.15'

依存gemを更新する。

$ bundle update

この時点で、`vendor/gems`以下および`Gemfile*`をコミットします。
1 change: 0 additions & 1 deletion README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,3 @@ Please follow these steps if you want to send a patch or a GitHub pull request:
Enjoy!

Glenn Rempe

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.15
0.9.19
1 change: 1 addition & 0 deletions amazon-ec2.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('rcov', '>= 0.9.9')
s.add_development_dependency('perftools.rb', '>= 0.5.4')
s.add_development_dependency('yard', '>= 0.6.2')
s.add_development_dependency('awesome_print')

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
Expand Down
60 changes: 56 additions & 4 deletions lib/AWS.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,50 @@ def pathkvlist(key, arr_of_hashes, key_name, value_name, mappings)
params
end

# Same as _pathhashlist_ except it generates explicit Filter.<n>.Name and Filter.<n>.Value.<m>
# depending on whether the value is a scalar or an array.
#
# So if you pass in arg
# (:name=>'jon', :names=>['chris', 'bob']),
#
# you should get
# {"Filter.1.Name"=>"name", "Filter.1.Value.1"=>'jon', "Filter.2.Name"=>'names', 'Filter.2.Value.1'=>'chris', 'Filter.2.Value.2'=>'bob'}
# or
# {"Filter.1.Name"=>'names', 'Filter.1.Value.1'=>'chris', 'Filter.1.Value.2'=>'bob', "Filter.1.Name"=>"name", "Filter.2.Value.1"=>'jon'}
#
# NOTICE: Results key order is NOT assured because of the Hash's each method does not assure the order.
# If you want to get the ordered results, please pass a Orderd Hash as the first argument. (ex. ActiveSupport::OrderedHash)
#
#
# If you use a underscored key, like
# {:instance_type => ['t1.micro', 'm1.small']}
#
# The :instance_type key is automatically fixed to 'instance-type', so you should get
# {"Filter.1.Name"=>'instance_type', 'Filter.1.Value.1'=>'t1.micro', 'Filter.1.Value.2'=>'m1.small'}
#
def filterlist(filters)
return {} if filters.nil?
raise ArgumentError, "filters must be a Hash" unless filters.is_a?(Hash)

filters.each do |key, val|
unless key.is_a?(String) || key.is_a?(Symbol)
raise ArgumentError, ":#{key} must be a String or Symbol (actual: #{key.class.name})"
end
unless val == true || val == false || val.is_a?(Symbol) || val.is_a?(String) || val.is_a?(Array)
raise ArgumentError, "#{key}[#{val}] must be a String or Symbol or Boolean or Array (actual: #{val.class.name})"
end
end

params = {}
filters.each_with_index do |key_val, idx|
params["Filter.#{idx+1}.Name"] = key_val[0].to_s.gsub(/_/, '-')
Array(key_val[1]).each_with_index do |value, i|
params["Filter.#{idx+1}.Value.#{i+1}"] = value.to_s
end
end
params
end

# Make the connection to AWS EC2 passing in our request. This is generally called from
# within a 'Response' class object or one of its sub-classes so the response is interpreted
# in its proper context. See lib/EC2/responses.rb
Expand All @@ -291,7 +335,7 @@ def make_request(action, params, data='')
end.join("&") + "&Signature=" + sig

req = Net::HTTP::Post.new(@path)
req.content_type = 'application/x-www-form-urlencoded'
req.content_type = 'application/x-www-form-urlencoded; charset=utf-8'
req['User-Agent'] = "github-amazon-ec2-ruby-gem"

response = @http.request(req, query)
Expand Down Expand Up @@ -346,17 +390,25 @@ def aws_error?(response)

# Check that the Error element is in the place we would expect.
# and if not raise a generic error exception
unless doc.root.elements['Errors'].elements['Error'].name == 'Error'
if doc.root.elements['Error'] and doc.root.elements['Error'].name == 'Error'
error_elem = doc.root.elements['Error']
elsif doc.root.elements['Errors'].elements['Error'].name == 'Error'
error_elem = doc.root.elements['Errors'].elements['Error']
else
raise Error, "Unexpected error format. response.body is: #{response.body}"
end

# An valid error response looks like this:
# <?xml version="1.0"?><Response><Errors><Error><Code>InvalidParameterCombination</Code><Message>Unknown parameter: foo</Message></Error></Errors><RequestID>291cef62-3e86-414b-900e-17246eccfae8</RequestID></Response>
#
# or this:
# <ErrorResponse xmlns="http://monitoring.amazonaws.com/doc/2009-05-15/"><Error><Type>Sender</Type><Code>InvalidClientTokenId</Code><Message>The security token included in the request is invalid</Message></Error><RequestId>1e77e1bb-2920-11e0-80c8-b71648ee0b72</RequestId></ErrorResponse>
#
# AWS throws some exception codes that look like Error.SubError. Since we can't name classes this way
# we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
# non '.' name as well.
error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text.gsub('.', '')
error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text
error_code = error_elem.elements['Code'].text.gsub('.', '')
error_message = error_elem.elements['Message'].text

# Raise one of our specific error classes if it exists.
# otherwise, throw a generic EC2 Error with a few details.
Expand Down
4 changes: 2 additions & 2 deletions lib/AWS/Cloudwatch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module Cloudwatch
DEFAULT_HOST = 'monitoring.amazonaws.com'
end

API_VERSION = '2009-05-15'
API_VERSION = '2010-08-01'

class Base < AWS::Base
def api_version
Expand All @@ -27,4 +27,4 @@ def default_host
end

end
end
end
50 changes: 40 additions & 10 deletions lib/AWS/Cloudwatch/monitoring.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,45 @@ class Base < AWS::Base
# account. To get further information from the metrics, you'll then need to
# call get_metric_statistics.
#
# there are no options available to this method.
def list_metrics
return response_generator(:action => 'ListMetrics', :params => {})
# @option options [String] :dimensions A list of dimensions to filter against. (InstanceId=i-00000001,VolumeId=vol-0000001)
# @option options [String] :metric_name The name of the metric to filter against.
# @option options [String] :namespace The namespace to filter against.
# @option options [String] :next_token The token returned by a previous call to indicate that there is more data available.
# @see http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_ListMetrics.html
def list_metrics( options ={} )
options = {
:dimensions => nil,
:metric_name => nil,
:next_token => nil,
:namespace => nil,
}.merge(options)

params = {}
params['MetricName'] = options[:metric_name] if options[:metric_name]
params['NextToken'] = options[:next_token] if options[:next_token]
params['Namespace'] = options[:namespace] if options[:namespace]

# FDT: Fix statistics and dimensions values
if !(options[:dimensions].nil? || options[:dimensions].empty?)
dims_params = {}
i = 1
options[:dimensions].split(',').each{ |dimension|
dimension_var = dimension.split('=')
dims_params = dims_params.merge!( "Dimensions.member.#{i}.Name" => "#{dimension_var[0]}", "Dimensions.member.#{i}.Value" => "#{dimension_var[1]}" )
i += 1
}
raise ArgumentError, "Maximum of 10 items in the :dimensions" if i > 10

params.merge!( dims_params )
end

return response_generator(:action => 'ListMetrics', :params => params)
end

# get_metric_statistics pulls a hashed array from Cloudwatch with the stats
# of your requested metric.
# Once you get the data out, if you assign the results into an object like:
# res = @mon.get_metric_statistics(:measure_name => 'RequestCount', \
# res = @mon.get_metric_statistics(:metric_name => 'RequestCount', \
# :statistics => 'Average', :namespace => 'AWS/ELB')
#
# This call gets the average request count against your ELB at each sampling period
Expand All @@ -25,18 +55,18 @@ def list_metrics
# @option options [String] :custom_unit (nil) not currently available, placeholder
# @option options [String] :dimensions (nil) Option to filter your data on. Check the developer guide
# @option options [Time] :end_time (Time.now()) Outer bound of the date range you want to view
# @option options [String] :measure_name (nil) The measure you want to check. Must correspond to
# => provided options
# @option options [String] :namespace ('AWS/EC2') The namespace of your measure_name. Currently, 'AWS/EC2' and 'AWS/ELB' are available
# @option options [String] :metric_name (nil) The name of the metric.
# @option options [String] :namespace ('AWS/EC2') The namespace of your metric_name. Currently, 'AWS/EC2' and 'AWS/ELB' are available
# @option options [Integer] :period (60) Granularity in seconds of the returned datapoints. Multiples of 60 only
# @option options [String] :statistics (nil) The statistics to be returned for your metric. See the developer guide for valid options. Required.
# @option options [Time] :start_time (Time.now() - 86400) Inner bound of the date range you want to view. Defaults to 24 hours ago
# @option options [String] :unit (nil) Standard unit for a given Measure. See the developer guide for valid options.
# @see http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/API_GetMetricStatistics.html
def get_metric_statistics ( options ={} )
options = { :custom_unit => nil,
:dimensions => nil,
:end_time => Time.now(), #req
:measure_name => "", #req
:metric_name => "", #req
:namespace => "AWS/EC2",
:period => 60,
:statistics => "", # req
Expand All @@ -48,13 +78,13 @@ def get_metric_statistics ( options ={} )
raise ArgumentError, ":start_time must be provided" if options[:start_time].nil?
raise ArgumentError, ":start_time must be a Time object" if options[:start_time].class != Time
raise ArgumentError, ":start_time must be before :end_time" if options[:start_time] > options[:end_time]
raise ArgumentError, ":measure_name must be provided" if options[:measure_name].nil? || options[:measure_name].empty?
raise ArgumentError, ":metric_name must be provided" if options[:metric_name].nil? || options[:metric_name].empty?
raise ArgumentError, ":statistics must be provided" if options[:statistics].nil? || options[:statistics].empty?

params = {
"CustomUnit" => options[:custom_unit],
"EndTime" => options[:end_time].iso8601,
"MeasureName" => options[:measure_name],
"MetricName" => options[:metric_name],
"Namespace" => options[:namespace],
"Period" => options[:period].to_s,
"StartTime" => options[:start_time].iso8601,
Expand Down
2 changes: 1 addition & 1 deletion lib/AWS/EC2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module EC2
DEFAULT_HOST = 'ec2.amazonaws.com'
end

API_VERSION = '2010-08-31'
API_VERSION = '2011-02-28'

class Base < AWS::Base
def api_version
Expand Down
50 changes: 46 additions & 4 deletions lib/AWS/EC2/availability_zones.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ module AWS
module EC2
class Base < AWS::Base

# describe_availability_zones filters list
DESCRIBE_AVAILABILITY_ZONES_FILTERS = [
:message,
:region_name,
:state,
:zone_name
]

# describe_availability_zones alternative filter names
DESCRIBE_AVAILABILITY_ZONES_FILTER_ALTERNATIVES = { :zone_name_filter => :zone_name, }

# describe_regions filter list
DESCRIBE_REGIONS_FILTERS = [:endpoint, :region_name]

# describe_regions alternative filter names
DESCRIBE_REGIONS_FILTER_ALTERNAITVES = { :region_name_filter => :region_name, }


# The DescribeAvailabilityZones operation describes availability zones that are currently
# available to the account and their states.
#
Expand All @@ -11,16 +29,40 @@ class Base < AWS::Base
#
def describe_availability_zones( options = {} )
options = { :zone_name => [] }.merge(options)
params = pathlist("ZoneName", options[:zone_name] )
params = pathlist("ZoneName", options.delete(:zone_name))

DESCRIBE_AVAILABILITY_ZONES_FILTER_ALTERNATIVES.each do |alternative_key, original_key|
next unless options.include?(alternative_key)
options[original_key] = options.delete(alternative_key)
end

invalid_filters = options.keys - DESCRIBE_AVAILABILITY_ZONES_FILTERS
raise ArgumentError, "invalid filter(s): #{invalid_filters.join(', ')}" if invalid_filters.any?
params.merge!(filterlist(options))
return response_generator(:action => "DescribeAvailabilityZones", :params => params)
end

# Not yet implemented
# The DescribeRegions operation describes regions.
#
# An optional list of region names can be passed.
#
# @todo Implement this method
# @option options [optional, String] :region_name ([]) an Array of region names
# @option options [optional, String] :endpoint ([]) an Array of endpoint
# @option options [optional, String] :region_name_filter ([]) an Array of region names
#
def describe_regions( options = {} )
raise "Not yet implemented"
options = { :zone_name => [] }.merge(options)
params = pathlist("ZoneName", options.delete(:zone_name))

DESCRIBE_REGIONS_FILTER_ALTERNAITVES.each do |alternative_key, original_key|
next unless options.include?(alternative_key)
options[original_key] = options.delete(alternative_key)
end

invalid_filters = options.keys - DESCRIBE_REGIONS_FILTERS
raise ArgumentError, "invalid filter(s): #{invalid_filters.join(', ')}" if invalid_filters.any?
params.merge!(filterlist(options))
return response_generator(:action => "DescribeRegions", :params => params)
end

end
Expand Down
Loading