Skip to content

Commit

Permalink
Merge pull request #343 from tseaver/314-bucket_lifecycle_support
Browse files Browse the repository at this point in the history
Add bucket lifecycle support
  • Loading branch information
tseaver committed Nov 4, 2014
2 parents aa22386 + 5684d32 commit f7af09f
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
30 changes: 30 additions & 0 deletions gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Bucket(_MetadataMixin):
CUSTOM_METADATA_FIELDS = {
'acl': 'get_acl',
'defaultObjectAcl': 'get_default_object_acl',
'lifecycle': 'get_lifecycle',
}
"""Mapping of field name -> accessor for fields w/ custom accessors."""

Expand Down Expand Up @@ -441,6 +442,35 @@ def make_public(self, recursive=False, future=False):
key.get_acl().all().grant_read()
key.save_acl()

def get_lifecycle(self):
"""Retrieve CORS policies configured for this bucket.
See: https://cloud.google.com/storage/docs/lifecycle and
https://cloud.google.com/storage/docs/json_api/v1/buckets
:rtype: list(dict)
:returns: A sequence of mappings describing each CORS policy.
"""
if not self.has_metadata('lifecycle'):
self.reload_metadata()
result = []
info = self.metadata.get('lifecycle', {})
for rule in info.get('rule', ()):
rule = rule.copy()
result.append(rule)
return result

def update_lifecycle(self, rules):
"""Update CORS policies configured for this bucket.
See: https://cloud.google.com/storage/docs/lifecycle and
https://cloud.google.com/storage/docs/json_api/v1/buckets
:type rules: list(dict)
:param rules: A sequence of mappings describing each lifecycle policy.
"""
self.patch_metadata({'lifecycle': {'rule': rules}})


class BucketIterator(Iterator):
"""An iterator listing all buckets.
Expand Down
64 changes: 64 additions & 0 deletions gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,23 @@ def test_get_metadata_none_set_defaultObjectAcl_miss_clear_default(self):
kw = connection._requested
self.assertEqual(len(kw), 0)

def test_get_metadata_lifecycle_no_default(self):
NAME = 'name'
connection = _Connection()
bucket = self._makeOne(connection, NAME)
self.assertRaises(KeyError, bucket.get_metadata, 'lifecycle')
kw = connection._requested
self.assertEqual(len(kw), 0)

def test_get_metadata_lifecycle_w_default(self):
NAME = 'name'
connection = _Connection()
bucket = self._makeOne(connection, NAME)
default = object()
self.assertRaises(KeyError, bucket.get_metadata, 'lifecycle', default)
kw = connection._requested
self.assertEqual(len(kw), 0)

def test_get_metadata_miss(self):
NAME = 'name'
before = {'bar': 'Bar'}
Expand Down Expand Up @@ -713,6 +730,53 @@ def get_items_from_response(self, response):
self.assertEqual(kw[1]['path'], '/b/%s/o' % NAME)
self.assertEqual(kw[1]['query_params'], None)

def test_get_lifecycle_eager(self):
NAME = 'name'
LC_RULE = {'action': {'type': 'Delete'}, 'condition': {'age': 42}}
before = {'lifecycle': {'rule': [LC_RULE]}}
connection = _Connection()
bucket = self._makeOne(connection, NAME, before)
entries = bucket.get_lifecycle()
self.assertEqual(len(entries), 1)
self.assertEqual(entries[0]['action']['type'], 'Delete')
self.assertEqual(entries[0]['condition']['age'], 42)
kw = connection._requested
self.assertEqual(len(kw), 0)

def test_get_lifecycle_lazy(self):
NAME = 'name'
LC_RULE = {'action': {'type': 'Delete'}, 'condition': {'age': 42}}
after = {'lifecycle': {'rule': [LC_RULE]}}
connection = _Connection(after)
bucket = self._makeOne(connection, NAME)
entries = bucket.get_lifecycle()
self.assertEqual(len(entries), 1)
self.assertEqual(entries[0]['action']['type'], 'Delete')
self.assertEqual(entries[0]['condition']['age'], 42)
kw = connection._requested
self.assertEqual(len(kw), 1)
self.assertEqual(kw[0]['method'], 'GET')
self.assertEqual(kw[0]['path'], '/b/%s' % NAME)
self.assertEqual(kw[0]['query_params'], {'projection': 'noAcl'})

def test_update_lifecycle(self):
NAME = 'name'
LC_RULE = {'action': {'type': 'Delete'}, 'condition': {'age': 42}}
after = {'lifecycle': {'rule': [LC_RULE]}}
connection = _Connection(after)
bucket = self._makeOne(connection, NAME)
bucket.update_lifecycle([LC_RULE])
kw = connection._requested
self.assertEqual(len(kw), 1)
self.assertEqual(kw[0]['method'], 'PATCH')
self.assertEqual(kw[0]['path'], '/b/%s' % NAME)
self.assertEqual(kw[0]['data'], after)
self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
entries = bucket.get_lifecycle()
self.assertEqual(len(entries), 1)
self.assertEqual(entries[0]['action']['type'], 'Delete')
self.assertEqual(entries[0]['condition']['age'], 42)


class TestBucketIterator(unittest2.TestCase):

Expand Down

0 comments on commit f7af09f

Please sign in to comment.