redaranj-right_aws 1.10.3 → 1.10.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,690 @@
1
+ #
2
+ # Copyright (c) 2007-2009 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ # = RightAWS::AsInterface -- RightScale Amazon Auto Scaling interface
27
+ # The RightAws::AsInterface class provides a complete interface to Amazon Auto Scaling service.
28
+ #
29
+ # For explanations of the semantics of each call, please refer to Amazon's documentation at
30
+ # http://docs.amazonwebservices.com/AutoScaling/latest/DeveloperGuide/
31
+ #
32
+ # Create an interface handle:
33
+ #
34
+ # as = RightAws::AsInterface.new(aws_access_key_id, aws_security_access_key)
35
+ #
36
+ # Create a launch configuration:
37
+ #
38
+ # as.create_launch_configuration('CentOS.5.1-c', 'ami-08f41161', 'm1.small',
39
+ # :key_name => 'kd-moo-test',
40
+ # :security_groups => ['default'],
41
+ # :user_data => "Woohoo: CentOS.5.1-c" )
42
+ #
43
+ # Create an AutoScaling group:
44
+ #
45
+ # as.create_auto_scaling_group('CentOS.5.1-c-array', 'CentOS.5.1-c', 'us-east-1c',
46
+ # :min_size => 2,
47
+ # :max_size => 5)
48
+ #
49
+ # Create a new trigger:
50
+ #
51
+ # as.create_or_update_scaling_trigger('kd.tr.1', 'CentOS.5.1-c-array',
52
+ # :measure_name => 'CPUUtilization',
53
+ # :statistic => :average,
54
+ # :dimentions => {
55
+ # 'AutoScalingGroupName' => 'CentOS.5.1-c-array',
56
+ # 'Namespace' => 'AWS',
57
+ # 'Service' => 'EC2' },
58
+ # :period => 60,
59
+ # :lower_threshold => 5,
60
+ # :lower_breach_scale_increment => -1,
61
+ # :upper_threshold => 60,
62
+ # :upper_breach_scale_increment => 1,
63
+ # :breach_duration => 300 )
64
+ #
65
+ # Describe scaling activity:
66
+ #
67
+ # as.incrementally_describe_scaling_activities('CentOS.5.1-c-array') #=> List of activities
68
+ #
69
+ # Describe the Auto Scaling group status:
70
+ #
71
+ # as.describe_auto_scaling_groups('CentOS.5.1-c-array') #=> Current group status
72
+ #
73
+ class AsInterface < RightAwsBase
74
+ include RightAwsBaseInterface
75
+
76
+ # Amazon AS API version being used
77
+ API_VERSION = '2009-05-15'
78
+ DEFAULT_HOST = 'autoscaling.amazonaws.com'
79
+ DEFAULT_PATH = '/'
80
+ DEFAULT_PROTOCOL = 'https'
81
+ DEFAULT_PORT = 443
82
+
83
+ @@bench = AwsBenchmarkingBlock.new
84
+ def self.bench_xml
85
+ @@bench.xml
86
+ end
87
+ def self.bench_service
88
+ @@bench.service
89
+ end
90
+
91
+ # Create a new handle to an CSLS account. All handles share the same per process or per thread
92
+ # HTTP connection to Amazon CSLS. Each handle is for a specific account. The params have the
93
+ # following options:
94
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). Example: 'https://autoscaling.amazonaws.com/'
95
+ # * <tt>:server</tt>: AS service host, default: DEFAULT_HOST
96
+ # * <tt>:port</tt>: AS service port, default: DEFAULT_PORT
97
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
98
+ # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
99
+ # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
100
+ # * <tt>:signature_version</tt>: The signature version : '0','1' or '2'(default)
101
+ # * <tt>:cache</tt>: true/false(default): describe_auto_scaling_groups
102
+ #
103
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
104
+ init({ :name => 'AS',
105
+ :default_host => ENV['AS_URL'] ? URI.parse(ENV['AS_URL']).host : DEFAULT_HOST,
106
+ :default_port => ENV['AS_URL'] ? URI.parse(ENV['AS_URL']).port : DEFAULT_PORT,
107
+ :default_service => ENV['AS_URL'] ? URI.parse(ENV['AS_URL']).path : DEFAULT_PATH,
108
+ :default_protocol => ENV['AS_URL'] ? URI.parse(ENV['AS_URL']).scheme : DEFAULT_PROTOCOL,
109
+ :default_api_version => ENV['AS_API_VERSION'] || API_VERSION },
110
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] ,
111
+ aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'],
112
+ params)
113
+ end
114
+
115
+ def generate_request(action, params={}) #:nodoc:
116
+ generate_request_impl(:get, action, params )
117
+ end
118
+
119
+ # Sends request to Amazon and parses the response
120
+ # Raises AwsError if any banana happened
121
+ def request_info(request, parser) #:nodoc:
122
+ request_info_impl(:aass_connection, @@bench, request, parser)
123
+ end
124
+
125
+ #-----------------------------------------------------------------
126
+ # Auto Scaling Groups
127
+ #-----------------------------------------------------------------
128
+
129
+ # Describe auto scaling groups.
130
+ # Returns a full description of the AutoScalingGroups from the given list.
131
+ # This includes all EC2 instances that are members of the group. If a list
132
+ # of names is not provided, then the full details of all AutoScalingGroups
133
+ # is returned. This style conforms to the EC2 DescribeInstances API behavior.
134
+ #
135
+ def describe_auto_scaling_groups(*auto_scaling_group_names)
136
+ auto_scaling_group_names = auto_scaling_group_names.flatten.compact
137
+ request_hash = amazonize_list('AutoScalingGroupNames.member', auto_scaling_group_names)
138
+ link = generate_request("DescribeAutoScalingGroups", request_hash)
139
+ request_cache_or_info(:describe_auto_scaling_groups, link, DescribeAutoScalingGroupsParser, @@bench, auto_scaling_group_names.blank?)
140
+ end
141
+
142
+ # Creates a new auto scaling group with the specified name.
143
+ # Returns +true+ or raises an exception.
144
+ #
145
+ # Options: +:min_size+, +:max_size+, +:cooldown+, +:load_balancer_names+
146
+ #
147
+ # as.create_auto_scaling_group('CentOS.5.1-c-array', 'CentOS.5.1-c', 'us-east-1c',
148
+ # :min_size => 2,
149
+ # :max_size => 5) #=> true
150
+ #
151
+ # Amazon's notice: Constraints: Restricted to one Availability Zone
152
+ def create_auto_scaling_group(auto_scaling_group_name, launch_configuration_name, availability_zones, options={})
153
+ options[:min_size] ||= 1
154
+ options[:max_size] ||= 20
155
+ options[:cooldown] ||= 0
156
+ request_hash = amazonize_list('AvailabilityZones.member', availability_zones.to_a)
157
+ request_hash.merge!( amazonize_list('LoadBalancerNames', options[:load_balancer_names].to_a) )
158
+ request_hash.merge!( 'AutoScalingGroupName' => auto_scaling_group_name,
159
+ 'LaunchConfigurationName' => launch_configuration_name,
160
+ 'MinSize' => options[:min_size],
161
+ 'MaxSize' => options[:max_size],
162
+ 'Cooldown' => options[:cooldown] )
163
+ link = generate_request("CreateAutoScalingGroup", request_hash)
164
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
165
+ end
166
+
167
+ # Deletes all configuration for this auto scaling group and also deletes the group.
168
+ # Returns +true+ or raises an exception.
169
+ #
170
+ def delete_auto_scaling_group(auto_scaling_group_name)
171
+ link = generate_request('DeleteAutoScalingGroup', 'AutoScalingGroupName' => auto_scaling_group_name)
172
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
173
+ end
174
+
175
+ # Adjusts the desired size of the Capacity Group by using scaling actions, as necessary. When
176
+ # adjusting the size of the group downward, it is not possible to define which EC2 instances will be
177
+ # terminated. This also applies to any auto-scaling decisions that might result in the termination of
178
+ # instances.
179
+ #
180
+ # Returns +true+ or raises an exception.
181
+ #
182
+ # as.set_desired_capacity('CentOS.5.1-c',3) #=> 3
183
+ #
184
+ def set_desired_capacity(auto_scaling_group_name, desired_capacity)
185
+ link = generate_request('SetDesiredCapacity', 'AutoScalingGroupName' => auto_scaling_group_name,
186
+ 'DesiredCapacity' => desired_capacity )
187
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
188
+ end
189
+
190
+ # Updates the configuration for the given AutoScalingGroup. If MaxSize is lower than the current size,
191
+ # then there will be an implicit call to SetDesiredCapacity to set the group to the new MaxSize. The
192
+ # same is true for MinSize there will also be an implicit call to SetDesiredCapacity. All optional
193
+ # parameters are left unchanged if not passed in the request.
194
+ #
195
+ # The new settings are registered upon the completion of this call. Any launch configuration settings
196
+ # will take effect on any triggers after this call returns. However, triggers that are currently in
197
+ # progress can not be affected. See key term Trigger.
198
+ #
199
+ # Returns +true+ or raises an exception.
200
+ #
201
+ # Options: +:launch_configuration_name+, +:min_size+, +:max_size+, +:cooldown+, +:availability_zones+.
202
+ # (Amazon's notice: +:availability_zones+ is reserved for future use.)
203
+ #
204
+ # as.update_auto_scaling_group('CentOS.5.1-c', :min_size => 1, :max_size => 4) #=> true
205
+ #
206
+ def update_auto_scaling_group(auto_scaling_group_name, options={})
207
+ request_hash = amazonize_list('AvailabilityZones.member', options[:availability_zones].to_a)
208
+ request_hash['AutoScalingGroupName'] = auto_scaling_group_name
209
+ request_hash['LaunchConfigurationName'] = options[:launch_configuration_name] if options[:launch_configuration_name]
210
+ request_hash['MinSize'] = options[:min_size] if options[:min_size]
211
+ request_hash['MaxSize'] = options[:max_size] if options[:max_size]
212
+ request_hash['Cooldown'] = options[:cooldown] if options[:cooldown]
213
+ link = generate_request("UpdateAutoScalingGroup", request_hash)
214
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
215
+ end
216
+
217
+ #-----------------------------------------------------------------
218
+ # Scaling Activities
219
+ #-----------------------------------------------------------------
220
+
221
+ # Describe all Scaling Activities.
222
+ #
223
+ # describe_scaling_activities('CentOS.5.1-c-array') #=>
224
+ # [{:cause=>
225
+ # "At 2009-05-28 10:11:35Z trigger kd.tr.1 breached high threshold value for
226
+ # CPUUtilization, 10.0, adjusting the desired capacity from 1 to 2. At 2009-05-28 10:11:35Z
227
+ # a breaching trigger explicitly set group desired capacity changing the desired capacity
228
+ # from 1 to 2. At 2009-05-28 10:11:40Z an instance was started in response to a difference
229
+ # between desired and actual capacity, increasing the capacity from 1 to 2.",
230
+ # :activity_id=>"067c9abb-f8a7-4cf8-8f3c-dc6f280457c4",
231
+ # :progress=>0,
232
+ # :description=>"Launching a new EC2 instance",
233
+ # :status_code=>"InProgress",
234
+ # :start_time=>Thu May 28 10:11:40 UTC 2009},
235
+ # {:end_time=>Thu May 28 09:35:23 UTC 2009,
236
+ # :cause=>
237
+ # "At 2009-05-28 09:31:21Z a user request created an AutoScalingGroup changing the desired
238
+ # capacity from 0 to 1. At 2009-05-28 09:32:35Z an instance was started in response to a
239
+ # difference between desired and actual capacity, increasing the capacity from 0 to 1.",
240
+ # :activity_id=>"90d506ba-1b75-4d29-8739-0a75b1ba8030",
241
+ # :progress=>100,
242
+ # :description=>"Launching a new EC2 instance",
243
+ # :status_code=>"Successful",
244
+ # :start_time=>Thu May 28 09:32:35 UTC 2009}]}
245
+ #
246
+ def describe_scaling_activities(auto_scaling_group_name, *activity_ids)
247
+ result = []
248
+ incrementally_describe_scaling_activities(auto_scaling_group_name, *activity_ids) do |response|
249
+ result += response[:scaling_activities]
250
+ true
251
+ end
252
+ result
253
+ end
254
+
255
+ # Incrementally describe Scaling Activities.
256
+ # Returns the scaling activities specified for the given group. If the input list is empty, all the
257
+ # activities from the past six weeks will be returned. Activities will be sorted by completion time.
258
+ # Activities that have no completion time will be considered as using the most recent possible time.
259
+ #
260
+ # Optional params: +:max_records+, +:next_token+.
261
+ #
262
+ # # get max 100 first activities
263
+ # as.incrementally_describe_scaling_activities('CentOS.5.1-c-array') #=>
264
+ # {:scaling_activities=>
265
+ # [{:cause=>
266
+ # "At 2009-05-28 10:11:35Z trigger kd.tr.1 breached high threshold value for
267
+ # CPUUtilization, 10.0, adjusting the desired capacity from 1 to 2. At 2009-05-28 10:11:35Z
268
+ # a breaching trigger explicitly set group desired capacity changing the desired capacity
269
+ # from 1 to 2. At 2009-05-28 10:11:40Z an instance was started in response to a difference
270
+ # between desired and actual capacity, increasing the capacity from 1 to 2.",
271
+ # :activity_id=>"067c9abb-f8a7-4cf8-8f3c-dc6f280457c4",
272
+ # :progress=>0,
273
+ # :description=>"Launching a new EC2 instance",
274
+ # :status_code=>"InProgress",
275
+ # :start_time=>Thu May 28 10:11:40 UTC 2009},
276
+ # {:end_time=>Thu May 28 09:35:23 UTC 2009,
277
+ # :cause=>
278
+ # "At 2009-05-28 09:31:21Z a user request created an AutoScalingGroup changing the desired
279
+ # capacity from 0 to 1. At 2009-05-28 09:32:35Z an instance was started in response to a
280
+ # difference between desired and actual capacity, increasing the capacity from 0 to 1.",
281
+ # :activity_id=>"90d506ba-1b75-4d29-8739-0a75b1ba8030",
282
+ # :progress=>100,
283
+ # :description=>"Launching a new EC2 instance",
284
+ # :status_code=>"Successful",
285
+ # :start_time=>Thu May 28 09:32:35 UTC 2009}]}
286
+ #
287
+ # # list by 5 records
288
+ # incrementally_describe_scaling_activities('CentOS.5.1-c-array', :max_records => 5) do |response|
289
+ # puts response.inspect
290
+ # true
291
+ # end
292
+ #
293
+ def incrementally_describe_scaling_activities(auto_scaling_group_name, *activity_ids, &block)
294
+ activity_ids = activity_ids.flatten.compact
295
+ params = activity_ids.last.kind_of?(Hash) ? activity_ids.pop : {}
296
+ request_hash = amazonize_list('ActivityIds.member', activity_ids)
297
+ request_hash['AutoScalingGroupName'] = auto_scaling_group_name
298
+ request_hash['MaxRecords'] = params[:max_records] if params[:max_records]
299
+ request_hash['NextToken'] = params[:next_token] if params[:next_token]
300
+ last_response = nil
301
+ loop do
302
+ link = generate_request("DescribeScalingActivities", request_hash)
303
+ last_response = request_info( link, DescribeScalingActivitiesParser.new(:logger => @logger))
304
+ request_hash['NextToken'] = last_response[:next_token]
305
+ break unless block && block.call(last_response) && !last_response[:next_token].blank?
306
+ end
307
+ last_response
308
+ end
309
+
310
+ #-----------------------------------------------------------------
311
+ # Instance and Instance Workflow Operations
312
+ #-----------------------------------------------------------------
313
+
314
+ # This call will terminate the specified Instance. Optionally, the desired group size can be adjusted.
315
+ # If set to true, the default, the AutoScalingGroup size will decrease by one. If the AutoScalingGroup
316
+ # is associated with a LoadBalancer, the system will deregister the instance before terminating it.
317
+ # This call simply registers a termination request. The termination of the instance can not happen
318
+ # immediately.
319
+ #
320
+ # Returns the activity to terminate the instance.
321
+ #
322
+ def terminate_instance_in_auto_scaling_group(instance_id, should_decrement_desired_capacity=true)
323
+ request_hash = { 'InstanceId' => instance_id }
324
+ request_hash['ShouldDecrementDesiredCapacity'] = should_decrement_desired_capacity
325
+ link = generate_request('TerminateInstanceInAutoScalingGroup', request_hash )
326
+ request_info(link, DescribeScalingActivitiesParser.new(:logger => @logger))[:scaling_activities].first
327
+ end
328
+
329
+ #-----------------------------------------------------------------
330
+ # Launch Configuration Operations
331
+ #-----------------------------------------------------------------
332
+
333
+ # Creates a new Launch Configuration. Please note that the launch configuration name used must
334
+ # be unique, within the scope of your Amazon Web Services AWS account, and the maximum limit of
335
+ # launch configurations must not yet have been met, or else the call will fail.
336
+ #
337
+ # Once created, the new launch configuration is available for immediate use.
338
+ #
339
+ # Options: +:security_groups+, +:block_device_mappings+, +:key_name+,
340
+ # +:user_data+, +:kernel_id+, +:ramdisk_id+
341
+ #
342
+ # as.create_launch_configuration('CentOS.5.1-c', 'ami-08f41161', 'm1.small',
343
+ # :key_name => 'kd-moo-test',
344
+ # :security_groups => ['default'],
345
+ # :user_data => "Woohoo: CentOS.5.1-c" ) #=> true
346
+ #
347
+ def create_launch_configuration(launch_configuration_name, image_id, instance_type, options={})
348
+ availability_zones = availability_zones.to_a
349
+ request_hash = { 'LaunchConfigurationName' => launch_configuration_name,
350
+ 'ImageId' => image_id,
351
+ 'InstanceType' => instance_type }
352
+ request_hash.merge!(amazonize_list('SecurityGroups.member', options[:security_groups])) unless options[:security_groups].blank?
353
+ request_hash.merge!(amazonize_list(['BlockDeviceMappings.member.?.DeviceName', 'BlockDeviceMappings.member.?.VirtualName'],
354
+ options[:block_device_mappings].to_a)) unless options[:block_device_mappings].blank?
355
+ request_hash['KeyName'] = options[:key_name] if options[:key_name]
356
+ request_hash['UserData'] = options[:user_data] if options[:user_data]
357
+ request_hash['KernelId'] = options[:kernel_id] if options[:kernel_id]
358
+ request_hash['RamdiskId'] = options[:ramdisk_id] if options[:ramdisk_id]
359
+ link = generate_request("CreateLaunchConfiguration", request_hash)
360
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
361
+ end
362
+
363
+
364
+ # Describe all Launch Configurations.
365
+ # Returns an array of configurations.
366
+ #
367
+ # as.describe_launch_configurations #=>
368
+ # [{:created_time=>Thu May 28 09:31:20 UTC 2009,
369
+ # :kernel_id=>"",
370
+ # :launch_configuration_name=>"CentOS.5.1-c",
371
+ # :ramdisk_id=>"",
372
+ # :security_groups=>["default"],
373
+ # :key_name=>"kd-moo-test",
374
+ # :user_data=>"Woohoo: CentOS.5.1-c-array",
375
+ # :image_id=>"ami-08f41161",
376
+ # :block_device_mappings=>[],
377
+ # :instance_type=>"m1.small"}, ... ]
378
+ #
379
+ def describe_launch_configurations(*launch_configuration_names)
380
+ result = []
381
+ incrementally_describe_launch_configurations(*launch_configuration_names) do |response|
382
+ result += response[:launch_configurations]
383
+ true
384
+ end
385
+ result
386
+ end
387
+
388
+ # Incrementally describe Launch Configurations.
389
+ # Returns a full description of the launch configurations given the specified names. If no names
390
+ # are specified, then the full details of all launch configurations are returned.
391
+ #
392
+ # Optional params: +:max_records+, +:next_token+.
393
+ #
394
+ # # get max 100 first configurations
395
+ # as.incrementally_describe_launch_configurations #=>
396
+ # {:launch_configurations=>
397
+ # [{:created_time=>Thu May 28 09:31:20 UTC 2009,
398
+ # :kernel_id=>"",
399
+ # :launch_configuration_name=>"CentOS.5.1-c",
400
+ # :ramdisk_id=>"",
401
+ # :security_groups=>["default"],
402
+ # :key_name=>"kd-moo-test",
403
+ # :user_data=>"Woohoo: CentOS.5.1-c-array",
404
+ # :image_id=>"ami-08f41161",
405
+ # :block_device_mappings=>[],
406
+ # :instance_type=>"m1.small"}, ... ]}
407
+ #
408
+ # # list by 5 records
409
+ # incrementally_describe_launch_configurations(:max_records => 5) do |response|
410
+ # puts response.inspect
411
+ # true
412
+ # end
413
+ #
414
+ def incrementally_describe_launch_configurations(*launch_configuration_names, &block)
415
+ launch_configuration_names = launch_configuration_names.flatten.compact
416
+ params = launch_configuration_names.last.kind_of?(Hash) ? launch_configuration_names.pop : {}
417
+ request_hash = amazonize_list('LaunchConfigurationNames.member', launch_configuration_names)
418
+ request_hash['MaxRecords'] = params[:max_records] if params[:max_records]
419
+ request_hash['NextToken'] = params[:next_token] if params[:next_token]
420
+ last_response = nil
421
+ loop do
422
+ link = generate_request("DescribeLaunchConfigurations", request_hash)
423
+ last_response = request_info( link, DescribeLaunchConfigurationsParser.new(:logger => @logger) )
424
+ request_hash['NextToken'] = last_response[:next_token]
425
+ break unless block && block.call(last_response) && !last_response[:next_token].blank?
426
+ end
427
+ last_response
428
+ end
429
+
430
+ # Delete launch configuration.
431
+ # Returns +true+ or an exception.
432
+ #
433
+ # as.delete_launch_configuration('CentOS.5.1') #=> true
434
+ #
435
+ def delete_launch_configuration(launch_configuration_name)
436
+ link = generate_request('DeleteLaunchConfiguration', 'LaunchConfigurationName' => launch_configuration_name)
437
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
438
+ end
439
+
440
+ #-----------------------------------------------------------------
441
+ # Trigger Operations
442
+ #-----------------------------------------------------------------
443
+
444
+ # Create or update specified trigger.
445
+ # This call sets the parameters that governs when and how to scale an AutoScalingGroup.
446
+ # If the Trigger, within the scope of the caller's AWS account, specified already exists,
447
+ # it will be updated. If a trigger with a different name already exists, this call will fail.
448
+ #
449
+ # Returns +true+ or an exception.
450
+ #
451
+ # Options: +:measure_name+, +:statistic+, +:period+, +:lower_threshold+, +:lower_breach_scale_increment+,
452
+ # +:upper_threshold+, +:upper_breach_scale_increment+, +:dimentions+, +:breach_duration+, +:unit+, +:custom_unit+
453
+ #
454
+ # as.create_or_update_scaling_trigger('kd.tr.1', 'CentOS.5.1-c-array',
455
+ # :measure_name => 'CPUUtilization',
456
+ # :statistic => :average,
457
+ # :dimentions => {
458
+ # 'AutoScalingGroupName' => 'CentOS.5.1-c-array',
459
+ # 'Namespace' => 'AWS',
460
+ # 'Service' => 'EC2' },
461
+ # :period => 60,
462
+ # :lower_threshold => 5,
463
+ # :lower_breach_scale_increment => -1,
464
+ # :upper_threshold => 60,
465
+ # :upper_breach_scale_increment => 1,
466
+ # :breach_duration => 300 ) #=> true
467
+ #
468
+ def create_or_update_scaling_trigger(trigger_name, auto_scaling_group_name, options={})
469
+ request_hash = { 'TriggerName' => trigger_name,
470
+ 'AutoScalingGroupName' => auto_scaling_group_name,
471
+ 'MeasureName' => options[:measure_name],
472
+ 'Statistic' => options[:statistic].to_s.capitalize,
473
+ 'Period' => options[:period],
474
+ 'LowerThreshold' => options[:lower_threshold],
475
+ 'LowerBreachScaleIncrement' => options[:lower_breach_scale_increment],
476
+ 'UpperThreshold' => options[:upper_threshold],
477
+ 'UpperBreachScaleIncrement' => options[:upper_breach_scale_increment],
478
+ 'BreachDuration' => options[:breach_duration] }
479
+ request_hash['Unit'] = options[:unit] if options[:unit]
480
+ request_hash['CustomUnit'] = options[:custom_unit] if options[:custom_unit]
481
+ dimentions = []
482
+ (options[:dimentions] || {}).each do |key, values|
483
+ values.to_a.each { |value| dimentions << [key, value] }
484
+ end
485
+ request_hash.merge!(amazonize_list(['Dimensions.member.?.Name', 'Dimensions.member.?.Value'], dimentions))
486
+ link = generate_request("CreateOrUpdateScalingTrigger", request_hash)
487
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
488
+ end
489
+
490
+ # Describe triggers.
491
+ # Returns a full description of the trigger in the specified Auto Scaling Group.
492
+ #
493
+ # as.describe_triggers('CentOS.5.1-c-array') #=>
494
+ # [{:status=>"HighBreaching",
495
+ # :breach_duration=>300,
496
+ # :measure_name=>"CPUUtilization",
497
+ # :trigger_name=>"kd.tr.1",
498
+ # :period=>60,
499
+ # :lower_threshold=>0.0,
500
+ # :lower_breach_scale_increment=>-1,
501
+ # :dimensions=>
502
+ # {"Namespace"=>"AWS",
503
+ # "AutoScalingGroupName"=>"CentOS.5.1-c-array",
504
+ # "Service"=>"EC2"},
505
+ # :statistic=>"Average",
506
+ # :upper_threshold=>10.0,
507
+ # :created_time=>Thu May 28 09:48:46 UTC 2009,
508
+ # :auto_scaling_group_name=>"CentOS.5.1-c-array",
509
+ # :upper_breach_scale_increment=>1}]
510
+ #
511
+ def describe_triggers(auto_scaling_group_name)
512
+ link = generate_request("DescribeTriggers", 'AutoScalingGroupName' => auto_scaling_group_name)
513
+ request_info(link, DescribeTriggersParser.new(:logger => @logger))
514
+ end
515
+
516
+ # Delete specified trigger.
517
+ # Returns +true+ or an exception.
518
+ #
519
+ # as.delete_trigger('kd.tr.1', 'CentOS.5.1-c-array') #=> true
520
+ #
521
+ def delete_trigger(trigger_name, auto_scaling_group_name)
522
+ link = generate_request('DeleteTrigger', 'TriggerName' => trigger_name,
523
+ 'AutoScalingGroupName' => auto_scaling_group_name)
524
+ request_info(link, RightHttp2xxParser.new(:logger => @logger))
525
+ end
526
+
527
+ #-----------------------------------------------------------------
528
+ # PARSERS: Scaling Activity
529
+ #-----------------------------------------------------------------
530
+
531
+ class DescribeScalingActivitiesParser < RightAWSParser #:nodoc:
532
+ def tagstart(name, attributes)
533
+ case name
534
+ when 'member', 'Activity' then @item = {}
535
+ end
536
+ end
537
+ def tagend(name)
538
+ case name
539
+ when 'ActivityId' then @item[:activity_id] = @text
540
+ when 'StartTime' then @item[:start_time] = Time::parse(@text)
541
+ when 'EndTime' then @item[:end_time] = Time::parse(@text)
542
+ when 'Progress' then @item[:progress] = @text.to_i
543
+ when 'StatusCode' then @item[:status_code] = @text
544
+ when 'Cause' then @item[:cause] = @text
545
+ when 'Description' then @item[:description] = @text
546
+ when 'member', 'Activity' then @result[:scaling_activities] << @item
547
+ when 'NextToken' then @result[:next_token] = @text
548
+ end
549
+ end
550
+ def reset
551
+ @result = { :scaling_activities => []}
552
+ end
553
+ end
554
+
555
+ #-----------------------------------------------------------------
556
+ # PARSERS: Auto Scaling Groups
557
+ #-----------------------------------------------------------------
558
+
559
+ class DescribeAutoScalingGroupsParser < RightAWSParser #:nodoc:
560
+ def tagstart(name, attributes)
561
+ case name
562
+ when 'member'
563
+ case @xmlpath
564
+ when @p then @item = { :instances => [ ],
565
+ :availability_zones => [],
566
+ :load_balancer_names => [] }
567
+ when "#@p/member/Instances" then @instance = { }
568
+ end
569
+ end
570
+ end
571
+ def tagend(name)
572
+ case name
573
+ when 'CreatedTime' then @item[:created_time] = Time::parse(@text)
574
+ when 'MinSize' then @item[:min_size] = @text.to_i
575
+ when 'MaxSize' then @item[:max_size] = @text.to_i
576
+ when 'DesiredCapacity' then @item[:desired_capacity] = @text.to_i
577
+ when 'Cooldown' then @item[:cooldown] = @text.to_i
578
+ when 'LaunchConfigurationName' then @item[:launch_configuration_name] = @text
579
+ when 'AutoScalingGroupName' then @item[:auto_scaling_group_name] = @text
580
+ when 'InstanceId' then @instance[:instance_id] = @text
581
+ when 'LifecycleState' then @instance[:lifecycle_state] = @text
582
+ when 'AvailabilityZone' then @instance[:availability_zone] = @text
583
+ when 'member'
584
+ case @xmlpath
585
+ when @p then
586
+ @item[:availability_zones].sort!
587
+ @result << @item
588
+ when "#@p/member/AvailabilityZones" then @item[:availability_zones] << @text
589
+ when "#@p/member/LoadBalancerNames" then @item[:load_balancer_names] << @text
590
+ when "#@p/member/Instances" then @item[:instances] << @instance
591
+ end
592
+ end
593
+ end
594
+ def reset
595
+ @p = 'DescribeAutoScalingGroupsResponse/DescribeAutoScalingGroupsResult/AutoScalingGroups'
596
+ @result = []
597
+ end
598
+ end
599
+
600
+ #-----------------------------------------------------------------
601
+ # PARSERS: Launch Configurations
602
+ #-----------------------------------------------------------------
603
+
604
+ class DescribeLaunchConfigurationsParser < RightAWSParser #:nodoc:
605
+ def tagstart(name, attributes)
606
+ case name
607
+ when 'member'
608
+ case @xmlpath
609
+ when @p
610
+ @item = { :block_device_mappings => [],
611
+ :security_groups => [] }
612
+ end
613
+ end
614
+ end
615
+ def tagend(name)
616
+ case name
617
+ when 'CreatedTime' then @item[:created_time] = Time::parse(@text)
618
+ when 'InstanceType' then @item[:instance_type] = @text
619
+ when 'KeyName' then @item[:key_name] = @text
620
+ when 'ImageId' then @item[:image_id] = @text
621
+ when 'KernelId' then @item[:kernel_id] = @text
622
+ when 'RamdiskId' then @item[:ramdisk_id] = @text
623
+ when 'LaunchConfigurationName' then @item[:launch_configuration_name] = @text
624
+ when 'UserData' then @item[:user_data] = @text
625
+ when 'member'
626
+ case @xmlpath
627
+ when "#@p/member/BlockDeviceMappings" then @item[:block_device_mappings] << @text
628
+ when "#@p/member/SecurityGroups" then @item[:security_groups] << @text
629
+ when @p
630
+ @item[:block_device_mappings].sort!
631
+ @item[:security_groups].sort!
632
+ @result[:launch_configurations] << @item
633
+ end
634
+ when 'NextToken' then @result[:next_token] = @text
635
+ end
636
+ end
637
+ def reset
638
+ @p = 'DescribeLaunchConfigurationsResponse/DescribeLaunchConfigurationsResult/LaunchConfigurations'
639
+ @result = { :launch_configurations => []}
640
+ end
641
+ end
642
+
643
+ #-----------------------------------------------------------------
644
+ # PARSERS: Triggers
645
+ #-----------------------------------------------------------------
646
+
647
+ class DescribeTriggersParser < RightAWSParser #:nodoc:
648
+ def tagstart(name, attributes)
649
+ case name
650
+ when 'member'
651
+ case @xmlpath
652
+ when 'DescribeTriggersResponse/DescribeTriggersResult/Triggers'
653
+ @item = { :dimensions => {} }
654
+ when 'DescribeTriggersResponse/DescribeTriggersResult/Triggers/member/Dimensions'
655
+ @dimension = {}
656
+ end
657
+ end
658
+ end
659
+ def tagend(name)
660
+ case name
661
+ when 'AutoScalingGroupName' then @item[:auto_scaling_group_name] = @text
662
+ when 'MeasureName' then @item[:measure_name] = @text
663
+ when 'CreatedTime' then @item[:created_time] = Time::parse(@text)
664
+ when 'BreachDuration' then @item[:breach_duration] = @text.to_i
665
+ when 'UpperBreachScaleIncrement' then @item[:upper_breach_scale_increment] = @text.to_i
666
+ when 'UpperThreshold' then @item[:upper_threshold] = @text.to_f
667
+ when 'LowerThreshold' then @item[:lower_threshold] = @text.to_f
668
+ when 'LowerBreachScaleIncrement' then @item[:lower_breach_scale_increment] = @text.to_i
669
+ when 'Period' then @item[:period] = @text.to_i
670
+ when 'Status' then @item[:status] = @text
671
+ when 'TriggerName' then @item[:trigger_name] = @text
672
+ when 'Statistic' then @item[:statistic] = @text
673
+ when 'Unit' then @item[:unit] = @text
674
+ when 'Name' then @dimension[:name] = @text
675
+ when 'Value' then @dimension[:value] = @text
676
+ when 'member'
677
+ case @xmlpath
678
+ when "#@p/member/Dimensions" then @item[:dimensions][@dimension[:name]] = @dimension[:value]
679
+ when @p then @result << @item
680
+ end
681
+ end
682
+ end
683
+ def reset
684
+ @p = 'DescribeTriggersResponse/DescribeTriggersResult/Triggers'
685
+ @result = []
686
+ end
687
+ end
688
+ end
689
+
690
+ end
@@ -0,0 +1,407 @@
1
+ #
2
+ # Copyright (c) 2007-2009 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ # = RightAWS::ElbInterface -- RightScale Amazon Elastic Load Balancer interface
27
+ # The RightAws::ElbInterface class provides a complete interface to Amazon's
28
+ # Elastic Load Balancer service.
29
+ #
30
+ # For explanations of the semantics of each call, please refer to Amazon's documentation at
31
+ # http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/DeveloperGuide/
32
+ #
33
+ # Create an interface handle:
34
+ #
35
+ # elb = RightAws::ElbInterface.new(aws_access_key_id, aws_security_access_key)
36
+ #
37
+ # Create an new load balancer:
38
+ #
39
+ # elb.create_load_balancer( 'test-kd1',
40
+ # ['us-east-1a', 'us-east-1b'],
41
+ # [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 },
42
+ # { :protocol => :tcp, :load_balancer_port => 443, :instance_port => 443 } ])
43
+ #
44
+ # Configure its health checking:
45
+ #
46
+ # elb.configure_health_check( 'test-kd1',
47
+ # { :healthy_threshold => 9,
48
+ # :unhealthy_threshold => 3,
49
+ # :target => "TCP:433",
50
+ # :timeout => 6,
51
+ # :interval => 31}
52
+ #
53
+ # Register instances with the balancer:
54
+ #
55
+ # elb.register_instances_with_load_balancer('test-kd1', 'i-8b8bcbe2', 'i-bf8bcbd6') #=> ["i-8b8bcbe2", "i-bf8bcbd6"]
56
+ #
57
+ # Add new availability zones:
58
+ #
59
+ # elb.enable_availability_zones_for_load_balancer("test-kd1", "us-east-1c")
60
+ #
61
+ class ElbInterface < RightAwsBase
62
+ include RightAwsBaseInterface
63
+
64
+ # Amazon ELB API version being used
65
+ API_VERSION = "2009-05-15"
66
+ DEFAULT_HOST = "elasticloadbalancing.amazonaws.com"
67
+ DEFAULT_PATH = '/'
68
+ DEFAULT_PROTOCOL = 'https'
69
+ DEFAULT_PORT = 443
70
+
71
+ @@bench = AwsBenchmarkingBlock.new
72
+ def self.bench_xml
73
+ @@bench.xml
74
+ end
75
+ def self.bench_service
76
+ @@bench.service
77
+ end
78
+
79
+ # Create a new handle to an ELB account. All handles share the same per process or per thread
80
+ # HTTP connection to Amazon ELB. Each handle is for a specific account. The params have the
81
+ # following options:
82
+ # * <tt>:endpoint_url</tt> a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). Example: 'https://elasticloadbalancing.amazonaws.com'
83
+ # * <tt>:server</tt>: ELB service host, default: DEFAULT_HOST
84
+ # * <tt>:port</tt>: ELB service port, default: DEFAULT_PORT
85
+ # * <tt>:protocol</tt>: 'http' or 'https', default: DEFAULT_PROTOCOL
86
+ # * <tt>:multi_thread</tt>: true=HTTP connection per thread, false=per process
87
+ # * <tt>:logger</tt>: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT
88
+ # * <tt>:signature_version</tt>: The signature version : '0','1' or '2'(default)
89
+ # * <tt>:cache</tt>: true/false(default): caching works for: describe_load_balancers
90
+ #
91
+ def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
92
+ init({ :name => 'ELB',
93
+ :default_host => ENV['ELB_URL'] ? URI.parse(ENV['ELB_URL']).host : DEFAULT_HOST,
94
+ :default_port => ENV['ELB_URL'] ? URI.parse(ENV['ELB_URL']).port : DEFAULT_PORT,
95
+ :default_service => ENV['ELB_URL'] ? URI.parse(ENV['ELB_URL']).path : DEFAULT_PATH,
96
+ :default_protocol => ENV['ELB_URL'] ? URI.parse(ENV['ELB_URL']).scheme : DEFAULT_PROTOCOL,
97
+ :default_api_version => ENV['ELB_API_VERSION'] || API_VERSION },
98
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] ,
99
+ aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'],
100
+ params)
101
+ end
102
+
103
+ def generate_request(action, params={}) #:nodoc:
104
+ generate_request_impl(:get, action, params )
105
+ end
106
+
107
+ # Sends request to Amazon and parses the response
108
+ # Raises AwsError if any banana happened
109
+ def request_info(request, parser) #:nodoc:
110
+ request_info_impl(:lbs_connection, @@bench, request, parser)
111
+ end
112
+
113
+ #-----------------------------------------------------------------
114
+ # Load Balancers
115
+ #-----------------------------------------------------------------
116
+ # Describe load balancers.
117
+ # Returns an array of load balancers.
118
+ #
119
+ # elb.describe_load_balancers #=>
120
+ # [ { :health_check =>
121
+ # { :healthy_threshold => 10,
122
+ # :unhealthy_threshold => 2,
123
+ # :target => "TCP:80",
124
+ # :timeout => 5,
125
+ # :interval => 30},
126
+ # :load_balancer_name => "test-kd1",
127
+ # :availability_zones => ["us-east-1a", "us-east-1b"],
128
+ # :listeners =>
129
+ # [ { :protocol => "HTTP", :load_balancer_port => "80", :instance_port => "80" },
130
+ # { :protocol => "TCP", :load_balancer_port => "443", :instance_port => "443" } ],
131
+ # :created_time => Wed May 27 11:59:11 UTC 2009,
132
+ # :dns_name => "test-kd1-1519253964.us-east-1.elb.amazonaws.com",
133
+ # :instances => [] } ]
134
+ #
135
+ def describe_load_balancers(*load_balancers)
136
+ load_balancers = load_balancers.flatten.compact
137
+ request_hash = amazonize_list("LoadBalancerNames.member", load_balancers)
138
+ link = generate_request("DescribeLoadBalancers", request_hash)
139
+ request_cache_or_info(:describe_load_balancers, link, DescribeLoadBalancersParser, @@bench, load_balancers.blank?)
140
+ end
141
+
142
+ # Create new load balancer.
143
+ # Returns a new load balancer DNS name.
144
+ #
145
+ # lb = elb.create_load_balancer( 'test-kd1',
146
+ # ['us-east-1a', 'us-east-1b'],
147
+ # [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 },
148
+ # { :protocol => :tcp, :load_balancer_port => 443, :instance_port => 443 } ])
149
+ # puts lb #=> "test-kd1-1519253964.us-east-1.elb.amazonaws.com"
150
+ #
151
+ def create_load_balancer(load_balancer_name, availability_zones=[], listeners=[])
152
+ request_hash = { 'LoadBalancerName' => load_balancer_name }
153
+ # merge zones
154
+ request_hash.merge!( amazonize_list("AvailabilityZones.member", availability_zones.to_a) )
155
+ # merge listeners
156
+ if listeners.blank?
157
+ listeners = { :protocol => :http,
158
+ :load_balancer_port => 80,
159
+ :instance_port => 80 }
160
+ end
161
+ listeners = [listeners] unless listeners.is_a?(Array)
162
+ request_hash.merge!( amazonize_list( ['Listeners.member.?.Protocol',
163
+ 'Listeners.member.?.LoadBalancerPort',
164
+ 'Listeners.member.?.InstancePort'],
165
+ listeners.map{|i| [ (i[:protocol] || 'HTTP').to_s.upcase,
166
+ (i[:load_balancer_port] || 80),
167
+ (i[:instance_port] || 80) ] } ) )
168
+ link = generate_request("CreateLoadBalancer", request_hash)
169
+ request_info(link, CreateLoadBalancerParser.new(:logger => @logger))
170
+ end
171
+
172
+ # Delete load balancer.
173
+ # Returns +true+ on success.
174
+ #
175
+ # elb.delete_load_balancer('test-kd1') #=> true
176
+ #
177
+ # Amazon: Because this API has been designed to be idempotent, even if the LoadBalancer does not exist or
178
+ # has been deleted, DeleteLoadBalancer still returns a success.
179
+ #
180
+ def delete_load_balancer(load_balancer_name)
181
+ link = generate_request("DeleteLoadBalancer", 'LoadBalancerName' => load_balancer_name)
182
+ request_info(link, DeleteLoadBalancerParser.new(:logger => @logger))
183
+ end
184
+
185
+ # Add one or more zones to a load balancer.
186
+ # Returns a list of updated availability zones for the load balancer.
187
+ #
188
+ # elb.enable_availability_zones_for_load_balancer("test-kd1", "us-east-1c") #=> ["us-east-1a", "us-east-1c"]
189
+ #
190
+ def enable_availability_zones_for_load_balancer(load_balancer_name, *availability_zones)
191
+ availability_zones.flatten!
192
+ request_hash = amazonize_list("AvailabilityZones.member", availability_zones)
193
+ request_hash.merge!( 'LoadBalancerName' => load_balancer_name )
194
+ link = generate_request("EnableAvailabilityZonesForLoadBalancer", request_hash)
195
+ request_info(link, AvailabilityZonesForLoadBalancerParser.new(:logger => @logger))
196
+ end
197
+
198
+ # Remove one or more zones from a load balancer.
199
+ # Returns a list of updated availability zones for the load balancer.
200
+ #
201
+ # elb.disable_availability_zones_for_load_balancer("test-kd1", "us-east-1c") #=> ["us-east-1a"]
202
+ #
203
+ def disable_availability_zones_for_load_balancer(load_balancer_name, *availability_zones)
204
+ availability_zones.flatten!
205
+ request_hash = amazonize_list("AvailabilityZones.member", availability_zones)
206
+ request_hash.merge!( 'LoadBalancerName' => load_balancer_name )
207
+ link = generate_request("DisableAvailabilityZonesForLoadBalancer", request_hash)
208
+ request_info(link, AvailabilityZonesForLoadBalancerParser.new(:logger => @logger))
209
+ end
210
+
211
+ # Define an application healthcheck for the instances.
212
+ # Returns an updated health check configuration for the load balancer.
213
+ #
214
+ # hc = elb.configure_health_check( 'test-kd1',
215
+ # { :healthy_threshold => 9,
216
+ # :unhealthy_threshold => 3,
217
+ # :target => "TCP:433",
218
+ # :timeout => 6,
219
+ # :interval => 31}
220
+ # pp hc #=> { :target=>"TCP:433", :timeout=>6, :interval=>31, :healthy_threshold=>9, :unhealthy_threshold=>3 }
221
+ #
222
+ def configure_health_check(load_balancer_name, health_check)
223
+ request_hash = { 'LoadBalancerName' => load_balancer_name }
224
+ health_check.each{ |key, value| request_hash["HealthCheck.#{key.to_s.camelize}"] = value }
225
+ link = generate_request("ConfigureHealthCheck", request_hash)
226
+ request_info(link, HealthCheckParser.new(:logger => @logger))
227
+ end
228
+
229
+ #-----------------------------------------------------------------
230
+ # Instances
231
+ #-----------------------------------------------------------------
232
+
233
+ # Describe the current state of the instances of the specified load balancer.
234
+ # Returns a list of the instances.
235
+ #
236
+ # elb.describe_instance_health('test-kd1', 'i-8b8bcbe2', 'i-bf8bcbd6') #=>
237
+ # [ { :description => "Instance registration is still in progress",
238
+ # :reason_code => "ELB",
239
+ # :instance_id => "i-8b8bcbe2",
240
+ # :state => "OutOfService" },
241
+ # { :description => "Instance has failed at least the UnhealthyThreshold number of health checks consecutively.",
242
+ # :reason_code => "Instance",
243
+ # :instance_id => "i-bf8bcbd6",
244
+ # :state => "OutOfService" } ]
245
+ #
246
+ def describe_instance_health(load_balancer_name, *instances)
247
+ instances.flatten!
248
+ request_hash = amazonize_list("Instances.member.?.InstanceId", instances)
249
+ request_hash.merge!( 'LoadBalancerName' => load_balancer_name )
250
+ link = generate_request("DescribeInstanceHealth", request_hash)
251
+ request_info(link, DescribeInstanceHealthParser.new(:logger => @logger))
252
+ end
253
+
254
+ # Add new instance(s) to the load balancer.
255
+ # Returns an updated list of instances for the load balancer.
256
+ #
257
+ # elb.register_instances_with_load_balancer('test-kd1', 'i-8b8bcbe2', 'i-bf8bcbd6') #=> ["i-8b8bcbe2", "i-bf8bcbd6"]
258
+ #
259
+ def register_instances_with_load_balancer(load_balancer_name, *instances)
260
+ instances.flatten!
261
+ request_hash = amazonize_list("Instances.member.?.InstanceId", instances)
262
+ request_hash.merge!( 'LoadBalancerName' => load_balancer_name )
263
+ link = generate_request("RegisterInstancesWithLoadBalancer", request_hash)
264
+ request_info(link, InstancesWithLoadBalancerParser.new(:logger => @logger))
265
+ end
266
+
267
+ # Remove instance(s) from the load balancer.
268
+ # Returns an updated list of instances for the load balancer.
269
+ #
270
+ # elb.deregister_instances_with_load_balancer('test-kd1', 'i-8b8bcbe2') #=> ["i-bf8bcbd6"]
271
+ #
272
+ def deregister_instances_with_load_balancer(load_balancer_name, *instances)
273
+ instances.flatten!
274
+ request_hash = amazonize_list("Instances.member.?.InstanceId", instances)
275
+ request_hash.merge!( 'LoadBalancerName' => load_balancer_name )
276
+ link = generate_request("DeregisterInstancesFromLoadBalancer", request_hash)
277
+ request_info(link, InstancesWithLoadBalancerParser.new(:logger => @logger))
278
+ end
279
+
280
+ #-----------------------------------------------------------------
281
+ # PARSERS: Load Balancers
282
+ #-----------------------------------------------------------------
283
+
284
+ class DescribeLoadBalancersParser < RightAWSParser #:nodoc:
285
+ def tagstart(name, attributes)
286
+ case name
287
+ when 'member'
288
+ case @xmlpath
289
+ when @p then @item = { :availability_zones => [],
290
+ :health_check => {},
291
+ :listeners => [],
292
+ :instances => [] }
293
+ when "#@p/member/Listeners" then @listener = {}
294
+ end
295
+ end
296
+ end
297
+ def tagend(name)
298
+ case name
299
+ when 'LoadBalancerName' then @item[:load_balancer_name] = @text
300
+ when 'DNSName' then @item[:dns_name] = @text
301
+ when 'CreatedTime' then @item[:created_time] = Time::parse(@text)
302
+ when 'Interval' then @item[:health_check][:interval] = @text.to_i
303
+ when 'Target' then @item[:health_check][:target] = @text
304
+ when 'HealthyThreshold' then @item[:health_check][:healthy_threshold] = @text.to_i
305
+ when 'Timeout' then @item[:health_check][:timeout] = @text.to_i
306
+ when 'UnhealthyThreshold' then @item[:health_check][:unhealthy_threshold] = @text.to_i
307
+ when 'Protocol' then @listener[:protocol] = @text
308
+ when 'LoadBalancerPort' then @listener[:load_balancer_port] = @text
309
+ when 'InstancePort' then @listener[:instance_port] = @text
310
+ when 'member'
311
+ case @xmlpath
312
+ when @p then
313
+ @item[:availability_zones].sort!
314
+ @item[:instances].sort!
315
+ @result << @item
316
+ when "#@p/member/AvailabilityZones" then @item[:availability_zones] << @text
317
+ when "#@p/member/Instances" then @item[:instances] << @text
318
+ when "#@p/member/Listeners" then @item[:listeners] << @listener
319
+ end
320
+ end
321
+ end
322
+ def reset
323
+ @p = 'DescribeLoadBalancersResponse/DescribeLoadBalancersResult/LoadBalancerDescriptions'
324
+ @result = []
325
+ end
326
+ end
327
+
328
+ class CreateLoadBalancerParser < RightAWSParser #:nodoc:
329
+ def tagend(name)
330
+ @result = @text if name == 'DNSName'
331
+ end
332
+ end
333
+
334
+ class DeleteLoadBalancerParser < RightAWSParser #:nodoc:
335
+ def tagend(name)
336
+ @result = true if name == 'DeleteLoadBalancerResult'
337
+ end
338
+ end
339
+
340
+ class AvailabilityZonesForLoadBalancerParser < RightAWSParser #:nodoc:
341
+ def tagend(name)
342
+ case name
343
+ when 'member'
344
+ @result << @text
345
+ when 'AvailabilityZones'
346
+ @result.sort!
347
+ end
348
+ end
349
+ def reset
350
+ @result = []
351
+ end
352
+ end
353
+
354
+ class HealthCheckParser < RightAWSParser #:nodoc:
355
+ def tagend(name)
356
+ case name
357
+ when 'Interval' then @result[:interval] = @text.to_i
358
+ when 'Target' then @result[:target] = @text
359
+ when 'HealthyThreshold' then @result[:healthy_threshold] = @text.to_i
360
+ when 'Timeout' then @result[:timeout] = @text.to_i
361
+ when 'UnhealthyThreshold' then @result[:unhealthy_threshold] = @text.to_i
362
+ end
363
+ end
364
+ def reset
365
+ @result = {}
366
+ end
367
+ end
368
+
369
+ #-----------------------------------------------------------------
370
+ # PARSERS: Instances
371
+ #-----------------------------------------------------------------
372
+
373
+ class DescribeInstanceHealthParser < RightAWSParser #:nodoc:
374
+ def tagstart(name, attributes)
375
+ @item = {} if name == 'member'
376
+ end
377
+ def tagend(name)
378
+ case name
379
+ when 'Description' then @item[:description] = @text
380
+ when 'State' then @item[:state] = @text
381
+ when 'InstanceId' then @item[:instance_id] = @text
382
+ when 'ReasonCode' then @item[:reason_code] = @text
383
+ when 'member' then @result << @item
384
+ end
385
+ end
386
+ def reset
387
+ @result = []
388
+ end
389
+ end
390
+
391
+ class InstancesWithLoadBalancerParser < RightAWSParser #:nodoc:
392
+ def tagend(name)
393
+ case name
394
+ when 'InstanceId'
395
+ @result << @text
396
+ when 'Instances'
397
+ @result.sort!
398
+ end
399
+ end
400
+ def reset
401
+ @result = []
402
+ end
403
+ end
404
+
405
+ end
406
+
407
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redaranj-right_aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.3
4
+ version: 1.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - RightScale, Inc.
@@ -52,6 +52,8 @@ files:
52
52
  - lib/sqs/right_sqs_gen2_interface.rb
53
53
  - lib/sqs/right_sqs_interface.rb
54
54
  - lib/acf/right_acf_interface.rb
55
+ - lib/elb/right_elb_interface.rb
56
+ - lib/as/right_as_interface.rb
55
57
  - test/ec2/test_helper.rb
56
58
  - test/ec2/test_right_ec2.rb
57
59
  - test/http_connection.rb
@@ -70,7 +72,6 @@ files:
70
72
  - test/acf/test_right_acf.rb
71
73
  has_rdoc: true
72
74
  homepage:
73
- licenses:
74
75
  post_install_message:
75
76
  rdoc_options:
76
77
  - --main
@@ -92,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
93
  requirements: []
93
94
 
94
95
  rubyforge_project: rightscale
95
- rubygems_version: 1.3.5
96
+ rubygems_version: 1.2.0
96
97
  signing_key:
97
98
  specification_version: 2
98
99
  summary: Interface classes for the Amazon EC2/EBS, SQS, S3, SDB, and ACF Web Services