nirvdrum-amazon-ec2 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +9 -0
  2. data/.yardopts +1 -0
  3. data/ChangeLog +304 -0
  4. data/LICENSE +66 -0
  5. data/README.rdoc +359 -0
  6. data/README_dev.rdoc +10 -0
  7. data/Rakefile +70 -0
  8. data/VERSION +1 -0
  9. data/amazon-ec2.gemspec +142 -0
  10. data/bin/ec2-gem-example.rb +137 -0
  11. data/bin/ec2-gem-profile.rb +10 -0
  12. data/bin/ec2sh +62 -0
  13. data/bin/setup.rb +29 -0
  14. data/deps.rip +1 -0
  15. data/lib/AWS.rb +321 -0
  16. data/lib/AWS/Autoscaling.rb +70 -0
  17. data/lib/AWS/Autoscaling/autoscaling.rb +273 -0
  18. data/lib/AWS/Cloudwatch.rb +32 -0
  19. data/lib/AWS/Cloudwatch/monitoring.rb +80 -0
  20. data/lib/AWS/EC2.rb +33 -0
  21. data/lib/AWS/EC2/availability_zones.rb +29 -0
  22. data/lib/AWS/EC2/console.rb +25 -0
  23. data/lib/AWS/EC2/devpay.rb +18 -0
  24. data/lib/AWS/EC2/elastic_ips.rb +86 -0
  25. data/lib/AWS/EC2/image_attributes.rb +133 -0
  26. data/lib/AWS/EC2/images.rb +117 -0
  27. data/lib/AWS/EC2/instances.rb +234 -0
  28. data/lib/AWS/EC2/keypairs.rb +47 -0
  29. data/lib/AWS/EC2/products.rb +21 -0
  30. data/lib/AWS/EC2/security_groups.rb +164 -0
  31. data/lib/AWS/EC2/snapshots.rb +102 -0
  32. data/lib/AWS/EC2/spot_instance_requests.rb +105 -0
  33. data/lib/AWS/EC2/volumes.rb +100 -0
  34. data/lib/AWS/ELB.rb +71 -0
  35. data/lib/AWS/ELB/load_balancers.rb +178 -0
  36. data/lib/AWS/RDS.rb +73 -0
  37. data/lib/AWS/RDS/rds.rb +522 -0
  38. data/lib/AWS/exceptions.rb +200 -0
  39. data/lib/AWS/responses.rb +21 -0
  40. data/perftools/ec2prof +0 -0
  41. data/perftools/ec2prof-results.dot +132 -0
  42. data/perftools/ec2prof-results.txt +100 -0
  43. data/perftools/ec2prof.symbols +102 -0
  44. data/test/test_Autoscaling_groups.rb +337 -0
  45. data/test/test_EC2.rb +68 -0
  46. data/test/test_EC2_availability_zones.rb +49 -0
  47. data/test/test_EC2_console.rb +54 -0
  48. data/test/test_EC2_elastic_ips.rb +144 -0
  49. data/test/test_EC2_image_attributes.rb +238 -0
  50. data/test/test_EC2_images.rb +229 -0
  51. data/test/test_EC2_instances.rb +611 -0
  52. data/test/test_EC2_keypairs.rb +123 -0
  53. data/test/test_EC2_products.rb +48 -0
  54. data/test/test_EC2_responses.rb +53 -0
  55. data/test/test_EC2_s3_xmlsimple.rb +80 -0
  56. data/test/test_EC2_security_groups.rb +205 -0
  57. data/test/test_EC2_snapshots.rb +83 -0
  58. data/test/test_EC2_spot_instance_requests.rb +178 -0
  59. data/test/test_EC2_volumes.rb +142 -0
  60. data/test/test_ELB_load_balancers.rb +239 -0
  61. data/test/test_RDS.rb +354 -0
  62. data/test/test_helper.rb +23 -0
  63. data/wsdl/2007-08-29.ec2.wsdl +1269 -0
  64. data/wsdl/2008-02-01.ec2.wsdl +1614 -0
  65. data/wsdl/2008-05-05.ec2.wsdl +2052 -0
  66. data/wsdl/2008-12-01.ec2.wsdl +2354 -0
  67. data/wsdl/2009-10-31.ec2.wsdl +4261 -0
  68. data/wsdl/2009-11-30.ec2.wsdl +4668 -0
  69. metadata +199 -0
@@ -0,0 +1 @@
1
+ xml-simple 1.0.12
@@ -0,0 +1,321 @@
1
+ #--
2
+ # Amazon Web Services EC2 + ELB API Ruby library
3
+ #
4
+ # Ruby Gem Name:: amazon-ec2
5
+ # Author:: Glenn Rempe (mailto:glenn@rempe.us)
6
+ # Copyright:: Copyright (c) 2007-2009 Glenn Rempe
7
+ # License:: Distributes under the same terms as Ruby
8
+ # Home:: http://github.com/grempe/amazon-ec2/tree/master
9
+ #++
10
+
11
+ %w[ base64 cgi openssl digest/sha1 net/https rexml/document time ostruct ].each { |f| require f }
12
+
13
+ begin
14
+ require 'xmlsimple' unless defined? XmlSimple
15
+ rescue Exception => e
16
+ require 'xml-simple' unless defined? XmlSimple
17
+ end
18
+
19
+
20
+ # A custom implementation of Hash that allows us to access hash values using dot notation
21
+ #
22
+ # @example Access the hash keys in the standard way or using dot notation
23
+ # foo[:bar] => "baz"
24
+ # foo.bar => "baz"
25
+ class Hash
26
+ def method_missing(meth, *args, &block)
27
+ if args.size == 0
28
+ self[meth.to_s] || self[meth.to_sym]
29
+ end
30
+ end
31
+
32
+ def type
33
+ self['type']
34
+ end
35
+
36
+ def has?(key)
37
+ self[key] && !self[key].to_s.empty?
38
+ end
39
+
40
+ def does_not_have?(key)
41
+ self[key].nil? || self[key].to_s.empty?
42
+ end
43
+ end
44
+
45
+
46
+ module AWS
47
+
48
+ # Builds the canonical string for signing requests. This strips out all '&', '?', and '='
49
+ # from the query string to be signed. The parameters in the path passed in must already
50
+ # be sorted in case-insensitive alphabetical order and must not be url encoded.
51
+ #
52
+ # @param [String] params the params that will be sorted and encoded as a canonical string.
53
+ # @param [String] host the hostname of the API endpoint.
54
+ # @param [String] method the HTTP method that will be used to submit the params.
55
+ # @param [String] base the URI path that this information will be submitted to.
56
+ # @return [String] the canonical request description string.
57
+ def AWS.canonical_string(params, host, method="POST", base="/")
58
+ # Sort, and encode parameters into a canonical string.
59
+ sorted_params = params.sort {|x,y| x[0] <=> y[0]}
60
+ encoded_params = sorted_params.collect do |p|
61
+ encoded = (CGI::escape(p[0].to_s) +
62
+ "=" + CGI::escape(p[1].to_s))
63
+ # Ensure spaces are encoded as '%20', not '+'
64
+ encoded.gsub('+', '%20')
65
+ end
66
+ sigquery = encoded_params.join("&")
67
+
68
+ # Generate the request description string
69
+ req_desc =
70
+ method + "\n" +
71
+ host + "\n" +
72
+ base + "\n" +
73
+ sigquery
74
+
75
+ end
76
+
77
+ # Encodes the given string with the secret_access_key by taking the
78
+ # hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
79
+ # url encode the result of that to protect the string if it's going to
80
+ # be used as a query string parameter.
81
+ #
82
+ # @param [String] secret_access_key the user's secret access key for signing.
83
+ # @param [String] str the string to be hashed and encoded.
84
+ # @param [Boolean] urlencode whether or not to url encode the result., true or false
85
+ # @return [String] the signed and encoded string.
86
+ def AWS.encode(secret_access_key, str, urlencode=true)
87
+ digest = OpenSSL::Digest::Digest.new('sha1')
88
+ b64_hmac =
89
+ Base64.encode64(
90
+ OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
91
+
92
+ if urlencode
93
+ return CGI::escape(b64_hmac)
94
+ else
95
+ return b64_hmac
96
+ end
97
+ end
98
+
99
+ # This class provides all the methods for using the EC2 or ELB service
100
+ # including the handling of header signing and other security concerns.
101
+ # This class uses the Net::HTTP library to interface with the AWS Query API
102
+ # interface. You should not instantiate this directly, instead
103
+ # you should setup an instance of 'AWS::EC2::Base' or 'AWS::ELB::Base'.
104
+ class Base
105
+
106
+ attr_reader :use_ssl, :server, :proxy_server, :port
107
+
108
+ # @option options [String] :access_key_id ("") The user's AWS Access Key ID
109
+ # @option options [String] :secret_access_key ("") The user's AWS Secret Access Key
110
+ # @option options [Boolean] :use_ssl (true) Connect using SSL?
111
+ # @option options [String] :server ("ec2.amazonaws.com") The server API endpoint host
112
+ # @option options [String] :proxy_server (nil) An HTTP proxy server FQDN
113
+ # @return [Object] the object.
114
+ def initialize( options = {} )
115
+
116
+ options = { :access_key_id => "",
117
+ :secret_access_key => "",
118
+ :use_ssl => true,
119
+ :server => default_host,
120
+ :proxy_server => nil
121
+ }.merge(options)
122
+
123
+ @server = options[:server]
124
+ @proxy_server = options[:proxy_server]
125
+ @use_ssl = options[:use_ssl]
126
+
127
+ raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty?
128
+ raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty?
129
+ raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
130
+ raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
131
+ raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
132
+
133
+ if options[:port]
134
+ # user-specified port
135
+ @port = options[:port]
136
+ elsif @use_ssl
137
+ # https
138
+ @port = 443
139
+ else
140
+ # http
141
+ @port = 80
142
+ end
143
+
144
+ @access_key_id = options[:access_key_id]
145
+ @secret_access_key = options[:secret_access_key]
146
+
147
+ # Use proxy server if defined
148
+ # Based on patch by Mathias Dalheimer. 20070217
149
+ proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new
150
+ @http = Net::HTTP::Proxy( proxy.host,
151
+ proxy.port,
152
+ proxy.user,
153
+ proxy.password).new(options[:server], @port)
154
+
155
+ @http.use_ssl = @use_ssl
156
+
157
+ # Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET.
158
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
159
+
160
+ end
161
+
162
+ # If :user_data is passed in then URL escape and Base64 encode it
163
+ # as needed. Need for URL Escape + Base64 encoding is determined
164
+ # by :base64_encoded param.
165
+ def extract_user_data( options = {} )
166
+ return unless options[:user_data]
167
+ if options[:user_data]
168
+ if options[:base64_encoded]
169
+ Base64.encode64(options[:user_data]).gsub(/\n/, "").strip()
170
+ else
171
+ options[:user_data]
172
+ end
173
+ end
174
+ end
175
+
176
+
177
+ protected
178
+
179
+ # pathlist is a utility method which takes a key string and and array as input.
180
+ # It converts the array into a Hash with the hash key being 'Key.n' where
181
+ # 'n' increments by 1 for each iteration. So if you pass in args
182
+ # ("ImageId", ["123", "456"]) you should get
183
+ # {"ImageId.1"=>"123", "ImageId.2"=>"456"} returned.
184
+ def pathlist(key, arr)
185
+ params = {}
186
+
187
+ # ruby 1.9 will barf if we pass in a string instead of the array expected.
188
+ # it will fail on each_with_index below since string is not enumerable.
189
+ if arr.is_a? String
190
+ new_arr = []
191
+ new_arr << arr
192
+ arr = new_arr
193
+ end
194
+
195
+ arr.each_with_index do |value, i|
196
+ params["#{key}.#{i+1}"] = value
197
+ end
198
+ params
199
+ end
200
+
201
+ # Same as _pathlist_ except it deals with arrays of hashes.
202
+ # So if you pass in args
203
+ # ("People", [{:name=>'jon', :age=>'22'}, {:name=>'chris'}], {:name => 'Name', :age => 'Age'}) you should get
204
+ # {"People.1.Name"=>"jon", "People.1.Age"=>'22', 'People.2.Name'=>'chris'}
205
+ def pathhashlist(key, arr_of_hashes, mappings)
206
+ raise ArgumentError, "expected a key that is a String" unless key.is_a? String
207
+ raise ArgumentError, "expected a arr_of_hashes that is an Array" unless arr_of_hashes.is_a? Array
208
+ arr_of_hashes.each{|h| raise ArgumentError, "expected each element of arr_of_hashes to be a Hash" unless h.is_a?(Hash)}
209
+ raise ArgumentError, "expected a mappings that is an Hash" unless mappings.is_a? Hash
210
+ params = {}
211
+ arr_of_hashes.each_with_index do |hash, i|
212
+ hash.each do |attribute, value|
213
+ params["#{key}.#{i+1}.#{mappings[attribute]}"] = value.to_s
214
+ end
215
+ end
216
+ params
217
+ end
218
+
219
+ # Make the connection to AWS EC2 passing in our request. This is generally called from
220
+ # within a 'Response' class object or one of its sub-classes so the response is interpreted
221
+ # in its proper context. See lib/EC2/responses.rb
222
+ def make_request(action, params, data='')
223
+
224
+ @http.start do
225
+
226
+ # remove any keys that have nil or empty values
227
+ params.reject! { |key, value| value.nil? or value.empty?}
228
+
229
+ params.merge!( {"Action" => action,
230
+ "SignatureVersion" => "2",
231
+ "SignatureMethod" => 'HmacSHA1',
232
+ "AWSAccessKeyId" => @access_key_id,
233
+ "Version" => api_version,
234
+ "Timestamp"=>Time.now.getutc.iso8601} )
235
+
236
+ sig = get_aws_auth_param(params, @secret_access_key, @server)
237
+
238
+ query = params.sort.collect do |param|
239
+ CGI::escape(param[0]) + "=" + CGI::escape(param[1])
240
+ end.join("&") + "&Signature=" + sig
241
+
242
+ req = Net::HTTP::Post.new("/")
243
+ req.content_type = 'application/x-www-form-urlencoded'
244
+ req['User-Agent'] = "github-amazon-ec2-ruby-gem"
245
+
246
+ response = @http.request(req, query)
247
+
248
+ # Make a call to see if we need to throw an error based on the response given by EC2
249
+ # All error classes are defined in EC2/exceptions.rb
250
+ aws_error?(response)
251
+ return response
252
+
253
+ end
254
+
255
+ end
256
+
257
+ # Set the Authorization header using AWS signed header authentication
258
+ def get_aws_auth_param(params, secret_access_key, server)
259
+ canonical_string = AWS.canonical_string(params, server)
260
+ encoded_canonical = AWS.encode(secret_access_key, canonical_string)
261
+ end
262
+
263
+ # allow us to have a one line call in each method which will do all of the work
264
+ # in making the actual request to AWS.
265
+ def response_generator( options = {} )
266
+
267
+ options = {
268
+ :action => "",
269
+ :params => {}
270
+ }.merge(options)
271
+
272
+ raise ArgumentError, ":action must be provided to response_generator" if options[:action].nil? || options[:action].empty?
273
+
274
+ http_response = make_request(options[:action], options[:params])
275
+ http_xml = http_response.body
276
+ return Response.parse(:xml => http_xml)
277
+ end
278
+
279
+ # Raises the appropriate error if the specified Net::HTTPResponse object
280
+ # contains an AWS error; returns +false+ otherwise.
281
+ def aws_error?(response)
282
+
283
+ # return false if we got a HTTP 200 code,
284
+ # otherwise there is some type of error (40x,50x) and
285
+ # we should try to raise an appropriate exception
286
+ # from one of our exception classes defined in
287
+ # exceptions.rb
288
+ return false if response.is_a?(Net::HTTPSuccess)
289
+
290
+ # parse the XML document so we can walk through it
291
+ doc = REXML::Document.new(response.body)
292
+
293
+ # Check that the Error element is in the place we would expect.
294
+ # and if not raise a generic error exception
295
+ unless doc.root.elements['Errors'].elements['Error'].name == 'Error'
296
+ raise Error, "Unexpected error format. response.body is: #{response.body}"
297
+ end
298
+
299
+ # An valid error response looks like this:
300
+ # <?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>
301
+ # AWS throws some exception codes that look like Error.SubError. Since we can't name classes this way
302
+ # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
303
+ # non '.' name as well.
304
+ error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text.gsub('.', '')
305
+ error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text
306
+
307
+ # Raise one of our specific error classes if it exists.
308
+ # otherwise, throw a generic EC2 Error with a few details.
309
+ if AWS.const_defined?(error_code)
310
+ raise AWS.const_get(error_code), error_message
311
+ else
312
+ raise AWS::Error, error_message
313
+ end
314
+
315
+ end
316
+
317
+ end
318
+ end
319
+
320
+ Dir[File.join(File.dirname(__FILE__), 'AWS/**/*.rb')].sort.each { |lib| require lib }
321
+
@@ -0,0 +1,70 @@
1
+ module AWS
2
+ module Autoscaling
3
+ # Which host FQDN will we connect to for all API calls to AWS?
4
+ # If AS_URL is defined in the users ENV we can override the default with that.
5
+ #
6
+ # @example
7
+ # export AS_URL='http://autoscaling.amazonaws.com'
8
+ if ENV['AS_URL']
9
+ AS_URL = ENV['AS_URL']
10
+ VALID_HOSTS = ['http://autoscaling.amazonaws.com']
11
+ raise ArgumentError, "Invalid AS_URL environment variable : #{AS_URL}" unless VALID_HOSTS.include?(AS_URL)
12
+ DEFAULT_HOST = URI.parse(AS_URL).host
13
+ else
14
+ # Default US API endpoint
15
+ DEFAULT_HOST = 'autoscaling.amazonaws.com'
16
+ end
17
+
18
+ API_VERSION = '2009-05-15'
19
+
20
+ class Base < AWS::Base
21
+ def api_version
22
+ API_VERSION
23
+ end
24
+
25
+ def default_host
26
+ DEFAULT_HOST
27
+ end
28
+
29
+ # Raises the appropriate error if the specified Net::HTTPResponse object
30
+ # contains an Amazon EC2 error; returns +false+ otherwise.
31
+ def aws_error?(response)
32
+
33
+ # return false if we got a HTTP 200 code,
34
+ # otherwise there is some type of error (40x,50x) and
35
+ # we should try to raise an appropriate exception
36
+ # from one of our exception classes defined in
37
+ # exceptions.rb
38
+ return false if response.is_a?(Net::HTTPSuccess)
39
+
40
+ # parse the XML document so we can walk through it
41
+ doc = REXML::Document.new(response.body)
42
+
43
+ # Check that the Error element is in the place we would expect.
44
+ # and if not raise a generic error exception
45
+ unless doc.root.elements[1].name == "Error"
46
+ raise Error, "Unexpected error format. response.body is: #{response.body}"
47
+ end
48
+
49
+ # An valid error response looks like this:
50
+ # <?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>
51
+ # AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way
52
+ # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
53
+ # non '.' name as well.
54
+ error_code = doc.root.elements['//ErrorResponse/Error/Code'].text.gsub('.', '')
55
+ error_message = doc.root.elements['//ErrorResponse/Error/Message'].text
56
+
57
+ # Raise one of our specific error classes if it exists.
58
+ # otherwise, throw a generic EC2 Error with a few details.
59
+ if AWS.const_defined?(error_code)
60
+ raise AWS.const_get(error_code), error_message
61
+ else
62
+ raise AWS::Error, error_message
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,273 @@
1
+ module AWS
2
+ module Autoscaling
3
+ class Base < AWS::Base
4
+
5
+ # Create a launch configuration
6
+ # Creates a new Launch Configuration. Please note that the launch configuration name used must be unique, within the scope of your AWS account, and the maximum limit of launch configurations must not yet have been met, or else the call will fail.
7
+ # Once created, the new launch configuration is available for immediate use.
8
+ #
9
+ # @option options [String] :launch_configuration_name (nil) the name of the launch configuration
10
+ # @option options [String] :image_id (nil) the image id to use with this launch configuration
11
+ # @option options [String] :instance_type (nil) the type of instance to launch
12
+ # @option options [Array] :security_groups (nil) the names of security_groups to launch within
13
+ # @option options [String] :key_name (nil) the name of the EC2 key pair
14
+ # @option options [String] :user_data (nil) the user data available to the launched EC2 instances
15
+ # @option options [String] :kernel_id (nil) the ID of the kernel associated with the EC2 ami
16
+ # @option options [String] :ramdisk_id (nil) the name of the RAM disk associated with the EC2 ami
17
+ # @option options [Array] :block_device_mappings (nil) specifies how block devices are exposed to the instance
18
+ def create_launch_configuration( options = {})
19
+ raise ArgumentError, "No :image_id provided" if options[:image_id].nil? || options[:image_id].empty?
20
+ raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty?
21
+ raise ArgumentError, "No :instance_type provided" if options[:instance_type].nil? || options[:instance_type].empty?
22
+
23
+ params = {}
24
+ params["ImageId"] = options[:image_id]
25
+ params["KeyName"] = options[:key_name] if options[:key_name]
26
+ params["LaunchConfigurationName"] = options[:launch_configuration_name]
27
+ params.merge!(pathlist('SecurityGroups.member', [options[:security_groups]].flatten)) if options[:security_groups]
28
+ params["UserData"] = options[:user_data] if options[:user_data]
29
+ params["InstanceType"] = options[:instance_type] if options[:instance_type]
30
+ params["KernelId"] = options[:kernel_id] if options[:kernel_id]
31
+ params["RamdiskId"] = options[:ramdisk_id] if options[:ramdisk_id]
32
+ params.merge!(pathlist('BlockDeviceMappings.member', [options[:block_device_mappings]].flatten)) if options[:block_device_mappings]
33
+
34
+ return response_generator(:action => "CreateLaunchConfiguration", :params => params)
35
+ end
36
+
37
+ # Creates a new AutoScalingGroup with the specified name.
38
+ # You must not have already used up your entire quota of AutoScalingGroups in order for this call to be successful. Once the creation request is completed, the AutoScalingGroup is ready to be used in other calls.
39
+ #
40
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group
41
+ # @option options [Array] :availability_zones (nil) The availability_zones for the group
42
+ # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration group
43
+ # @option options [String] :min_size (nil) minimum size of the group
44
+ # @option options [String] :max_size (nil) the maximum size of the group
45
+ # @option options [optional,Array] :load_balancer_names (nil) the names of the load balancers
46
+ # @option options [optional,String] :cooldown (nil) the amount of time after a scaling activity complese before any further trigger-related scaling activities can start
47
+ def create_autoscaling_group( options = {} )
48
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
49
+ raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty?
50
+ raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty?
51
+ raise ArgumentError, "No :min_size provided" if options[:min_size].nil?
52
+ raise ArgumentError, "No :max_size provided" if options[:max_size].nil?
53
+
54
+ params = {}
55
+
56
+ params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten))
57
+ params['LaunchConfigurationName'] = options[:launch_configuration_name]
58
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
59
+ params['MinSize'] = options[:min_size].to_s
60
+ params['MaxSize'] = options[:max_size].to_s
61
+ params.merge!(pathlist("LoadBalancerNames.member", [options[:load_balancer_names]].flatten)) if options.has_key?(:load_balancer_names)
62
+ params['CoolDown'] = options[:cooldown] if options[:cooldown]
63
+
64
+ return response_generator(:action => "CreateAutoScalingGroup", :params => params)
65
+ end
66
+
67
+ # Create or update scaling trigger
68
+ # This call sets the parameters that governs when and how to scale an AutoScalingGroup.
69
+ #
70
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group
71
+ # @option options [Array|Hash] :dimensions (nil) The dimensions associated with the metric used by the trigger to determine whether to activate
72
+ # This must be given as either an array or a hash
73
+ # When called as a hash, the values must look like: {:name => "name", :value => "value"}
74
+ # In the array format, the first value is assumed to be the name and the second is assumed to be the value
75
+ # @option options [String] :measure_name (nil) the measure name associated with the metric used by the trigger
76
+ # @option options [String|Integer] :period (nil) the period associated with the metric in seconds
77
+ # @option options [String] :statistic (nil) The particular statistic used by the trigger when fetching metric statistics to examine. Must be one of the following: Minimum, Maximum, Sum, Average
78
+ # @option options [String] :trigger_name (nil) the name for this trigger
79
+ # @option options [String] :unit (nil) the standard unit of measurement for a given measure
80
+ # @option options [String|Integer] :lower_threshold (nil) the lower limit for the metric. If all datapoints in the last :breach_duration seconds fall below the lower threshold, the trigger will activate
81
+ # @option options [String|Integer] :lower_breach_scale_increment (nil) the incremental amount to use when performing scaling activities when the lower threshold has been breached
82
+ # @option options [String|Integer] :upper_threshold (nil) the upper limit for the metric. If all datapoints in the last :breach_duration seconds exceed the upper threshold, the trigger will activate
83
+ # @option options [String|Integer] :upper_breach_scale_increment (nil) the incremental amount to use when performing scaling activities when the upper threshold has been breached
84
+ def create_or_updated_scaling_trigger( options = {} )
85
+ if options[:dimensions].nil? || options[:dimensions].empty?
86
+ raise ArgumentError, "No :dimensions provided"
87
+ end
88
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
89
+ raise ArgumentError, "No :measure_name provided" if options[:measure_name].nil? || options[:measure_name].empty?
90
+ raise ArgumentError, "No :statistic provided" if options[:statistic].nil? || options[:statistic].empty?
91
+ raise ArgumentError, "No :period provided" if options[:period].nil?
92
+ raise ArgumentError, "No :trigger_name provided" if options[:trigger_name].nil? || options[:trigger_name].empty?
93
+ raise ArgumentError, "No :lower_threshold provided" if options[:lower_threshold].nil?
94
+ raise ArgumentError, "No :lower_breach_scale_increment provided" if options[:lower_breach_scale_increment].nil?
95
+ raise ArgumentError, "No :upper_threshold provided" if options[:upper_threshold].nil?
96
+ raise ArgumentError, "No :upper_breach_scale_increment provided" if options[:upper_breach_scale_increment].nil?
97
+ raise ArgumentError, "No :breach_duration provided" if options[:breach_duration].nil?
98
+ statistic_option_list = %w(minimum maximum average sum)
99
+ unless statistic_option_list.include?(options[:statistic].downcase)
100
+
101
+ raise ArgumentError, "The statistic option must be one of the following: #{statistic_option_list.join(", ")}"
102
+ end
103
+
104
+ params = {}
105
+ params['Unit'] = options[:unit] || "Seconds"
106
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
107
+ case options[:dimensions]
108
+ when Array
109
+ params["Dimensions.member.1.Name"] = options[:dimensions][0]
110
+ params["Dimensions.member.1.Value"] = options[:dimensions][1]
111
+ when Hash
112
+ params["Dimensions.member.1.Name"] = options[:dimensions][:name]
113
+ params["Dimensions.member.1.Value"] = options[:dimensions][:value]
114
+ else
115
+ raise ArgumentError, "Dimensionss must be either an array or a hash"
116
+ end
117
+ params['MeasureName'] = options[:measure_name]
118
+ params['Statistic'] = options[:statistic]
119
+ params['Period'] = options[:period].to_s
120
+ params['TriggerName'] = options[:trigger_name]
121
+ params['LowerThreshold'] = options[:lower_threshold].to_s
122
+ params['LowerBreachScaleIncrement'] = options[:lower_breach_scale_increment].to_s
123
+ params['UpperThreshold'] = options[:upper_threshold].to_s
124
+ params['UpperBreachScaleIncrement'] = options[:upper_breach_scale_increment].to_s
125
+ params['BreachDuration'] = options[:breach_duration].to_s
126
+
127
+ return response_generator(:action => "CreateOrUpdateScalingTrigger", :params => params)
128
+ end
129
+
130
+ # Deletes all configuration for this AutoScalingGroup and also deletes the group.
131
+ # In order to successfully call this API, no triggers (and therefore, Scaling Activity) can be currently in progress. Once this call successfully executes, no further triggers will begin and the AutoScalingGroup will not be available for use in other API calls. See key term Trigger.
132
+ #
133
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group
134
+ def delete_autoscaling_group( options = {} )
135
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
136
+ params = { 'AutoScalingGroupName' => options[:autoscaling_group_name] }
137
+ return response_generator(:action => "DeleteAutoScalingGroup", :params => params)
138
+ end
139
+
140
+ # Deletes the given Launch Configuration.
141
+ # The launch configuration to be deleted must not be currently attached to any AutoScalingGroup. Once this call completes, the launch configuration is no longer available for use by any other API call.
142
+ #
143
+ # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration
144
+ def delete_launch_configuration( options = {} )
145
+ raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty?
146
+ params = { 'LaunchConfigurationName' => options[:launch_configuration_name] }
147
+ return response_generator(:action => "DeleteLaunchConfiguration", :params => params)
148
+ end
149
+
150
+ # Deletes the given trigger
151
+ # If a trigger is currently in progress, it will continue to run until its activities are complete.
152
+ #
153
+ # @option options [String] :trigger_name (nil) the name of the trigger to delete
154
+ def delete_trigger( options = {} )
155
+ raise ArgumentError, "No :trigger_name provided" if options[:trigger_name].nil? || options[:trigger_name].empty?
156
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
157
+ params = { 'TriggerName' => options[:trigger_name], 'AutoScalingGroupName' => options[:autoscaling_group_name] }
158
+ return response_generator(:action => "DeleteTrigger", :params => params)
159
+ end
160
+
161
+ # Describe autoscaling group
162
+ # Returns a full description of the AutoScalingGroups from the given list. This includes all EC2 instances that are members of the group. If a list of names is not provided, then the full details of all AutoScalingGroups is returned. This style conforms to the EC2 DescribeInstances API behavior. See key term AutoScalingGroup.
163
+ #
164
+ # @option options [Array] :autoscaling_group_names (nil) the name of the autoscaling groups to describe
165
+ def describe_autoscaling_groups( options = {} )
166
+ options = { :autoscaling_group_names => [] }.merge(options)
167
+ params = pathlist("AutoScalingGroupNames.member", options[:autoscaling_group_names])
168
+ return response_generator(:action => "DescribeAutoScalingGroups", :params => params)
169
+ end
170
+
171
+ # Describe launch configurations
172
+ # Returns a full description of the launch configurations given the specified names. If no names are specified, then the full details of all launch configurations are returned. See key term Launch Configuration.
173
+ #
174
+ # @option options [Array] :launch_configuration_names (nil) the name of the launch_configurations to describe
175
+ def describe_launch_configurations( options = {} )
176
+ options = { :launch_configuration_names => [] }.merge(options)
177
+ params = pathlist("AutoScalingGroupNames.member", options[:launch_configuration_names])
178
+ params['MaxRecords'] = options[:max_records].to_s if options.has_key?(:max_records)
179
+ return response_generator(:action => "DescribeLaunchConfigurations", :params => params)
180
+ end
181
+
182
+ # Describe autoscaling activities
183
+ # Returns the scaling activities specified for the given group. If the input list is empty, all the activities from the past six weeks will be returned. Activities will be sorted by completion time. Activities that have no completion time will be considered as using the most recent possible time. See key term Scaling Activity.
184
+ #
185
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name
186
+ # @option options [String] :max_records (nil) the maximum number of scaling activities to return
187
+ # @option options [String] :launch_configuration_names (nil) activity_ids to return
188
+ def describe_scaling_activities( options = {} )
189
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
190
+
191
+ params = {}
192
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
193
+ params['MaxRecords'] = options[:max_records] if options.has_key?(:max_records)
194
+ params['ActivityIds'] = options[:activity_ids] if options.has_key?(:activity_ids)
195
+ return response_generator(:action => "DescribeScalingActivities", :params => params)
196
+ end
197
+
198
+ # Describe triggers
199
+ # Returns a full description of the trigger (see Trigger), in the specified AutoScalingGroup.
200
+ #
201
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name
202
+ def describe_triggers( options = {} )
203
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
204
+ params = {}
205
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
206
+
207
+ return response_generator(:action => "DescribeTriggers", :params => params)
208
+ end
209
+
210
+ # Set desired capacity
211
+ # This API adjusts the desired size of the AutoScalingGroup by initiating scaling activities, as necessary. When adjusting the size of the group downward, it is not possible to define which EC2 instances will be terminated. This applies to any auto-scaling decisions that might result in the termination of instances.
212
+ # To check the scaling status of the system, query the desired capacity using DescribeAutoScalingGroups and then query the actual capacity using DescribeAutoScalingGroups and looking at the instance lifecycle state in order to understand how close the system is to the desired capacity at any given time.
213
+ #
214
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name
215
+ # @option options [String] :desired_capacity (nil) the new capacity setting for the group
216
+ def set_desired_capacity( options = {} )
217
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
218
+ raise ArgumentError, "No :desired_capacity provided" if options[:desired_capacity].nil? || options[:desired_capacity].empty?
219
+
220
+ params = {}
221
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
222
+ params['DesiredCapacity'] = options[:desired_capacity].to_s
223
+
224
+ return response_generator(:action => "SetDesiredCapacity", :params => params)
225
+ end
226
+
227
+
228
+ # Terminate instance in an autoscaling group
229
+ # This call will terminate the specified Instance. Optionally, the desired group size can be adjusted. If set to true, the default, the AutoScalingGroup size will decrease by one. If the AutoScalingGroup is associated with a LoadBalancer, the system will deregister the instance before terminating it.
230
+ # This call simply registers a termination request. The termination of the instance can not happen immediately.
231
+ #
232
+ # @option options [String] :instance_id (nil) the instance id to terminate
233
+ # @option options [String] :decrement_desired_capacity (nil) specified whether terminating this instance should also decrement the size of the autoscaling group
234
+ def terminate_instance_in_autoscaling_group( options = {} )
235
+ raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty?
236
+
237
+ params = {}
238
+ params['InstanceId'] = options[:instance_id]
239
+ params['ShouldDecrementDesiredCapacity'] = options[:decrement_desired_capacity].to_s if options.has_key?(:decrement_desired_capacity)
240
+
241
+ return response_generator(:action => "TerminateInstanceInAutoScalingGroup", :params => params)
242
+ end
243
+
244
+ # Creates a new AutoScalingGroup with the specified name.
245
+ # Updates the configuration for the given AutoScalingGroup. If MaxSize is lower than the current size, then there will be an implicit call to SetDesiredCapacity to set the group to the new MaxSize. The same is true for MinSize there will also be an implicit call to SetDesiredCapacity. All optional parameters are left unchanged if not passed in the request.=
246
+ # The new settings are registered upon the completion of this call. Any launch configuration settings will take effect on any triggers after this call returns. However, triggers that are currently in progress can not be affected. See key term Trigger.
247
+ #
248
+ # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group
249
+ # @option options [Array] :availability_zones (nil) The availability_zones for the group
250
+ # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration group
251
+ # @option options [String] :min_size (nil) minimum size of the group
252
+ # @option options [String] :max_size (nil) the maximum size of the group
253
+ # @option options [String] :cooldown (nil) the amount of time after a scaling activity complese before any further trigger-related scaling activities can start
254
+ def update_autoscaling_group( options = {})
255
+ raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty?
256
+
257
+ params = {}
258
+
259
+ params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) if options.has_key?(:availability_zones)
260
+ params['LaunchConfigurationName'] = options[:launch_configuration_name] if options.has_key?(:launch_configuration_name)
261
+ params['AutoScalingGroupName'] = options[:autoscaling_group_name]
262
+ params['MinSize'] = options[:min_size] if options.has_key?(:min_size)
263
+ params['MaxSize'] = options[:max_size] if options.has_key?(:max_size)
264
+ params['CoolDown'] = options[:cooldown] if options.has_key?(:cooldown)
265
+
266
+ return response_generator(:action => "UpdateAutoScalingGroup", :params => params)
267
+
268
+ end
269
+
270
+ end
271
+ end
272
+ end
273
+