diff --git a/lib/fog/aws/requests/s3/copy_object.rb b/lib/fog/aws/requests/s3/copy_object.rb index 80252619d..ddb2ec86f 100644 --- a/lib/fog/aws/requests/s3/copy_object.rb +++ b/lib/fog/aws/requests/s3/copy_object.rb @@ -1,40 +1,86 @@ -module Fog - module AWS - class S3 +unless Fog.mocking? + + module Fog + module AWS + class S3 + + # Copy an object from one S3 bucket to another + # + # ==== Parameters + # * source_bucket_name<~String> - Name of source bucket + # * source_object_name<~String> - Name of source object + # * target_bucket_name<~String> - Name of bucket to create copy in + # * target_object_name<~String> - Name for new copy of object + # * options<~Hash>: + # * 'x-amz-metadata-directive'<~String> - Specifies whether to copy metadata from source or replace with data in request. Must be in ['COPY', 'REPLACE'] + # * 'x-amz-copy_source-if-match'<~String> - Copies object if its etag matches this value + # * 'x-amz-copy_source-if-modified_since'<~Time> - Copies object it it has been modified since this time + # * 'x-amz-copy_source-if-none-match'<~String> - Copies object if its etag does not match this value + # * 'x-amz-copy_source-if-unmodified-since'<~Time> - Copies object it it has not been modified since this time + # + # ==== Returns + # * response<~Fog::AWS::Response>: + # * body<~Hash>: + # * 'ETag'<~String> - etag of new object + # * 'LastModified'<~Time> - date object was last modified + # + # TODO: allow specifying new metadata (support all/some of put_object?) + def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {}) + headers = { 'x-amz-copy-source' => "/#{source_bucket_name}/#{source_object_name}" }.merge!(options) + request({ + :expects => 200, + :headers => headers, + :host => "#{target_bucket_name}.#{@host}", + :method => 'PUT', + :parser => Fog::Parsers::AWS::S3::CopyObject.new, + :path => target_object_name + }) + end - # Copy an object from one S3 bucket to another - # - # ==== Parameters - # * source_bucket_name<~String> - Name of source bucket - # * source_object_name<~String> - Name of source object - # * destination_bucket_name<~String> - Name of bucket to create copy in - # * destination_object_name<~String> - Name for new copy of object - # * options<~Hash>: - # * 'x-amz-metadata-directive'<~String> - Specifies whether to copy metadata from source or replace with data in request. Must be in ['COPY', 'REPLACE'] - # * 'x-amz-copy_source-if-match'<~String> - Copies object if its etag matches this value - # * 'x-amz-copy_source-if-modified_since'<~Time> - Copies object it it has been modified since this time - # * 'x-amz-copy_source-if-none-match'<~String> - Copies object if its etag does not match this value - # * 'x-amz-copy_source-if-unmodified-since'<~Time> - Copies object it it has not been modified since this time - # - # ==== Returns - # * response<~Fog::AWS::Response>: - # * body<~Hash>: - # * 'ETag'<~String> - etag of new object - # * 'LastModified'<~Time> - date object was last modified - # - # TODO: allow specifying new metadata (support all/some of put_object?) - def copy_object(source_bucket_name, source_object_name, destination_bucket_name, destination_object_name, options = {}) - headers = { 'x-amz-copy-source' => "/#{source_bucket_name}/#{source_object_name}" }.merge!(options) - request({ - :expects => 200, - :headers => headers, - :host => "#{destination_bucket_name}.#{@host}", - :method => 'PUT', - :parser => Fog::Parsers::AWS::S3::CopyObject.new, - :path => destination_object_name - }) end - end end -end + +else + + module Fog + module AWS + class S3 + + def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {}) + response = Fog::Response.new + source_bucket_status = get_bucket(source_bucket_name).status + target_bucket_status = get_bucket(target_bucket_name).status + source_object_status = get_object(source_bucket_name, source_object_name).status + + if source_bucket_status != 200 + response.status = source_bucket_status + elsif target_bucket_status != 200 + response.status = target_bucket_status + elsif source_bucket_status != 200 + response.status = source_bucket_status + else + response.status = 200 + end + + if response.status == 200 + source_bucket = @data['Buckets'].select {|bucket| bucket['Name'] == source_bucket_name}.first + source_object = source_bucket['Contents'].select {|object| object['Key'] == source_object_name}.first + target_bucket = @data['Buckets'].select {|bucket| bucket['Name'] == target_bucket_name}.first + target_object = source_object.dup + target_object['Name'] = target_object_name + target_bucket['Contents'] << target_object + response.body = { + 'ETag' => target_object['ETag'], + 'LastModified' => Time.parse(target_object['LastModified']) + } + end + + response + end + + end + end + end + +end \ No newline at end of file diff --git a/lib/fog/aws/requests/s3/get_bucket.rb b/lib/fog/aws/requests/s3/get_bucket.rb index aee5107ed..03e3f2a5b 100644 --- a/lib/fog/aws/requests/s3/get_bucket.rb +++ b/lib/fog/aws/requests/s3/get_bucket.rb @@ -70,7 +70,9 @@ else response.body = { 'IsTruncated' => false, 'Contents' => bucket['Contents'].map do |object| - object.reject {|key, value| !['ETag', 'Key', 'LastModified', 'Owner', 'StorageClass'].include?(key)} + data = object.reject {|key, value| !['ETag', 'Key', 'LastModified', 'Owner', 'StorageClass'].include?(key)} + data['LastModified'] = Time.parse(data['LastModified']) + data end } end diff --git a/lib/fog/aws/requests/s3/get_request_payment.rb b/lib/fog/aws/requests/s3/get_request_payment.rb index 853e37ea0..04e4b5576 100644 --- a/lib/fog/aws/requests/s3/get_request_payment.rb +++ b/lib/fog/aws/requests/s3/get_request_payment.rb @@ -1,27 +1,54 @@ -module Fog - module AWS - class S3 +unless Fog.mocking? + + module Fog + module AWS + class S3 + + # Get configured payer for an S3 bucket + # + # ==== Parameters + # * bucket_name<~String> - name of bucket to get payer for + # + # ==== Returns + # * response<~Fog::AWS::Response>: + # * body<~Hash>: + # * 'Payer'<~String> - Specifies who pays for download and requests + def get_request_payment(bucket_name) + request({ + :expects => 200, + :headers => {}, + :host => "#{bucket_name}.#{@host}", + :method => 'GET', + :parser => Fog::Parsers::AWS::S3::GetRequestPayment.new, + :query => 'requestPayment' + }) + end - # Get configured payer for an S3 bucket - # - # ==== Parameters - # * bucket_name<~String> - name of bucket to get payer for - # - # ==== Returns - # * response<~Fog::AWS::Response>: - # * body<~Hash>: - # * 'Payer'<~String> - Specifies who pays for download and requests - def get_request_payment(bucket_name) - request({ - :expects => 200, - :headers => {}, - :host => "#{bucket_name}.#{@host}", - :method => 'GET', - :parser => Fog::Parsers::AWS::S3::GetRequestPayment.new, - :query => 'requestPayment' - }) end - end end + +else + + module Fog + module AWS + class S3 + + def get_request_payment(bucket_name) + response = Fog::Response.new + bucket_status = get_bucket(bucket_name).status + if bucket_status == 200 + response.status = 200 + bucket = @data['Buckets'].select {|bucket| bucket['Name'] == bucket_name}.first + response.body = { 'Payer' => bucket['Payer'] } + else + response.status = bucket_status + end + response + end + + end + end + end + end diff --git a/lib/fog/aws/requests/s3/head_object.rb b/lib/fog/aws/requests/s3/head_object.rb index a47e43809..4e38d1d79 100644 --- a/lib/fog/aws/requests/s3/head_object.rb +++ b/lib/fog/aws/requests/s3/head_object.rb @@ -1,41 +1,61 @@ -module Fog - module AWS - class S3 +unless Fog.mocking? + + module Fog + module AWS + class S3 + + # Get headers for an object from S3 + # + # ==== Parameters + # * bucket_name<~String> - Name of bucket to read from + # * object_name<~String> - Name of object to read + # * options<~Hash>: + # * 'If-Match'<~String> - Returns object only if its etag matches this value, otherwise returns 412 (Precondition Failed). + # * 'If-Modified-Since'<~Time> - Returns object only if it has been modified since this time, otherwise returns 304 (Not Modified). + # * 'If-None-Match'<~String> - Returns object only if its etag differs from this value, otherwise returns 304 (Not Modified) + # * 'If-Unmodified-Since'<~Time> - Returns object only if it has not been modified since this time, otherwise returns 412 (Precodition Failed). + # * 'Range'<~String> - Range of object to download + # + # ==== Returns + # * response<~Fog::AWS::Response>: + # * body<~String> - Contents of object + # * headers<~Hash>: + # * 'Content-Length'<~String> - Size of object contents + # * 'Content-Type'<~String> - MIME type of object + # * 'ETag'<~String> - Etag of object + # * 'Last-Modified'<~String> - Last modified timestamp for object + def head_object(bucket_name, object_name, options={}) + headers = {} + headers['If-Modified-Since'] = options['If-Modified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since'] + headers['If-Unmodified-Since'] = options['If-Unmodified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since'] + headers.merge!(options) + request({ + :expects => 200, + :headers => headers, + :host => "#{bucket_name}.#{@host}", + :method => 'HEAD', + :path => object_name + }) + end - # Get headers for an object from S3 - # - # ==== Parameters - # * bucket_name<~String> - Name of bucket to read from - # * object_name<~String> - Name of object to read - # * options<~Hash>: - # * 'If-Match'<~String> - Returns object only if its etag matches this value, otherwise returns 412 (Precondition Failed). - # * 'If-Modified-Since'<~Time> - Returns object only if it has been modified since this time, otherwise returns 304 (Not Modified). - # * 'If-None-Match'<~String> - Returns object only if its etag differs from this value, otherwise returns 304 (Not Modified) - # * 'If-Unmodified-Since'<~Time> - Returns object only if it has not been modified since this time, otherwise returns 412 (Precodition Failed). - # * 'Range'<~String> - Range of object to download - # - # ==== Returns - # * response<~Fog::AWS::Response>: - # * body<~String> - Contents of object - # * headers<~Hash>: - # * 'Content-Length'<~String> - Size of object contents - # * 'Content-Type'<~String> - MIME type of object - # * 'ETag'<~String> - Etag of object - # * 'Last-Modified'<~String> - Last modified timestamp for object - def head_object(bucket_name, object_name, options={}) - headers = {} - headers['If-Modified-Since'] = options['If-Modified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since'] - headers['If-Unmodified-Since'] = options['If-Unmodified-Since'].utc.strftime("%a, %d %b %Y %H:%M:%S +0000") if options['If-Modified-Since'] - headers.merge!(options) - request({ - :expects => 200, - :headers => headers, - :host => "#{bucket_name}.#{@host}", - :method => 'HEAD', - :path => object_name - }) end - end end -end + +else + + module Fog + module AWS + class S3 + + def head_object(bucket_name, object_name, options = {}) + response = get_object(bucket_name, object_name, options) + response.body = nil + response + end + + end + end + end + +end \ No newline at end of file diff --git a/lib/fog/aws/requests/s3/put_bucket.rb b/lib/fog/aws/requests/s3/put_bucket.rb index 3af80b1de..b4473c9ca 100644 --- a/lib/fog/aws/requests/s3/put_bucket.rb +++ b/lib/fog/aws/requests/s3/put_bucket.rb @@ -50,7 +50,8 @@ else @data['Buckets'] << { 'Name' => bucket_name, 'Contents' => [], - 'CreationDate' => Time.now + 'CreationDate' => Time.now, + 'Payer' => 'BucketOwner' } response end diff --git a/lib/fog/aws/requests/s3/put_request_payment.rb b/lib/fog/aws/requests/s3/put_request_payment.rb index 592bedc00..839ca6501 100644 --- a/lib/fog/aws/requests/s3/put_request_payment.rb +++ b/lib/fog/aws/requests/s3/put_request_payment.rb @@ -1,29 +1,57 @@ -module Fog - module AWS - class S3 +unless Fog.mocking? - # Change who pays for requests to an S3 bucket - # - # ==== Parameters - # * bucket_name<~String> - name of bucket to modify - # * payer<~String> - valid values are BucketOwner or Requester - def put_request_payment(bucket_name, payer) - data = + module Fog + module AWS + class S3 + + # Change who pays for requests to an S3 bucket + # + # ==== Parameters + # * bucket_name<~String> - name of bucket to modify + # * payer<~String> - valid values are BucketOwner or Requester + def put_request_payment(bucket_name, payer) + data = <<-DATA #{payer} DATA - request({ - :body => data, - :expects => 200, - :headers => {}, - :host => "#{bucket_name}.#{@host}", - :method => 'PUT', - :query => "requestPayment" - }) - end + request({ + :body => data, + :expects => 200, + :headers => {}, + :host => "#{bucket_name}.#{@host}", + :method => 'PUT', + :query => "requestPayment" + }) + end + end end end -end + +else + + module Fog + module AWS + class S3 + + def put_request_payment(bucket_name, payer) + response = Fog::Response.new + bucket_status = get_bucket(bucket_name).status + if bucket_status == 200 + response.status = 200 + bucket = @data['Buckets'].select {|bucket| bucket['Name'] == bucket_name}.first + bucket['Payer'] = payer + else + response.status = bucket_status + end + response + end + + end + end + end + + +end \ No newline at end of file diff --git a/spec/aws/s3/copy_object_spec.rb b/spec/aws/s3/copy_object_spec.rb index caf44411d..acfe6f87b 100644 --- a/spec/aws/s3/copy_object_spec.rb +++ b/spec/aws/s3/copy_object_spec.rb @@ -3,21 +3,22 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe 'S3.copy_object' do before(:all) do - s3.put_bucket('fogcopyobjectsource') + @s3 = s3 + @s3.put_bucket('fogcopyobjectsource') file = File.open(File.dirname(__FILE__) + '/../../lorem.txt', 'r') - s3.put_object('fogcopyobjectsource', 'fog_copy_object_source', file) - s3.put_bucket('fogcopyobjectdestination') + @s3.put_object('fogcopyobjectsource', 'fog_copy_object_source', file) + @s3.put_bucket('fogcopyobjectdestination') end after(:all) do - s3.delete_object('fogcopyobjectdestination', 'fog_copy_object_destination') - s3.delete_bucket('fogcopyobjectdestination') - s3.delete_object('fogcopyobjectsource', 'fog_copy_object_source') - s3.delete_bucket('fogcopyobjectsource') + @s3.delete_object('fogcopyobjectdestination', 'fog_copy_object_destination') + @s3.delete_bucket('fogcopyobjectdestination') + @s3.delete_object('fogcopyobjectsource', 'fog_copy_object_source') + @s3.delete_bucket('fogcopyobjectsource') end it 'should return proper attributes' do - actual = s3.copy_object( + actual = @s3.copy_object( 'fogcopyobjectsource', 'fog_copy_object_source', 'fogcopyobjectdestination', 'fog_copy_object_destination' ) diff --git a/spec/aws/s3/get_bucket_spec.rb b/spec/aws/s3/get_bucket_spec.rb index 482e8bc32..721d01245 100644 --- a/spec/aws/s3/get_bucket_spec.rb +++ b/spec/aws/s3/get_bucket_spec.rb @@ -3,18 +3,19 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe 'S3.get_bucket' do before(:all) do - s3.put_bucket('foggetbucket') + @s3 = s3 + @s3.put_bucket('foggetbucket') file = File.open(File.dirname(__FILE__) + '/../../lorem.txt', 'r') - s3.put_object('foggetbucket', 'fog_get_bucket', file) + @s3.put_object('foggetbucket', 'fog_get_bucket', file) end after(:all) do - s3.delete_object('foggetbucket', 'fog_get_bucket') - s3.delete_bucket('foggetbucket') + @s3.delete_object('foggetbucket', 'fog_get_bucket') + @s3.delete_bucket('foggetbucket') end it 'should return proper attributes' do - actual = s3.get_bucket('foggetbucket') + actual = @s3.get_bucket('foggetbucket') actual.body['IsTruncated'].should == false actual.body['Marker'].should be_a(String) actual.body['MaxKeys'].should be_an(Integer) diff --git a/spec/aws/s3/get_request_payment_spec.rb b/spec/aws/s3/get_request_payment_spec.rb index 364061e4b..eade904af 100644 --- a/spec/aws/s3/get_request_payment_spec.rb +++ b/spec/aws/s3/get_request_payment_spec.rb @@ -3,15 +3,16 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe 'S3.get_request_payment' do before(:all) do - s3.put_bucket('foggetrequestpayment') + @s3 = s3 + @s3.put_bucket('foggetrequestpayment') end after(:all) do - s3.delete_bucket('foggetrequestpayment') + @s3.delete_bucket('foggetrequestpayment') end it 'should return proper attributes' do - actual = s3.get_request_payment('foggetrequestpayment') + actual = @s3.get_request_payment('foggetrequestpayment') actual.status.should == 200 actual.body['Payer'].should == 'BucketOwner' end diff --git a/spec/aws/s3/head_object_spec.rb b/spec/aws/s3/head_object_spec.rb index 3e3dab8d0..06297a65c 100644 --- a/spec/aws/s3/head_object_spec.rb +++ b/spec/aws/s3/head_object_spec.rb @@ -3,18 +3,19 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe 'S3.head_object' do before(:all) do - s3.put_bucket('fogheadobject') + @s3 = s3 + @s3.put_bucket('fogheadobject') file = File.open(File.dirname(__FILE__) + '/../../lorem.txt', 'r') - s3.put_object('fogheadobject', 'fog_head_object', file) + @s3.put_object('fogheadobject', 'fog_head_object', file) end after(:all) do - s3.delete_object('fogheadobject', 'fog_head_object') - s3.delete_bucket('fogheadobject') + @s3.delete_object('fogheadobject', 'fog_head_object') + @s3.delete_bucket('fogheadobject') end it 'should return proper attributes' do - actual = s3.head_object('fogheadobject', 'fog_head_object') + actual = @s3.head_object('fogheadobject', 'fog_head_object') actual.status.should == 200 file = File.open(File.dirname(__FILE__) + '/../../lorem.txt', 'r') data = file.read diff --git a/spec/aws/s3/put_request_payment_spec.rb b/spec/aws/s3/put_request_payment_spec.rb index 5ca03d896..a3f1365c8 100644 --- a/spec/aws/s3/put_request_payment_spec.rb +++ b/spec/aws/s3/put_request_payment_spec.rb @@ -3,15 +3,16 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe 'S3.put_request_payment' do before(:all) do - s3.put_bucket('fogputrequestpayment') + @s3 = s3 + @s3.put_bucket('fogputrequestpayment') end after(:all) do - s3.delete_bucket('fogputrequestpayment') + @s3.delete_bucket('fogputrequestpayment') end it 'should return proper attributes' do - actual = s3.put_request_payment('fogputrequestpayment', 'Requester') + actual = @s3.put_request_payment('fogputrequestpayment', 'Requester') actual.status.should == 200 end