From 60cd79c6e2006da56c35a98ee1dfea5dc23d101b Mon Sep 17 00:00:00 2001 From: Steve Pulec Date: Sun, 16 Mar 2014 21:25:14 -0400 Subject: [PATCH] S3 Mock should return an HTTP 409 if trying to create a bucket that already exists. Closes #94. --- moto/s3/exceptions.py | 2 ++ moto/s3/models.py | 7 +++++-- moto/s3/responses.py | 8 ++++++-- tests/test_s3/test_s3.py | 10 +++++++++- tests/test_s3/test_server.py | 16 ++++++++-------- .../test_bucket_path_server.py | 6 +++--- 6 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 moto/s3/exceptions.py diff --git a/moto/s3/exceptions.py b/moto/s3/exceptions.py new file mode 100644 index 000000000..ba7b09429 --- /dev/null +++ b/moto/s3/exceptions.py @@ -0,0 +1,2 @@ +class BucketAlreadyExists(Exception): + pass diff --git a/moto/s3/models.py b/moto/s3/models.py index e59558864..e6f6af9d9 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -5,10 +5,11 @@ import hashlib from moto.core import BaseBackend from moto.core.utils import iso_8601_datetime, rfc_1123_datetime +from .exceptions import BucketAlreadyExists from .utils import clean_key_name -UPLOAD_ID_BYTES=43 -UPLOAD_PART_MIN_SIZE=5242880 +UPLOAD_ID_BYTES = 43 +UPLOAD_PART_MIN_SIZE = 5242880 class FakeKey(object): @@ -107,6 +108,8 @@ class S3Backend(BaseBackend): self.buckets = {} def create_bucket(self, bucket_name): + if bucket_name in self.buckets: + raise BucketAlreadyExists() new_bucket = FakeBucket(name=bucket_name) self.buckets[bucket_name] = new_bucket return new_bucket diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 83b53cb99..127d61faa 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -3,6 +3,7 @@ import re from jinja2 import Template +from .exceptions import BucketAlreadyExists from .models import s3_backend from .utils import bucket_name_from_url @@ -66,7 +67,10 @@ class ResponseObject(object): else: return 404, headers, "" elif method == 'PUT': - new_bucket = self.backend.create_bucket(bucket_name) + try: + new_bucket = self.backend.create_bucket(bucket_name) + except BucketAlreadyExists: + return 409, headers, "" template = Template(S3_BUCKET_CREATE_RESPONSE) return template.render(bucket=new_bucket) elif method == 'DELETE': @@ -148,7 +152,7 @@ class ResponseObject(object): upload_id=upload_id, count=len(parts), parts=parts - ) + ) key = self.backend.get_key(bucket_name, key_name) if key: headers.update(key.metadata) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 3d9e3f1fb..66866335a 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -2,7 +2,7 @@ import urllib2 from io import BytesIO import boto -from boto.exception import S3ResponseError +from boto.exception import S3CreateError, S3ResponseError from boto.s3.key import Key from freezegun import freeze_time import requests @@ -171,6 +171,14 @@ def test_bucket_with_dash(): conn.get_bucket.when.called_with('mybucket-test').should.throw(S3ResponseError) +@mock_s3 +def test_create_existing_bucket(): + "Trying to create a bucket that already exists should raise an Error" + conn = boto.connect_s3('the_key', 'the_secret') + conn.create_bucket("foobar") + conn.create_bucket.when.called_with('foobar').should.throw(S3CreateError) + + @mock_s3 def test_bucket_deletion(): conn = boto.connect_s3('the_key', 'the_secret') diff --git a/tests/test_s3/test_server.py b/tests/test_s3/test_server.py index ee1429819..18e123940 100644 --- a/tests/test_s3/test_server.py +++ b/tests/test_s3/test_server.py @@ -20,20 +20,20 @@ def test_s3_server_bucket_create(): backend = server.create_backend_app("s3") test_client = backend.test_client() - res = test_client.put('/', 'http://foobar.localhost:5000/') + res = test_client.put('/', 'http://foobaz.localhost:5000/') res.status_code.should.equal(200) res = test_client.get('/') - res.data.should.contain('foobar') + res.data.should.contain('foobaz') - res = test_client.get('/', 'http://foobar.localhost:5000/') + res = test_client.get('/', 'http://foobaz.localhost:5000/') res.status_code.should.equal(200) res.data.should.contain("ListBucketResult") - res = test_client.put('/bar', 'http://foobar.localhost:5000/', data='test value') + res = test_client.put('/bar', 'http://foobaz.localhost:5000/', data='test value') res.status_code.should.equal(200) - res = test_client.get('/bar', 'http://foobar.localhost:5000/') + res = test_client.get('/bar', 'http://foobaz.localhost:5000/') res.status_code.should.equal(200) res.data.should.equal("test value") @@ -42,14 +42,14 @@ def test_s3_server_post_to_bucket(): backend = server.create_backend_app("s3") test_client = backend.test_client() - res = test_client.put('/', 'http://foobar.localhost:5000/') + res = test_client.put('/', 'http://tester.localhost:5000/') res.status_code.should.equal(200) - test_client.post('/', "https://foobar.localhost:5000/", data={ + test_client.post('/', "https://tester.localhost:5000/", data={ 'key': 'the-key', 'file': 'nothing' }) - res = test_client.get('/the-key', 'http://foobar.localhost:5000/') + res = test_client.get('/the-key', 'http://tester.localhost:5000/') res.status_code.should.equal(200) res.data.should.equal("nothing") diff --git a/tests/test_s3bucket_path/test_bucket_path_server.py b/tests/test_s3bucket_path/test_bucket_path_server.py index b8eea77e1..aa2369491 100644 --- a/tests/test_s3bucket_path/test_bucket_path_server.py +++ b/tests/test_s3bucket_path/test_bucket_path_server.py @@ -42,14 +42,14 @@ def test_s3_server_post_to_bucket(): backend = server.create_backend_app("s3bucket_path") test_client = backend.test_client() - res = test_client.put('/foobar', 'http://localhost:5000/') + res = test_client.put('/foobar2', 'http://localhost:5000/') res.status_code.should.equal(200) - test_client.post('/foobar', "https://localhost:5000/", data={ + test_client.post('/foobar2', "https://localhost:5000/", data={ 'key': 'the-key', 'file': 'nothing' }) - res = test_client.get('/foobar/the-key', 'http://localhost:5000/') + res = test_client.get('/foobar2/the-key', 'http://localhost:5000/') res.status_code.should.equal(200) res.data.should.equal("nothing")