add s3 copy_key

This commit is contained in:
Steve Pulec 2013-02-19 23:29:46 -05:00
parent c3ae62e7a5
commit 4fa9cac7d6
4 changed files with 43 additions and 2 deletions

View File

@ -64,5 +64,9 @@ class S3Backend(BaseBackend):
bucket = self.buckets[bucket_name] bucket = self.buckets[bucket_name]
return bucket.keys.pop(key_name) return bucket.keys.pop(key_name)
def copy_key(self, src_bucket_name, src_key_name, dest_bucket_name, dest_key_name):
src_bucket = self.buckets[src_bucket_name]
dest_bucket = self.buckets[dest_bucket_name]
dest_bucket.keys[dest_key_name] = src_bucket.keys[src_key_name]
s3_backend = S3Backend() s3_backend = S3Backend()

View File

@ -1,7 +1,7 @@
from jinja2 import Template from jinja2 import Template
from .models import s3_backend from .models import s3_backend
from .utils import bucket_name_from_hostname from .utils import bucket_name_from_hostname, headers_to_dict
def all_buckets(uri, body, method): def all_buckets(uri, body, method):
@ -51,6 +51,7 @@ def key_response(uri_info, body, headers):
key_name = uri_info.path.lstrip('/') key_name = uri_info.path.lstrip('/')
hostname = uri_info.hostname hostname = uri_info.hostname
method = uri_info.method method = uri_info.method
headers = headers_to_dict(headers)
bucket_name = bucket_name_from_hostname(hostname) bucket_name = bucket_name_from_hostname(hostname)
@ -59,6 +60,11 @@ def key_response(uri_info, body, headers):
return key.value return key.value
if method == 'PUT': if method == 'PUT':
if 'x-amz-copy-source' in headers:
# Copy key
src_bucket, src_key = headers.get("x-amz-copy-source").split("/")
s3_backend.copy_key(src_bucket, src_key, bucket_name, key_name)
return S3_OBJECT_COPY_RESPONSE
if body: if body:
new_key = s3_backend.set_key(bucket_name, key_name, body) new_key = s3_backend.set_key(bucket_name, key_name, body)
return S3_OBJECT_RESPONSE, dict(etag=new_key.etag) return S3_OBJECT_RESPONSE, dict(etag=new_key.etag)
@ -147,4 +153,11 @@ S3_OBJECT_RESPONSE = """<PutObjectResponse xmlns="http://s3.amazonaws.com/doc/20
<ETag>&quot;asdlfkdalsjfsalfkjsadlfjsdjkk&quot;</ETag> <ETag>&quot;asdlfkdalsjfsalfkjsadlfjsdjkk&quot;</ETag>
<LastModified>2006-03-01T12:00:00.183Z</LastModified> <LastModified>2006-03-01T12:00:00.183Z</LastModified>
</PutObjectResponse> </PutObjectResponse>
</PutObjectResponse>""" </PutObjectResponse>"""
S3_OBJECT_COPY_RESPONSE = """<CopyObjectResponse xmlns="http://doc.s3.amazonaws.com/2006-03-01">
<CopyObjectResponse>
<ETag>"asdfadsfdsafjsadfdafsadf"</ETag>
<LastModified>2008-02-18T13:54:10.183Z</LastModified>
</CopyObjectResponse>
</CopyObjectResponse>"""

View File

@ -6,3 +6,13 @@ bucket_name_regex = re.compile("(.+).s3.amazonaws.com")
def bucket_name_from_hostname(hostname): def bucket_name_from_hostname(hostname):
bucket_result = bucket_name_regex.search(hostname) bucket_result = bucket_name_regex.search(hostname)
return bucket_result.groups()[0] return bucket_result.groups()[0]
def headers_to_dict(headers):
result = {}
for header in headers.split("\r\n"):
if ':' in header:
key, value = header.split(":", 1)
result[key.strip()] = value.strip()
return result

View File

@ -40,6 +40,20 @@ def test_missing_key():
bucket.get_key("the-key").should.equal(None) bucket.get_key("the-key").should.equal(None)
@mock_s3
def test_copy_key():
conn = boto.connect_s3('the_key', 'the_secret')
bucket = conn.create_bucket("foobar")
key = Key(bucket)
key.key = "the-key"
key.set_contents_from_string("some value")
bucket.copy_key('new-key', 'foobar', 'the-key')
bucket.get_key("the-key").get_contents_as_string().should.equal("some value")
bucket.get_key("new-key").get_contents_as_string().should.equal("some value")
@mock_s3 @mock_s3
def test_missing_bucket(): def test_missing_bucket():
conn = boto.connect_s3('the_key', 'the_secret') conn = boto.connect_s3('the_key', 'the_secret')