right_aws-yodal 1.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
data/lib/right_aws.rb ADDED
@@ -0,0 +1,79 @@
1
+ #
2
+ # Copyright (c) 2007-2008 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
+ require 'benchmark'
25
+ require 'net/https'
26
+ require 'uri'
27
+ require 'time'
28
+ require "cgi"
29
+ require "base64"
30
+ require "rexml/document"
31
+ require "openssl"
32
+ require "digest/sha1"
33
+
34
+ require 'rubygems'
35
+ require 'right_http_connection'
36
+
37
+ $:.unshift(File.dirname(__FILE__))
38
+ require 'awsbase/benchmark_fix'
39
+ require 'awsbase/support'
40
+ require 'awsbase/right_awsbase'
41
+ require 'ec2/right_ec2'
42
+ require 'ec2/right_ec2_images'
43
+ require 'ec2/right_ec2_instances'
44
+ require 'ec2/right_ec2_ebs'
45
+ require 'ec2/right_ec2_reserved_instances'
46
+ require 'ec2/right_ec2_vpc'
47
+ require 'ec2/right_ec2_monitoring'
48
+ require 'elb/right_elb_interface'
49
+ require 'acw/right_acw_interface'
50
+ require 'as/right_as_interface'
51
+ require 's3/right_s3_interface'
52
+ require 's3/right_s3'
53
+ require 'sqs/right_sqs_interface'
54
+ require 'sqs/right_sqs'
55
+ require 'sqs/right_sqs_gen2_interface'
56
+ require 'sqs/right_sqs_gen2'
57
+ require 'sdb/right_sdb_interface'
58
+ require 'acf/right_acf_interface'
59
+ require 'rds/right_rds_interface'
60
+
61
+
62
+ module RightAws #:nodoc:
63
+ module VERSION #:nodoc:
64
+ MAJOR = 1
65
+ MINOR = 11
66
+ TINY = 0
67
+
68
+ STRING = [MAJOR, MINOR, TINY].join('.')
69
+ end
70
+ end
71
+
72
+ #-
73
+
74
+ # We also want everything available in the Rightscale namespace for backward
75
+ # compatibility reasons.
76
+ module Rightscale #:nodoc:
77
+ include RightAws
78
+ extend RightAws
79
+ end