aboisvert_aws 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +329 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +163 -0
  4. data/Rakefile +130 -0
  5. data/lib/acf/right_acf_interface.rb +549 -0
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +229 -0
  9. data/lib/acw/right_acw_interface.rb +248 -0
  10. data/lib/as/right_as_interface.rb +698 -0
  11. data/lib/awsbase/benchmark_fix.rb +39 -0
  12. data/lib/awsbase/right_awsbase.rb +1343 -0
  13. data/lib/awsbase/support.rb +35 -0
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +541 -0
  16. data/lib/ec2/right_ec2_ebs.rb +481 -0
  17. data/lib/ec2/right_ec2_images.rb +444 -0
  18. data/lib/ec2/right_ec2_instances.rb +788 -0
  19. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  20. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  21. data/lib/ec2/right_ec2_reserved_instances.rb +184 -0
  22. data/lib/ec2/right_ec2_security_groups.rb +491 -0
  23. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  24. data/lib/ec2/right_ec2_tags.rb +139 -0
  25. data/lib/ec2/right_ec2_vpc.rb +590 -0
  26. data/lib/ec2/right_ec2_vpc2.rb +381 -0
  27. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  28. data/lib/elb/right_elb_interface.rb +573 -0
  29. data/lib/emr/right_emr_interface.rb +727 -0
  30. data/lib/iam/right_iam_access_keys.rb +71 -0
  31. data/lib/iam/right_iam_groups.rb +195 -0
  32. data/lib/iam/right_iam_interface.rb +341 -0
  33. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  34. data/lib/iam/right_iam_users.rb +251 -0
  35. data/lib/rds/right_rds_interface.rb +1384 -0
  36. data/lib/right_aws.rb +86 -0
  37. data/lib/route_53/right_route_53_interface.rb +640 -0
  38. data/lib/s3/right_s3.rb +1138 -0
  39. data/lib/s3/right_s3_interface.rb +1278 -0
  40. data/lib/sdb/active_sdb.rb +1107 -0
  41. data/lib/sdb/right_sdb_interface.rb +762 -0
  42. data/lib/sns/right_sns_interface.rb +286 -0
  43. data/lib/sqs/right_sqs.rb +387 -0
  44. data/lib/sqs/right_sqs_gen2.rb +342 -0
  45. data/lib/sqs/right_sqs_gen2_interface.rb +523 -0
  46. data/lib/sqs/right_sqs_interface.rb +593 -0
  47. data/right_aws.gemspec +90 -0
  48. data/test/README.mdown +39 -0
  49. data/test/acf/test_helper.rb +2 -0
  50. data/test/acf/test_right_acf.rb +138 -0
  51. data/test/awsbase/test_helper.rb +2 -0
  52. data/test/awsbase/test_right_awsbase.rb +11 -0
  53. data/test/ec2/test_helper.rb +2 -0
  54. data/test/ec2/test_right_ec2.rb +107 -0
  55. data/test/elb/test_helper.rb +2 -0
  56. data/test/elb/test_right_elb.rb +43 -0
  57. data/test/http_connection.rb +87 -0
  58. data/test/rds/test_helper.rb +2 -0
  59. data/test/rds/test_right_rds.rb +120 -0
  60. data/test/route_53/fixtures/a_record.xml +18 -0
  61. data/test/route_53/fixtures/alias_record.xml +18 -0
  62. data/test/route_53/test_helper.rb +2 -0
  63. data/test/route_53/test_right_route_53.rb +141 -0
  64. data/test/s3/test_helper.rb +2 -0
  65. data/test/s3/test_right_s3.rb +528 -0
  66. data/test/s3/test_right_s3_stubbed.rb +97 -0
  67. data/test/sdb/test_active_sdb.rb +357 -0
  68. data/test/sdb/test_batch_put_attributes.rb +54 -0
  69. data/test/sdb/test_helper.rb +3 -0
  70. data/test/sdb/test_right_sdb.rb +253 -0
  71. data/test/sns/test_helper.rb +2 -0
  72. data/test/sns/test_right_sns.rb +153 -0
  73. data/test/sqs/test_helper.rb +2 -0
  74. data/test/sqs/test_right_sqs.rb +285 -0
  75. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  76. data/test/test_credentials.rb +37 -0
  77. data/test/ts_right_aws.rb +15 -0
  78. metadata +257 -0
@@ -0,0 +1,87 @@
1
+ =begin
2
+ Copyright (c) 2007 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 NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ =end
23
+
24
+ # Stub extension/redefinition of RightHttpConnection for testing purposes.
25
+ require 'net/http'
26
+ require 'rubygems'
27
+ require 'right_http_connection'
28
+
29
+ module Net
30
+ class HTTPResponse
31
+ alias_method :real_body, :body
32
+ def setmsg(msg)
33
+ @mymsg = msg
34
+ end
35
+
36
+ def body
37
+ # defined?() helps us to get rid of a bunch of 'warnings'
38
+ (defined?(@mymsg) && @mymsg) ? @mymsg : real_body
39
+ end
40
+ end
41
+ end
42
+
43
+ module Rightscale
44
+
45
+ class HttpConnection
46
+ @@response_stack = []
47
+
48
+ alias_method :real_request, :request
49
+
50
+ def request(request_params, &block)
51
+ if(@@response_stack.length == 0)
52
+ return real_request(request_params, &block)
53
+ end
54
+
55
+ if(block)
56
+ # Do something special
57
+ else
58
+ next_response = HttpConnection::pop()
59
+ classname = Net::HTTPResponse::CODE_TO_OBJ["#{next_response[:code]}"]
60
+ response = classname.new("1.1", next_response[:code], next_response[:msg])
61
+ if(next_response[:msg])
62
+ response.setmsg(next_response[:msg])
63
+ end
64
+ response
65
+ end
66
+ end
67
+
68
+ def self.reset
69
+ @@response_stack = []
70
+ end
71
+
72
+ def self.push(code, msg=nil)
73
+ response = {:code => code, :msg => msg}
74
+ @@response_stack << response
75
+ end
76
+
77
+ def self.pop
78
+ @@response_stack.pop
79
+ end
80
+
81
+ def self.length
82
+ @@response_stack.length
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/right_aws'
@@ -0,0 +1,120 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestRds < Test::Unit::TestCase
4
+
5
+ STDOUT.sync = true
6
+
7
+ TEST_SG_NAME = 'RightRdsSGTest0123456789'
8
+
9
+ def setup
10
+ @rds = Rightscale::RdsInterface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :logger => Logger.new('/dev/null'))
11
+ end
12
+
13
+ def test_00_instances
14
+ assert_nothing_raised do
15
+ items = @rds.describe_db_instances
16
+ assert items.is_a?(Array)
17
+ end
18
+ #
19
+ assert_nothing_raised do
20
+ @rds.describe_db_instances do |response|
21
+ assert response.is_a?(Hash)
22
+ assert response[:db_instances].is_a?(Array)
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_10_security_groups
28
+ assert_nothing_raised do
29
+ items = @rds.describe_db_security_groups
30
+ assert items.is_a?(Array)
31
+ end
32
+ #
33
+ assert_nothing_raised do
34
+ @rds.describe_db_security_groups do |response|
35
+ assert response.is_a?(Hash)
36
+ assert response[:db_security_groups].is_a?(Array)
37
+ end
38
+ end
39
+ end
40
+
41
+ def test_11_remove_security_group
42
+ @rds.delete_db_security_group rescue nil
43
+ end
44
+
45
+ def test_12_create_security_group
46
+ sg = nil
47
+ assert_nothing_raised do
48
+ sg = @rds.create_db_security_group(TEST_SG_NAME, 'sg-description')
49
+ end
50
+ assert sg.is_a?(Hash)
51
+ end
52
+
53
+ def test_13_authorize
54
+ assert_nothing_raised do
55
+ sg = @rds.authorize_db_security_group_ingress(TEST_SG_NAME, :cidrip => '131.0.0.1/8')
56
+ assert sg.is_a?(Hash)
57
+ assert_equal 1, sg[:ip_ranges].size
58
+ end
59
+ assert_nothing_raised do
60
+ sg = @rds.authorize_db_security_group_ingress(TEST_SG_NAME, :ec2_security_group_owner => '826693181925',
61
+ :ec2_security_group_name => 'default' )
62
+ assert sg.is_a?(Hash)
63
+ assert_equal 1, sg[:ec2_security_groups].size
64
+ end
65
+ sleep 30
66
+ end
67
+
68
+ def test_14_revoke
69
+ assert_nothing_raised do
70
+ sg = @rds.revoke_db_security_group_ingress(TEST_SG_NAME, :cidrip => '131.0.0.1/8')
71
+ assert sg.is_a?(Hash)
72
+ end
73
+ assert_nothing_raised do
74
+ sg = @rds.revoke_db_security_group_ingress(TEST_SG_NAME, :ec2_security_group_owner => '826693181925',
75
+ :ec2_security_group_name => 'default' )
76
+ assert sg.is_a?(Hash)
77
+ end
78
+ sleep 30
79
+ #
80
+ sg = @rds.describe_db_security_groups(TEST_SG_NAME).first
81
+ assert_equal 0, sg[:ip_ranges].size
82
+ assert_equal 0, sg[:ec2_security_groups].size
83
+ end
84
+
85
+ def test_15_delete_security_group
86
+ assert_nothing_raised do
87
+ @rds.delete_db_security_group(TEST_SG_NAME)
88
+ end
89
+ end
90
+
91
+
92
+ def test_20_db_snapshots
93
+ assert_nothing_raised do
94
+ items = @rds.describe_db_snapshots
95
+ assert items.is_a?(Array)
96
+ end
97
+ #
98
+ assert_nothing_raised do
99
+ @rds.describe_db_snapshots do |response|
100
+ assert response.is_a?(Hash)
101
+ assert response[:db_snapshots].is_a?(Array)
102
+ end
103
+ end
104
+ end
105
+
106
+ def test_30_events
107
+ assert_nothing_raised do
108
+ items = @rds.describe_events
109
+ assert items.is_a?(Array)
110
+ end
111
+ #
112
+ assert_nothing_raised do
113
+ @rds.describe_events do |response|
114
+ assert response.is_a?(Hash)
115
+ assert response[:events].is_a?(Array)
116
+ end
117
+ end
118
+ end
119
+
120
+ end
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2011-05-05/">
3
+ <ChangeBatch>
4
+ <Changes>
5
+ <Change>
6
+ <Action>CREATE</Action>
7
+ <ResourceRecordSet>
8
+ <Name>host.right-aws.example.com.</Name>
9
+ <Type>A</Type>
10
+ <TTL>600</TTL>
11
+ <ResourceRecords>
12
+ <ResourceRecord><Value>10.0.0.1</Value></ResourceRecord>
13
+ </ResourceRecords>
14
+ </ResourceRecordSet>
15
+ </Change>
16
+ </Changes>
17
+ </ChangeBatch>
18
+ </ChangeResourceRecordSetsRequest>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2011-05-05/">
3
+ <ChangeBatch>
4
+ <Changes>
5
+ <Change>
6
+ <Action>CREATE</Action>
7
+ <ResourceRecordSet>
8
+ <Name>right-aws.example.com.</Name>
9
+ <Type>A</Type>
10
+ <AliasTarget>
11
+ <HostedZoneId>Z1234567890123</HostedZoneId>
12
+ <DNSName>example-load-balancer-1111111111.us-east-1.elb.amazonaws.com.</DNSName>
13
+ </AliasTarget>
14
+ </ResourceRecordSet>
15
+ </Change>
16
+ </Changes>
17
+ </ChangeBatch>
18
+ </ChangeResourceRecordSetsRequest>
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/right_aws'
@@ -0,0 +1,141 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestRoute53 < Test::Unit::TestCase
4
+
5
+ STDOUT.sync = true
6
+ BALANCER_NAME = 'right-aws-test-lb'
7
+
8
+ def setup
9
+ @r53 = Rightscale::Route53Interface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :logger => Logger.new('/dev/null'))
10
+ @zone_config = {:name => "right-aws.example.com.", :config => {:comment => 'a comment'}}
11
+
12
+ @elb = Rightscale::ElbInterface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :logger => Logger.new('/dev/null'))
13
+ end
14
+
15
+ def teardown
16
+ @r53.list_hosted_zones.each do |zone|
17
+ next unless zone[:name] == @zone_config[:name]
18
+ zone_id = zone[:aws_id]
19
+ puts zone_id
20
+ records = @r53.list_resource_record_sets(zone_id)
21
+ # The NS and SOA records are provided by AWS and must not be deleted
22
+ records.reject! { |rr| %w[NS SOA].include? rr[:type] }
23
+ if records.any?
24
+ response = @r53.delete_resource_record_sets(zone_id, records)
25
+ puts response.inspect
26
+ end
27
+ puts @r53.delete_hosted_zone(zone_id).inspect
28
+ end
29
+ # Uncomment to shut down at the end of the day.
30
+ # @elb.delete_load_balancer BALANCER_NAME
31
+ end
32
+
33
+ def test_00_list_hosted_zones
34
+ items = @r53.list_hosted_zones
35
+ assert items.is_a?(Array)
36
+ end
37
+
38
+ def test_create_and_delete_zone
39
+ response = @r53.create_hosted_zone(@zone_config)
40
+ assert_equal response[:name], @zone_config[:name]
41
+ assert response[:aws_id].is_a?(String)
42
+ assert response[:name_servers].is_a?(Array)
43
+
44
+ response2 = @r53.delete_hosted_zone(response[:aws_id])
45
+ assert_equal response2[:status], 'PENDING'
46
+ end
47
+
48
+ def test_add_and_remove_A_record
49
+ zone = @r53.create_hosted_zone(@zone_config)
50
+ zone_id = zone[:aws_id]
51
+ # add
52
+ a_record = { :name => 'host.right-aws.example.com.', :type => 'A', :ttl => 600, :resource_records => ['10.0.0.1'] }
53
+ response = @r53.create_resource_record_sets(zone_id, [a_record.dup]) # .dup since it will get :action => :create
54
+ assert_equal response[:status], 'PENDING'
55
+
56
+ # It should be there now
57
+ records = @r53.list_resource_record_sets(zone_id)
58
+ assert records.is_a?(Array)
59
+ assert records.detect { |rr| rr == a_record }, "Could not find '#{a_record.inspect}' in '#{records.inspect}'"
60
+
61
+ # remove
62
+ response = @r53.delete_resource_record_sets(zone_id, [a_record.dup])
63
+ assert_equal response[:status], 'PENDING'
64
+
65
+ # It should not be there anymore
66
+ records = @r53.list_resource_record_sets(zone_id)
67
+ assert records.is_a?(Array)
68
+ assert ! records.detect { |rr| rr == a_record }, "Record '#{a_record.inspect}' is still in '#{records.inspect}'"
69
+
70
+ @r53.delete_hosted_zone(zone_id)
71
+ end
72
+
73
+ def test_add_and_remove_Alias_record
74
+ lb = find_or_create_load_balancer
75
+
76
+ zone = @r53.create_hosted_zone(@zone_config)
77
+ zone_id = zone[:aws_id]
78
+
79
+ # add
80
+ alias_target = { :hosted_zone_id => lb[:canonical_hosted_zone_name_id], :dns_name => lb[:dns_name] }
81
+ alias_record = { :name => 'right-aws.example.com', :type => 'A', :alias_target => alias_target }
82
+ response = @r53.create_resource_record_sets(zone_id, [alias_record.dup]) # .dup since it will get :action => :create
83
+ assert_equal response[:status], 'PENDING'
84
+
85
+ # It should be there now
86
+ records = @r53.list_resource_record_sets(zone_id)
87
+ assert records.is_a?(Array)
88
+ record = records.detect { |rr| rr[:alias_target] }
89
+ assert record, "Could not find '#{alias_record.inspect}' in '#{records.inspect}'"
90
+ # AWS adds final dots to names
91
+ assert_equal "#{alias_record[:name]}.", record[:name]
92
+ assert_equal "#{alias_target[:dns_name]}.", record[:alias_target][:dns_name]
93
+
94
+ # remove
95
+ response = @r53.delete_resource_record_sets(zone_id, [alias_record.dup])
96
+ assert_equal response[:status], 'PENDING'
97
+
98
+ # It should not be there anymore
99
+ records = @r53.list_resource_record_sets(zone_id)
100
+ assert records.is_a?(Array)
101
+ record = records.detect { |rr| rr[:alias_target] }
102
+ assert ! record, "Record '#{alias_record.inspect}' is still in '#{records.inspect}'"
103
+
104
+ @r53.delete_hosted_zone(zone_id)
105
+ end
106
+
107
+ def find_or_create_load_balancer
108
+ unless @elb.describe_load_balancers.detect { |lb| lb[:load_balancer_name] == BALANCER_NAME }
109
+ @elb.create_load_balancer(BALANCER_NAME, %w[us-east-1b], [])
110
+ puts "WARNING: Started load balancer. Remember to shut it down (see teardown)."
111
+ puts "NOTE: Tests might not pass during first few seconds after load balancer is created."
112
+ end
113
+ @elb.describe_load_balancers.detect { |lb| lb[:load_balancer_name] == BALANCER_NAME }
114
+ end
115
+
116
+ def test_rr_sets_to_xml
117
+ a_record = { :name => 'host.right-aws.example.com.', :type => 'A', :ttl => 600, :resource_records => ['10.0.0.1'], :action => :create }
118
+ expected = load_fixture('a_record.xml')
119
+ assert_equal expected, @r53.resource_record_sets_to_xml([a_record], '')
120
+
121
+ # Note final full stop
122
+ alias_target = { :hosted_zone_id => 'Z1234567890123', :dns_name => 'example-load-balancer-1111111111.us-east-1.elb.amazonaws.com.' }
123
+ alias_record = { :name => 'right-aws.example.com.', :type => 'A', :alias_target => alias_target, :action => :create }
124
+ expected = load_fixture('alias_record.xml')
125
+ assert_same_lines expected, @r53.resource_record_sets_to_xml([alias_record], '')
126
+ end
127
+
128
+ def load_fixture (name)
129
+ File.read(File.join(File.dirname(__FILE__), 'fixtures', name))
130
+ end
131
+
132
+ def assert_same_lines (expected, actual)
133
+ expected = expected.split "\n"
134
+ actual = actual.split "\n"
135
+ previous = []
136
+ while e = expected.shift and a = actual.shift
137
+ assert_equal e, a, "After:\n#{previous.join("\n")}"
138
+ previous << e
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../../lib/right_aws'
@@ -0,0 +1,528 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestS3 < Test::Unit::TestCase
4
+
5
+ RIGHT_OBJECT_TEXT = 'Right test message'
6
+ INTERFACE = Rightscale::S3Interface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
7
+ CONNECTION = Rightscale::S3.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key)
8
+
9
+ def setup
10
+ @s3 = INTERFACE
11
+ @bucket = 'right_s3_awesome_test_bucket_000B1_officedrop'
12
+ @bucket2 = 'right_s3_awesome_test_bucket_000B2_officedrop'
13
+ @key1 = 'test/woohoo1/'
14
+ @key2 = 'test1/key/woohoo2'
15
+ @key3 = 'test2/A%B@C_D&E?F+G=H"I'
16
+ @key1_copy = 'test/woohoo1_2'
17
+ @key1_new_name = 'test/woohoo1_3'
18
+ @key2_new_name = 'test1/key/woohoo2_new'
19
+ @s = CONNECTION
20
+ end
21
+
22
+ #---------------------------
23
+ # Rightscale::S3Interface
24
+ #---------------------------
25
+
26
+ def test_01_create_bucket
27
+ assert @s3.create_bucket(@bucket), 'Create_bucket fail'
28
+ end
29
+
30
+ def test_02_list_all_my_buckets
31
+ assert @s3.list_all_my_buckets.map{|bucket| bucket[:name]}.include?(@bucket), "#{@bucket} must exist in bucket list"
32
+ end
33
+
34
+ def test_03_list_empty_bucket
35
+ assert_equal 0, @s3.list_bucket(@bucket).size, "#{@bucket} isn't empty, arrgh!"
36
+ end
37
+
38
+ def test_04_put
39
+ assert @s3.put(@bucket, @key1, RIGHT_OBJECT_TEXT, 'x-amz-meta-family'=>'Woohoo1!'), 'Put bucket fail'
40
+ assert @s3.put(@bucket, @key2, RIGHT_OBJECT_TEXT, 'x-amz-meta-family'=>'Woohoo2!'), 'Put bucket fail'
41
+ assert @s3.put(@bucket, @key3, RIGHT_OBJECT_TEXT, 'x-amz-meta-family'=>'Woohoo3!'), 'Put bucket fail'
42
+ end
43
+
44
+ def test_05_get_and_get_object
45
+ assert_raise(Rightscale::AwsError) { @s3.get(@bucket, 'undefined/key') }
46
+ data1 = @s3.get(@bucket, @key1)
47
+ assert_equal RIGHT_OBJECT_TEXT, data1[:object], "Object text must be equal to '#{RIGHT_OBJECT_TEXT}'"
48
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1), "Get_object text must return '#{RIGHT_OBJECT_TEXT}'"
49
+ assert_equal 'Woohoo1!', data1[:headers]['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
50
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key3), "Get_object text must return '#{RIGHT_OBJECT_TEXT}'"
51
+ end
52
+
53
+ def test_06_head
54
+ assert_equal 'Woohoo1!', @s3.head(@bucket,@key1)['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
55
+ end
56
+
57
+
58
+ def test_07_streaming_get
59
+ resp = String.new
60
+ assert_raise(Rightscale::AwsError) do
61
+ @s3.get(@bucket, 'undefined/key') do |chunk|
62
+ resp += chunk
63
+ end
64
+ end
65
+
66
+ resp = String.new
67
+ data1 = @s3.get(@bucket, @key1) do |chunk|
68
+ resp += chunk
69
+ end
70
+ assert_equal RIGHT_OBJECT_TEXT, resp, "Object text must be equal to '#{RIGHT_OBJECT_TEXT}'"
71
+ assert_equal @s3.get_object(@bucket, @key1), resp, "Streaming iface must return same as non-streaming"
72
+ assert_equal 'Woohoo1!', data1[:headers]['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
73
+ end
74
+
75
+ def test_08_keys
76
+ keys = @s3.list_bucket(@bucket).map{|b| b[:key]}
77
+ assert_equal keys.size, 3, "There should be 3 keys"
78
+ assert(keys.include?(@key1))
79
+ assert(keys.include?(@key2))
80
+ assert(keys.include?(@key3))
81
+ end
82
+
83
+ def test_09_copy_key
84
+ #--- test COPY
85
+ # copy a key
86
+ assert @s3.copy(@bucket, @key1, @bucket, @key1_copy)
87
+ # check it was copied well
88
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_copy), "copied object must have the same data"
89
+ # check meta-headers were copied
90
+ headers = @s3.head(@bucket, @key1_copy)
91
+ assert_equal 'Woohoo1!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
92
+ #--- test REPLACE
93
+ assert @s3.copy(@bucket, @key1, @bucket, @key1_copy, :replace, 'x-amz-meta-family' => 'oooops!')
94
+ # check it was copied well
95
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_copy), "copied object must have the same data"
96
+ # check meta-headers were overwrittenn
97
+ headers = @s3.head(@bucket, @key1_copy)
98
+ assert_equal 'oooops!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'oooops!'"
99
+ end
100
+
101
+ def test_10_move_key
102
+ # move a key
103
+ assert @s3.move(@bucket, @key1, @bucket, @key1_new_name)
104
+ # check it's data was moved correctly
105
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key1_new_name), "moved object must have the same data"
106
+ # check meta-headers were moved
107
+ headers = @s3.head(@bucket, @key1_new_name)
108
+ assert_equal 'Woohoo1!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
109
+ # check the original key is not exists any more
110
+ keys = @s3.list_bucket(@bucket).map{|b| b[:key]}
111
+ assert(!keys.include?(@key1))
112
+ end
113
+
114
+ def test_11_rename_key
115
+ # rename a key
116
+ assert @s3.rename(@bucket, @key2, @key2_new_name)
117
+ # check the new key data
118
+ assert_equal RIGHT_OBJECT_TEXT, @s3.get_object(@bucket, @key2_new_name), "moved object must have the same data"
119
+ # check meta-headers
120
+ headers = @s3.head(@bucket, @key2_new_name)
121
+ assert_equal 'Woohoo2!', headers['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo2!'"
122
+ # check the original key is not exists any more
123
+ keys = @s3.list_bucket(@bucket).map{|b| b[:key]}
124
+ assert(!keys.include?(@key2))
125
+ end
126
+ def test_12_retrieve_object
127
+ assert_raise(Rightscale::AwsError) { @s3.retrieve_object(:bucket => @bucket, :key => 'undefined/key') }
128
+ data1 = @s3.retrieve_object(:bucket => @bucket, :key => @key1_new_name)
129
+ assert_equal RIGHT_OBJECT_TEXT, data1[:object], "Object text must be equal to '#{RIGHT_OBJECT_TEXT}'"
130
+ assert_equal 'Woohoo1!', data1[:headers]['x-amz-meta-family'], "x-amz-meta-family header must be equal to 'Woohoo1!'"
131
+ end
132
+ def test_13_delete_folder
133
+ assert_equal 1, @s3.delete_folder(@bucket, 'test').size, "Only one key(#{@key1}) must be deleted!"
134
+ end
135
+
136
+ def test_14_delete_bucket
137
+ assert_raise(Rightscale::AwsError) { @s3.delete_bucket(@bucket) }
138
+ assert @s3.clear_bucket(@bucket), 'Clear_bucket fail'
139
+ assert_equal 0, @s3.list_bucket(@bucket).size, 'Bucket must be empty'
140
+ assert @s3.delete_bucket(@bucket)
141
+ assert !@s3.list_all_my_buckets.map{|bucket| bucket[:name]}.include?(@bucket), "#{@bucket} must not exist"
142
+ end
143
+
144
+
145
+
146
+
147
+ #---------------------------
148
+ # Rightscale::S3 classes
149
+ #---------------------------
150
+
151
+ def test_20_s3
152
+ # create bucket
153
+ bucket = @s.bucket(@bucket, true)
154
+ assert bucket
155
+ # check that the bucket exists
156
+ assert @s.buckets.map{|b| b.name}.include?(@bucket)
157
+ # delete bucket
158
+ assert bucket.clear
159
+ assert bucket.delete
160
+ end
161
+
162
+ def test_21_bucket_create_put_get_key
163
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, true)
164
+ # check that the bucket exists
165
+ assert @s.buckets.map{|b| b.name}.include?(@bucket)
166
+ assert bucket.keys.empty?
167
+ # put data
168
+ assert bucket.put(@key3, RIGHT_OBJECT_TEXT, {'family'=>'123456'})
169
+ # get data and compare
170
+ assert_equal RIGHT_OBJECT_TEXT, bucket.get(@key3)
171
+ # get key object
172
+ key = bucket.key(@key3, true)
173
+ assert_equal Rightscale::S3::Key, key.class
174
+ assert key.exists?
175
+ assert_equal '123456', key.meta_headers['family']
176
+ end
177
+
178
+ def test_22_keys
179
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
180
+ # create first key
181
+ key3 = Rightscale::S3::Key.create(bucket, @key3)
182
+ key3.refresh
183
+ assert key3.exists?
184
+ assert_equal '123456', key3.meta_headers['family']
185
+ # create second key
186
+ key2 = Rightscale::S3::Key.create(bucket, @key2)
187
+ assert !key2.refresh
188
+ assert !key2.exists?
189
+ assert_raise(Rightscale::AwsError) { key2.head }
190
+ # store key
191
+ key2.meta_headers = {'family'=>'111222333'}
192
+ assert key2.put(RIGHT_OBJECT_TEXT)
193
+ # make sure that the key exists
194
+ assert key2.refresh
195
+ assert key2.exists?
196
+ assert key2.head
197
+ # get its data
198
+ assert_equal RIGHT_OBJECT_TEXT, key2.get
199
+ # drop key
200
+ assert key2.delete
201
+ assert !key2.exists?
202
+ end
203
+
204
+ def test_23_rename_key
205
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
206
+ # -- 1 -- (key based rename)
207
+ # create a key
208
+ key = bucket.key('test/copy/1')
209
+ key.put(RIGHT_OBJECT_TEXT)
210
+ original_key = key.clone
211
+ assert key.exists?, "'test/copy/1' should exist"
212
+ # rename it
213
+ key.rename('test/copy/2')
214
+ assert_equal 'test/copy/2', key.name
215
+ assert key.exists?, "'test/copy/2' should exist"
216
+ # the original key should not exist
217
+ assert !original_key.exists?, "'test/copy/1' should not exist"
218
+ # -- 2 -- (bucket based rename)
219
+ bucket.rename_key('test/copy/2', 'test/copy/3')
220
+ assert bucket.key('test/copy/3').exists?, "'test/copy/3' should exist"
221
+ assert !bucket.key('test/copy/2').exists?, "'test/copy/2' should not exist"
222
+ end
223
+
224
+ def test_24_copy_key
225
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
226
+ # -- 1 -- (key based copy)
227
+ # create a key
228
+ key = bucket.key('test/copy/10')
229
+ key.put(RIGHT_OBJECT_TEXT)
230
+ # make copy
231
+ new_key = key.copy('test/copy/11')
232
+ # make sure both the keys exist and have a correct data
233
+ assert key.exists?, "'test/copy/10' should exist"
234
+ assert new_key.exists?, "'test/copy/11' should exist"
235
+ assert_equal RIGHT_OBJECT_TEXT, key.get
236
+ assert_equal RIGHT_OBJECT_TEXT, new_key.get
237
+ # -- 2 -- (bucket based copy)
238
+ bucket.copy_key('test/copy/11', 'test/copy/12')
239
+ assert bucket.key('test/copy/11').exists?, "'test/copy/11' should exist"
240
+ assert bucket.key('test/copy/12').exists?, "'test/copy/12' should exist"
241
+ assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/11').get
242
+ assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/12').get
243
+ end
244
+
245
+ def test_25_move_key
246
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
247
+ # -- 1 -- (key based copy)
248
+ # create a key
249
+ key = bucket.key('test/copy/20')
250
+ key.put(RIGHT_OBJECT_TEXT)
251
+ # move
252
+ new_key = key.move('test/copy/21')
253
+ # make sure both the keys exist and have a correct data
254
+ assert !key.exists?, "'test/copy/20' should not exist"
255
+ assert new_key.exists?, "'test/copy/21' should exist"
256
+ assert_equal RIGHT_OBJECT_TEXT, new_key.get
257
+ # -- 2 -- (bucket based copy)
258
+ bucket.copy_key('test/copy/21', 'test/copy/22')
259
+ assert bucket.key('test/copy/21').exists?, "'test/copy/21' should not exist"
260
+ assert bucket.key('test/copy/22').exists?, "'test/copy/22' should exist"
261
+ assert_equal RIGHT_OBJECT_TEXT, bucket.key('test/copy/22').get
262
+ end
263
+
264
+ def test_26_save_meta
265
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
266
+ # create a key
267
+ key = bucket.key('test/copy/30')
268
+ key.put(RIGHT_OBJECT_TEXT)
269
+ assert key.meta_headers.right_blank?
270
+ # store some meta keys
271
+ meta = {'family' => 'oops','race' => 'troll'}
272
+ assert_equal meta, key.save_meta(meta)
273
+ # reload meta
274
+ assert_equal meta, key.reload_meta
275
+ end
276
+
277
+ def test_27_clear_delete
278
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
279
+ # add another key
280
+ bucket.put(@key2, RIGHT_OBJECT_TEXT)
281
+ # delete 'folder'
282
+ assert_equal 1, bucket.delete_folder(@key1).size
283
+ # delete
284
+ assert_raise(Rightscale::AwsError) { bucket.delete }
285
+ bucket.delete(:force => true)
286
+ end
287
+
288
+ # Grantees
289
+
290
+ def test_30_create_bucket
291
+ bucket = @s.bucket(@bucket, true, 'public-read')
292
+ assert bucket
293
+ end
294
+
295
+ def test_31_list_grantees
296
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
297
+ # get grantees list
298
+ grantees = bucket.grantees
299
+ # check that the grantees count equal to 2 (root, AllUsers)
300
+ assert_equal 2, grantees.size
301
+ end
302
+
303
+ def test_32_grant_revoke_drop
304
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
305
+ # Take 'AllUsers' grantee
306
+ grantee = Rightscale::S3::Grantee.new(bucket,'http://acs.amazonaws.com/groups/global/AllUsers')
307
+ # Check exists?
308
+ assert grantee.exists?
309
+ # Add grant as String
310
+ assert grantee.grant('WRITE')
311
+ # Add grants as Array
312
+ assert grantee.grant(['READ_ACP', 'WRITE_ACP'])
313
+ # Check perms count
314
+ assert_equal 4, grantee.perms.size
315
+ # revoke 'WRITE_ACP'
316
+ assert grantee.revoke('WRITE_ACP')
317
+ # Check manual perm removal method
318
+ grantee.perms -= ['READ_ACP']
319
+ grantee.apply
320
+ assert_equal 2, grantee.perms.size
321
+ # Check grantee removal if it has no permissions
322
+ assert grantee.perms = []
323
+ assert grantee.apply
324
+ assert !grantee.exists?
325
+ # Check multiple perms assignment
326
+ assert grantee.grant('FULL_CONTROL', 'READ', 'WRITE')
327
+ assert_equal ['FULL_CONTROL','READ','WRITE'].sort, grantee.perms.sort
328
+ # Check multiple perms removal
329
+ assert grantee.revoke('FULL_CONTROL', 'WRITE')
330
+ assert_equal ['READ'], grantee.perms
331
+ # check 'Drop' method
332
+ assert grantee.drop
333
+ assert !grantee.exists?
334
+ assert_equal 1, bucket.grantees.size
335
+ # Delete bucket
336
+ bucket.delete(:force => true)
337
+ end
338
+
339
+ def test_33_key_grantees
340
+ # Create bucket
341
+ bucket = @s.bucket(@bucket, true)
342
+ # Create key
343
+ key = bucket.key(@key1)
344
+ assert key.put(RIGHT_OBJECT_TEXT, 'public-read')
345
+ # Get grantees list (must be == 2)
346
+ grantees = key.grantees
347
+ assert grantees
348
+ assert_equal 2, grantees.size
349
+ # Take one of grantees and give him 'Write' perms
350
+ grantee = grantees[0]
351
+ assert grantee.grant('WRITE')
352
+ # Drop grantee
353
+ assert grantee.drop
354
+ # Drop bucket
355
+ bucket.delete(:force => true)
356
+ end
357
+
358
+ def test_34_bucket_create_put_with_perms
359
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, true)
360
+ # check that the bucket exists
361
+ assert @s.buckets.map{|b| b.name}.include?(@bucket)
362
+ assert bucket.keys.empty?
363
+ # put data (with canned ACL)
364
+ assert bucket.put(@key1, RIGHT_OBJECT_TEXT, {'family'=>'123456'}, "public-read")
365
+ # get data and compare
366
+ assert_equal RIGHT_OBJECT_TEXT, bucket.get(@key1)
367
+ # get key object
368
+ key = bucket.key(@key1, true)
369
+ assert_equal Rightscale::S3::Key, key.class
370
+ assert key.exists?
371
+ assert_equal '123456', key.meta_headers['family']
372
+ end
373
+
374
+ def test_35_key_put_with_perms
375
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
376
+ # create first key
377
+ key1 = Rightscale::S3::Key.create(bucket, @key1)
378
+ key1.refresh
379
+ assert key1.exists?
380
+ assert key1.put(RIGHT_OBJECT_TEXT, "public-read")
381
+ # get its data
382
+ assert_equal RIGHT_OBJECT_TEXT, key1.get
383
+ # drop key
384
+ assert key1.delete
385
+ assert !key1.exists?
386
+ end
387
+
388
+ def test_36_set_amazon_problems
389
+ original_problems = RightAws::S3Interface.amazon_problems
390
+ assert(original_problems.length > 0)
391
+ RightAws::S3Interface.amazon_problems= original_problems << "A New Problem"
392
+ new_problems = RightAws::S3Interface.amazon_problems
393
+ assert_equal(new_problems, original_problems)
394
+
395
+ RightAws::S3Interface.amazon_problems= nil
396
+ assert_nil(RightAws::S3Interface.amazon_problems)
397
+ end
398
+
399
+ def test_37_access_logging
400
+ bucket = Rightscale::S3::Bucket.create(@s, @bucket, false)
401
+ targetbucket = Rightscale::S3::Bucket.create(@s, @bucket2, true)
402
+ # Take 'AllUsers' grantee
403
+ grantee = Rightscale::S3::Grantee.new(targetbucket,'http://acs.amazonaws.com/groups/s3/LogDelivery')
404
+
405
+ assert grantee.grant(['READ_ACP', 'WRITE'])
406
+
407
+ assert bucket.enable_logging(:targetbucket => targetbucket, :targetprefix => "loggylogs/")
408
+ sleep 10
409
+
410
+ assert_equal({:enabled => true, :targetbucket => @bucket2, :targetprefix => "loggylogs/"}, bucket.logging_info)
411
+
412
+ assert bucket.disable_logging
413
+
414
+ # check 'Drop' method
415
+ assert grantee.drop
416
+ end
417
+
418
+ def test_40_delete_buckets
419
+ Rightscale::S3::Bucket.create(@s, @bucket, false).delete(:force => true)
420
+ Rightscale::S3::Bucket.create(@s, @bucket2, false).delete(:force => true)
421
+ end
422
+
423
+ def test_41_add_cache_control_response_parameter
424
+ @cache_control = 'max-age=3600'
425
+ perform_request( 'response-cache-control' => @cache_control ) do |response|
426
+ assert_equal response['Cache-Control'], @cache_control
427
+ end
428
+ end
429
+
430
+ def test_42_add_cache_control_and_content_type_and_content_disposition
431
+ @cache_control = 'max-age=3600'
432
+ @content_type = 'text/plain'
433
+ @content_disposition = 'attachment; filename=sample.txt'
434
+ perform_request(
435
+ 'response-cache-control' => @cache_control,
436
+ 'response-content-type' => @content_type,
437
+ 'response-content-disposition' => @content_disposition
438
+ ) do |response|
439
+ assert_equal response['Cache-Control'], @cache_control
440
+ assert_equal response['Content-Type'], @content_type
441
+ assert_equal response['Content-Disposition'], @content_disposition
442
+ end
443
+ end
444
+
445
+ def test_43_add_expires_and_content_type_and_content_disposition
446
+ @expires = 'Sun, 26 Jun 2011 02:58:26 GMT'
447
+ @content_type = 'text/plain'
448
+ @content_disposition = 'attachment; filename=sample.txt'
449
+ perform_request(
450
+ 'response-expires' => @expires,
451
+ 'response-content-type' => @content_type,
452
+ 'response-content-disposition' => @content_disposition
453
+ ) do |response|
454
+ assert_equal response['Expires'], @expires
455
+ assert_equal response['Content-Type'], @content_type
456
+ assert_equal response['Content-Disposition'], @content_disposition
457
+ end
458
+ end
459
+
460
+ def test_44_delete_multiple
461
+ bucket = RightAws::S3::Bucket.create(@s, @bucket, true)
462
+
463
+ key1 = Rightscale::S3::Key.create(bucket, @key1)
464
+ key2 = Rightscale::S3::Key.create(bucket, @key2)
465
+ key3 = Rightscale::S3::Key.create(bucket, @key3)
466
+
467
+ assert @s3.put(@bucket, @key1, RIGHT_OBJECT_TEXT), 'Put bucket fail'
468
+ assert @s3.put(@bucket, @key2, RIGHT_OBJECT_TEXT), 'Put bucket fail'
469
+ assert @s3.put(@bucket, @key3, RIGHT_OBJECT_TEXT), 'Put bucket fail'
470
+
471
+ key1.refresh
472
+ key2.refresh
473
+ key3.refresh
474
+
475
+ assert key1.exists?
476
+ assert key2.exists?
477
+ assert key3.exists?
478
+
479
+ result = @s3.delete_multiple(@bucket, [@key1, @key2, @key3])
480
+ assert result.empty?
481
+
482
+ key1.refresh
483
+ key2.refresh
484
+ key3.refresh
485
+
486
+ assert !key1.exists?
487
+ assert !key2.exists?
488
+ assert !key3.exists?
489
+ end
490
+
491
+ def test_45_delete_multiple_more_than_1000_objects
492
+ n = 1200
493
+ keys = (1..n).map { |i| "key-#{i}"}
494
+
495
+ keys.each do |key|
496
+ assert @s3.put(@bucket, key, RIGHT_OBJECT_TEXT), 'Put bucket fail'
497
+ end
498
+
499
+ result = @s3.delete_multiple(@bucket, keys)
500
+ assert result.empty?
501
+
502
+ keys_after = @s3.list_bucket(@bucket).map { |obj| obj[:key] }
503
+
504
+ keys.each do |key|
505
+ keys_after.include?(key)
506
+ end
507
+ end
508
+
509
+ private
510
+
511
+ def request( uri )
512
+ url = URI.parse( uri )
513
+
514
+ http = Net::HTTP.new(url.host, 443)
515
+ http.use_ssl = true
516
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
517
+ http.request(Net::HTTP::Get.new( url.request_uri ))
518
+ end
519
+
520
+ def perform_request( headers, &block )
521
+ @s3.create_bucket( @bucket )
522
+ @s3.put( @bucket, @key2, RIGHT_OBJECT_TEXT )
523
+ response = request( @s3.get_link( @bucket, @key2, nil, {}, headers ) )
524
+ block.call( response )
525
+ @s3.force_delete_bucket(@bucket)
526
+ end
527
+
528
+ end