add more s3 functions
This commit is contained in:
parent
e20ae8e91c
commit
28a46a5a3a
@ -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()
|
||||||
|
@ -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>"asdlfkdalsjfsalfkjsadlfjsdjkk"</ETag>
|
<ETag>"asdlfkdalsjfsalfkjsadlfjsdjkk"</ETag>
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user