diff --git a/lib/fog/aws/parsers/storage/get_bucket_lifecycle.rb b/lib/fog/aws/parsers/storage/get_bucket_lifecycle.rb
new file mode 100644
index 000000000..81014f229
--- /dev/null
+++ b/lib/fog/aws/parsers/storage/get_bucket_lifecycle.rb
@@ -0,0 +1,32 @@
+module Fog
+ module Parsers
+ module Storage
+ module AWS
+
+ class GetBucketLifecycle < Fog::Parsers::Base
+
+ def reset
+ @rule = {}
+ @response = { 'Rules' => [] }
+ end
+
+ def end_element(name)
+ case name
+ when 'ID', 'Prefix'
+ @rule[name] = value
+ when 'Status'
+ @rule['Enabled'] = value == 'Enabled'
+ when 'Days'
+ @rule[name] = value.to_i
+ when 'Rule'
+ @response['Rules'] << @rule
+ @rule = {}
+ end
+ end
+
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/fog/aws/requests/storage/delete_bucket_lifecycle.rb b/lib/fog/aws/requests/storage/delete_bucket_lifecycle.rb
new file mode 100644
index 000000000..72f2a7328
--- /dev/null
+++ b/lib/fog/aws/requests/storage/delete_bucket_lifecycle.rb
@@ -0,0 +1,30 @@
+module Fog
+ module Storage
+ class AWS
+ class Real
+
+ # Delete lifecycle configuration for a bucket
+ #
+ # ==== Parameters
+ # * bucket_name<~String> - name of bucket to delete lifecycle configuration from
+ #
+ # ==== Returns
+ # * response<~Excon::Response>:
+ # * status<~Integer> - 204
+ #
+ # ==== See Also
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETElifecycle.html
+
+ def delete_bucket_lifecycle(bucket_name)
+ request({
+ :expects => 204,
+ :headers => {},
+ :host => "#{bucket_name}.#{@host}",
+ :method => 'DELETE',
+ :query => {'lifecycle' => nil}
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/lib/fog/aws/requests/storage/get_bucket_lifecycle.rb b/lib/fog/aws/requests/storage/get_bucket_lifecycle.rb
new file mode 100644
index 000000000..56791471e
--- /dev/null
+++ b/lib/fog/aws/requests/storage/get_bucket_lifecycle.rb
@@ -0,0 +1,41 @@
+module Fog
+ module Storage
+ class AWS
+ class Real
+
+ require 'fog/aws/parsers/storage/get_bucket_lifecycle'
+
+ # Get bucket lifecycle configuration
+ #
+ # ==== Parameters
+ # * bucket_name<~String> - name of bucket to get lifecycle configuration for
+ #
+ # ==== Returns
+ # * response<~Excon::Response>:
+ # * body<~Hash>:
+ # * 'Rules'<~Array> - object expire rules
+ # * 'ID'<~String> - Unique identifier for the rule
+ # * 'Prefix'<~String> - Prefix identifying one or more objects to which the rule applies
+ # * 'Enabled'<~Boolean> - if rule is currently being applied
+ # * 'Days'<~Integer> - lifetime, in days, of the objects that are subject to the rule
+ #
+ # ==== See Also
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETlifecycle.html
+
+ def get_bucket_lifecycle(bucket_name)
+ request({
+ :expects => 200,
+ :headers => {},
+ :host => "#{bucket_name}.#{@host}",
+ :idempotent => true,
+ :method => 'GET',
+ :parser => Fog::Parsers::Storage::AWS::GetBucketLifecycle.new,
+ :query => {'lifecycle' => nil}
+ })
+ end
+
+ end
+ end
+ end
+end
+
diff --git a/lib/fog/aws/requests/storage/put_bucket_lifecycle.rb b/lib/fog/aws/requests/storage/put_bucket_lifecycle.rb
new file mode 100644
index 000000000..a147560d2
--- /dev/null
+++ b/lib/fog/aws/requests/storage/put_bucket_lifecycle.rb
@@ -0,0 +1,48 @@
+module Fog
+ module Storage
+ class AWS
+ class Real
+
+ # Change lifecycle configuration for an S3 bucket
+ #
+ # ==== Parameters
+ # * bucket_name<~String> - name of bucket to set lifecycle configuration for
+ # * lifecycle<~Hash>:
+ # * 'Rules'<~Array> - object expire rules
+ # * 'ID'<~String> - Unique identifier for the rule
+ # * 'Prefix'<~String> - Prefix identifying one or more objects to which the rule applies
+ # * 'Enabled'<~Boolean> - if rule is currently being applied
+ # * 'Days'<~Integer> - lifetime, in days, of the objects that are subject to the rule
+ # ==== See Also
+ # http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html
+
+ def put_bucket_lifecycle(bucket_name, lifecycle)
+ builder = Nokogiri::XML::Builder.new do
+ LifecycleConfiguration {
+ lifecycle['Rules'].each do |rule|
+ Rule {
+ ID rule['ID']
+ Prefix rule['Prefix']
+ Status rule['Enabled'] ? 'Enabled' : 'Disabled'
+ Expiration { Days rule['Days'] }
+ }
+ end
+ }
+ end
+
+ body = builder.to_xml
+
+ request({
+ :body => body,
+ :expects => 200,
+ :headers => {'Content-MD5' => Base64.encode64(Digest::MD5.digest(body)).chomp!,
+ 'Content-Type' => 'application/xml'},
+ :host => "#{bucket_name}.#{@host}",
+ :method => 'PUT',
+ :query => {'lifecycle' => nil}
+ })
+ end
+ end
+ end
+ end
+end
diff --git a/lib/fog/aws/storage.rb b/lib/fog/aws/storage.rb
index 77bdcf003..483265241 100644
--- a/lib/fog/aws/storage.rb
+++ b/lib/fog/aws/storage.rb
@@ -19,11 +19,13 @@ module Fog
request :complete_multipart_upload
request :copy_object
request :delete_bucket
+ request :delete_bucket_lifecycle
request :delete_bucket_policy
request :delete_bucket_website
request :delete_object
request :get_bucket
request :get_bucket_acl
+ request :get_bucket_lifecycle
request :get_bucket_location
request :get_bucket_logging
request :get_bucket_object_versions
@@ -45,6 +47,7 @@ module Fog
request :post_object_hidden_fields
request :put_bucket
request :put_bucket_acl
+ request :put_bucket_lifecycle
request :put_bucket_logging
request :put_bucket_policy
request :put_bucket_versioning
@@ -338,6 +341,7 @@ DATA
for key in (params[:query] || {}).keys.sort
if %w{
acl
+ lifecycle
location
logging
notification
diff --git a/tests/aws/requests/storage/bucket_tests.rb b/tests/aws/requests/storage/bucket_tests.rb
index 48b5b212f..4850c9394 100644
--- a/tests/aws/requests/storage/bucket_tests.rb
+++ b/tests/aws/requests/storage/bucket_tests.rb
@@ -179,6 +179,68 @@ Shindo.tests('Fog::Storage[:aws] | bucket requests', [:aws]) do
Fog::Storage[:aws].delete_bucket_website(@aws_bucket_name)
end
+ tests('bucket lifecycle') do
+ pending if Fog.mocking?
+
+ lifecycle = {'Rules' => [{'ID' => 'test rule', 'Prefix' => '/prefix', 'Enabled' => true, 'Days' => 42}]}
+ tests('non-existant bucket') do
+ tests('#put_bucket_lifecycle').returns([404, 'NoSuchBucket']) do
+ begin
+ Fog::Storage[:aws].put_bucket_lifecycle('fognonbucket', lifecycle)
+ rescue Excon::Errors::NotFound => e
+ [e.response.status, e.response.body.match(%r{(.*)
})[1]]
+ end
+ end
+ tests('#get_bucket_lifecycle').returns([404, 'NoSuchBucket']) do
+ begin
+ Fog::Storage[:aws].get_bucket_lifecycle('fognonbucket')
+ rescue Excon::Errors::NotFound => e
+ [e.response.status, e.response.body.match(%r{(.*)
})[1]]
+ end
+ end
+ tests('#delete_bucket_lifecycle').returns([404, 'NoSuchBucket']) do
+ begin
+ Fog::Storage[:aws].delete_bucket_lifecycle('fognonbucket')
+ rescue Excon::Errors::NotFound => e
+ [e.response.status, e.response.body.match(%r{(.*)
})[1]]
+ end
+ end
+ end
+ tests('no lifecycle') do
+ tests('#get_bucket_lifecycle').returns([404, 'NoSuchLifecycleConfiguration']) do
+ begin
+ Fog::Storage[:aws].get_bucket_lifecycle(@aws_bucket_name)
+ rescue Excon::Errors::NotFound => e
+ [e.response.status, e.response.body.match(%r{(.*)
})[1]]
+ end
+ end
+ tests('#delete_bucket_lifecycle').succeeds do
+ Fog::Storage[:aws].delete_bucket_lifecycle(@aws_bucket_name)
+ end
+ end
+ tests('create').succeeds do
+ Fog::Storage[:aws].put_bucket_lifecycle(@aws_bucket_name, lifecycle)
+ end
+ tests('read').returns(lifecycle) do
+ Fog::Storage[:aws].get_bucket_lifecycle(@aws_bucket_name).body
+ end
+ lifecycle = { 'Rules' => 5.upto(6).map { |i| {'ID' => "rule\##{i}", 'Prefix' => i.to_s, 'Enabled' => true, 'Days' => i} } }
+ tests('update').returns(lifecycle) do
+ Fog::Storage[:aws].put_bucket_lifecycle(@aws_bucket_name, lifecycle)
+ Fog::Storage[:aws].get_bucket_lifecycle(@aws_bucket_name).body
+ end
+ tests('delete').succeeds do
+ Fog::Storage[:aws].delete_bucket_lifecycle(@aws_bucket_name)
+ end
+ tests('read').returns([404, 'NoSuchLifecycleConfiguration']) do
+ begin
+ Fog::Storage[:aws].get_bucket_lifecycle(@aws_bucket_name)
+ rescue Excon::Errors::NotFound => e
+ [e.response.status, e.response.body.match(%r{(.*)
})[1]]
+ end
+ end
+ end
+
tests("#delete_bucket('#{@aws_bucket_name}')").succeeds do
Fog::Storage[:aws].delete_bucket(@aws_bucket_name)
end