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:
parent
4bfe6748fd
commit
97b5f59ea4
@ -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``
|
||||||
|
@ -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,9 +59,12 @@ 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:
|
||||||
resp = account_listing_response(self.account_name, req,
|
if resp.headers.get('X-Account-Status', '').lower() == 'deleted':
|
||||||
get_listing_content_type(req))
|
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):
|
if not req.environ.get('swift_owner', False):
|
||||||
for key in self.app.swift_owner_headers:
|
for key in self.app.swift_owner_headers:
|
||||||
if key in resp.headers:
|
if key in resp.headers:
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user