right_aws 1.7.1 → 1.7.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 +46 -66
- data/Manifest.txt +1 -0
- data/README.txt +8 -1
- data/lib/awsbase/benchmark_fix.rb +1 -1
- data/lib/awsbase/file_fix.rb +33 -0
- data/lib/awsbase/right_awsbase.rb +23 -4
- data/lib/ec2/right_ec2.rb +112 -94
- data/lib/right_aws.rb +2 -1
- data/lib/s3/right_s3.rb +120 -6
- data/lib/s3/right_s3_interface.rb +79 -10
- data/lib/sdb/right_sdb_interface.rb +7 -3
- data/lib/sqs/right_sqs.rb +1 -1
- data/lib/sqs/right_sqs_gen2_interface.rb +1 -0
- data/lib/sqs/right_sqs_interface.rb +14 -11
- data/test/ec2/test_right_ec2.rb +8 -0
- data/test/s3/test_right_s3.rb +124 -6
- data/test/s3/test_right_s3_stubbed.rb +25 -0
- data/test/sdb/test_right_sdb.rb +21 -2
- data/test/sqs/test_right_sqs.rb +36 -3
- data/test/sqs/test_right_sqs_gen2.rb +9 -0
- metadata +52 -44
data/lib/right_aws.rb
CHANGED
|
@@ -36,6 +36,7 @@ require 'right_http_connection'
|
|
|
36
36
|
|
|
37
37
|
$:.unshift(File.dirname(__FILE__))
|
|
38
38
|
require 'awsbase/benchmark_fix'
|
|
39
|
+
require 'awsbase/file_fix'
|
|
39
40
|
require 'awsbase/support'
|
|
40
41
|
require 'awsbase/right_awsbase'
|
|
41
42
|
require 'ec2/right_ec2'
|
|
@@ -52,7 +53,7 @@ module RightAws #:nodoc:
|
|
|
52
53
|
module VERSION #:nodoc:
|
|
53
54
|
MAJOR = 1
|
|
54
55
|
MINOR = 7
|
|
55
|
-
TINY =
|
|
56
|
+
TINY = 2
|
|
56
57
|
|
|
57
58
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
|
58
59
|
end
|
data/lib/s3/right_s3.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2007 RightScale Inc
|
|
2
|
+
# Copyright (c) 2007-2008 RightScale Inc
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
5
|
# a copy of this software and associated documentation files (the
|
|
@@ -249,6 +249,40 @@ module RightAws
|
|
|
249
249
|
key = Key.create(self, key.to_s) unless key.is_a?(Key)
|
|
250
250
|
key.get(headers)
|
|
251
251
|
end
|
|
252
|
+
|
|
253
|
+
# Rename object. Returns RightAws::S3::Key instance.
|
|
254
|
+
#
|
|
255
|
+
# new_key = bucket.rename_key('logs/today/1.log','logs/today/2.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
256
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
257
|
+
# key.exists? #=> true
|
|
258
|
+
#
|
|
259
|
+
def rename_key(old_key_or_name, new_name)
|
|
260
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
261
|
+
old_key_or_name.rename(new_name)
|
|
262
|
+
old_key_or_name
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Create an object copy. Returns a destination RightAws::S3::Key instance.
|
|
266
|
+
#
|
|
267
|
+
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
268
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
269
|
+
# key.exists? #=> true
|
|
270
|
+
#
|
|
271
|
+
def copy_key(old_key_or_name, new_key_or_name)
|
|
272
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
273
|
+
old_key_or_name.copy(new_key_or_name)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Move an object to other location. Returns a destination RightAws::S3::Key instance.
|
|
277
|
+
#
|
|
278
|
+
# new_key = bucket.copy_key('logs/today/1.log','logs/today/2.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
279
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
280
|
+
# key.exists? #=> true
|
|
281
|
+
#
|
|
282
|
+
def move_key(old_key_or_name, new_key_or_name)
|
|
283
|
+
old_key_or_name = Key.create(self, old_key_or_name.to_s) unless old_key_or_name.is_a?(Key)
|
|
284
|
+
old_key_or_name.move(new_key_or_name)
|
|
285
|
+
end
|
|
252
286
|
|
|
253
287
|
# Remove all keys from a bucket.
|
|
254
288
|
# Returns +true+.
|
|
@@ -260,7 +294,7 @@ module RightAws
|
|
|
260
294
|
end
|
|
261
295
|
|
|
262
296
|
# Delete all keys where the 'folder_key' can be interpreted
|
|
263
|
-
|
|
297
|
+
# as a 'folder' name.
|
|
264
298
|
# Returns an array of string keys that have been deleted.
|
|
265
299
|
#
|
|
266
300
|
# bucket.keys.map{|key| key.name}.join(', ') #=> 'test, test/2/34, test/3, test1, test1/logs'
|
|
@@ -334,7 +368,7 @@ module RightAws
|
|
|
334
368
|
end
|
|
335
369
|
|
|
336
370
|
# Create a new Key instance, but do not create the actual key.
|
|
337
|
-
|
|
371
|
+
# In normal use this method should not be called directly.
|
|
338
372
|
# Use RightAws::S3::Key.create or bucket.key() instead.
|
|
339
373
|
#
|
|
340
374
|
def initialize(bucket, name, data=nil, headers={}, meta_headers={},
|
|
@@ -417,6 +451,66 @@ module RightAws
|
|
|
417
451
|
@bucket.s3.interface.put(@bucket.name, @name, @data, meta.merge(headers))
|
|
418
452
|
end
|
|
419
453
|
|
|
454
|
+
# Rename an object. Returns new object name.
|
|
455
|
+
#
|
|
456
|
+
# key = RightAws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
457
|
+
# key.rename('logs/today/2.log') #=> 'logs/today/2.log'
|
|
458
|
+
# puts key.name #=> 'logs/today/2.log'
|
|
459
|
+
# key.exists? #=> true
|
|
460
|
+
#
|
|
461
|
+
def rename(new_name)
|
|
462
|
+
@bucket.s3.interface.rename(@bucket.name, @name, new_name)
|
|
463
|
+
@name = new_name
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# Create an object copy. Returns a destination RightAws::S3::Key instance.
|
|
467
|
+
#
|
|
468
|
+
# # Key instance as destination
|
|
469
|
+
# key1 = RightAws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
470
|
+
# key2 = RightAws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
471
|
+
# key1.put('Olala!') #=> true
|
|
472
|
+
# key1.copy(key2) #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
473
|
+
# key1.exists? #=> true
|
|
474
|
+
# key2.exists? #=> true
|
|
475
|
+
# puts key2.data #=> 'Olala!'
|
|
476
|
+
#
|
|
477
|
+
# # String as destination
|
|
478
|
+
# key = RightAws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
479
|
+
# key.put('Olala!') #=> true
|
|
480
|
+
# new_key = key.copy('logs/today/888.log') #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
481
|
+
# key.exists? #=> true
|
|
482
|
+
# new_key.exists? #=> true
|
|
483
|
+
#
|
|
484
|
+
def copy(new_key_or_name)
|
|
485
|
+
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
486
|
+
@bucket.s3.interface.copy(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
487
|
+
new_key_or_name
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
# Move an object to other location. Returns a destination RightAws::S3::Key instance.
|
|
491
|
+
#
|
|
492
|
+
# # Key instance as destination
|
|
493
|
+
# key1 = RightAws::S3::Key.create(bucket, 'logs/today/1.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
494
|
+
# key2 = RightAws::S3::Key.create(bucket, 'logs/today/2.log') #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
495
|
+
# key1.put('Olala!') #=> true
|
|
496
|
+
# key1.move(key2) #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
497
|
+
# key1.exists? #=> false
|
|
498
|
+
# key2.exists? #=> true
|
|
499
|
+
# puts key2.data #=> 'Olala!'
|
|
500
|
+
#
|
|
501
|
+
# # String as destination
|
|
502
|
+
# key = RightAws::S3::Key.create(bucket, 'logs/today/777.log') #=> #<RightAws::S3::Key:0xb7b1e240 ... >
|
|
503
|
+
# key.put('Olala!') #=> true
|
|
504
|
+
# new_key = key.move('logs/today/888.log') #=> #<RightAws::S3::Key:0xb7b5e240 ... >
|
|
505
|
+
# key.exists? #=> false
|
|
506
|
+
# new_key.exists? #=> true
|
|
507
|
+
#
|
|
508
|
+
def move(new_key_or_name)
|
|
509
|
+
new_key_or_name = Key.create(@bucket, new_key_or_name.to_s) unless new_key_or_name.is_a?(Key)
|
|
510
|
+
@bucket.s3.interface.move(@bucket.name, @name, new_key_or_name.bucket.name, new_key_or_name.name)
|
|
511
|
+
new_key_or_name
|
|
512
|
+
end
|
|
513
|
+
|
|
420
514
|
# Retrieve key info from bucket and update attributes.
|
|
421
515
|
# Refresh meta-headers (by calling +head+ method) if +head+ is set.
|
|
422
516
|
# Returns +true+ if the key exists in bucket and +false+ otherwise.
|
|
@@ -444,7 +538,7 @@ module RightAws
|
|
|
444
538
|
end
|
|
445
539
|
end
|
|
446
540
|
|
|
447
|
-
#
|
|
541
|
+
# Updates headers and meta-headers from S3.
|
|
448
542
|
# Returns +true+.
|
|
449
543
|
#
|
|
450
544
|
# key.meta_headers #=> {"family"=>"qwerty"}
|
|
@@ -455,7 +549,27 @@ module RightAws
|
|
|
455
549
|
@headers, @meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name))
|
|
456
550
|
true
|
|
457
551
|
end
|
|
458
|
-
|
|
552
|
+
|
|
553
|
+
# Reload meta-headers only. Returns meta-headers hash.
|
|
554
|
+
#
|
|
555
|
+
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
556
|
+
#
|
|
557
|
+
def reload_meta
|
|
558
|
+
@meta_headers = self.class.split_meta(@bucket.s3.interface.head(@bucket, @name)).last
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
# Replace meta-headers by new hash at S3. Returns new meta-headers hash.
|
|
562
|
+
#
|
|
563
|
+
# key.reload_meta #=> {"family"=>"qwerty", "name"=>"asdfg"}
|
|
564
|
+
# key.save_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
565
|
+
# key.reload_meta #=> {"family"=>"oops", "race" => "troll"}
|
|
566
|
+
#
|
|
567
|
+
def save_meta(meta_headers)
|
|
568
|
+
meta = self.class.add_meta_prefix(meta_headers)
|
|
569
|
+
@bucket.s3.interface.copy(@bucket.name, @name, @bucket.name, @name, :replace, meta)
|
|
570
|
+
@meta_headers = self.class.split_meta(meta)[1]
|
|
571
|
+
end
|
|
572
|
+
|
|
459
573
|
# Check for existence of the key in the given bucket.
|
|
460
574
|
# Returns +true+ or +false+.
|
|
461
575
|
#
|
|
@@ -703,7 +817,7 @@ module RightAws
|
|
|
703
817
|
|
|
704
818
|
# Apply current grantee @perms to +thing+. This method is called internally by the +grant+
|
|
705
819
|
# and +revoke+ methods. In normal use this method should not
|
|
706
|
-
|
|
820
|
+
# be called directly.
|
|
707
821
|
#
|
|
708
822
|
# grantee.perms = ['FULL_CONTROL']
|
|
709
823
|
# grantee.apply #=> true
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2007 RightScale Inc
|
|
2
|
+
# Copyright (c) 2007-2008 RightScale Inc
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
5
|
# a copy of this software and associated documentation files (the
|
|
@@ -33,7 +33,8 @@ module RightAws
|
|
|
33
33
|
DEFAULT_PORT = 443
|
|
34
34
|
DEFAULT_PROTOCOL = 'https'
|
|
35
35
|
REQUEST_TTL = 30
|
|
36
|
-
DEFAULT_EXPIRES_AFTER =
|
|
36
|
+
DEFAULT_EXPIRES_AFTER = 1 * 24 * 60 * 60 # One day's worth of seconds
|
|
37
|
+
ONE_YEAR_IN_SECONDS = 365 * 24 * 60 * 60
|
|
37
38
|
AMAZON_HEADER_PREFIX = 'x-amz-'
|
|
38
39
|
AMAZON_METADATA_PREFIX = 'x-amz-meta-'
|
|
39
40
|
|
|
@@ -372,12 +373,12 @@ module RightAws
|
|
|
372
373
|
# :headers => {"last-modified" => "Wed, 23 May 2007 09:08:04 GMT",
|
|
373
374
|
# "content-type" => "",
|
|
374
375
|
# "etag" => "\"000000000096f4ee74bc4596443ef2a4\"",
|
|
375
|
-
#
|
|
376
|
-
#
|
|
377
|
-
#
|
|
378
|
-
#
|
|
379
|
-
#
|
|
380
|
-
#
|
|
376
|
+
# "date" => "Wed, 23 May 2007 09:08:03 GMT",
|
|
377
|
+
# "x-amz-id-2" => "ZZZZZZZZZZZZZZZZZZZZ1HJXZoehfrS4QxcxTdNGldR7w/FVqblP50fU8cuIMLiu",
|
|
378
|
+
# "x-amz-meta-family" => "Woho556!",
|
|
379
|
+
# "x-amz-request-id" => "0000000C246D770C",
|
|
380
|
+
# "server" => "AmazonS3",
|
|
381
|
+
# "content-length" => "7"}}
|
|
381
382
|
#
|
|
382
383
|
# If a block is provided, yields incrementally to the block as
|
|
383
384
|
# the response is read. For large responses, this function is ideal as
|
|
@@ -429,6 +430,54 @@ module RightAws
|
|
|
429
430
|
on_exception
|
|
430
431
|
end
|
|
431
432
|
|
|
433
|
+
# Copy an object.
|
|
434
|
+
# directive: :copy - copy meta-headers from source (default value)
|
|
435
|
+
# :replace - replace meta-headers by passed ones
|
|
436
|
+
#
|
|
437
|
+
# # copy a key with meta-headers
|
|
438
|
+
# s3.copy('b1', 'key1', 'b1', 'key1_copy') #=> {:e_tag=>"\"e8b...8d\"", :last_modified=>"2008-05-11T10:25:22.000Z"}
|
|
439
|
+
#
|
|
440
|
+
# # copy a key, overwrite meta-headers
|
|
441
|
+
# s3.copy('b1', 'key2', 'b1', 'key2_copy', :replace, 'x-amz-meta-family'=>'Woho555!') #=> {:e_tag=>"\"e8b...8d\"", :last_modified=>"2008-05-11T10:26:22.000Z"}
|
|
442
|
+
#
|
|
443
|
+
# see: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingCopyingObjects.html
|
|
444
|
+
# http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTObjectCOPY.html
|
|
445
|
+
#
|
|
446
|
+
def copy(src_bucket, src_key, dest_bucket, dest_key=nil, directive=:copy, headers={})
|
|
447
|
+
dest_key ||= src_key
|
|
448
|
+
headers['x-amz-metadata-directive'] = directive.to_s.upcase
|
|
449
|
+
headers['x-amz-copy-source'] = "#{src_bucket}/#{src_key}"
|
|
450
|
+
req_hash = generate_rest_request('PUT', headers.merge(:url=>"#{dest_bucket}/#{CGI::escape dest_key}"))
|
|
451
|
+
request_info(req_hash, S3CopyParser.new)
|
|
452
|
+
rescue
|
|
453
|
+
on_exception
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Move an object.
|
|
457
|
+
# directive: :copy - copy meta-headers from source (default value)
|
|
458
|
+
# :replace - replace meta-headers by passed ones
|
|
459
|
+
#
|
|
460
|
+
# # move bucket1/key1 to bucket1/key2
|
|
461
|
+
# s3.move('bucket1', 'key1', 'bucket1', 'key2') #=> {:e_tag=>"\"e8b...8d\"", :last_modified=>"2008-05-11T10:27:22.000Z"}
|
|
462
|
+
#
|
|
463
|
+
# # move bucket1/key1 to bucket2/key2 with new meta-headers assignment
|
|
464
|
+
# s3.copy('bucket1', 'key1', 'bucket2', 'key2', :replace, 'x-amz-meta-family'=>'Woho555!') #=> {:e_tag=>"\"e8b...8d\"", :last_modified=>"2008-05-11T10:28:22.000Z"}
|
|
465
|
+
#
|
|
466
|
+
def move(src_bucket, src_key, dest_bucket, dest_key=nil, directive=:copy, headers={})
|
|
467
|
+
copy_result = copy(src_bucket, src_key, dest_bucket, dest_key, directive, headers)
|
|
468
|
+
# delete an original key if it differs from a destination one
|
|
469
|
+
delete(src_bucket, src_key) unless src_bucket == dest_bucket && src_key == dest_key
|
|
470
|
+
copy_result
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Rename an object.
|
|
474
|
+
#
|
|
475
|
+
# # rename bucket1/key1 to bucket1/key2
|
|
476
|
+
# s3.rename('bucket1', 'key1', 'key2') #=> {:e_tag=>"\"e8b...8d\"", :last_modified=>"2008-05-11T10:29:22.000Z"}
|
|
477
|
+
#
|
|
478
|
+
def rename(src_bucket, src_key, dest_key, headers={})
|
|
479
|
+
move(src_bucket, src_key, src_bucket, dest_key, :copy, headers)
|
|
480
|
+
end
|
|
432
481
|
|
|
433
482
|
# Retieves the ACL (access control policy) for a bucket or object. Returns a hash of headers and xml doc with ACL data. See: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAccessPolicy.html.
|
|
434
483
|
#
|
|
@@ -601,7 +650,7 @@ module RightAws
|
|
|
601
650
|
end
|
|
602
651
|
# expiration time
|
|
603
652
|
expires ||= DEFAULT_EXPIRES_AFTER
|
|
604
|
-
expires = Time.now.utc
|
|
653
|
+
expires = Time.now.utc + expires if expires.is_a?(Fixnum) && (expires < ONE_YEAR_IN_SECONDS)
|
|
605
654
|
expires = expires.to_i
|
|
606
655
|
# remove unset(==optional) and symbolyc keys
|
|
607
656
|
headers.each{ |key, value| headers.delete(key) if (value.nil? || key.is_a?(Symbol)) }
|
|
@@ -669,8 +718,16 @@ module RightAws
|
|
|
669
718
|
|
|
670
719
|
# Generates link for 'GetObject'.
|
|
671
720
|
#
|
|
672
|
-
#
|
|
721
|
+
# if a bucket comply with virtual hosting naming then retuns a link with the
|
|
722
|
+
# bucket as a part of host name:
|
|
723
|
+
#
|
|
724
|
+
# s3.get_link('my-awesome-bucket',key) #=> https://my-awesome-bucket.s3.amazonaws.com:443/asia%2Fcustomers?Signature=nh7...
|
|
725
|
+
#
|
|
726
|
+
# otherwise returns an old style link (the bucket is a part of path):
|
|
727
|
+
#
|
|
728
|
+
# s3.get_link('my_awesome_bucket',key) #=> https://s3.amazonaws.com:443/my_awesome_bucket/asia%2Fcustomers?Signature=QAO...
|
|
673
729
|
#
|
|
730
|
+
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html
|
|
674
731
|
def get_link(bucket, key, expires=nil, headers={})
|
|
675
732
|
generate_link('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}"), expires)
|
|
676
733
|
rescue
|
|
@@ -875,6 +932,18 @@ module RightAws
|
|
|
875
932
|
end
|
|
876
933
|
end
|
|
877
934
|
end
|
|
935
|
+
|
|
936
|
+
class S3CopyParser < RightAWSParser # :nodoc:
|
|
937
|
+
def reset
|
|
938
|
+
@result = {}
|
|
939
|
+
end
|
|
940
|
+
def tagend(name)
|
|
941
|
+
case name
|
|
942
|
+
when 'LastModified' : @result[:last_modified] = @text
|
|
943
|
+
when 'ETag' : @result[:e_tag] = @text
|
|
944
|
+
end
|
|
945
|
+
end
|
|
946
|
+
end
|
|
878
947
|
|
|
879
948
|
#-----------------------------------------------------------------
|
|
880
949
|
# PARSERS: Non XML
|
|
@@ -29,7 +29,6 @@ module RightAws
|
|
|
29
29
|
|
|
30
30
|
include RightAwsBaseInterface
|
|
31
31
|
|
|
32
|
-
SIGNATURE_VERSION = '1'
|
|
33
32
|
DEFAULT_HOST = 'sdb.amazonaws.com'
|
|
34
33
|
DEFAULT_PORT = 443
|
|
35
34
|
DEFAULT_PROTOCOL = 'https'
|
|
@@ -45,6 +44,7 @@ module RightAws
|
|
|
45
44
|
# { :server => 'sdb.amazonaws.com' # Amazon service host: 'sdb.amazonaws.com'(default)
|
|
46
45
|
# :port => 443 # Amazon service port: 80 or 443(default)
|
|
47
46
|
# :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default)
|
|
47
|
+
# :signature_version => '0' # The signature version : '0' or '1'(default)
|
|
48
48
|
# :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
|
|
49
49
|
# :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
|
|
50
50
|
#
|
|
@@ -76,9 +76,13 @@ module RightAws
|
|
|
76
76
|
"AWSAccessKeyId" => @aws_access_key_id,
|
|
77
77
|
"Version" => API_VERSION,
|
|
78
78
|
"Timestamp" => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
|
|
79
|
-
"SignatureVersion" =>
|
|
79
|
+
"SignatureVersion" => signature_version }
|
|
80
|
+
service_hash.update(params)
|
|
80
81
|
# prepare string to sight
|
|
81
|
-
string_to_sign =
|
|
82
|
+
string_to_sign = case signature_version
|
|
83
|
+
when '0' : service_hash["Action"] + service_hash["Timestamp"]
|
|
84
|
+
when '1' : service_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
|
|
85
|
+
end
|
|
82
86
|
service_hash.update('Signature' => AwsUtils::sign(@aws_secret_access_key, string_to_sign))
|
|
83
87
|
service_string = service_hash.to_a.collect{|key,val| key + "=#{CGI::escape(val.to_s)}" }.join("&")
|
|
84
88
|
#
|
data/lib/sqs/right_sqs.rb
CHANGED
|
@@ -73,6 +73,7 @@ module RightAws
|
|
|
73
73
|
# {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default)
|
|
74
74
|
# :port => 443 # Amazon service port: 80 or 443 (default)
|
|
75
75
|
# :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default)
|
|
76
|
+
# :signature_version => '0' # The signature version : '0' or '1'(default)
|
|
76
77
|
# :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
|
|
77
78
|
#
|
|
78
79
|
def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
|
@@ -26,7 +26,6 @@ module RightAws
|
|
|
26
26
|
class SqsInterface < RightAwsBase
|
|
27
27
|
include RightAwsBaseInterface
|
|
28
28
|
|
|
29
|
-
SIGNATURE_VERSION = "1"
|
|
30
29
|
API_VERSION = "2007-05-01"
|
|
31
30
|
DEFAULT_HOST = "queue.amazonaws.com"
|
|
32
31
|
DEFAULT_PORT = 443
|
|
@@ -57,6 +56,7 @@ module RightAws
|
|
|
57
56
|
# {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com'(default)
|
|
58
57
|
# :port => 443 # Amazon service port: 80 or 443(default)
|
|
59
58
|
# :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
|
|
59
|
+
# :signature_version => '0' # The signature version : '0' or '1'(default)
|
|
60
60
|
# :logger => Logger Object} # Logger instance: logs to STDOUT if omitted }
|
|
61
61
|
#
|
|
62
62
|
def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
|
|
@@ -75,23 +75,26 @@ module RightAws
|
|
|
75
75
|
#-----------------------------------------------------------------
|
|
76
76
|
|
|
77
77
|
# Generates a request hash for the query API
|
|
78
|
-
def generate_request(action,
|
|
78
|
+
def generate_request(action, params={}) # :nodoc:
|
|
79
79
|
# Sometimes we need to use queue uri (delete queue etc)
|
|
80
80
|
# In that case we will use Symbol key: 'param[:queue_url]'
|
|
81
|
-
queue_uri =
|
|
81
|
+
queue_uri = params[:queue_url] ? URI(params[:queue_url]).path : '/'
|
|
82
82
|
# remove unset(=optional) and symbolyc keys
|
|
83
|
-
|
|
83
|
+
params.each{ |key, value| params.delete(key) if (value.nil? || key.is_a?(Symbol)) }
|
|
84
84
|
# prepare output hash
|
|
85
|
-
|
|
86
|
-
# "Expires" => Time.now.utc.since(REQUEST_TTL).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
85
|
+
service_hash = { "Action" => action,
|
|
87
86
|
"Expires" => (Time.now + REQUEST_TTL).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
88
87
|
"AWSAccessKeyId" => @aws_access_key_id,
|
|
89
88
|
"Version" => API_VERSION,
|
|
90
|
-
"SignatureVersion" =>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
"SignatureVersion" => signature_version }
|
|
90
|
+
service_hash.update(params)
|
|
91
|
+
# prepare string to sight
|
|
92
|
+
string_to_sign = case signature_version
|
|
93
|
+
when '0' : service_hash["Action"] + service_hash["Expires"]
|
|
94
|
+
when '1' : service_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
|
|
95
|
+
end
|
|
96
|
+
service_hash['Signature'] = AwsUtils::sign(@aws_secret_access_key, string_to_sign)
|
|
97
|
+
request_params = service_hash.to_a.collect{|key,val| key.to_s + "=" + CGI::escape(val.to_s) }.join("&")
|
|
95
98
|
request = Net::HTTP::Get.new("#{queue_uri}?#{request_params}")
|
|
96
99
|
# prepare output hash
|
|
97
100
|
{ :request => request,
|
data/test/ec2/test_right_ec2.rb
CHANGED
|
@@ -65,4 +65,12 @@ class TestEc2 < Test::Unit::TestCase
|
|
|
65
65
|
## assert_raise(Rightscale::AwsError) { @ec2.delete_key_pair(@key) }
|
|
66
66
|
end
|
|
67
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
|
+
|
|
68
76
|
end
|
data/test/s3/test_right_s3.rb
CHANGED
|
@@ -6,10 +6,13 @@ class TestS3 < Test::Unit::TestCase
|
|
|
6
6
|
|
|
7
7
|
def setup
|
|
8
8
|
@s3 = Rightscale::S3Interface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
|
|
9
|
-
@bucket = '
|
|
9
|
+
@bucket = 'right_s3_awesome_test_bucket_00001'
|
|
10
10
|
@key1 = 'test/woohoo1/'
|
|
11
11
|
@key2 = 'test1/key/woohoo2'
|
|
12
12
|
@key3 = 'test2/A%B@C_D&E?F+G=H"I'
|
|
13
|
+
@key1_copy = 'test/woohoo1_2'
|
|
14
|
+
@key1_new_name = 'test/woohoo1_3'
|
|
15
|
+
@key2_new_name = 'test1/key/woohoo2_new'
|
|
13
16
|
@s = Rightscale::S3.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
|
|
14
17
|
end
|
|
15
18
|
|
|
@@ -74,12 +77,55 @@ class TestS3 < Test::Unit::TestCase
|
|
|
74
77
|
assert(keys.include? @key3)
|
|
75
78
|
end
|
|
76
79
|
|
|
77
|
-
def
|
|
78
|
-
|
|
80
|
+
def test_09_copy_key
|
|
81
|
+
#--- test COPY
|
|
82
|
+
# copy a key
|
|
83
|
+
assert @s3.copy(@bucket, @key1, @bucket, @key1_copy)
|
|
84
|
+
# check it was copied well
|
|
85
|
+
assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_copy), "copied object must have the same data"
|
|
86
|
+
# check meta-headers were copied
|
|
87
|
+
headers = @s3.head(@bucket, @key1_copy)
|
|
88
|
+
assert_equal 'Woohoo1!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
|
|
89
|
+
#--- test REPLACE
|
|
90
|
+
assert @s3.copy(@bucket, @key1, @bucket, @key1_copy, :replace, 'x-amz-meta-family' => 'oooops!')
|
|
91
|
+
# check it was copied well
|
|
92
|
+
assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_copy), "copied object must have the same data"
|
|
93
|
+
# check meta-headers were overwrittenn
|
|
94
|
+
headers = @s3.head(@bucket, @key1_copy)
|
|
95
|
+
assert_equal 'oooops!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'oooops!'"
|
|
79
96
|
end
|
|
80
97
|
|
|
98
|
+
def test_10_move_key
|
|
99
|
+
# move a key
|
|
100
|
+
assert @s3.move(@bucket, @key1, @bucket, @key1_new_name)
|
|
101
|
+
# check it's data was moved correctly
|
|
102
|
+
assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_new_name), "moved object must have the same data"
|
|
103
|
+
# check meta-headers were moved
|
|
104
|
+
headers = @s3.head(@bucket, @key1_new_name)
|
|
105
|
+
assert_equal 'Woohoo1!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
|
|
106
|
+
# check the original key is not exists any more
|
|
107
|
+
keys = @s3.list_bucket(@bucket).map{|b| b[:key]}
|
|
108
|
+
assert(!keys.include?(@key1))
|
|
109
|
+
end
|
|
81
110
|
|
|
82
|
-
def
|
|
111
|
+
def test_11_rename_key
|
|
112
|
+
# rename a key
|
|
113
|
+
assert @s3.rename(@bucket, @key2, @key2_new_name)
|
|
114
|
+
# check the new key data
|
|
115
|
+
assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key2_new_name), "moved object must have the same data"
|
|
116
|
+
# check meta-headers
|
|
117
|
+
headers = @s3.head(@bucket, @key2_new_name)
|
|
118
|
+
assert_equal 'Woohoo2!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo2!'"
|
|
119
|
+
# check the original key is not exists any more
|
|
120
|
+
keys = @s3.list_bucket(@bucket).map{|b| b[:key]}
|
|
121
|
+
assert(!keys.include?(@key2))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_12_delete_folder
|
|
125
|
+
assert_equal 1, @s3.delete_folder(@bucket, 'test').size, "Only one key(#{@key1}) must be deleted!"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_13_delete_bucket
|
|
83
129
|
assert_raise(Rightscale::AwsError) { @s3.delete_bucket(@bucket) }
|
|
84
130
|
assert @s3.clear_bucket(@bucket), 'Clear_bucket fail'
|
|
85
131
|
assert_equal 0, @s3.list_bucket(@bucket).size, 'Bucket must be empty'
|
|
@@ -87,7 +133,6 @@ class TestS3 < Test::Unit::TestCase
|
|
|
87
133
|
assert !@s3.list_all_my_buckets.map{|bucket| bucket[:name]}.include?(@bucket), "#{@bucket} must not exist"
|
|
88
134
|
end
|
|
89
135
|
|
|
90
|
-
|
|
91
136
|
#---------------------------
|
|
92
137
|
# Rightscale::S3 classes
|
|
93
138
|
#---------------------------
|
|
@@ -145,7 +190,80 @@ class TestS3 < Test::Unit::TestCase
|
|
|
145
190
|
assert !key2.exists?
|
|
146
191
|
end
|
|
147
192
|
|
|
148
|
-
def
|
|
193
|
+
def test_23_rename_key
|
|
194
|
+
bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
|
|
195
|
+
# -- 1 -- (key based rename)
|
|
196
|
+
# create a key
|
|
197
|
+
key = bucket.key('test/copy/1')
|
|
198
|
+
key.put(RIGHT_OBJECT_TEXT)
|
|
199
|
+
original_key = key.clone
|
|
200
|
+
assert key.exists?, "'test/copy/1' should exist"
|
|
201
|
+
# rename it
|
|
202
|
+
key.rename('test/copy/2')
|
|
203
|
+
assert_equal 'test/copy/2', key.name
|
|
204
|
+
assert key.exists?, "'test/copy/2' should exist"
|
|
205
|
+
# the original key should not exist
|
|
206
|
+
assert !original_key.exists?, "'test/copy/1' should not exist"
|
|
207
|
+
# -- 2 -- (bucket based rename)
|
|
208
|
+
bucket.rename_key('test/copy/2', 'test/copy/3')
|
|
209
|
+
assert bucket.key('test/copy/3').exists?, "'test/copy/3' should exist"
|
|
210
|
+
assert !bucket.key('test/copy/2').exists?, "'test/copy/2' should not exist"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def test_24_copy_key
|
|
214
|
+
bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
|
|
215
|
+
# -- 1 -- (key based copy)
|
|
216
|
+
# create a key
|
|
217
|
+
key = bucket.key('test/copy/10')
|
|
218
|
+
key.put(RIGHT_OBJECT_TEXT)
|
|
219
|
+
# make copy
|
|
220
|
+
new_key = key.copy('test/copy/11')
|
|
221
|
+
# make sure both the keys exist and have a correct data
|
|
222
|
+
assert key.exists?, "'test/copy/10' should exist"
|
|
223
|
+
assert new_key.exists?, "'test/copy/11' should exist"
|
|
224
|
+
assert_equal RIGHT_OBJECT_TEXT, key.get
|
|
225
|
+
assert_equal RIGHT_OBJECT_TEXT, new_key.get
|
|
226
|
+
# -- 2 -- (bucket based copy)
|
|
227
|
+
bucket.copy_key('test/copy/11', 'test/copy/12')
|
|
228
|
+
assert bucket.key('test/copy/11').exists?, "'test/copy/11' should exist"
|
|
229
|
+
assert bucket.key('test/copy/12').exists?, "'test/copy/12' should exist"
|
|
230
|
+
assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/11').get
|
|
231
|
+
assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/12').get
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def test_25_move_key
|
|
235
|
+
bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
|
|
236
|
+
# -- 1 -- (key based copy)
|
|
237
|
+
# create a key
|
|
238
|
+
key = bucket.key('test/copy/20')
|
|
239
|
+
key.put(RIGHT_OBJECT_TEXT)
|
|
240
|
+
# move
|
|
241
|
+
new_key = key.move('test/copy/21')
|
|
242
|
+
# make sure both the keys exist and have a correct data
|
|
243
|
+
assert !key.exists?, "'test/copy/20' should not exist"
|
|
244
|
+
assert new_key.exists?, "'test/copy/21' should exist"
|
|
245
|
+
assert_equal RIGHT_OBJECT_TEXT, new_key.get
|
|
246
|
+
# -- 2 -- (bucket based copy)
|
|
247
|
+
bucket.copy_key('test/copy/21', 'test/copy/22')
|
|
248
|
+
assert bucket.key('test/copy/21').exists?, "'test/copy/21' should not exist"
|
|
249
|
+
assert bucket.key('test/copy/22').exists?, "'test/copy/22' should exist"
|
|
250
|
+
assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/22').get
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def test_26_save_meta
|
|
254
|
+
bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
|
|
255
|
+
# create a key
|
|
256
|
+
key = bucket.key('test/copy/30')
|
|
257
|
+
key.put(RIGHT_OBJECT_TEXT)
|
|
258
|
+
assert key.meta_headers.blank?
|
|
259
|
+
# store some meta keys
|
|
260
|
+
meta = {'family' => 'oops','race' => 'troll'}
|
|
261
|
+
assert_equal meta, key.save_meta(meta)
|
|
262
|
+
# reload meta
|
|
263
|
+
assert_equal meta, key.reload_meta
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def test_27_clear_delete
|
|
149
267
|
bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
|
|
150
268
|
# add another key
|
|
151
269
|
bucket.put(@key2, RIGHT_OBJECT_TEXT)
|