Added Filtering support for S3 lifecycle (#1535)
* Added Filtering support for S3 lifecycle Also added `ExpiredObjectDeleteMarker`. closes #1533 closes #1479 * Result set no longer contains "Prefix" if "Filter" is set.
This commit is contained in:
parent
0a4d2037df
commit
4184acc0d2
4 changed files with 253 additions and 7 deletions
|
|
@ -1,12 +1,16 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import boto
|
||||
import boto3
|
||||
from boto.exception import S3ResponseError
|
||||
from boto.s3.lifecycle import Lifecycle, Transition, Expiration, Rule
|
||||
|
||||
import sure # noqa
|
||||
from botocore.exceptions import ClientError
|
||||
from datetime import datetime
|
||||
from nose.tools import assert_raises
|
||||
|
||||
from moto import mock_s3_deprecated
|
||||
from moto import mock_s3_deprecated, mock_s3
|
||||
|
||||
|
||||
@mock_s3_deprecated
|
||||
|
|
@ -26,6 +30,167 @@ def test_lifecycle_create():
|
|||
list(lifecycle.transition).should.equal([])
|
||||
|
||||
|
||||
@mock_s3
|
||||
def test_lifecycle_with_filters():
|
||||
client = boto3.client("s3")
|
||||
client.create_bucket(Bucket="bucket")
|
||||
|
||||
# Create a lifecycle rule with a Filter (no tags):
|
||||
lfc = {
|
||||
"Rules": [
|
||||
{
|
||||
"Expiration": {
|
||||
"Days": 7
|
||||
},
|
||||
"ID": "wholebucket",
|
||||
"Filter": {
|
||||
"Prefix": ""
|
||||
},
|
||||
"Status": "Enabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert result["Rules"][0]["Filter"]["Prefix"] == ''
|
||||
assert not result["Rules"][0]["Filter"].get("And")
|
||||
assert not result["Rules"][0]["Filter"].get("Tag")
|
||||
with assert_raises(KeyError):
|
||||
assert result["Rules"][0]["Prefix"]
|
||||
|
||||
# With a tag:
|
||||
lfc["Rules"][0]["Filter"]["Tag"] = {
|
||||
"Key": "mytag",
|
||||
"Value": "mytagvalue"
|
||||
}
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert result["Rules"][0]["Filter"]["Prefix"] == ''
|
||||
assert not result["Rules"][0]["Filter"].get("And")
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Value"] == "mytagvalue"
|
||||
with assert_raises(KeyError):
|
||||
assert result["Rules"][0]["Prefix"]
|
||||
|
||||
# With And (single tag):
|
||||
lfc["Rules"][0]["Filter"]["And"] = {
|
||||
"Prefix": "some/prefix",
|
||||
"Tags": [
|
||||
{
|
||||
"Key": "mytag",
|
||||
"Value": "mytagvalue"
|
||||
}
|
||||
]
|
||||
}
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert result["Rules"][0]["Filter"]["Prefix"] == ""
|
||||
assert result["Rules"][0]["Filter"]["And"]["Prefix"] == "some/prefix"
|
||||
assert len(result["Rules"][0]["Filter"]["And"]["Tags"]) == 1
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Value"] == "mytagvalue"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Value"] == "mytagvalue"
|
||||
with assert_raises(KeyError):
|
||||
assert result["Rules"][0]["Prefix"]
|
||||
|
||||
# With multiple And tags:
|
||||
lfc["Rules"][0]["Filter"]["And"] = {
|
||||
"Prefix": "some/prefix",
|
||||
"Tags": [
|
||||
{
|
||||
"Key": "mytag",
|
||||
"Value": "mytagvalue"
|
||||
},
|
||||
{
|
||||
"Key": "mytag2",
|
||||
"Value": "mytagvalue2"
|
||||
}
|
||||
]
|
||||
}
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert result["Rules"][0]["Filter"]["Prefix"] == ""
|
||||
assert result["Rules"][0]["Filter"]["And"]["Prefix"] == "some/prefix"
|
||||
assert len(result["Rules"][0]["Filter"]["And"]["Tags"]) == 2
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][0]["Value"] == "mytagvalue"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Value"] == "mytagvalue"
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Key"] == "mytag2"
|
||||
assert result["Rules"][0]["Filter"]["And"]["Tags"][1]["Value"] == "mytagvalue2"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Key"] == "mytag"
|
||||
assert result["Rules"][0]["Filter"]["Tag"]["Value"] == "mytagvalue"
|
||||
with assert_raises(KeyError):
|
||||
assert result["Rules"][0]["Prefix"]
|
||||
|
||||
# Can't have both filter and prefix:
|
||||
lfc["Rules"][0]["Prefix"] = ''
|
||||
with assert_raises(ClientError) as err:
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
assert err.exception.response["Error"]["Code"] == "MalformedXML"
|
||||
|
||||
lfc["Rules"][0]["Prefix"] = 'some/path'
|
||||
with assert_raises(ClientError) as err:
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
assert err.exception.response["Error"]["Code"] == "MalformedXML"
|
||||
|
||||
# No filters -- just a prefix:
|
||||
del lfc["Rules"][0]["Filter"]
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert not result["Rules"][0].get("Filter")
|
||||
assert result["Rules"][0]["Prefix"] == "some/path"
|
||||
|
||||
|
||||
@mock_s3
|
||||
def test_lifecycle_with_eodm():
|
||||
client = boto3.client("s3")
|
||||
client.create_bucket(Bucket="bucket")
|
||||
|
||||
lfc = {
|
||||
"Rules": [
|
||||
{
|
||||
"Expiration": {
|
||||
"ExpiredObjectDeleteMarker": True
|
||||
},
|
||||
"ID": "wholebucket",
|
||||
"Filter": {
|
||||
"Prefix": ""
|
||||
},
|
||||
"Status": "Enabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert result["Rules"][0]["Expiration"]["ExpiredObjectDeleteMarker"]
|
||||
|
||||
# Set to False:
|
||||
lfc["Rules"][0]["Expiration"]["ExpiredObjectDeleteMarker"] = False
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
result = client.get_bucket_lifecycle_configuration(Bucket="bucket")
|
||||
assert len(result["Rules"]) == 1
|
||||
assert not result["Rules"][0]["Expiration"]["ExpiredObjectDeleteMarker"]
|
||||
|
||||
# With failure:
|
||||
lfc["Rules"][0]["Expiration"]["Days"] = 7
|
||||
with assert_raises(ClientError) as err:
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
assert err.exception.response["Error"]["Code"] == "MalformedXML"
|
||||
del lfc["Rules"][0]["Expiration"]["Days"]
|
||||
|
||||
lfc["Rules"][0]["Expiration"]["Date"] = datetime(2015, 1, 1)
|
||||
with assert_raises(ClientError) as err:
|
||||
client.put_bucket_lifecycle_configuration(Bucket="bucket", LifecycleConfiguration=lfc)
|
||||
assert err.exception.response["Error"]["Code"] == "MalformedXML"
|
||||
|
||||
|
||||
@mock_s3_deprecated
|
||||
def test_lifecycle_with_glacier_transition():
|
||||
conn = boto.s3.connect_to_region("us-west-1")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue