aws 1.10.1 → 1.10.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -244,3 +244,11 @@ the source key.
244
244
  - S3: Fixed overzealous URL-encoding when generating URLs for S3 keys
245
245
  (thanks to a bug report on the RubyForge forum)
246
246
 
247
+ === 1.10.1
248
+
249
+ Release Notes:
250
+
251
+ First fork release.
252
+
253
+ - Fixed to_a warnings
254
+ - Added different connection modes.
@@ -223,10 +223,12 @@ module RightAws
223
223
  @params[:protocol] ||= service_info[:default_protocol]
224
224
  end
225
225
  @params[:multi_thread] ||= defined?(AWS_DAEMON)
226
+ @params[:connection_mode] ||= @params[:multi_thread] ? :per_thread : :default
227
+ @params[:connection_mode] = :per_request if @params[:connection_mode] == :default
226
228
  @logger = @params[:logger]
227
229
  @logger = RAILS_DEFAULT_LOGGER if !@logger && defined?(RAILS_DEFAULT_LOGGER)
228
230
  @logger = Logger.new(STDOUT) if !@logger
229
- @logger.info "New #{self.class.name} using #{@params[:multi_thread] ? 'multi' : 'single'}-threaded mode"
231
+ @logger.info "New #{self.class.name} using #{@params[:connection_mode].to_s}-connection mode"
230
232
  @error_handler = nil
231
233
  @cache = {}
232
234
  @signature_version = (params[:signature_version] || DEFAULT_SIGNATURE_VERSION).to_s
data/lib/right_aws.rb CHANGED
@@ -53,7 +53,7 @@ module RightAws #:nodoc:
53
53
  module VERSION #:nodoc:
54
54
  MAJOR = 1
55
55
  MINOR = 10
56
- TINY = 1
56
+ TINY = 2
57
57
 
58
58
  STRING = [MAJOR, MINOR, TINY].join('.')
59
59
  end
@@ -98,11 +98,7 @@ module RightAws
98
98
  def connection
99
99
  @connection || raise(ActiveSdbError.new('Connection to SDB is not established'))
100
100
  end
101
- def close
102
- if @connection
103
- @connection.fin
104
- end
105
- end
101
+
106
102
  # Create a new handle to an Sdb account. All handles share the same per process or per thread
107
103
  # HTTP connection to Amazon Sdb. Each handle is for a specific account.
108
104
  # The +params+ are passed through as-is to RightAws::SdbInterface.new
@@ -112,13 +108,21 @@ module RightAws
112
108
  # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
113
109
  # :signature_version => '0' # The signature version : '0' or '1'(default)
114
110
  # DEPRECATED :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
115
- # :connection_mode => :default # options are :single, :multi (same as old multi_thread=>true), :pool, :per_request
116
- # :logger => Logger Object # Logger instance: logs to STDOUT if omitted
111
+ # :connection_mode => :default # options are :default (will use best known option, may change in the future)
112
+ # :per_request (opens and closes a connection on every request to SDB)
113
+ # :single (same as old multi_thread=>false)
114
+ # :per_thread (same as old multi_thread=>true)
115
+ # :pool (uses a connection pool with a maximum number of connections - NOT IMPLEMENTED YET)
116
+ # :logger => Logger Object # Logger instance: logs to STDOUT if omitted
117
117
  # :nil_representation => 'mynil'} # interpret Ruby nil as this string value; i.e. use this string in SDB to represent Ruby nils (default is the string 'nil')
118
118
 
119
119
  def establish_connection(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
120
120
  @connection = RightAws::SdbInterface.new(aws_access_key_id, aws_secret_access_key, params)
121
121
  end
122
+
123
+ def close_connection
124
+ @connection.close_connection unless @connection.nil?
125
+ end
122
126
  end
123
127
 
124
128
  class ActiveSdbError < RuntimeError ; end
@@ -26,7 +26,7 @@ require "right_aws"
26
26
  module RightAws
27
27
 
28
28
  class SdbInterface < RightAwsBase
29
-
29
+
30
30
  include RightAwsBaseInterface
31
31
 
32
32
  DEFAULT_HOST = 'sdb.amazonaws.com'
@@ -61,12 +61,12 @@ module RightAws
61
61
  def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
62
62
  @nil_rep = params[:nil_representation] ? params[:nil_representation] : DEFAULT_NIL_REPRESENTATION
63
63
  params.delete(:nil_representation)
64
- init({ :name => 'SDB',
65
- :default_host => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).host : DEFAULT_HOST,
66
- :default_port => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).port : DEFAULT_PORT,
67
- :default_protocol => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).scheme : DEFAULT_PROTOCOL },
68
- aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
69
- aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
64
+ init({ :name => 'SDB',
65
+ :default_host => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).host : DEFAULT_HOST,
66
+ :default_port => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).port : DEFAULT_PORT,
67
+ :default_protocol => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).scheme : DEFAULT_PROTOCOL },
68
+ aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
69
+ aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
70
70
  params)
71
71
  end
72
72
 
@@ -99,7 +99,7 @@ module RightAws
99
99
  request = Net::HTTP::Get.new("#{service}?#{service_params}")
100
100
  end
101
101
  # prepare output hash
102
- { :request => request,
102
+ { :request => request,
103
103
  :server => @params[:server],
104
104
  :port => @params[:port],
105
105
  :protocol => @params[:protocol] }
@@ -108,14 +108,32 @@ module RightAws
108
108
  # Sends request to Amazon and parses the response
109
109
  # Raises AwsError if any banana happened
110
110
  def request_info(request, parser) #:nodoc:
111
- # thread = @params[:multi_thread] ? Thread.current : Thread.main
112
- # thread[:sdb_connection] ||= Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
113
- http_conn = Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
114
- ret = request_info_impl(http_conn, @@bench, request, parser)
115
- http_conn.finish
111
+ ret = nil
112
+ conn_mode = @params[:connection_mode]
113
+ if conn_mode == :per_request
114
+ http_conn = Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
115
+ ret = request_info_impl(http_conn, @@bench, request, parser)
116
+ http_conn.finish
117
+ elsif conn_mode == :per_thread || conn_mode == :single
118
+ thread = conn_mode == :per_thread ? Thread.current : Thread.main
119
+ thread[:sdb_connection] ||= Rightscale::HttpConnection.new(:exception => AwsError, :logger => @logger)
120
+ http_conn = thread[:sdb_connection]
121
+ ret = request_info_impl(http_conn, @@bench, request, parser)
122
+ end
116
123
  ret
117
124
  end
118
125
 
126
+ def close_connection
127
+ conn_mode = @params[:connection_mode]
128
+ if conn_mode == :per_thread || conn_mode == :single
129
+ thread = conn_mode == :per_thread ? Thread.current : Thread.main
130
+ if !thread[:sdb_connection].nil?
131
+ thread[:sdb_connection].finish
132
+ thread[:sdb_connection] = nil
133
+ end
134
+ end
135
+ end
136
+
119
137
  # Prepare attributes for putting.
120
138
  # (used by put_attributes)
121
139
  def pack_attributes(attributes, replace = false) #:nodoc:
@@ -142,7 +160,7 @@ module RightAws
142
160
  end
143
161
  result
144
162
  end
145
-
163
+
146
164
  # Use this helper to manually escape the fields in the query expressions.
147
165
  # To escape the single quotes and backslashes and to wrap the string into the single quotes.
148
166
  #
@@ -151,13 +169,13 @@ module RightAws
151
169
  def escape(value)
152
170
  %Q{'#{value.to_s.gsub(/(['\\])/){ "\\#{$1}" }}'} if value
153
171
  end
154
-
172
+
155
173
  # Convert a Ruby language value to a SDB value by replacing Ruby nil with the user's chosen string representation of nil.
156
174
  # Non-nil values are unaffected by this filter.
157
175
  def ruby_to_sdb(value)
158
176
  value.nil? ? @nil_rep : value
159
177
  end
160
-
178
+
161
179
  # Convert a SDB value to a Ruby language value by replacing the user's chosen string representation of nil with Ruby nil.
162
180
  # Values are unaffected by this filter unless they match the nil representation exactly.
163
181
  def sdb_to_ruby(value)
@@ -245,7 +263,7 @@ module RightAws
245
263
  rescue Exception
246
264
  on_exception
247
265
  end
248
-
266
+
249
267
  # Create new SDB domain at Amazon.
250
268
  #
251
269
  # Returns a hash: { :box_usage, :request_id } on success or an exception on error.
@@ -286,7 +304,7 @@ module RightAws
286
304
  rescue Exception
287
305
  on_exception
288
306
  end
289
-
307
+
290
308
  # Add/Replace item attributes.
291
309
  #
292
310
  # Params:
@@ -336,7 +354,7 @@ module RightAws
336
354
  rescue Exception
337
355
  on_exception
338
356
  end
339
-
357
+
340
358
  # Retrieve SDB item's attribute(s).
341
359
  #
342
360
  # Returns a hash:
@@ -398,10 +416,10 @@ module RightAws
398
416
  rescue Exception
399
417
  on_exception
400
418
  end
401
-
402
-
419
+
420
+
403
421
  # QUERY:
404
-
422
+
405
423
  # Perform a query on SDB.
406
424
  #
407
425
  # Returns a hash:
@@ -460,7 +478,7 @@ module RightAws
460
478
  rescue Exception
461
479
  on_exception
462
480
  end
463
-
481
+
464
482
  # Perform a query and fetch specified attributes.
465
483
  # If attributes are not specified then fetches the whole list of attributes.
466
484
  #
@@ -697,5 +715,5 @@ module RightAws
697
715
  end
698
716
 
699
717
  end
700
-
718
+
701
719
  end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/right_aws'
@@ -0,0 +1,146 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestAcf < Test::Unit::TestCase
4
+
5
+ RIGHT_OBJECT_TEXT = 'Right test message'
6
+
7
+ STDOUT.sync = true
8
+
9
+ def setup
10
+ @acf= Rightscale::AcfInterface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
11
+ @s3 = Rightscale::S3.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
12
+ @bucket_name = "right-acf-awesome-test-bucket-0001"
13
+ @bucket_domain = "#{@bucket_name}.s3.amazonaws.com"
14
+ end
15
+
16
+ def test_01_list_distributions_part1
17
+ distributions = nil
18
+ assert_nothing_raised(Rightscale::AwsError) do
19
+ distributions = @acf.list_distributions
20
+ end
21
+ assert distributions.is_a?(Array)
22
+ end
23
+
24
+ def test_02_try_to_create_for_bad_bucket
25
+ # a bucket does not exist
26
+ assert_raise(Rightscale::AwsError) do
27
+ @acf.create_distribution("right-cloudfront-awesome-test-bucket-not-exist", "Mustn't to be born", true)
28
+ end
29
+ # a bucket is not a domain naming complied guy
30
+ bucket_name = 'right_cloudfront_awesome_test_bucket_BAD'
31
+ @s3.bucket(bucket_name, :create)
32
+ assert_raise(Rightscale::AwsError) do
33
+ @acf.create_distribution(bucket_name, "Mustn't to be born", true)
34
+ end
35
+ end
36
+
37
+ def test_03_create
38
+ comment = 'WooHoo!!!'
39
+ # create a test bucket
40
+ @s3.bucket(@bucket_name, :create)
41
+ # create a distribution
42
+ distribution = @acf.create_distribution(@bucket_domain, comment, true)
43
+ assert_equal comment, distribution[:comment]
44
+ assert distribution[:cnames].size == 0
45
+ assert distribution[:enabled]
46
+ end
47
+
48
+ def test_04_list_distributions_part2
49
+ distributions = @acf.list_distributions
50
+ assert distributions.size > 0
51
+ end
52
+
53
+ def get_test_distribution
54
+ @acf.list_distributions.select{ |d| d[:origin] == @bucket_domain }.first
55
+ end
56
+
57
+ def test_05_get_distribution
58
+ old = get_test_distribution
59
+ assert_nothing_raised do
60
+ @acf.get_distribution(old[:aws_id])
61
+ end
62
+ end
63
+
64
+ def test_06_get_and_set_config
65
+ config = nil
66
+ old = get_test_distribution
67
+ assert_nothing_raised do
68
+ config = @acf.get_distribution_config(old[:aws_id])
69
+ end
70
+ # change a config
71
+ config[:enabled] = false
72
+ config[:cnames] << 'x1.myawesomesite.com'
73
+ config[:cnames] << 'x2.myawesomesite.com'
74
+ # set config
75
+ set_config_result = nil
76
+ assert_nothing_raised do
77
+ set_config_result = @acf.set_distribution_config(old[:aws_id], config)
78
+ end
79
+ assert set_config_result
80
+ # reget the config and check
81
+ new_config = nil
82
+ assert_nothing_raised do
83
+ new_config = @acf.get_distribution_config(old[:aws_id])
84
+ end
85
+ assert !new_config[:enabled]
86
+ assert_equal new_config[:cnames].sort, ['x1.myawesomesite.com', 'x2.myawesomesite.com']
87
+ assert_not_equal config[:e_tag], new_config[:e_tag]
88
+
89
+ # try to update the old config again (must fail because ETAG has changed)
90
+ assert_raise(Rightscale::AwsError) do
91
+ @acf.set_distribution_config(old[:aws_id], config)
92
+ end
93
+ end
94
+
95
+ def test_07_caching
96
+ # enable caching
97
+ @acf.params[:cache] = true
98
+ # list distributions
99
+ @acf.list_distributions
100
+ # list the distributions again - cache should hit
101
+ assert_raise(Rightscale::AwsNoChange) do
102
+ @acf.list_distributions
103
+ end
104
+ # disable caching
105
+ @acf.params[:cache] = true
106
+ end
107
+
108
+ def test_08_delete_distribution
109
+ # we need ETAG so use get_distribution
110
+ distribution = @acf.get_distribution(get_test_distribution[:aws_id])
111
+ # try to delete a distribution
112
+ # should fail because
113
+ if distribution[:status] == 'InProgress'
114
+ # should fail because the distribution is not deployed yet
115
+ assert_raise(Rightscale::AwsError) do
116
+ @acf.delete_distribution(distribution[:aws_id], distribution[:e_tag])
117
+ end
118
+ # wait for a deployed state
119
+ print "waiting up to 5 min while the distribution is being deployed: "
120
+ 100.times do
121
+ print '.'
122
+ distribution = @acf.get_distribution(distribution[:aws_id])
123
+ if distribution[:status] == 'Deployed'
124
+ print ' done'
125
+ break
126
+ end
127
+ sleep 3
128
+ end
129
+ puts
130
+ end
131
+
132
+ # only disabled and deployed distribution can be deleted
133
+ assert_equal 'Deployed', distribution[:status]
134
+ assert !distribution[:enabled]
135
+
136
+ # delete the distribution
137
+ assert_nothing_raised do
138
+ @acf.delete_distribution(distribution[:aws_id], distribution[:e_tag])
139
+ end
140
+ end
141
+
142
+ def test_09_drop_bucket
143
+ assert @s3.bucket(@bucket_name).delete
144
+ end
145
+
146
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/right_aws'
@@ -0,0 +1,108 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'pp'
3
+
4
+ class TestEc2 < Test::Unit::TestCase
5
+
6
+ # Some of RightEc2 instance methods concerning instance launching and image registration
7
+ # are not tested here due to their potentially risk.
8
+
9
+ def setup
10
+ @ec2 = Rightscale::Ec2.new(TestCredentials.aws_access_key_id,
11
+ TestCredentials.aws_secret_access_key)
12
+ @key = 'right_ec2_awesome_test_key'
13
+ @group = 'right_ec2_awesome_test_security_group'
14
+ end
15
+
16
+ def test_01_create_describe_key_pairs
17
+ new_key = @ec2.create_key_pair(@key)
18
+ assert new_key[:aws_material][/BEGIN RSA PRIVATE KEY/], "New key material is absent"
19
+ keys = @ec2.describe_key_pairs
20
+ assert keys.map{|key| key[:aws_key_name] }.include?(@key), "#{@key} must exist"
21
+ end
22
+
23
+ def test_02_create_security_group
24
+ assert @ec2.create_security_group(@group,'My awesone test group'), 'Create_security_group fail'
25
+ group = @ec2.describe_security_groups([@group])[0]
26
+ assert_equal @group, group[:aws_group_name], 'Group must be created but does not exist'
27
+ end
28
+
29
+ def test_03_perms_add
30
+ assert @ec2.authorize_security_group_named_ingress(@group, TestCredentials.account_number, 'default')
31
+ assert @ec2.authorize_security_group_IP_ingress(@group, 80,80,'udp','192.168.1.0/8')
32
+ end
33
+
34
+ def test_04_check_new_perms_exist
35
+ assert_equal 2, @ec2.describe_security_groups([@group])[0][:aws_perms].size
36
+ end
37
+
38
+ def test_05_perms_remove
39
+ assert @ec2.revoke_security_group_IP_ingress(@group, 80,80,'udp','192.168.1.0/8')
40
+ assert @ec2.revoke_security_group_named_ingress(@group,
41
+ TestCredentials.account_number, 'default')
42
+ end
43
+
44
+ def test_06_describe_images
45
+ images = @ec2.describe_images
46
+ assert images.size>0, 'Amazon must have at least some public images'
47
+ # unknown image
48
+ assert_raise(Rightscale::AwsError){ @ec2.describe_images(['ami-ABCDEFGH'])}
49
+ end
50
+
51
+ def test_07_describe_instanses
52
+ assert @ec2.describe_instances
53
+ # unknown image
54
+ assert_raise(Rightscale::AwsError){ @ec2.describe_instances(['i-ABCDEFGH'])}
55
+ end
56
+
57
+ def test_08_delete_security_group
58
+ assert @ec2.delete_security_group(@group), 'Delete_security_group fail'
59
+ end
60
+
61
+ def test_09_delete_key_pair
62
+ assert @ec2.delete_key_pair(@key), 'Delete_key_pair fail'
63
+ ## Hmmm... Amazon does not through the exception any more. It now just returns a 'true' if the key does not exist any more...
64
+ ## # key must be deleted already
65
+ ## assert_raise(Rightscale::AwsError) { @ec2.delete_key_pair(@key) }
66
+ end
67
+
68
+ def test_10_signature_version_0
69
+ ec2 = Rightscale::Ec2.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :signature_version => '0')
70
+ images = ec2.describe_images
71
+ assert images.size>0, 'Amazon must have at least some public images'
72
+ # check that the request has correct signature version
73
+ assert ec2.last_request.path.include?('SignatureVersion=0')
74
+ end
75
+
76
+ def test_11_regions
77
+ regions = nil
78
+ assert_nothing_raised do
79
+ regions = @ec2.describe_regions
80
+ end
81
+ # check we got more that 0 regions
82
+ assert regions.size > 0
83
+ # check an access to regions
84
+ regions.each do |region|
85
+ regional_ec2 = Rightscale::Ec2.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :region => region)
86
+ # do we have a correct endpoint server?
87
+ assert_equal "#{region}.ec2.amazonaws.com", regional_ec2.params[:server]
88
+ # get a list of images from every region
89
+ images = nil
90
+ assert_nothing_raised do
91
+ images = regional_ec2.describe_regions
92
+ end
93
+ # every region must have images
94
+ assert images.size > 0
95
+ end
96
+ end
97
+
98
+ def test_12_endpoint_url
99
+ ec2 = Rightscale::Ec2.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :endpoint_url => 'a://b.c:0/d/', :region => 'z')
100
+ # :endpoint_url has a priority hence :region should be ommitted
101
+ assert_equal 'a', ec2.params[:protocol]
102
+ assert_equal 'b.c', ec2.params[:server]
103
+ assert_equal '/d/', ec2.params[:service]
104
+ assert_equal 0, ec2.params[:port]
105
+ assert_nil ec2.params[:region]
106
+ end
107
+
108
+ end