add more s3 functions

This commit is contained in:
Steve Pulec 2013-02-18 17:17:19 -05:00
parent e20ae8e91c
commit 28a46a5a3a
3 changed files with 89 additions and 13 deletions

View File

@ -19,7 +19,7 @@ class FakeKey(object):
class FakeBucket(object): class FakeBucket(object):
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
self.keys = [] self.keys = {}
class S3Backend(BaseBackend): class S3Backend(BaseBackend):
@ -36,22 +36,33 @@ class S3Backend(BaseBackend):
def get_bucket(self, bucket_name): def get_bucket(self, bucket_name):
return self.buckets.get(bucket_name) return self.buckets.get(bucket_name)
def delete_bucket(self, bucket_name):
bucket = self.buckets.get(bucket_name)
if bucket:
if bucket.keys:
# Can't delete a bucket with keys
return False
else:
return self.buckets.pop(bucket_name)
else:
# implement this
import pdb;pdb.set_trace()
def set_key(self, bucket_name, key_name, value): def set_key(self, bucket_name, key_name, value):
bucket = self.buckets[bucket_name] bucket = self.buckets[bucket_name]
new_key = FakeKey(name=key_name, value=value) new_key = FakeKey(name=key_name, value=value)
bucket.keys.append(new_key) bucket.keys[key_name] = new_key
return new_key return new_key
def get_key(self, bucket_name, key_name): def get_key(self, bucket_name, key_name):
bucket = self.buckets[bucket_name] bucket = self.buckets[bucket_name]
found_key = None return bucket.keys.get(key_name)
for key in bucket.keys:
if key.name == key_name:
found_key = key
break
return found_key def delete_key(self, bucket_name, key_name):
bucket = self.buckets[bucket_name]
return bucket.keys.pop(key_name)
s3_backend = S3Backend() s3_backend = S3Backend()

View File

@ -5,18 +5,31 @@ from .models import s3_backend
def bucket_response(uri, body, headers): def bucket_response(uri, body, headers):
hostname = uri.hostname hostname = uri.hostname
bucket_name = hostname.replace(".s3.amazonaws.com", "") bucket_name = hostname.replace(".s3.amazonaws.com", "")
method = uri.method
if uri.method == 'GET': if method == 'GET':
bucket = s3_backend.get_bucket(bucket_name) bucket = s3_backend.get_bucket(bucket_name)
if bucket: if bucket:
template = Template(S3_BUCKET_GET_RESPONSE) template = Template(S3_BUCKET_GET_RESPONSE)
return template.render(bucket=bucket) return template.render(bucket=bucket)
else: else:
return "", dict(status=404) return "", dict(status=404)
else: elif method == 'PUT':
new_bucket = s3_backend.create_bucket(bucket_name) new_bucket = s3_backend.create_bucket(bucket_name)
template = Template(S3_BUCKET_CREATE_RESPONSE) template = Template(S3_BUCKET_CREATE_RESPONSE)
return template.render(bucket=new_bucket) return template.render(bucket=new_bucket)
elif method == 'DELETE':
removed_bucket = s3_backend.delete_bucket(bucket_name)
if removed_bucket:
template = Template(S3_DELETE_BUCKET_SUCCESS)
return template.render(bucket=removed_bucket), dict(status=204)
else:
# Tried to delete a bucket that still has keys
template = Template(S3_DELETE_BUCKET_WITH_ITEMS_ERROR)
return template.render(bucket=removed_bucket), dict(status=409)
else:
import pdb;pdb.set_trace()
def key_response(uri_info, body, headers): def key_response(uri_info, body, headers):
@ -24,15 +37,16 @@ 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
bucket_name = hostname.replace(".s3.amazonaws.com", "") bucket_name = hostname.replace(".s3.amazonaws.com", "")
method = uri_info.method
if uri_info.method == 'GET': if method == 'GET':
key = s3_backend.get_key(bucket_name, key_name) key = s3_backend.get_key(bucket_name, key_name)
if key: if key:
return key.value return key.value
else: else:
return "", dict(status=404) return "", dict(status=404)
if uri_info.method == 'PUT': if method == 'PUT':
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)
@ -41,9 +55,13 @@ def key_response(uri_info, body, headers):
return "", dict(etag=key.etag) return "", dict(etag=key.etag)
else: else:
return "" return ""
elif uri_info.method == 'HEAD': elif method == 'HEAD':
key = s3_backend.get_key(bucket_name, key_name) key = s3_backend.get_key(bucket_name, key_name)
return S3_OBJECT_RESPONSE, dict(etag=key.etag) return S3_OBJECT_RESPONSE, dict(etag=key.etag)
elif method == 'DELETE':
removed_key = s3_backend.delete_key(bucket_name, key_name)
template = Template(S3_DELETE_OBJECT_SUCCESS)
return template.render(bucket=removed_key), dict(status=204)
else: else:
import pdb;pdb.set_trace() import pdb;pdb.set_trace()
@ -64,6 +82,28 @@ S3_BUCKET_CREATE_RESPONSE = """<CreateBucketResponse xmlns="http://s3.amazonaws.
</CreateBucketResponse> </CreateBucketResponse>
</CreateBucketResponse>""" </CreateBucketResponse>"""
S3_DELETE_BUCKET_SUCCESS = """<DeleteBucketResponse xmlns="http://s3.amazonaws.com/doc/2006-03-01">
<DeleteBucketResponse>
<Code>204</Code>
<Description>No Content</Description>
</DeleteBucketResponse>
</DeleteBucketResponse>"""
S3_DELETE_BUCKET_WITH_ITEMS_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>BucketNotEmpty</Code>
<Message>The bucket you tried to delete is not empty</Message>
<BucketName>{{ bucket.name }}</BucketName>
<RequestId>asdfasdfsdafds</RequestId>
<HostId>sdfgdsfgdsfgdfsdsfgdfs</HostId>
</Error>"""
S3_DELETE_OBJECT_SUCCESS = """<DeleteObjectResponse xmlns="http://s3.amazonaws.com/doc/2006-03-01">
<DeleteObjectResponse>
<Code>200</Code>
<Description>OK</Description>
</DeleteObjectResponse>
</DeleteObjectResponse>"""
S3_OBJECT_RESPONSE = """<PutObjectResponse xmlns="http://s3.amazonaws.com/doc/2006-03-01"> S3_OBJECT_RESPONSE = """<PutObjectResponse xmlns="http://s3.amazonaws.com/doc/2006-03-01">
<PutObjectResponse> <PutObjectResponse>
<ETag>&quot;asdlfkdalsjfsalfkjsadlfjsdjkk&quot;</ETag> <ETag>&quot;asdlfkdalsjfsalfkjsadlfjsdjkk&quot;</ETag>

View File

@ -1,6 +1,9 @@
import boto import boto
from boto.exception import S3ResponseError
from boto.s3.key import Key from boto.s3.key import Key
import sure
from moto import mock_s3 from moto import mock_s3
@ -28,3 +31,25 @@ def test_my_model_save():
model_instance.save() model_instance.save()
assert conn.get_bucket('mybucket').get_key('steve').get_contents_as_string() == 'is awesome' assert conn.get_bucket('mybucket').get_key('steve').get_contents_as_string() == 'is awesome'
@mock_s3
def test_missing_bucket():
conn = boto.connect_s3('the_key', 'the_secret')
conn.get_bucket.when.called_with('mybucket').should.throw(S3ResponseError)
@mock_s3
def test_bucket_deletion():
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")
conn.delete_bucket.when.called_with("foobar").should.throw(S3ResponseError)
bucket.delete_key("the-key")
conn.delete_bucket("foobar")
conn.get_bucket.when.called_with("foobar").should.throw(S3ResponseError)