HEAD on account returns 410 if account was deleted and not yet reaped

* updated CONTRIBUTING.md
 * improved unit tests
 * 100% coverage for proxy acct controller tests
 * invoke fake_http_connect correctly

Change-Id: I0826c5a1c52efdd5ae95f7fde8024f2bff0751ba
This commit is contained in:
Jon Snitow 2013-10-28 17:28:57 -07:00
parent 4bfe6748fd
commit 97b5f59ea4
3 changed files with 61 additions and 8 deletions

View File

@ -6,7 +6,24 @@ Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following should be submitted for review via the Gerrit tool, following
the workflow documented at [http://wiki.openstack.org/GerritWorkflow](http://wiki.openstack.org/GerritWorkflow). the workflow documented at [http://wiki.openstack.org/GerritWorkflow](http://wiki.openstack.org/GerritWorkflow).
Pull requests submitted through GitHub will be ignored. Gerrit is the review system used in the OpenStack projects. We're sorry, but
we won't be able to respond to pull requests submitted through GitHub.
Bugs should be filed [on Launchpad](https://bugs.launchpad.net/swift), Bugs should be filed [on Launchpad](https://bugs.launchpad.net/swift),
not in GitHub's issue tracker. not in GitHub's issue tracker.
Recommended workflow
====================
* Set up a [Swift All-In-One VM](http://docs.openstack.org/developer/swift/development_saio.html).
* Make your changes.
* Run unit tests, functional tests, probe tests
``./.unittests``
``./.functests``
``./.probetests``
* Run ``tox`` (no command-line args needed)
* ``git review``

View File

@ -31,7 +31,7 @@ from swift.account.utils import account_listing_response
from swift.common.request_helpers import get_listing_content_type from swift.common.request_helpers import get_listing_content_type
from swift.common.utils import public from swift.common.utils import public
from swift.common.constraints import check_metadata, MAX_ACCOUNT_NAME_LENGTH from swift.common.constraints import check_metadata, MAX_ACCOUNT_NAME_LENGTH
from swift.common.http import HTTP_NOT_FOUND from swift.common.http import HTTP_NOT_FOUND, HTTP_GONE
from swift.proxy.controllers.base import Controller, clear_info_cache from swift.proxy.controllers.base import Controller, clear_info_cache
from swift.common.swob import HTTPBadRequest, HTTPMethodNotAllowed from swift.common.swob import HTTPBadRequest, HTTPMethodNotAllowed
@ -59,7 +59,10 @@ class AccountController(Controller):
resp = self.GETorHEAD_base( resp = self.GETorHEAD_base(
req, _('Account'), self.app.account_ring, partition, req, _('Account'), self.app.account_ring, partition,
req.path_info.rstrip('/')) req.path_info.rstrip('/'))
if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate: if resp.status_int == HTTP_NOT_FOUND:
if resp.headers.get('X-Account-Status', '').lower() == 'deleted':
resp.status = HTTP_GONE
elif self.app.account_autocreate:
resp = account_listing_response(self.account_name, req, resp = account_listing_response(self.account_name, req,
get_listing_content_type(req)) get_listing_content_type(req))
if not req.environ.get('swift_owner', False): if not req.environ.get('swift_owner', False):

View File

@ -19,6 +19,7 @@ import unittest
from swift.common.swob import Request from swift.common.swob import Request
from swift.proxy import server as proxy_server from swift.proxy import server as proxy_server
from swift.proxy.controllers.base import headers_to_account_info from swift.proxy.controllers.base import headers_to_account_info
from swift.common.constraints import MAX_ACCOUNT_NAME_LENGTH as MAX_ANAME_LEN
from test.unit import fake_http_connect, FakeRing, FakeMemcache from test.unit import fake_http_connect, FakeRing, FakeMemcache
@ -32,7 +33,7 @@ class TestAccountController(unittest.TestCase):
def test_account_info_in_response_env(self): def test_account_info_in_response_env(self):
controller = proxy_server.AccountController(self.app, 'AUTH_bob') controller = proxy_server.AccountController(self.app, 'AUTH_bob')
with mock.patch('swift.proxy.controllers.base.http_connect', with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200, 200, body='')): fake_http_connect(200, body='')):
req = Request.blank('/AUTH_bob', {'PATH_INFO': '/AUTH_bob'}) req = Request.blank('/AUTH_bob', {'PATH_INFO': '/AUTH_bob'})
resp = controller.HEAD(req) resp = controller.HEAD(req)
self.assertEqual(2, resp.status_int // 100) self.assertEqual(2, resp.status_int // 100)
@ -48,7 +49,7 @@ class TestAccountController(unittest.TestCase):
req = Request.blank('/a') req = Request.blank('/a')
with mock.patch('swift.proxy.controllers.base.http_connect', with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200, 200, headers=owner_headers)): fake_http_connect(200, headers=owner_headers)):
resp = controller.HEAD(req) resp = controller.HEAD(req)
self.assertEquals(2, resp.status_int // 100) self.assertEquals(2, resp.status_int // 100)
for key in owner_headers: for key in owner_headers:
@ -56,12 +57,44 @@ class TestAccountController(unittest.TestCase):
req = Request.blank('/a', environ={'swift_owner': True}) req = Request.blank('/a', environ={'swift_owner': True})
with mock.patch('swift.proxy.controllers.base.http_connect', with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200, 200, headers=owner_headers)): fake_http_connect(200, headers=owner_headers)):
resp = controller.HEAD(req) resp = controller.HEAD(req)
self.assertEquals(2, resp.status_int // 100) self.assertEquals(2, resp.status_int // 100)
for key in owner_headers: for key in owner_headers:
self.assertTrue(key in resp.headers) self.assertTrue(key in resp.headers)
def test_get_deleted_account(self):
resp_headers = {
'x-account-status': 'deleted',
}
controller = proxy_server.AccountController(self.app, 'a')
req = Request.blank('/a')
with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(404, headers=resp_headers)):
resp = controller.HEAD(req)
self.assertEquals(410, resp.status_int)
def test_long_acct_names(self):
long_acct_name = '%sLongAccountName' % ('Very' * (MAX_ANAME_LEN // 4))
controller = proxy_server.AccountController(self.app, long_acct_name)
req = Request.blank('/%s' % long_acct_name)
with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200)):
resp = controller.HEAD(req)
self.assertEquals(400, resp.status_int)
with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200)):
resp = controller.GET(req)
self.assertEquals(400, resp.status_int)
with mock.patch('swift.proxy.controllers.base.http_connect',
fake_http_connect(200)):
resp = controller.POST(req)
self.assertEquals(400, resp.status_int)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()