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
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),
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.utils import public
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.common.swob import HTTPBadRequest, HTTPMethodNotAllowed
@ -59,9 +59,12 @@ class AccountController(Controller):
resp = self.GETorHEAD_base(
req, _('Account'), self.app.account_ring, partition,
req.path_info.rstrip('/'))
if resp.status_int == HTTP_NOT_FOUND and self.app.account_autocreate:
resp = account_listing_response(self.account_name, req,
get_listing_content_type(req))
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,
get_listing_content_type(req))
if not req.environ.get('swift_owner', False):
for key in self.app.swift_owner_headers:
if key in resp.headers:

View File

@ -19,6 +19,7 @@ import unittest
from swift.common.swob import Request
from swift.proxy import server as proxy_server
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
@ -32,7 +33,7 @@ class TestAccountController(unittest.TestCase):
def test_account_info_in_response_env(self):
controller = proxy_server.AccountController(self.app, 'AUTH_bob')
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'})
resp = controller.HEAD(req)
self.assertEqual(2, resp.status_int // 100)
@ -48,7 +49,7 @@ class TestAccountController(unittest.TestCase):
req = Request.blank('/a')
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)
self.assertEquals(2, resp.status_int // 100)
for key in owner_headers:
@ -56,12 +57,44 @@ class TestAccountController(unittest.TestCase):
req = Request.blank('/a', environ={'swift_owner': True})
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)
self.assertEquals(2, resp.status_int // 100)
for key in owner_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__':
unittest.main()