aws 1.10.1 → 1.10.2

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.
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