From 8d78f4d135ef3aa848c1023c92584b885e61cda9 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Tue, 6 Dec 2011 12:22:17 -0500 Subject: [PATCH 01/25] [aws|storage|test] Added mock support for setting and retrieving versioning on a bucket. --- .../requests/storage/get_bucket_versioning.rb | 30 ++++++++++++++++ .../requests/storage/put_bucket_versioning.rb | 36 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/lib/fog/aws/requests/storage/get_bucket_versioning.rb b/lib/fog/aws/requests/storage/get_bucket_versioning.rb index f04d3ecbb..1b979ed21 100644 --- a/lib/fog/aws/requests/storage/get_bucket_versioning.rb +++ b/lib/fog/aws/requests/storage/get_bucket_versioning.rb @@ -33,7 +33,37 @@ module Fog :query => {'versioning' => nil} }) end + end + class Mock + def get_bucket_versioning(bucket_name) + response = Excon::Response.new + bucket = self.data[:buckets][bucket_name] + + if bucket + response.status = 200 + + if bucket[:versioning] + response.body = { 'VersioningConfiguration' => { 'Status' => bucket[:versioning] } } + else + response.body = { 'VersioningConfiguration' => {} } + end + + else + response.status = 404 + response.body = { + 'Error' => { + 'Code' => 'NoSuchBucket', + 'Message' => 'The specified bucket does not exist', + 'BucketName' => bucket_name, + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + end + + response + end end end end diff --git a/lib/fog/aws/requests/storage/put_bucket_versioning.rb b/lib/fog/aws/requests/storage/put_bucket_versioning.rb index 696ff038d..ca6e1befe 100644 --- a/lib/fog/aws/requests/storage/put_bucket_versioning.rb +++ b/lib/fog/aws/requests/storage/put_bucket_versioning.rb @@ -29,7 +29,43 @@ DATA :query => {'versioning' => nil} }) end + end + class Mock + def put_bucket_versioning(bucket_name, status) + response = Excon::Response.new + bucket = self.data[:buckets][bucket_name] + + if bucket + if ['Enabled', 'Suspended'].include?(status) + bucket[:versioning] = status + + response.status = 200 + else + response.status = 400 + response.body = { + 'Error' => { + 'Code' => 'MalformedXML', + 'Message' => 'The XML you provided was not well-formed or did not validate against our published schema', + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + end + else + response.status = 403 + response.body = { + 'Error' => { + 'Code' => 'AccessDenied', + 'Message' => 'AccessDenied', + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + end + + response + end end end end From d53f2409b0d8c4c49ce8b64fceb9f432ad0b0075 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Wed, 7 Dec 2011 10:32:08 -0500 Subject: [PATCH 02/25] [aws|storage|test] Added in versioning support for S3 objects, sans deletion markers. --- lib/fog/aws/requests/storage/get_bucket.rb | 2 +- .../storage/get_bucket_object_versions.rb | 64 ++++++++++++++++++- lib/fog/aws/requests/storage/get_object.rb | 2 +- lib/fog/aws/requests/storage/put_object.rb | 6 +- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/lib/fog/aws/requests/storage/get_bucket.rb b/lib/fog/aws/requests/storage/get_bucket.rb index bec419508..27497bd17 100644 --- a/lib/fog/aws/requests/storage/get_bucket.rb +++ b/lib/fog/aws/requests/storage/get_bucket.rb @@ -69,7 +69,7 @@ module Fog end response = Excon::Response.new if bucket = self.data[:buckets][bucket_name] - contents = bucket[:objects].values.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object| + contents = bucket[:objects].values.collect(&:last).sort {|x,y| x['Key'] <=> y['Key']}.reject do |object| (prefix && object['Key'][0...prefix.length] != prefix) || (marker && object['Key'] <= marker) || (delimiter && object['Key'][(prefix ? prefix.length : 0)..-1].include?(delimiter) \ diff --git a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb index e417dba37..95f73d93a 100644 --- a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb +++ b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb @@ -65,11 +65,71 @@ module Fog :idempotent => true, :method => 'GET', :parser => Fog::Parsers::Storage::AWS::GetBucketObjectVersions.new, - :query => {'versions' => nil}.merge!(options) - }) + :query => {'versions' => nil}.merge!(options) }) end end + + class Mock + def get_bucket_object_versions(bucket_name, options = {}) + delimiter, key_marker, max_keys, prefix, version_id_marker = \ + options['delimiter'], options['key_marker'], options['max_keys'],options['prefix'],options['version_id_marker'] + + unless bucket_name + raise ArgumentError.new('bucket_name is required') + end + + response = Excon::Response.new + if bucket = self.data[:buckets][bucket_name] + contents = bucket[:objects].values.flatten.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object| + (prefix && object['Key'][0...prefix.length] != prefix) || + (key_marker && object['Key'] <= key_marker) || + (delimiter && object['Key'][(prefix ? prefix.length : 0)..-1].include?(delimiter) \ + && common_prefixes << object['Key'].sub(/^(#{prefix}[^#{delimiter}]+.).*/, '\1')) + end.map do |object| + data = { 'Version' => {} } + data['Version'] = object.reject {|key, value| !['ETag', 'Key', 'StorageClass', 'VersionId'].include?(key)} + data['Version'].merge!({ + 'LastModified' => Time.parse(object['Last-Modified']), + 'Owner' => bucket['Owner'], + 'Size' => object['Content-Length'].to_i, + 'IsLatest' => true + }) + data + end + + max_keys = max_keys || 1000 + size = [max_keys, 1000].min + truncated_contents = contents[0...size] + + response.status = 200 + response.body = { + 'Versions' => truncated_contents, + 'IsTruncated' => truncated_contents.size != contents.size, + 'KeyMarker' => key_marker, + 'VersionIdMarker' => version_id_marker, + 'MaxKeys' => max_keys, + 'Name' => bucket['Name'], + 'Prefix' => prefix + } + if max_keys && max_keys < response.body['Versions'].length + response.body['IsTruncated'] = true + response.body['Versions'] = response.body['Versions'][0...max_keys] + end + else + response.status = 403 + response.body = { + 'Error' => { + 'Code' => 'AccessDenied', + 'Message' => 'AccessDenied', + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + end + response + end + end end end end diff --git a/lib/fog/aws/requests/storage/get_object.rb b/lib/fog/aws/requests/storage/get_object.rb index 2b4ecf8c1..ba68e6cf1 100644 --- a/lib/fog/aws/requests/storage/get_object.rb +++ b/lib/fog/aws/requests/storage/get_object.rb @@ -70,7 +70,7 @@ module Fog end response = Excon::Response.new if (bucket = self.data[:buckets][bucket_name]) - if (object = bucket[:objects][object_name]) + if (object = bucket[:objects][object_name].last) if options['If-Match'] && options['If-Match'] != object['ETag'] response.status = 412 elsif options['If-Modified-Since'] && options['If-Modified-Since'] > Time.parse(object['Last-Modified']) diff --git a/lib/fog/aws/requests/storage/put_object.rb b/lib/fog/aws/requests/storage/put_object.rb index 17f7eabb4..3d802a9e9 100644 --- a/lib/fog/aws/requests/storage/put_object.rb +++ b/lib/fog/aws/requests/storage/put_object.rb @@ -70,7 +70,8 @@ module Fog 'Key' => object_name, 'Last-Modified' => Fog::Time.now.to_date_header, 'Content-Length' => options['Content-Length'] || data[:headers]['Content-Length'], - 'StorageClass' => options['x-amz-storage-class'] || 'STANDARD' + 'StorageClass' => options['x-amz-storage-class'] || 'STANDARD', + 'VersionId' => bucket[:versioning] == 'Enabled' ? Fog::Mock.random_base64(32) : 'null' } for key, value in options @@ -80,7 +81,8 @@ module Fog end end - bucket[:objects][object_name] = object + bucket[:objects][object_name] ||= [] + bucket[:objects][object_name] << object response.headers = { 'Content-Length' => object['Content-Length'], 'Content-Type' => object['Content-Type'], From f9de06b60383f92f87bfca5f912c6e283f5d35c8 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Wed, 7 Dec 2011 10:41:51 -0500 Subject: [PATCH 03/25] [aws|storage|test] Track if the version is the latest or not. --- lib/fog/aws/requests/storage/get_bucket_object_versions.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb index 95f73d93a..fe2616a4f 100644 --- a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb +++ b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb @@ -93,7 +93,7 @@ module Fog 'LastModified' => Time.parse(object['Last-Modified']), 'Owner' => bucket['Owner'], 'Size' => object['Content-Length'].to_i, - 'IsLatest' => true + 'IsLatest' => object == bucket[:objects][object['Key']].last }) data end From f2b61321bba116e900e7ac38e7f23f776bc9bd59 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 15 Dec 2011 14:26:08 -0500 Subject: [PATCH 04/25] [aws|storage] Handle S3 object deletions in the face of versioning. --- lib/fog/aws/requests/storage/delete_object.rb | 15 ++++++++++++++- lib/fog/aws/requests/storage/get_bucket.rb | 3 ++- .../storage/get_bucket_object_versions.rb | 17 +++++++++++++---- lib/fog/aws/requests/storage/get_object.rb | 3 ++- lib/fog/aws/requests/storage/put_object.rb | 9 +++++++-- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/fog/aws/requests/storage/delete_object.rb b/lib/fog/aws/requests/storage/delete_object.rb index d738ebb88..435ec8e06 100644 --- a/lib/fog/aws/requests/storage/delete_object.rb +++ b/lib/fog/aws/requests/storage/delete_object.rb @@ -36,7 +36,20 @@ module Fog response = Excon::Response.new if bucket = self.data[:buckets][bucket_name] response.status = 204 - bucket[:objects].delete(object_name) + + if bucket[:versioning] + delete_marker = { + :delete_marker => true, + 'Key' => object_name, + 'VersionId' => Fog::Mock.random_base64(32), + 'Last-Modified' => Fog::Time.now.to_date_header + } + + bucket[:objects][object_name] ||= [] + bucket[:objects][object_name] << delete_marker + else + bucket[:objects].delete(object_name) + end else response.status = 404 raise(Excon::Errors.status_error({:expects => 204}, response)) diff --git a/lib/fog/aws/requests/storage/get_bucket.rb b/lib/fog/aws/requests/storage/get_bucket.rb index 27497bd17..f9a3b0ff7 100644 --- a/lib/fog/aws/requests/storage/get_bucket.rb +++ b/lib/fog/aws/requests/storage/get_bucket.rb @@ -73,7 +73,8 @@ module Fog (prefix && object['Key'][0...prefix.length] != prefix) || (marker && object['Key'] <= marker) || (delimiter && object['Key'][(prefix ? prefix.length : 0)..-1].include?(delimiter) \ - && common_prefixes << object['Key'].sub(/^(#{prefix}[^#{delimiter}]+.).*/, '\1')) + && common_prefixes << object['Key'].sub(/^(#{prefix}[^#{delimiter}]+.).*/, '\1')) || + object.has_key?(:delete_marker) end.map do |object| data = object.reject {|key, value| !['ETag', 'Key', 'StorageClass'].include?(key)} data.merge!({ diff --git a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb index fe2616a4f..3c78d3955 100644 --- a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb +++ b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb @@ -87,14 +87,23 @@ module Fog (delimiter && object['Key'][(prefix ? prefix.length : 0)..-1].include?(delimiter) \ && common_prefixes << object['Key'].sub(/^(#{prefix}[^#{delimiter}]+.).*/, '\1')) end.map do |object| - data = { 'Version' => {} } - data['Version'] = object.reject {|key, value| !['ETag', 'Key', 'StorageClass', 'VersionId'].include?(key)} - data['Version'].merge!({ + if object.has_key?(:delete_marker) + tag_name = 'DeleteMarker' + extracted_attrs = ['Key', 'VersionId'] + else + tag_name = 'Version' + extracted_attrs = ['ETag', 'Key', 'StorageClass', 'VersionId'] + end + + data = {} + data[tag_name] = object.reject { |key, value| !extracted_attrs.include?(key) } + data[tag_name].merge!({ 'LastModified' => Time.parse(object['Last-Modified']), 'Owner' => bucket['Owner'], - 'Size' => object['Content-Length'].to_i, 'IsLatest' => object == bucket[:objects][object['Key']].last }) + + data[tag_name]['Size'] = object['Content-Length'].to_i if tag_name == 'Version' data end diff --git a/lib/fog/aws/requests/storage/get_object.rb b/lib/fog/aws/requests/storage/get_object.rb index ba68e6cf1..044c1a357 100644 --- a/lib/fog/aws/requests/storage/get_object.rb +++ b/lib/fog/aws/requests/storage/get_object.rb @@ -70,7 +70,8 @@ module Fog end response = Excon::Response.new if (bucket = self.data[:buckets][bucket_name]) - if (object = bucket[:objects][object_name].last) + object = bucket[:objects][object_name].last if bucket[:objects].has_key?(object_name) + if (object && !object[:delete_marker]) if options['If-Match'] && options['If-Match'] != object['ETag'] response.status = 412 elsif options['If-Modified-Since'] && options['If-Modified-Since'] > Time.parse(object['Last-Modified']) diff --git a/lib/fog/aws/requests/storage/put_object.rb b/lib/fog/aws/requests/storage/put_object.rb index 3d802a9e9..684450eac 100644 --- a/lib/fog/aws/requests/storage/put_object.rb +++ b/lib/fog/aws/requests/storage/put_object.rb @@ -81,8 +81,13 @@ module Fog end end - bucket[:objects][object_name] ||= [] - bucket[:objects][object_name] << object + if bucket[:versioning] + bucket[:objects][object_name] ||= [] + bucket[:objects][object_name] << object + else + bucket[:objects][object_name] = [object] + end + response.headers = { 'Content-Length' => object['Content-Length'], 'Content-Type' => object['Content-Type'], From 5290d0f96013d2f188809e3460ee4f5e8ae8cea9 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 15 Dec 2011 17:04:26 -0500 Subject: [PATCH 05/25] [aws|storage|test] Basic handling of version-id-marker. --- .../storage/get_bucket_object_versions.rb | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb index 3c78d3955..c7d0bf9f4 100644 --- a/lib/fog/aws/requests/storage/get_bucket_object_versions.rb +++ b/lib/fog/aws/requests/storage/get_bucket_object_versions.rb @@ -80,7 +80,23 @@ module Fog end response = Excon::Response.new - if bucket = self.data[:buckets][bucket_name] + + # Invalid arguments. + if version_id_marker && !key_marker + response.status = 400 + response.body = { + 'Error' => { + 'Code' => 'InvalidArgument', + 'Message' => 'A version-id marker cannot be specified without a key marker.', + 'ArgumentValue' => version_id_marker, + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + + # Valid case. + # TODO: (nirvdrum 12/15/11) It's not clear to me how to actually use version-id-marker, so I didn't implement it below. + elsif bucket = self.data[:buckets][bucket_name] contents = bucket[:objects].values.flatten.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object| (prefix && object['Key'][0...prefix.length] != prefix) || (key_marker && object['Key'] <= key_marker) || @@ -125,6 +141,8 @@ module Fog response.body['IsTruncated'] = true response.body['Versions'] = response.body['Versions'][0...max_keys] end + + # Missing bucket case. else response.status = 403 response.body = { From 701175a0a7473ca7b13f7e035a67555e8a6f2d20 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 15 Dec 2011 17:23:50 -0500 Subject: [PATCH 06/25] [aws|storage|test] Added the ability to get_object by versionId. --- lib/fog/aws/requests/storage/get_object.rb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/fog/aws/requests/storage/get_object.rb b/lib/fog/aws/requests/storage/get_object.rb index 044c1a357..35d9f8c12 100644 --- a/lib/fog/aws/requests/storage/get_object.rb +++ b/lib/fog/aws/requests/storage/get_object.rb @@ -62,15 +62,23 @@ module Fog class Mock # :nodoc:all def get_object(bucket_name, object_name, options = {}, &block) + version_id = options.delete('versionId') + unless bucket_name raise ArgumentError.new('bucket_name is required') end + unless object_name raise ArgumentError.new('object_name is required') end + response = Excon::Response.new if (bucket = self.data[:buckets][bucket_name]) - object = bucket[:objects][object_name].last if bucket[:objects].has_key?(object_name) + object = nil + if bucket[:objects].has_key?(object_name) + object = version_id ? bucket[:objects][object_name].find { |object| object['VersionId'] == version_id} : bucket[:objects][object_name].last + end + if (object && !object[:delete_marker]) if options['If-Match'] && options['If-Match'] != object['ETag'] response.status = 412 @@ -100,6 +108,18 @@ module Fog end end end + elsif version_id && !object + response.status = 400 + response.body = { + 'Error' => { + 'Code' => 'InvalidArgument', + 'Message' => 'Invalid version id specified', + 'ArgumentValue' => version_id, + 'ArgumentName' => 'versionId', + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } else response.status = 404 response.body = "...NoSuchKey<\/Code>..." From f391ae7b940530fea52f5e82f4a084bb2922ea08 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Tue, 20 Dec 2011 11:32:52 -0500 Subject: [PATCH 07/25] [aws|storage|test] Added S3 versioning support for delete_object. --- lib/fog/aws/requests/storage/delete_object.rb | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/lib/fog/aws/requests/storage/delete_object.rb b/lib/fog/aws/requests/storage/delete_object.rb index 435ec8e06..5a9cc57dd 100644 --- a/lib/fog/aws/requests/storage/delete_object.rb +++ b/lib/fog/aws/requests/storage/delete_object.rb @@ -17,6 +17,12 @@ module Fog # http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html def delete_object(bucket_name, object_name, options = {}) + if version_id = options.delete('versionId') + path = "#{CGI.escape(object_name)}?versionId=#{CGI.escape(version_id)}" + else + path = CGI.escape(object_name) + end + headers = options request({ :expects => 204, @@ -24,7 +30,7 @@ module Fog :host => "#{bucket_name}.#{@host}", :idempotent => true, :method => 'DELETE', - :path => CGI.escape(object_name) + :path => path }) end @@ -37,18 +43,45 @@ module Fog if bucket = self.data[:buckets][bucket_name] response.status = 204 - if bucket[:versioning] - delete_marker = { - :delete_marker => true, - 'Key' => object_name, - 'VersionId' => Fog::Mock.random_base64(32), - 'Last-Modified' => Fog::Time.now.to_date_header - } + version_id = options.delete('versionId') + if bucket[:versioning] bucket[:objects][object_name] ||= [] - bucket[:objects][object_name] << delete_marker + + if version_id + version = bucket[:objects][object_name].find { |object| object['VersionId'] == version_id} + + # S3 special cases the 'null' value to not error out if no such version exists. + if version || version_id == 'null' + bucket[:objects][object_name].delete(version) + + response.headers['x-amz-delete-marker'] = 'true' if version[:delete_marker] + response.headers['x-amz-version-id'] = version_id + else + response.status = 400 + response.body = invalid_version_id_payload(version_id) + end + else + delete_marker = { + :delete_marker => true, + 'Key' => object_name, + 'VersionId' => Fog::Mock.random_base64(32), + 'Last-Modified' => Fog::Time.now.to_date_header + } + + bucket[:objects][object_name] << delete_marker + response.headers['x-amz-delete-marker'] = 'true' + response.headers['x-amz-version-id'] = delete_marker['VersionId'] + end else - bucket[:objects].delete(object_name) + if version_id && version_id != 'null' + response.status = 400 + response.body = invalid_version_id_payload(version_id) + else + bucket[:objects].delete(object_name) + + response.headers['x-amz-version-id'] = 'null' + end end else response.status = 404 @@ -57,6 +90,21 @@ module Fog response end + private + + def invalid_version_id_payload(version_id) + { + 'Error' => { + 'Code' => 'InvalidArgument', + 'Message' => 'Invalid version id specified', + 'ArgumentValue' => version_id, + 'ArgumentName' => 'versionId', + 'RequestId' => Fog::Mock.random_hex(16), + 'HostId' => Fog::Mock.random_base64(65) + } + } + end + end end end From eb75723f87571bc45b37302bb6cf1595d29aef45 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Tue, 20 Dec 2011 15:59:23 -0500 Subject: [PATCH 08/25] [aws|storage|test] Deal with suspended buckets properly. --- lib/fog/aws/requests/storage/delete_object.rb | 9 ++++++++- lib/fog/aws/requests/storage/put_object.rb | 13 ++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/fog/aws/requests/storage/delete_object.rb b/lib/fog/aws/requests/storage/delete_object.rb index 5a9cc57dd..d8603df7c 100644 --- a/lib/fog/aws/requests/storage/delete_object.rb +++ b/lib/fog/aws/requests/storage/delete_object.rb @@ -65,11 +65,18 @@ module Fog delete_marker = { :delete_marker => true, 'Key' => object_name, - 'VersionId' => Fog::Mock.random_base64(32), + 'VersionId' => bucket[:versioning] == 'Enabled' ? Fog::Mock.random_base64(32) : 'null', 'Last-Modified' => Fog::Time.now.to_date_header } + # When versioning is suspended, a delete marker is placed if the last object ID is not the value 'null', + # otherwise the last object is replaced. + if bucket[:versioning] == 'Suspended' && bucket[:objects][object_name].last['VersionId'] == 'null' + bucket[:objects][object_name].pop + end + bucket[:objects][object_name] << delete_marker + response.headers['x-amz-delete-marker'] = 'true' response.headers['x-amz-version-id'] = delete_marker['VersionId'] end diff --git a/lib/fog/aws/requests/storage/put_object.rb b/lib/fog/aws/requests/storage/put_object.rb index 684450eac..5cc087bc2 100644 --- a/lib/fog/aws/requests/storage/put_object.rb +++ b/lib/fog/aws/requests/storage/put_object.rb @@ -32,9 +32,9 @@ module Fog def put_object(bucket_name, object_name, data, options = {}) data = Fog::Storage.parse_data(data) headers = data[:headers].merge!(options) - request({ - :body => data[:body], - :expects => 200, + request({ :body => data[:body], + :expects => 200, + :headers => headers, :host => "#{bucket_name}.#{@host}", :idempotent => true, @@ -83,6 +83,13 @@ module Fog if bucket[:versioning] bucket[:objects][object_name] ||= [] + + # When versioning is suspended, putting an object will create a new 'null' version if the latest version + # is a value other than 'null', otherwise it will replace the latest version. + if bucket[:versioning] == 'Suspended' && bucket[:objects][object_name].last['VersionId'] == 'null' + bucket[:objects][object_name].pop + end + bucket[:objects][object_name] << object else bucket[:objects][object_name] = [object] From abf8b5e670acd64616ae8d54fda3b950e3f360b7 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 29 Dec 2011 14:08:22 -0500 Subject: [PATCH 09/25] [aws|storage] Return the object version in the request header and set an attribute value in the model. --- lib/fog/aws/models/storage/file.rb | 1 + lib/fog/aws/requests/storage/get_object.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/lib/fog/aws/models/storage/file.rb b/lib/fog/aws/models/storage/file.rb index 669307251..992f9559e 100644 --- a/lib/fog/aws/models/storage/file.rb +++ b/lib/fog/aws/models/storage/file.rb @@ -22,6 +22,7 @@ module Fog attribute :owner, :aliases => 'Owner' attribute :storage_class, :aliases => ['x-amz-storage-class', 'StorageClass'] attribute :encryption, :aliases => 'x-amz-server-side-encryption' + attribute :version, :aliases => 'x-amz-version-id' def acl=(new_acl) valid_acls = ['private', 'public-read', 'public-read-write', 'authenticated-read'] diff --git a/lib/fog/aws/requests/storage/get_object.rb b/lib/fog/aws/requests/storage/get_object.rb index 35d9f8c12..b8c426493 100644 --- a/lib/fog/aws/requests/storage/get_object.rb +++ b/lib/fog/aws/requests/storage/get_object.rb @@ -96,6 +96,9 @@ module Fog response.headers[key] = value end end + + response.headers['x-amz-version-id'] = object['VersionId'] if bucket[:versioning] + unless block_given? response.body = object[:body] else From 28df463458727dd583dec6c2dfe01308fc54c266 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 29 Dec 2011 14:08:58 -0500 Subject: [PATCH 10/25] [aws|storage] Allow options to be passed to the destroy method, facilitating passing of versionId. --- lib/fog/aws/models/storage/file.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/fog/aws/models/storage/file.rb b/lib/fog/aws/models/storage/file.rb index 992f9559e..2b704c507 100644 --- a/lib/fog/aws/models/storage/file.rb +++ b/lib/fog/aws/models/storage/file.rb @@ -55,9 +55,10 @@ module Fog target_directory.files.head(target_file_key) end - def destroy + def destroy(options = {}) requires :directory, :key - connection.delete_object(directory.key, key) + attributes[:body] = nil if options['versionId'] == version + connection.delete_object(directory.key, key, options) true end From 2d084c784449d6f00869a26195ad098ac22a67ed Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 29 Dec 2011 14:47:50 -0500 Subject: [PATCH 11/25] [aws|storage] Added ability to control bucket versioning from Directory model. --- lib/fog/aws/models/storage/directory.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/fog/aws/models/storage/directory.rb b/lib/fog/aws/models/storage/directory.rb index d13017fbe..9f31a49cf 100644 --- a/lib/fog/aws/models/storage/directory.rb +++ b/lib/fog/aws/models/storage/directory.rb @@ -58,6 +58,17 @@ module Fog @payer = new_payer end + def versioning? + requires :key + data = connection.get_bucket_versioning(key) + data.body['VersioningConfiguration']['Status'] == 'Enabled' + end + + def versioning=(new_versioning) + requires :key + connection.put_bucket_versioning(key, new_versioning ? 'Enabled' : 'Suspended') + end + def public=(new_public) if new_public @acl = 'public-read' From a57fdd21dde48f38b83a38648d83c33862c340d1 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 29 Dec 2011 16:19:39 -0500 Subject: [PATCH 12/25] [aws|storage] Added the ability to fetch a list of versions from a file. --- lib/fog/aws/models/storage/file.rb | 10 ++++++++ lib/fog/aws/models/storage/version.rb | 24 ++++++++++++++++++ lib/fog/aws/models/storage/versions.rb | 34 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 lib/fog/aws/models/storage/version.rb create mode 100644 lib/fog/aws/models/storage/versions.rb diff --git a/lib/fog/aws/models/storage/file.rb b/lib/fog/aws/models/storage/file.rb index 2b704c507..5883cf5aa 100644 --- a/lib/fog/aws/models/storage/file.rb +++ b/lib/fog/aws/models/storage/file.rb @@ -1,4 +1,5 @@ require 'fog/core/model' +require 'fog/aws/models/storage/versions' module Fog module Storage @@ -132,6 +133,15 @@ module Fog collection.get_https_url(key, expires, options) end + def versions + @versions ||= begin + Fog::Storage::AWS::Versions.new( + :file => self, + :connection => connection + ) + end + end + private def directory=(new_directory) diff --git a/lib/fog/aws/models/storage/version.rb b/lib/fog/aws/models/storage/version.rb new file mode 100644 index 000000000..5e83cd6a4 --- /dev/null +++ b/lib/fog/aws/models/storage/version.rb @@ -0,0 +1,24 @@ +require 'fog/core/model' + +module Fog + module Storage + class AWS + + class Version < Fog::Model + + identity :version, :aliases => 'VersionId' + + attribute :key, :aliases => 'Key' + attribute :last_modified, :aliases => ['Last-Modified', 'LastModified'] + attribute :latest, :aliases => 'IsLatest', :type => :boolean + attribute :content_length, :aliases => ['Content-Length', 'Size'], :type => :integer + attribute :delete_marker, :type => :boolean + + def file + @file ||= collection.file.directory.files.get(key, 'versionId' => version) + end + end + + end + end +end diff --git a/lib/fog/aws/models/storage/versions.rb b/lib/fog/aws/models/storage/versions.rb new file mode 100644 index 000000000..42f1ccd5d --- /dev/null +++ b/lib/fog/aws/models/storage/versions.rb @@ -0,0 +1,34 @@ +require 'fog/core/collection' +require 'fog/aws/models/storage/version' + +module Fog + module Storage + class AWS + + class Versions < Fog::Collection + + attribute :file + + model Fog::Storage::AWS::Version + + def all + data = connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + load(data) + end + + def new(attributes = {}) + requires :file + + version_type = attributes.keys.first + + model = super({ :file => file }.merge!(attributes[version_type])) + model.delete_marker = version_type == 'DeleteMarker' + + model + end + + end + + end + end +end \ No newline at end of file From dab6b61997b6a2b6bfc5646bf5bc7ce456ce18f5 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Tue, 3 Jan 2012 19:19:18 -0500 Subject: [PATCH 13/25] [aws|storage|test] Added request tests for put_bucket_versioning and get_bucket_versioning. --- .../aws/requests/storage/versioning_tests.rb | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/aws/requests/storage/versioning_tests.rb diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb new file mode 100644 index 000000000..f0db37236 --- /dev/null +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -0,0 +1,72 @@ +Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do + tests('success') do + tests("#put_bucket_versioning") do + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + + before do + Fog::Storage[:aws].put_bucket(@aws_bucket_name) + end + + after do + Fog::Storage[:aws].delete_bucket(@aws_bucket_name) + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + end + + tests("#put_bucket_versioning('#{@aws_bucket_name}', 'Enabled')").succeeds do + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') + end + + tests("#put_bucket_versioning('#{@aws_bucket_name}', 'Suspended')").succeeds do + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Suspended') + end + end + + tests("#get_bucket_versioning('#{@aws_bucket_name}')") do + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + + before do + Fog::Storage[:aws].put_bucket(@aws_bucket_name) + end + + after do + Fog::Storage[:aws].delete_bucket(@aws_bucket_name) + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + end + + tests("#get_bucket_versioning('#{@aws_bucket_name}') without versioning").returns({}) do + Fog::Storage[:aws].get_bucket_versioning(@aws_bucket_name).body['VersioningConfiguration'] + end + + tests("#get_bucket_versioning('#{@aws_bucket_name}') with versioning enabled").returns('Enabled') do + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') + Fog::Storage[:aws].get_bucket_versioning(@aws_bucket_name).body['VersioningConfiguration']['Status'] + end + + tests("#get_bucket_versioning('#{@aws_bucket_name}') with versioning suspended").returns('Suspended') do + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Suspended') + Fog::Storage[:aws].get_bucket_versioning(@aws_bucket_name).body['VersioningConfiguration']['Status'] + end + end + end + + tests('failure') do + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + Fog::Storage[:aws].put_bucket(@aws_bucket_name) + + tests("#put_bucket_versioning('#{@aws_bucket_name}', 'bad_value')").raises(Excon::Errors::BadRequest) do + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'bad_value') + end + + tests("#put_bucket_versioning('fognonbucket', 'Enabled')").raises(Excon::Errors::NotFound) do + Fog::Storage[:aws].put_bucket_versioning('fognonbucket', 'Enabled') + end + + tests("#get_bucket_versioning('fognonbucket')").raises(Excon::Errors::NotFound) do + Fog::Storage[:aws].get_bucket_versioning('fognonbucket') + end + end + + # don't keep the bucket around + Fog::Storage[:aws].delete_bucket(@aws_bucket_name) rescue nil +end \ No newline at end of file From c0f2e43ea60b7bc9c69ae2feba79b216456ccfb9 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 5 Jan 2012 15:55:11 -0500 Subject: [PATCH 14/25] [aws|storage|test] Added tests for get_bucket_object_versions. --- .../aws/requests/storage/versioning_tests.rb | 127 +++++++++++++++--- 1 file changed, 107 insertions(+), 20 deletions(-) diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb index f0db37236..0915f7b86 100644 --- a/tests/aws/requests/storage/versioning_tests.rb +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -1,16 +1,30 @@ +def clear_bucket + Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name).body['Versions'].each do |version| + object = version[version.keys.first] + Fog::Storage[:aws].delete_object(@aws_bucket_name, object['Key'], 'versionId' => object['VersionId']) + end +end + +def create_versioned_bucket + @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) + Fog::Storage[:aws].put_bucket(@aws_bucket_name) + Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') +end + +def delete_bucket + Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name).body['Versions'].each do |version| + object = version[version.keys.first] + Fog::Storage[:aws].delete_object(@aws_bucket_name, object['Key'], 'versionId' => object['VersionId']) + end + + Fog::Storage[:aws].delete_bucket(@aws_bucket_name) +end + Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do tests('success') do tests("#put_bucket_versioning") do @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) - - before do - Fog::Storage[:aws].put_bucket(@aws_bucket_name) - end - - after do - Fog::Storage[:aws].delete_bucket(@aws_bucket_name) - @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) - end + Fog::Storage[:aws].put_bucket(@aws_bucket_name) tests("#put_bucket_versioning('#{@aws_bucket_name}', 'Enabled')").succeeds do Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') @@ -19,19 +33,13 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do tests("#put_bucket_versioning('#{@aws_bucket_name}', 'Suspended')").succeeds do Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Suspended') end + + delete_bucket end tests("#get_bucket_versioning('#{@aws_bucket_name}')") do @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) - - before do - Fog::Storage[:aws].put_bucket(@aws_bucket_name) - end - - after do - Fog::Storage[:aws].delete_bucket(@aws_bucket_name) - @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) - end + Fog::Storage[:aws].put_bucket(@aws_bucket_name) tests("#get_bucket_versioning('#{@aws_bucket_name}') without versioning").returns({}) do Fog::Storage[:aws].get_bucket_versioning(@aws_bucket_name).body['VersioningConfiguration'] @@ -43,10 +51,85 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do end tests("#get_bucket_versioning('#{@aws_bucket_name}') with versioning suspended").returns('Suspended') do - Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Enabled') Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'Suspended') Fog::Storage[:aws].get_bucket_versioning(@aws_bucket_name).body['VersioningConfiguration']['Status'] end + + delete_bucket + end + + tests("#get_bucket_object_versions('#{@aws_bucket_name}')") do + @versions_format = { + 'IsTruncated' => Fog::Boolean, + 'MaxKeys' => Integer, + 'Name' => String, + 'Prefix' => NilClass, + 'KeyMarker' => NilClass, + 'VersionIdMarker' => NilClass, + 'Versions' => [{ + 'DeleteMarker' => { + 'Key' => String, + 'LastModified' => Time, + 'Owner' => { + 'DisplayName' => String, + 'ID' => String + }, + 'IsLatest' => Fog::Boolean, + 'VersionId' => String + }, + 'Version' => { + 'ETag' => String, + 'Key' => String, + 'LastModified' => Time, + 'Owner' => { + 'DisplayName' => String, + 'ID' => String + }, + 'Size' => Integer, + 'StorageClass' => String, + 'IsLatest' => Fog::Boolean, + 'VersionId' => String + } + }] + } + + create_versioned_bucket + + file = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'y', :key => 'x') + file.destroy + +# tests("#get_bucket_object_versions('#{@aws_bucket_name}')").formats(@versions_format) do +# Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name).body +# end + + clear_bucket + + before do + @versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) + end + + + create_versioned_bucket + + v1 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'a', :key => 'file') + v2 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'ab', :key => 'file') + v3 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abc', :key => 'file') + v4 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abcd', :key => 'file') + + tests("versions").returns([v4.version, v3.version, v2.version, v1.version]) do + @versions.body['Versions'].collect {|v| v['Version']['VersionId']} + end + + tests("version sizes").returns([4, 3, 2, 1]) do + @versions.body['Versions'].collect {|v| v['Version']['Size']} + end + + tests("latest version").returns(v4.version) do + latest = @versions.body['Versions'].find {|v| v['Version']['IsLatest']} + latest['Version']['VersionId'] + end + + delete_bucket end end @@ -65,8 +148,12 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do tests("#get_bucket_versioning('fognonbucket')").raises(Excon::Errors::NotFound) do Fog::Storage[:aws].get_bucket_versioning('fognonbucket') end + + tests("#get_bucket_object_versions('fognonbucket')").raises(Excon::Errors::NotFound) do + Fog::Storage[:aws].get_bucket_object_versions('fognonbucket') + end end # don't keep the bucket around Fog::Storage[:aws].delete_bucket(@aws_bucket_name) rescue nil -end \ No newline at end of file +end From 002d6e4dc5d44369b686b492d42e8cfeb0187043 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 5 Jan 2012 17:26:17 -0500 Subject: [PATCH 15/25] [aws|storage|test] Added request test for get_object with versioning. --- .../aws/requests/storage/versioning_tests.rb | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb index 0915f7b86..d9ef70abd 100644 --- a/tests/aws/requests/storage/versioning_tests.rb +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -108,13 +108,10 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do @versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) end - - create_versioned_bucket - v1 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'a', :key => 'file') - v2 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'ab', :key => 'file') - v3 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abc', :key => 'file') - v4 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abcd', :key => 'file') + v2 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'ab', :key => v1.key) + v3 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abc', :key => v1.key) + v4 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'abcd', :key => v1.key) tests("versions").returns([v4.version, v3.version, v2.version, v1.version]) do @versions.body['Versions'].collect {|v| v['Version']['VersionId']} @@ -128,14 +125,36 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do latest = @versions.body['Versions'].find {|v| v['Version']['IsLatest']} latest['Version']['VersionId'] end - - delete_bucket end + + tests("get_object('#{@aws_bucket_name}', 'file')") do + clear_bucket + + v1 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'a', :key => 'file') + v2 = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'ab', :key => v1.key) + + tests("get_object('#{@aws_bucket_name}', '#{v2.key}') returns the latest version").returns(v2.version) do + res = Fog::Storage[:aws].get_object(@aws_bucket_name, v2.key) + res.headers['x-amz-version-id'] + end + + tests("get_object('#{@aws_bucket_name}', '#{v1.key}', 'versionId' => '#{v1.version}') returns the specified version").returns(v1.version) do + res = Fog::Storage[:aws].get_object(@aws_bucket_name, v1.key, 'versionId' => v1.version) + res.headers['x-amz-version-id'] + end + + v2.destroy + + tests("get_object('#{@aws_bucket_name}', '#{v2.key}') raises exception if delete marker is latest version").raises(Excon::Errors::NotFound) do + Fog::Storage[:aws].get_object(@aws_bucket_name, v2.key) + end + end + + delete_bucket end tests('failure') do - @aws_bucket_name = 'fogbuckettests-' + Fog::Mock.random_hex(16) - Fog::Storage[:aws].put_bucket(@aws_bucket_name) + create_versioned_bucket tests("#put_bucket_versioning('#{@aws_bucket_name}', 'bad_value')").raises(Excon::Errors::BadRequest) do Fog::Storage[:aws].put_bucket_versioning(@aws_bucket_name, 'bad_value') @@ -150,10 +169,16 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do end tests("#get_bucket_object_versions('fognonbucket')").raises(Excon::Errors::NotFound) do - Fog::Storage[:aws].get_bucket_object_versions('fognonbucket') - end + Fog::Storage[:aws].get_bucket_object_versions('fognonbucket') + end + + file = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'y', :key => 'x') + + tests("#get_object('#{@aws_bucket_name}', 'x', 'versionId' => 'bad_version'").raises(Excon::Errors::BadRequest) do + Fog::Storage[:aws].get_object(@aws_bucket_name, 'x', 'versionId' => '-1') + end end # don't keep the bucket around - Fog::Storage[:aws].delete_bucket(@aws_bucket_name) rescue nil + delete_bucket end From 590ae9c67bdd3a8c0611c55a0d5eb63afb0ad49a Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 5 Jan 2012 17:56:26 -0500 Subject: [PATCH 16/25] [aws|storage|test] Added request tests for delete_object with versioning. --- .../aws/requests/storage/versioning_tests.rb | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb index d9ef70abd..3f661a001 100644 --- a/tests/aws/requests/storage/versioning_tests.rb +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -150,6 +150,32 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do end end + tests("delete_object('#{@aws_bucket_name}', 'file')") do + clear_bucket + + file = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'a', :key => 'file') + + tests("deleting an object just stores a delete marker").returns(true) do + file.destroy + versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) + versions.body['Versions'].first.has_key?('DeleteMarker') + end + + tests("there are two versions: the original and the delete marker").returns(2) do + versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) + versions.body['Versions'].size + end + + tests("deleting the delete marker makes the object available again").returns(file.version) do + versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) + delete_marker = versions.body['Versions'].find { |v| v.has_key?('DeleteMarker') } + Fog::Storage[:aws].delete_object(@aws_bucket_name, file.key, 'versionId' => delete_marker['DeleteMarker']['VersionId']) + + res = Fog::Storage[:aws].get_object(@aws_bucket_name, file.key) + res.headers['x-amz-version-id'] + end + end + delete_bucket end From 69bdbe00b895b2f7bbd069404a4a7ce46bd1894b Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 5 Jan 2012 18:29:13 -0500 Subject: [PATCH 17/25] [aws|storage|test] Added failing request test for delete_object with versioning. --- tests/aws/models/storage/directory_test.rb | 48 +++++++++++++++++++ .../aws/requests/storage/versioning_tests.rb | 8 +++- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/aws/models/storage/directory_test.rb diff --git a/tests/aws/models/storage/directory_test.rb b/tests/aws/models/storage/directory_test.rb new file mode 100644 index 000000000..31d9fe20b --- /dev/null +++ b/tests/aws/models/storage/directory_test.rb @@ -0,0 +1,48 @@ +Fog.mock! + +Shindo.tests("Storage[aws] | directory", [:aws]) do + + directory_attributes = { + :key => 'fogdirectorytests' + } + + model_tests(Fog::Storage[:aws].directories, directory_attributes, true) do + + tests("#versioning=") do + tests("#versioning=(true)").succeeds do + @instance.versioning = true + end + + tests("#versioning=(true) sets versioning to 'Enabled'").returns('Enabled') do + @instance.versioning = true + @instance.connection.get_bucket_versioning(@instance.key).body['VersioningConfiguration']['Status'] + end + + tests("#versioning=(false)").succeeds do + @instance.versioning = false + end + + tests("#versioning=(false) sets versioning to 'Suspended'").returns('Suspended') do + @instance.versioning = false + @instance.connection.get_bucket_versioning(@instance.key).body['VersioningConfiguration']['Status'] + end + end + + tests("#versioning?") do + tests("#versioning? false if not enabled").returns(false) do + @instance.versioning? + end + + tests("#versioning? true if enabled").returns(true) do + @instance.connection.put_bucket_versioning(@instance.key, 'Enabled') + @instance.versioning? + end + + tests("#versioning? false if suspended").returns(false) do + @instance.connection.put_bucket_versioning(@instance.key, 'Suspended') + @instance.versioning? + end + end + end + +end \ No newline at end of file diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb index 3f661a001..fff64a044 100644 --- a/tests/aws/requests/storage/versioning_tests.rb +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -200,8 +200,12 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do file = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'y', :key => 'x') - tests("#get_object('#{@aws_bucket_name}', 'x', 'versionId' => 'bad_version'").raises(Excon::Errors::BadRequest) do - Fog::Storage[:aws].get_object(@aws_bucket_name, 'x', 'versionId' => '-1') + tests("#get_object('#{@aws_bucket_name}', '#{file.key}', 'versionId' => 'bad_version'").raises(Excon::Errors::BadRequest) do + Fog::Storage[:aws].get_object(@aws_bucket_name, file.key, 'versionId' => '-1') + end + + tests("#delete_object('#{@aws_bucket_name}', '#{file.key}', 'versionId' => 'bad_version'").raises(Excon::Errors::BadRequest) do + Fog::Storage[:aws].delete_object(@aws_bucket_name, file.key, 'versionId' => '-1') end end From bfc882c7e0af07c46c45f4c67ad34bd59d2f4358 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 19 Jan 2012 18:19:03 -0500 Subject: [PATCH 18/25] [aws|storage|test] Added in some file and directory model tests. --- lib/fog/aws/requests/storage/put_object.rb | 10 +++-- .../{directory_test.rb => directory_tests.rb} | 4 +- tests/aws/models/storage/file_tests.rb | 41 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) rename tests/aws/models/storage/{directory_test.rb => directory_tests.rb} (94%) create mode 100644 tests/aws/models/storage/file_tests.rb diff --git a/lib/fog/aws/requests/storage/put_object.rb b/lib/fog/aws/requests/storage/put_object.rb index 5cc087bc2..416bc1f8c 100644 --- a/lib/fog/aws/requests/storage/put_object.rb +++ b/lib/fog/aws/requests/storage/put_object.rb @@ -96,11 +96,13 @@ module Fog end response.headers = { - 'Content-Length' => object['Content-Length'], - 'Content-Type' => object['Content-Type'], - 'ETag' => object['ETag'], - 'Last-Modified' => object['Last-Modified'] + 'Content-Length' => object['Content-Length'], + 'Content-Type' => object['Content-Type'], + 'ETag' => object['ETag'], + 'Last-Modified' => object['Last-Modified'], } + + response.headers['x-amz-version-id'] = object['VersionId'] if object['VersionId'] != 'null' else response.status = 404 raise(Excon::Errors.status_error({:expects => 200}, response)) diff --git a/tests/aws/models/storage/directory_test.rb b/tests/aws/models/storage/directory_tests.rb similarity index 94% rename from tests/aws/models/storage/directory_test.rb rename to tests/aws/models/storage/directory_tests.rb index 31d9fe20b..e6b0b8774 100644 --- a/tests/aws/models/storage/directory_test.rb +++ b/tests/aws/models/storage/directory_tests.rb @@ -1,12 +1,12 @@ Fog.mock! -Shindo.tests("Storage[aws] | directory", [:aws]) do +Shindo.tests("Storage[:aws] | directory", [:aws]) do directory_attributes = { :key => 'fogdirectorytests' } - model_tests(Fog::Storage[:aws].directories, directory_attributes, true) do + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do tests("#versioning=") do tests("#versioning=(true)").succeeds do diff --git a/tests/aws/models/storage/file_tests.rb b/tests/aws/models/storage/file_tests.rb new file mode 100644 index 000000000..dace1cb43 --- /dev/null +++ b/tests/aws/models/storage/file_tests.rb @@ -0,0 +1,41 @@ +Fog.mock! + +Shindo.tests("Storage[:aws] | file", [:aws]) do + + file_attributes = { + :key => 'fog_file_tests', + :body => lorem_file, + :public => true + } + + directory_attributes = { + :key => 'fogfilestests' + } + + @directory = Fog::Storage[:aws].directories.create(directory_attributes) + + model_tests(@directory.files, file_attributes, Fog.mocking?) do + + tests("#version") do + tests("#version should be null if versioning isn't enabled").returns(nil) do + @instance.version + end + end + + end + + @directory.versioning = true + + model_tests(@directory.files, file_attributes, Fog.mocking?) do + + tests("#version") do + tests("#version should not be null if versioning is enabled").returns(false) do + @instance.version == nil + end + end + + end + + @directory.destroy + +end From a5a3f8fdf40c90c19c6655bb038b70c2b2ee798c Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 10:06:40 -0500 Subject: [PATCH 19/25] [aws|storage|test] Added model tests for versioning Directory and File models. --- lib/fog/aws/models/storage/directory.rb | 10 +++++++ lib/fog/aws/models/storage/version.rb | 14 +++++++++- lib/fog/aws/models/storage/versions.rb | 12 ++++++--- lib/fog/aws/requests/storage/delete_object.rb | 3 ++- tests/aws/models/storage/directory_tests.rb | 27 +++++++++++++++++++ tests/aws/models/storage/file_tests.rb | 22 +++++++++++++++ 6 files changed, 82 insertions(+), 6 deletions(-) diff --git a/lib/fog/aws/models/storage/directory.rb b/lib/fog/aws/models/storage/directory.rb index 9f31a49cf..fcd5707f1 100644 --- a/lib/fog/aws/models/storage/directory.rb +++ b/lib/fog/aws/models/storage/directory.rb @@ -1,5 +1,6 @@ require 'fog/core/model' require 'fog/aws/models/storage/files' +require 'fog/aws/models/storage/versions' module Fog module Storage @@ -69,6 +70,15 @@ module Fog connection.put_bucket_versioning(key, new_versioning ? 'Enabled' : 'Suspended') end + def versions + @versions ||= begin + Fog::Storage::AWS::Versions.new( + :directory => self, + :connection => connection + ) + end + end + def public=(new_public) if new_public @acl = 'public-read' diff --git a/lib/fog/aws/models/storage/version.rb b/lib/fog/aws/models/storage/version.rb index 5e83cd6a4..eaffa083f 100644 --- a/lib/fog/aws/models/storage/version.rb +++ b/lib/fog/aws/models/storage/version.rb @@ -15,7 +15,19 @@ module Fog attribute :delete_marker, :type => :boolean def file - @file ||= collection.file.directory.files.get(key, 'versionId' => version) + @file ||= if collection.file + collection.file.directory.files.get(key, 'versionId' => version) + else + collection.directory.files.get(key, 'versionId' => version) + end + end + + def destroy + if collection.file + collection.connection.delete_object(collection.file.directory.key, key, 'versionId' => version) + else + collection.connection.delete_object(collection.directory.key, key, 'versionId' => version) + end end end diff --git a/lib/fog/aws/models/storage/versions.rb b/lib/fog/aws/models/storage/versions.rb index 42f1ccd5d..8ed61d4f0 100644 --- a/lib/fog/aws/models/storage/versions.rb +++ b/lib/fog/aws/models/storage/versions.rb @@ -8,20 +8,24 @@ module Fog class Versions < Fog::Collection attribute :file + attribute :directory model Fog::Storage::AWS::Version def all - data = connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + data = if file + connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + else + connection.get_bucket_object_versions(directory.key).body['Versions'] + end + load(data) end def new(attributes = {}) - requires :file - version_type = attributes.keys.first - model = super({ :file => file }.merge!(attributes[version_type])) + model = super(attributes[version_type]) model.delete_marker = version_type == 'DeleteMarker' model diff --git a/lib/fog/aws/requests/storage/delete_object.rb b/lib/fog/aws/requests/storage/delete_object.rb index d8603df7c..e28bf91f8 100644 --- a/lib/fog/aws/requests/storage/delete_object.rb +++ b/lib/fog/aws/requests/storage/delete_object.rb @@ -52,8 +52,9 @@ module Fog version = bucket[:objects][object_name].find { |object| object['VersionId'] == version_id} # S3 special cases the 'null' value to not error out if no such version exists. - if version || version_id == 'null' + if version || (version_id == 'null') bucket[:objects][object_name].delete(version) + bucket[:objects].delete(object_name) if bucket[:objects][object_name].empty? response.headers['x-amz-delete-marker'] = 'true' if version[:delete_marker] response.headers['x-amz-version-id'] = version_id diff --git a/tests/aws/models/storage/directory_tests.rb b/tests/aws/models/storage/directory_tests.rb index e6b0b8774..d1fb399e2 100644 --- a/tests/aws/models/storage/directory_tests.rb +++ b/tests/aws/models/storage/directory_tests.rb @@ -28,6 +28,10 @@ Shindo.tests("Storage[:aws] | directory", [:aws]) do end end + end + + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do + tests("#versioning?") do tests("#versioning? false if not enabled").returns(false) do @instance.versioning? @@ -43,6 +47,29 @@ Shindo.tests("Storage[:aws] | directory", [:aws]) do @instance.versioning? end end + + end + + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do + @instance.versioning = true + + versions = [] + versions << @instance.connection.put_object(@instance.key, 'one', 'abcde').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'one', '32423').headers['x-amz-version-id'] + versions << @instance.connection.delete_object(@instance.key, 'one').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'two', 'aoeu').headers['x-amz-version-id'] + + tests('#versions') do + tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(4) do + @instance.versions.size + end + + tests('#versions returns the correct versions').returns(versions) do + @instance.versions.collect(&:version) + end + end + + @instance.versions.each(&:destroy) end end \ No newline at end of file diff --git a/tests/aws/models/storage/file_tests.rb b/tests/aws/models/storage/file_tests.rb index dace1cb43..04cac2c12 100644 --- a/tests/aws/models/storage/file_tests.rb +++ b/tests/aws/models/storage/file_tests.rb @@ -34,8 +34,30 @@ Shindo.tests("Storage[:aws] | file", [:aws]) do end end + + @directory.files.create(:key => @instance.key) + @instance.destroy + + tests("#versions") do + tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(3) do + @instance.versions.size + end + + tests('#versions are all for the correct key').returns(true) do + @instance.versions.all? { |v| v.key == @instance.key } + end + end + + tests("#destroy") do + tests("#destroy a specific version should delete the version, not create a DeleteMarker").returns(2) do + @instance.destroy('versionId' => @instance.version) + @instance.versions.all.size + end + end + end + @directory.versions.each(&:destroy) @directory.destroy end From 6a97b6065094592381b624b6d9e148de6f56dedd Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 11:29:10 -0500 Subject: [PATCH 20/25] [aws|storage|test] Added tests for the Version model. --- tests/aws/models/storage/version_tests.rb | 54 +++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/aws/models/storage/version_tests.rb diff --git a/tests/aws/models/storage/version_tests.rb b/tests/aws/models/storage/version_tests.rb new file mode 100644 index 000000000..dd53fd819 --- /dev/null +++ b/tests/aws/models/storage/version_tests.rb @@ -0,0 +1,54 @@ +Fog.mock! + +Shindo.tests("Storage[:aws] | version", [:aws]) do + + file_attributes = { + :key => 'fog_file_tests', + :body => lorem_file, + :public => true + } + + directory_attributes = { + :key => 'fogfilestests' + } + + @directory = Fog::Storage[:aws].directories.create(directory_attributes) + @directory.versioning = true + + model_tests(@directory.files, file_attributes, Fog.mocking?) do + + @version_instance = @instance.versions.first + @directory.connection.put_object(@directory.key, @instance.key, 'second version content') + + tests("#file") do + tests("#file should return the object associated with the version").returns(@version_instance.version) do + @version_instance.file.version + end + end + + tests("#delete_marker") do + tests("#delete_marker should be false if the version isn't a DeleteMarker'").returns(false) do + @version_instance.delete_marker + end + + tests("#delete_marker should be true if the version isn't a DeleteMarker'").returns(true) do + @instance.destroy + + @instance.versions.all.last.delete_marker + end + end + + tests("#destroy") do + tests("#destroy removes the specific version").returns(false) do + @version_instance.destroy + + @instance.versions.all.collect(&:version).include?(@version_instance.version) + end + end + + end + + @directory.versions.each(&:destroy) + @directory.destroy + +end From 0287c0f7a485a9f3ef1ace27775adda2c479718a Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 13:39:22 -0500 Subject: [PATCH 21/25] [aws|storage|test] Added versioning test for Files collection. --- tests/aws/models/storage/files_test.rb | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/aws/models/storage/files_test.rb diff --git a/tests/aws/models/storage/files_test.rb b/tests/aws/models/storage/files_test.rb new file mode 100644 index 000000000..3ea2d321b --- /dev/null +++ b/tests/aws/models/storage/files_test.rb @@ -0,0 +1,44 @@ +Fog.mock! + +Shindo.tests("Storage[:aws] | files", [:aws]) do + + file_attributes = { + :key => 'fog_file_tests', + :body => lorem_file, + :public => true + } + + directory_attributes = { + :key => 'fogfilestests' + } + + @directory = Fog::Storage[:aws].directories.create(directory_attributes) + @directory.versioning = true + + model_tests(@directory.files, file_attributes, Fog.mocking?) do + + v1 = @instance.version + v2 = @directory.connection.put_object(@directory.key, @instance.key, 'version 2 content').headers['x-amz-version-id'] + v3 = @directory.connection.delete_object(@directory.key, @instance.key).headers['x-amz-version-id'] + v4 = @directory.connection.put_object(@directory.key, @instance.key, 'version 3 content').headers['x-amz-version-id'] + + tests("#get") do + tests("#get without version fetches the latest version").returns(v4) do + @directory.files.get(@instance.key).version + end + + tests("#get with version fetches that exact version").returns(v2) do + @directory.files.get(@instance.key, 'versionId' => v2).version + end + + tests("#get with a deleted version returns nil").returns(nil) do + @directory.files.get(@instance.key, 'versionId' => v3) + end + end + + end + + @directory.versions.each(&:destroy) + @directory.destroy + +end From 9d02af6f7a9e3c0e8f3be177b7b7508a986e3d1e Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 13:51:29 -0500 Subject: [PATCH 22/25] [aws|storage|test] Added versioning tests for Versions collection. --- lib/fog/aws/models/storage/versions.rb | 2 +- tests/aws/models/storage/directory_tests.rb | 22 --------- tests/aws/models/storage/versions_tests.rb | 51 +++++++++++++++++++++ 3 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 tests/aws/models/storage/versions_tests.rb diff --git a/lib/fog/aws/models/storage/versions.rb b/lib/fog/aws/models/storage/versions.rb index 8ed61d4f0..6a9dc1697 100644 --- a/lib/fog/aws/models/storage/versions.rb +++ b/lib/fog/aws/models/storage/versions.rb @@ -14,7 +14,7 @@ module Fog def all data = if file - connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + connection.get_bucket_object_versions(file.directory.key, 'prefix' => file.key).body['Versions'] else connection.get_bucket_object_versions(directory.key).body['Versions'] end diff --git a/tests/aws/models/storage/directory_tests.rb b/tests/aws/models/storage/directory_tests.rb index d1fb399e2..4c506fcde 100644 --- a/tests/aws/models/storage/directory_tests.rb +++ b/tests/aws/models/storage/directory_tests.rb @@ -50,26 +50,4 @@ Shindo.tests("Storage[:aws] | directory", [:aws]) do end - model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do - @instance.versioning = true - - versions = [] - versions << @instance.connection.put_object(@instance.key, 'one', 'abcde').headers['x-amz-version-id'] - versions << @instance.connection.put_object(@instance.key, 'one', '32423').headers['x-amz-version-id'] - versions << @instance.connection.delete_object(@instance.key, 'one').headers['x-amz-version-id'] - versions << @instance.connection.put_object(@instance.key, 'two', 'aoeu').headers['x-amz-version-id'] - - tests('#versions') do - tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(4) do - @instance.versions.size - end - - tests('#versions returns the correct versions').returns(versions) do - @instance.versions.collect(&:version) - end - end - - @instance.versions.each(&:destroy) - end - end \ No newline at end of file diff --git a/tests/aws/models/storage/versions_tests.rb b/tests/aws/models/storage/versions_tests.rb new file mode 100644 index 000000000..8c3bdef13 --- /dev/null +++ b/tests/aws/models/storage/versions_tests.rb @@ -0,0 +1,51 @@ +Fog.mock! + +Shindo.tests("Storage[:aws] | versions", [:aws]) do + + file_attributes = { + :key => 'fog_file_tests', + :body => lorem_file, + :public => true + } + + directory_attributes = { + :key => 'fogfilestests' + } + + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do + @instance.versioning = true + + versions = [] + versions << @instance.connection.put_object(@instance.key, 'one', 'abcde').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'one', '32423').headers['x-amz-version-id'] + versions << @instance.connection.delete_object(@instance.key, 'one').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'two', 'aoeu').headers['x-amz-version-id'] + + tests('#versions') do + tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(4) do + @instance.versions.size + end + + tests('#versions returns the correct versions').returns(versions) do + @instance.versions.collect(&:version) + end + end + + tests("#all") do + tests("#all for a directory returns all versions, regardless of key").returns(versions) do + @instance.versions.all.collect(&:version) + end + + tests("#all for file returns only versions for that file").returns(1) do + @instance.files.get('two').versions.collect(&:version).size + end + + tests("#all for file returns only versions for that file").returns(versions.last) do + @instance.files.get('two').versions.collect(&:version).first + end + end + + @instance.versions.each(&:destroy) + end + +end From df503d6ab85adb0d9e8b08734ce3b20bf031da83 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 13:51:50 -0500 Subject: [PATCH 23/25] Fixed a filename. --- tests/aws/models/storage/{files_test.rb => files_tests.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/aws/models/storage/{files_test.rb => files_tests.rb} (100%) diff --git a/tests/aws/models/storage/files_test.rb b/tests/aws/models/storage/files_tests.rb similarity index 100% rename from tests/aws/models/storage/files_test.rb rename to tests/aws/models/storage/files_tests.rb From 4899785ec5a42e69ceb93ad71ca203180107f321 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 14:15:22 -0500 Subject: [PATCH 24/25] [aws|storage|test] Added versioning test for Files#head. --- tests/aws/models/storage/files_tests.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/aws/models/storage/files_tests.rb b/tests/aws/models/storage/files_tests.rb index 3ea2d321b..233c6eb99 100644 --- a/tests/aws/models/storage/files_tests.rb +++ b/tests/aws/models/storage/files_tests.rb @@ -36,6 +36,20 @@ Shindo.tests("Storage[:aws] | files", [:aws]) do end end + tests("#head") do + tests("#head without version fetches the latest version").returns(v4) do + @directory.files.head(@instance.key).version + end + + tests("#head with version fetches that exact version").returns(v2) do + @directory.files.head(@instance.key, 'versionId' => v2).version + end + + tests("#head with a deleted version returns nil").returns(nil) do + @directory.files.head(@instance.key, 'versionId' => v3) + end + end + end @directory.versions.each(&:destroy) From 9c88964f02b478a3a187265257d8130f392558f6 Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Thu, 26 Jan 2012 18:10:05 -0500 Subject: [PATCH 25/25] [aws|storage|test] Removed a commented-out test. --- .../aws/requests/storage/versioning_tests.rb | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/tests/aws/requests/storage/versioning_tests.rb b/tests/aws/requests/storage/versioning_tests.rb index fff64a044..8fa173fdf 100644 --- a/tests/aws/requests/storage/versioning_tests.rb +++ b/tests/aws/requests/storage/versioning_tests.rb @@ -59,51 +59,9 @@ Shindo.tests('Fog::Storage[:aws] | versioning', [:aws]) do end tests("#get_bucket_object_versions('#{@aws_bucket_name}')") do - @versions_format = { - 'IsTruncated' => Fog::Boolean, - 'MaxKeys' => Integer, - 'Name' => String, - 'Prefix' => NilClass, - 'KeyMarker' => NilClass, - 'VersionIdMarker' => NilClass, - 'Versions' => [{ - 'DeleteMarker' => { - 'Key' => String, - 'LastModified' => Time, - 'Owner' => { - 'DisplayName' => String, - 'ID' => String - }, - 'IsLatest' => Fog::Boolean, - 'VersionId' => String - }, - 'Version' => { - 'ETag' => String, - 'Key' => String, - 'LastModified' => Time, - 'Owner' => { - 'DisplayName' => String, - 'ID' => String - }, - 'Size' => Integer, - 'StorageClass' => String, - 'IsLatest' => Fog::Boolean, - 'VersionId' => String - } - }] - } create_versioned_bucket - file = Fog::Storage[:aws].directories.get(@aws_bucket_name).files.create(:body => 'y', :key => 'x') - file.destroy - -# tests("#get_bucket_object_versions('#{@aws_bucket_name}')").formats(@versions_format) do -# Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name).body -# end - - clear_bucket - before do @versions = Fog::Storage[:aws].get_bucket_object_versions(@aws_bucket_name) end