import xml.etree.ElementTree as ET
+from collections import namedtuple
from email.Utils import formatdate
from httplib import HTTPConnection, HTTPSConnection
from urlparse import urlparse
else:
for rule in rules:
expiration = boto.s3.lifecycle.Expiration(days=rule['days'])
- rule = boto.s3.lifecycle.Rule(id=rule['id'], prefix=rule['prefix'],
+ _id = rule.get('id',None)
+ rule = boto.s3.lifecycle.Rule(id=_id, prefix=rule['prefix'],
status=rule['status'], expiration=expiration)
lifecycle.append(rule)
return lifecycle
eq(current[1].id, 'test2/')
eq(current[1].prefix, 'test2/')
+
+
+@attr(resource='bucket')
+@attr(method='get')
+@attr(operation='get lifecycle config no id')
+@attr('lifecycle')
+def test_lifecycle_get_no_id():
+ Rule = namedtuple('Rule',['prefix','status','days'])
+ rules = {'rule1' : Rule('test1/','Enabled',31),
+ 'rule2' : Rule('test2/','Enabled',120)}
+ bucket = set_lifecycle(rules=[{'days': rules['rule1'].days ,
+ 'prefix': rules['rule1'].prefix,
+ 'status': rules['rule1'].status},
+ {'days': rules['rule2'].days,
+ 'prefix': rules['rule2'].prefix,
+ 'status': rules['rule2'].status}])
+ current_lc = bucket.get_lifecycle_config()
+ # We can't guarantee the order of XML, since the id is random, let's walk
+ # through the rules and validate that both were present
+ for lc_rule in current_lc:
+ if lc_rule.expiration.days == rules['rule1'].days:
+ eq(lc_rule.prefix, rules['rule1'].prefix)
+ assert len(lc_rule.id) > 0
+ elif lc_rule.expiration.days == rules['rule2'].days:
+ eq(lc_rule.prefix, rules['rule2'].prefix)
+ assert len(lc_rule.id) > 0
+ else:
+ # neither of the rules we supplied, something wrong
+ assert False
+
+
# The test harnass for lifecycle is configured to treat days as 2 second intervals.
@attr(resource='bucket')
@attr(method='put')
def generate_lifecycle_body(rules):
body = '<?xml version="1.0" encoding="UTF-8"?><LifecycleConfiguration>'
for rule in rules:
- body += '<Rule><ID>%s</ID><Prefix>%s</Prefix><Status>%s</Status>' % (rule['ID'], rule['Prefix'], rule['Status'])
+ body += '<Rule><ID>%s</ID><Status>%s</Status>' % (rule['ID'], rule['Status'])
+ if 'Prefix' in rule.keys():
+ body += '<Prefix>%s</Prefix>' % rule['Prefix']
+ if 'Filter' in rule.keys():
+ prefix_str= '' # AWS supports empty filters
+ if 'Prefix' in rule['Filter'].keys():
+ prefix_str = '<Prefix>%s</Prefix>' % rule['Filter']['Prefix']
+ body += '<Filter>%s</Filter>' % prefix_str
+
if 'Expiration' in rule.keys():
if 'ExpiredObjectDeleteMarker' in rule['Expiration'].keys():
body += '<Expiration><ExpiredObjectDeleteMarker>%s</ExpiredObjectDeleteMarker></Expiration>' \
eq(res.status, 200)
eq(res.reason, 'OK')
+@attr(resource='bucket')
+@attr(method='put')
+@attr(operation='set lifecycle config with Filter')
+@attr('lifecycle')
+def test_lifecycle_set_filter():
+ bucket = get_new_bucket()
+ rules = [
+ {'ID': 'rule1', 'Filter': {'Prefix': 'foo'}, 'Status': 'Enabled', 'Expiration': {'ExpiredObjectDeleteMarker': 'true'}}
+ ]
+ body = generate_lifecycle_body(rules)
+ fp = StringIO(body)
+ md5 = boto.utils.compute_md5(fp)
+ headers = {'Content-MD5': md5[1], 'Content-Type': 'text/xml'}
+ res = bucket.connection.make_request('PUT', bucket.name, data=fp.getvalue(), query_args='lifecycle',
+ headers=headers)
+ eq(res.status, 200)
+ eq(res.reason, 'OK')
+
+@attr(resource='bucket')
+@attr(method='put')
+@attr(operation='set lifecycle config with empty Filter')
+@attr('lifecycle')
+def test_lifecycle_set_empty_filter():
+ bucket = get_new_bucket()
+ rules = [
+ {'ID': 'rule1', 'Filter': {}, 'Status': 'Enabled', 'Expiration': {'ExpiredObjectDeleteMarker': 'true'}}
+ ]
+ body = generate_lifecycle_body(rules)
+ fp = StringIO(body)
+ md5 = boto.utils.compute_md5(fp)
+ headers = {'Content-MD5': md5[1], 'Content-Type': 'text/xml'}
+ res = bucket.connection.make_request('PUT', bucket.name, data=fp.getvalue(), query_args='lifecycle',
+ headers=headers)
+ eq(res.status, 200)
+ eq(res.reason, 'OK')
+
+
+
# The test harnass for lifecycle is configured to treat days as 1 second intervals.
@attr(resource='bucket')