Remove all post_as_copy related code and configes
It was deprecated and we discussed on this topic in Denver PTG for Queen cycle. Main motivation for this work is that deprecated post_as_copy option and its gate blocks future symlink work. Change-Id: I411893db1565864ed5beb6ae75c38b982a574476
This commit is contained in:
parent
834b733d29
commit
1e79f828ad
@ -996,8 +996,6 @@ Error count to consider a node error limited. The default is 10.
|
||||
Whether account PUTs and DELETEs are even callable. If set to 'true' any authorized
|
||||
user may create and delete accounts; if 'false' no one, even authorized, can. The default
|
||||
is false.
|
||||
.IP \fBobject_post_as_copy\fR
|
||||
Deprecated. The default is False.
|
||||
.IP \fBaccount_autocreate\fR
|
||||
If set to 'true' authorized accounts that do not yet exist within the Swift cluster
|
||||
will be automatically created. The default is set to false.
|
||||
|
@ -1884,7 +1884,6 @@ error_suppression_limit 10 Error count to consider
|
||||
node error limited
|
||||
allow_account_management false Whether account PUTs and DELETEs
|
||||
are even callable
|
||||
object_post_as_copy false Deprecated.
|
||||
account_autocreate false If set to 'true' authorized
|
||||
accounts that do not yet exist
|
||||
within the Swift cluster will
|
||||
|
@ -127,9 +127,6 @@ set using environment variables:
|
||||
environment variable ``SWIFT_TEST_IN_PROCESS_CONF_LOADER`` to
|
||||
``ec``.
|
||||
|
||||
- the deprecated proxy-server ``object_post_as_copy`` option may be set using
|
||||
the environment variable ``SWIFT_TEST_IN_PROCESS_OBJECT_POST_AS_COPY``.
|
||||
|
||||
- logging to stdout may be enabled by setting ``SWIFT_TEST_DEBUG_LOGS``.
|
||||
|
||||
For example, this command would run the in-process mode functional tests with
|
||||
@ -147,7 +144,6 @@ The ``tox.ini`` file also specifies test environments for running other
|
||||
in-process functional test configurations, e.g.::
|
||||
|
||||
tox -e func-ec
|
||||
tox -e func-post-as-copy
|
||||
|
||||
To debug the functional tests, use the 'in-process test' mode and pass the
|
||||
``--pdb`` flag to ``tox``::
|
||||
|
@ -860,8 +860,6 @@ use = egg:swift#copy
|
||||
# requests are transformed into COPY requests where source and destination are
|
||||
# the same. All client-visible behavior (save response time) should be
|
||||
# identical.
|
||||
# This option is deprecated and will be ignored in a future release.
|
||||
# object_post_as_copy = false
|
||||
|
||||
# Note: To enable encryption, add the following 2 dependent pieces of crypto
|
||||
# middleware to the proxy-server pipeline. They should be to the right of all
|
||||
|
@ -112,20 +112,6 @@ If a request is sent without the query parameter, an attempt will be made to
|
||||
copy the whole object but will fail if the object size is
|
||||
greater than 5GB.
|
||||
|
||||
-------------------
|
||||
Object Post as Copy
|
||||
-------------------
|
||||
Historically, this has been a feature (and a configurable option with default
|
||||
set to True) in proxy server configuration. This has been moved to server side
|
||||
copy middleware and the default changed to False.
|
||||
|
||||
When ``object_post_as_copy`` is set to ``true``, an incoming POST request is
|
||||
morphed into a COPY request where source and destination objects are same.
|
||||
|
||||
This feature was necessary because of a previous behavior where POSTS would
|
||||
update the metadata on the object but not on the container. As a result,
|
||||
features like container sync would not work correctly. This is no longer the
|
||||
case and this option is now deprecated. It will be removed in a future release.
|
||||
"""
|
||||
|
||||
import os
|
||||
@ -137,8 +123,7 @@ from swift.common.utils import get_logger, \
|
||||
config_true_value, FileLikeIter, read_conf_dir, close_if_possible
|
||||
from swift.common.swob import Request, HTTPPreconditionFailed, \
|
||||
HTTPRequestEntityTooLarge, HTTPBadRequest, HTTPException
|
||||
from swift.common.http import HTTP_MULTIPLE_CHOICES, HTTP_CREATED, \
|
||||
is_success, HTTP_OK
|
||||
from swift.common.http import HTTP_MULTIPLE_CHOICES, is_success, HTTP_OK
|
||||
from swift.common.constraints import check_account_format, MAX_FILE_SIZE
|
||||
from swift.common.request_helpers import copy_header_subset, remove_items, \
|
||||
is_sys_meta, is_sys_or_user_meta, is_object_transient_sysmeta
|
||||
@ -238,13 +223,7 @@ class ServerSideCopyWebContext(WSGIContext):
|
||||
return app_resp
|
||||
|
||||
def _adjust_put_response(self, req, additional_resp_headers):
|
||||
if 'swift.post_as_copy' in req.environ:
|
||||
# Older editions returned 202 Accepted on object POSTs, so we'll
|
||||
# convert any 201 Created responses to that for compatibility with
|
||||
# picky clients.
|
||||
if self._get_status_int() == HTTP_CREATED:
|
||||
self._response_status = '202 Accepted'
|
||||
elif is_success(self._get_status_int()):
|
||||
if is_success(self._get_status_int()):
|
||||
for header, value in additional_resp_headers.items():
|
||||
self._response_headers.append((header, value))
|
||||
|
||||
@ -269,17 +248,12 @@ class ServerSideCopyMiddleware(object):
|
||||
def __init__(self, app, conf):
|
||||
self.app = app
|
||||
self.logger = get_logger(conf, log_route="copy")
|
||||
# Read the old object_post_as_copy option from Proxy app just in case
|
||||
# someone has set it to false (non default). This wouldn't cause
|
||||
# problems during upgrade.
|
||||
self._load_object_post_as_copy_conf(conf)
|
||||
self.object_post_as_copy = \
|
||||
config_true_value(conf.get('object_post_as_copy', 'false'))
|
||||
if self.object_post_as_copy:
|
||||
msg = ('object_post_as_copy=true is deprecated; remove all '
|
||||
'references to it from %s to disable this warning. This '
|
||||
'option will be ignored in a future release' % conf.get(
|
||||
'__file__', 'proxy-server.conf'))
|
||||
msg = ('object_post_as_copy=true is deprecated; This '
|
||||
'option is now ignored')
|
||||
self.logger.warning(msg)
|
||||
|
||||
def _load_object_post_as_copy_conf(self, conf):
|
||||
@ -330,9 +304,6 @@ class ServerSideCopyMiddleware(object):
|
||||
elif req.method == 'COPY':
|
||||
req.environ['swift.orig_req_method'] = req.method
|
||||
return self.handle_COPY(req, start_response)
|
||||
elif req.method == 'POST' and self.object_post_as_copy:
|
||||
req.environ['swift.orig_req_method'] = req.method
|
||||
return self.handle_object_post_as_copy(req, start_response)
|
||||
elif req.method == 'OPTIONS':
|
||||
# Does not interfere with OPTIONS response from
|
||||
# (account,container) servers and /info response.
|
||||
@ -343,21 +314,6 @@ class ServerSideCopyMiddleware(object):
|
||||
|
||||
return self.app(env, start_response)
|
||||
|
||||
def handle_object_post_as_copy(self, req, start_response):
|
||||
req.method = 'PUT'
|
||||
req.path_info = '/v1/%s/%s/%s' % (
|
||||
self.account_name, self.container_name, self.object_name)
|
||||
req.headers['Content-Length'] = 0
|
||||
req.headers.pop('Range', None)
|
||||
req.headers['X-Copy-From'] = quote('/%s/%s' % (self.container_name,
|
||||
self.object_name))
|
||||
req.environ['swift.post_as_copy'] = True
|
||||
params = req.params
|
||||
# for post-as-copy always copy the manifest itself if source is *LO
|
||||
params['multipart-manifest'] = 'get'
|
||||
req.params = params
|
||||
return self.handle_PUT(req, start_response)
|
||||
|
||||
def handle_COPY(self, req, start_response):
|
||||
if not req.headers.get('Destination'):
|
||||
return HTTPPreconditionFailed(request=req,
|
||||
@ -394,11 +350,6 @@ class ServerSideCopyMiddleware(object):
|
||||
source_req.headers.pop('X-Backend-Storage-Policy-Index', None)
|
||||
source_req.path_info = quote(source_path)
|
||||
source_req.headers['X-Newest'] = 'true'
|
||||
if 'swift.post_as_copy' in req.environ:
|
||||
# We're COPYing one object over itself because of a POST; rely on
|
||||
# the PUT for write authorization, don't require read authorization
|
||||
source_req.environ['swift.authorize'] = lambda req: None
|
||||
source_req.environ['swift.authorize_override'] = True
|
||||
|
||||
# in case we are copying an SLO manifest, set format=raw parameter
|
||||
params = source_req.params
|
||||
@ -470,11 +421,7 @@ class ServerSideCopyMiddleware(object):
|
||||
def is_object_sysmeta(k):
|
||||
return is_sys_meta('object', k)
|
||||
|
||||
if 'swift.post_as_copy' in sink_req.environ:
|
||||
# Post-as-copy: ignore new sysmeta, copy existing sysmeta
|
||||
remove_items(sink_req.headers, is_object_sysmeta)
|
||||
copy_header_subset(source_resp, sink_req, is_object_sysmeta)
|
||||
elif config_true_value(req.headers.get('x-fresh-metadata', 'false')):
|
||||
if config_true_value(req.headers.get('x-fresh-metadata', 'false')):
|
||||
# x-fresh-metadata only applies to copy, not post-as-copy: ignore
|
||||
# existing user metadata, update existing sysmeta with new
|
||||
copy_header_subset(source_resp, sink_req, is_object_sysmeta)
|
||||
@ -497,9 +444,8 @@ class ServerSideCopyMiddleware(object):
|
||||
params['multipart-manifest'] = 'put'
|
||||
if 'X-Object-Manifest' in source_resp.headers:
|
||||
del params['multipart-manifest']
|
||||
if 'swift.post_as_copy' not in sink_req.environ:
|
||||
sink_req.headers['X-Object-Manifest'] = \
|
||||
source_resp.headers['X-Object-Manifest']
|
||||
sink_req.headers['X-Object-Manifest'] = \
|
||||
source_resp.headers['X-Object-Manifest']
|
||||
sink_req.params = params
|
||||
|
||||
# Set swift.source, data source, content length and etag
|
||||
|
@ -826,8 +826,7 @@ class VersionedWritesMiddleware(object):
|
||||
allow_versioned_writes)
|
||||
except HTTPException as error_response:
|
||||
return error_response(env, start_response)
|
||||
elif (obj and req.method in ('PUT', 'DELETE') and
|
||||
not req.environ.get('swift.post_as_copy')):
|
||||
elif (obj and req.method in ('PUT', 'DELETE')):
|
||||
try:
|
||||
return self.object_request(
|
||||
req, api_version, account, container, obj,
|
||||
|
@ -505,15 +505,6 @@ def in_process_setup(the_object_server=object_server):
|
||||
'password6': 'testing6'
|
||||
})
|
||||
|
||||
# If an env var explicitly specifies the proxy-server object_post_as_copy
|
||||
# option then use its value, otherwise leave default config unchanged.
|
||||
object_post_as_copy = os.environ.get(
|
||||
'SWIFT_TEST_IN_PROCESS_OBJECT_POST_AS_COPY')
|
||||
if object_post_as_copy is not None:
|
||||
object_post_as_copy = config_true_value(object_post_as_copy)
|
||||
config['object_post_as_copy'] = str(object_post_as_copy)
|
||||
_debug('Setting object_post_as_copy to %r' % object_post_as_copy)
|
||||
|
||||
acc1lis = listen_zero()
|
||||
acc2lis = listen_zero()
|
||||
con1lis = listen_zero()
|
||||
|
@ -448,7 +448,7 @@ class ProbeTest(unittest.TestCase):
|
||||
else:
|
||||
os.system('sudo mount %s' % device)
|
||||
|
||||
def make_internal_client(self, object_post_as_copy=True):
|
||||
def make_internal_client(self):
|
||||
tempdir = mkdtemp()
|
||||
try:
|
||||
conf_path = os.path.join(tempdir, 'internal_client.conf')
|
||||
@ -464,14 +464,13 @@ class ProbeTest(unittest.TestCase):
|
||||
|
||||
[filter:copy]
|
||||
use = egg:swift#copy
|
||||
object_post_as_copy = %s
|
||||
|
||||
[filter:cache]
|
||||
use = egg:swift#memcache
|
||||
|
||||
[filter:catch_errors]
|
||||
use = egg:swift#catch_errors
|
||||
""" % object_post_as_copy
|
||||
"""
|
||||
with open(conf_path, 'w') as f:
|
||||
f.write(dedent(conf_body))
|
||||
return internal_client.InternalClient(conf_path, 'test', 1)
|
||||
|
@ -93,7 +93,7 @@ class TestContainerSync(ReplProbeTest):
|
||||
|
||||
return source['name'], dest['name']
|
||||
|
||||
def _test_sync(self, object_post_as_copy):
|
||||
def test_sync(self):
|
||||
source_container, dest_container = self._setup_synced_containers()
|
||||
|
||||
# upload to source
|
||||
@ -111,12 +111,10 @@ class TestContainerSync(ReplProbeTest):
|
||||
self.assertIn('x-object-meta-test', resp_headers)
|
||||
self.assertEqual('put_value', resp_headers['x-object-meta-test'])
|
||||
|
||||
# update metadata with a POST, using an internal client so we can
|
||||
# vary the object_post_as_copy setting - first use post-as-copy
|
||||
# update metadata with a POST
|
||||
post_headers = {'Content-Type': 'image/jpeg',
|
||||
'X-Object-Meta-Test': 'post_value'}
|
||||
int_client = self.make_internal_client(
|
||||
object_post_as_copy=object_post_as_copy)
|
||||
int_client = self.make_internal_client()
|
||||
int_client.set_object_metadata(self.account, source_container,
|
||||
object_name, post_headers)
|
||||
# sanity checks...
|
||||
@ -154,12 +152,6 @@ class TestContainerSync(ReplProbeTest):
|
||||
self.url, self.token, dest_container, object_name)
|
||||
self.assertEqual(404, cm.exception.http_status) # sanity check
|
||||
|
||||
def test_sync_with_post_as_copy(self):
|
||||
self._test_sync(True)
|
||||
|
||||
def test_sync_with_fast_post(self):
|
||||
self._test_sync(False)
|
||||
|
||||
def test_sync_slo_manifest(self):
|
||||
# Verify that SLO manifests are sync'd even if their segments can not
|
||||
# be found in the destination account at time of sync'ing.
|
||||
|
@ -237,8 +237,7 @@ class TestUpdateOverridesEC(ECProbeTest):
|
||||
self.assertFalse(direct_client.direct_get_container(
|
||||
cnodes[0], cpart, self.account, 'c1')[1])
|
||||
|
||||
# use internal client for POST so we can force fast-post mode
|
||||
int_client = self.make_internal_client(object_post_as_copy=False)
|
||||
int_client = self.make_internal_client()
|
||||
int_client.set_object_metadata(
|
||||
self.account, 'c1', 'o1', {'X-Object-Meta-Fruit': 'Tomato'})
|
||||
self.assertEqual(
|
||||
@ -296,8 +295,7 @@ class TestUpdateOverridesEC(ECProbeTest):
|
||||
content_type='test/ctype')
|
||||
meta = client.head_object(self.url, self.token, 'c1', 'o1')
|
||||
|
||||
# use internal client for POST so we can force fast-post mode
|
||||
int_client = self.make_internal_client(object_post_as_copy=False)
|
||||
int_client = self.make_internal_client()
|
||||
int_client.set_object_metadata(
|
||||
self.account, 'c1', 'o1', {'X-Object-Meta-Fruit': 'Tomato'})
|
||||
self.assertEqual(
|
||||
|
@ -47,7 +47,7 @@ class Test(ReplProbeTest):
|
||||
policy=self.policy)
|
||||
self.container_brain = BrainSplitter(self.url, self.token,
|
||||
self.container_name)
|
||||
self.int_client = self.make_internal_client(object_post_as_copy=False)
|
||||
self.int_client = self.make_internal_client()
|
||||
|
||||
def _get_object_info(self, account, container, obj, number):
|
||||
obj_conf = self.configs['object-server']
|
||||
|
@ -618,14 +618,5 @@ class TestCryptoPipelineChanges(unittest.TestCase):
|
||||
self._check_listing(self.crypto_app)
|
||||
|
||||
|
||||
class TestCryptoPipelineChangesFastPost(TestCryptoPipelineChanges):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# set proxy config to use fast post
|
||||
extra_conf = {'object_post_as_copy': 'False'}
|
||||
cls._test_context = setup_servers(extra_conf=extra_conf)
|
||||
cls.proxy_app = cls._test_context["test_servers"][0]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -14,7 +14,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import time
|
||||
import mock
|
||||
import shutil
|
||||
import tempfile
|
||||
@ -93,9 +92,7 @@ class TestCopyConstraints(unittest.TestCase):
|
||||
class TestServerSideCopyMiddleware(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.app = FakeSwift()
|
||||
self.ssc = copy.filter_factory({
|
||||
'object_post_as_copy': 'yes',
|
||||
})(self.app)
|
||||
self.ssc = copy.filter_factory({})(self.app)
|
||||
self.ssc.logger = self.app.logger
|
||||
|
||||
def tearDown(self):
|
||||
@ -166,92 +163,6 @@ class TestServerSideCopyMiddleware(unittest.TestCase):
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
self.assertNotIn('swift.orig_req_method', req.environ)
|
||||
|
||||
def test_POST_as_COPY_simple(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPAccepted, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST')
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
# For basic test cases, assert orig_req_method behavior
|
||||
self.assertEqual(req.environ['swift.orig_req_method'], 'POST')
|
||||
|
||||
def test_POST_as_COPY_201_return_202(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPCreated, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST')
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_POST_delete_at(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPAccepted, {})
|
||||
t = str(int(time.time() + 100))
|
||||
req = Request.blank('/v1/a/c/o', method='POST',
|
||||
headers={'Content-Type': 'foo/bar',
|
||||
'X-Delete-At': t})
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
|
||||
calls = self.app.calls_with_headers
|
||||
method, path, req_headers = calls[1]
|
||||
self.assertEqual('PUT', method)
|
||||
self.assertTrue('X-Delete-At' in req_headers)
|
||||
self.assertEqual(req_headers['X-Delete-At'], str(t))
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_POST_as_COPY_static_large_object(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk,
|
||||
{'X-Static-Large-Object': True}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPAccepted, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST',
|
||||
headers={})
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
|
||||
calls = self.app.calls_with_headers
|
||||
method, path, req_headers = calls[1]
|
||||
self.assertEqual('PUT', method)
|
||||
self.assertNotIn('X-Static-Large-Object', req_headers)
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_POST_as_COPY_dynamic_large_object_manifest(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk,
|
||||
{'X-Object-Manifest': 'orig_manifest'}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPCreated, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST',
|
||||
headers={'X-Object-Manifest': 'new_manifest'})
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
|
||||
calls = self.app.calls_with_headers
|
||||
method, path, req_headers = calls[1]
|
||||
self.assertEqual('PUT', method)
|
||||
self.assertEqual('new_manifest', req_headers['x-object-manifest'])
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_POST_as_COPY_dynamic_large_object_no_manifest(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk,
|
||||
{'X-Object-Manifest': 'orig_manifest'}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPCreated, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST',
|
||||
headers={})
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
|
||||
calls = self.app.calls_with_headers
|
||||
method, path, req_headers = calls[1]
|
||||
self.assertEqual('PUT', method)
|
||||
self.assertNotIn('X-Object-Manifest', req_headers)
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_basic_put_with_x_copy_from(self):
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||
self.app.register('PUT', '/v1/a/c/o2', swob.HTTPCreated, {})
|
||||
@ -1345,100 +1256,6 @@ class TestServerSideCopyMiddleware(unittest.TestCase):
|
||||
req_headers.get('X-Object-Transient-Sysmeta-Test'))
|
||||
self.assertEqual('Not Bar', req_headers.get('X-Foo'))
|
||||
|
||||
def _test_POST_source_headers(self, extra_post_headers):
|
||||
# helper method to perform a POST with metadata headers that should
|
||||
# always be sent to the destination
|
||||
post_headers = {'X-Object-Meta-Test2': 'added',
|
||||
'X-Object-Sysmeta-Test2': 'added',
|
||||
'X-Object-Transient-Sysmeta-Test2': 'added'}
|
||||
post_headers.update(extra_post_headers)
|
||||
get_resp_headers = {
|
||||
'X-Timestamp': '1234567890.12345',
|
||||
'X-Backend-Timestamp': '1234567890.12345',
|
||||
'Content-Type': 'text/original',
|
||||
'Content-Encoding': 'gzip',
|
||||
'Content-Disposition': 'attachment; filename=myfile',
|
||||
'X-Object-Meta-Test': 'original',
|
||||
'X-Object-Sysmeta-Test': 'original',
|
||||
'X-Object-Transient-Sysmeta-Test': 'original',
|
||||
'X-Foo': 'Bar'}
|
||||
self.app.register(
|
||||
'GET', '/v1/a/c/o', swob.HTTPOk, headers=get_resp_headers)
|
||||
self.app.register('PUT', '/v1/a/c/o', swob.HTTPCreated, {})
|
||||
req = Request.blank('/v1/a/c/o', method='POST', headers=post_headers)
|
||||
status, headers, body = self.call_ssc(req)
|
||||
self.assertEqual(status, '202 Accepted')
|
||||
calls = self.app.calls_with_headers
|
||||
self.assertEqual(2, len(calls))
|
||||
method, path, req_headers = calls[1]
|
||||
self.assertEqual('PUT', method)
|
||||
# these headers should always be applied to the destination
|
||||
self.assertEqual('added', req_headers.get('X-Object-Meta-Test2'))
|
||||
self.assertEqual('added',
|
||||
req_headers.get('X-Object-Transient-Sysmeta-Test2'))
|
||||
# POSTed sysmeta should never be applied to the destination
|
||||
self.assertNotIn('X-Object-Sysmeta-Test2', req_headers)
|
||||
# existing sysmeta should always be preserved
|
||||
self.assertEqual('original',
|
||||
req_headers.get('X-Object-Sysmeta-Test'))
|
||||
return req_headers
|
||||
|
||||
def test_POST_no_updates(self):
|
||||
post_headers = {}
|
||||
req_headers = self._test_POST_source_headers(post_headers)
|
||||
self.assertEqual('text/original', req_headers.get('Content-Type'))
|
||||
self.assertNotIn('X-Object-Meta-Test', req_headers)
|
||||
self.assertNotIn('X-Object-Transient-Sysmeta-Test', req_headers)
|
||||
self.assertNotIn('X-Timestamp', req_headers)
|
||||
self.assertNotIn('X-Backend-Timestamp', req_headers)
|
||||
self.assertNotIn('Content-Encoding', req_headers)
|
||||
self.assertNotIn('Content-Disposition', req_headers)
|
||||
self.assertNotIn('X-Foo', req_headers)
|
||||
|
||||
def test_POST_with_updates(self):
|
||||
post_headers = {
|
||||
'Content-Type': 'text/not_original',
|
||||
'Content-Encoding': 'not_gzip',
|
||||
'Content-Disposition': 'attachment; filename=notmyfile',
|
||||
'X-Object-Meta-Test': 'not_original',
|
||||
'X-Object-Sysmeta-Test': 'not_original',
|
||||
'X-Object-Transient-Sysmeta-Test': 'not_original',
|
||||
'X-Foo': 'Not Bar',
|
||||
}
|
||||
req_headers = self._test_POST_source_headers(post_headers)
|
||||
self.assertEqual('text/not_original', req_headers.get('Content-Type'))
|
||||
self.assertEqual('not_gzip', req_headers.get('Content-Encoding'))
|
||||
self.assertEqual('attachment; filename=notmyfile',
|
||||
req_headers.get('Content-Disposition'))
|
||||
self.assertEqual('not_original', req_headers.get('X-Object-Meta-Test'))
|
||||
self.assertEqual('not_original',
|
||||
req_headers.get('X-Object-Transient-Sysmeta-Test'))
|
||||
self.assertEqual('Not Bar', req_headers.get('X-Foo'))
|
||||
|
||||
def test_POST_x_fresh_metadata_with_updates(self):
|
||||
# post-as-copy trumps x-fresh-metadata i.e. existing user metadata
|
||||
# should not be copied, sysmeta is copied *and not updated with new*
|
||||
post_headers = {
|
||||
'X-Fresh-Metadata': 'true',
|
||||
'Content-Type': 'text/not_original',
|
||||
'Content-Encoding': 'not_gzip',
|
||||
'Content-Disposition': 'attachment; filename=notmyfile',
|
||||
'X-Object-Meta-Test': 'not_original',
|
||||
'X-Object-Sysmeta-Test': 'not_original',
|
||||
'X-Object-Transient-Sysmeta-Test': 'not_original',
|
||||
'X-Foo': 'Not Bar',
|
||||
}
|
||||
req_headers = self._test_POST_source_headers(post_headers)
|
||||
self.assertEqual('text/not_original', req_headers.get('Content-Type'))
|
||||
self.assertEqual('not_gzip', req_headers.get('Content-Encoding'))
|
||||
self.assertEqual('attachment; filename=notmyfile',
|
||||
req_headers.get('Content-Disposition'))
|
||||
self.assertEqual('not_original', req_headers.get('X-Object-Meta-Test'))
|
||||
self.assertEqual('not_original',
|
||||
req_headers.get('X-Object-Transient-Sysmeta-Test'))
|
||||
self.assertEqual('Not Bar', req_headers.get('X-Foo'))
|
||||
self.assertIn('X-Fresh-Metadata', req_headers)
|
||||
|
||||
def test_COPY_with_single_range(self):
|
||||
# verify that source etag is not copied when copying a range
|
||||
self.app.register('GET', '/v1/a/c/o', swob.HTTPOk,
|
||||
@ -1472,67 +1289,6 @@ class TestServerSideCopyConfiguration(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmpdir)
|
||||
|
||||
def test_post_as_copy_defaults_to_false(self):
|
||||
ssc = copy.filter_factory({})("no app here")
|
||||
self.assertEqual(ssc.object_post_as_copy, False)
|
||||
|
||||
def test_reading_proxy_conf_when_no_middleware_conf_present(self):
|
||||
proxy_conf = dedent("""
|
||||
[DEFAULT]
|
||||
bind_ip = 10.4.5.6
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = catch_errors copy ye-olde-proxy-server
|
||||
|
||||
[filter:copy]
|
||||
use = egg:swift#copy
|
||||
|
||||
[app:ye-olde-proxy-server]
|
||||
use = egg:swift#proxy
|
||||
object_post_as_copy = no
|
||||
""")
|
||||
|
||||
conffile = tempfile.NamedTemporaryFile()
|
||||
conffile.write(proxy_conf)
|
||||
conffile.flush()
|
||||
|
||||
ssc = copy.filter_factory({
|
||||
'__file__': conffile.name
|
||||
})("no app here")
|
||||
|
||||
self.assertEqual(ssc.object_post_as_copy, False)
|
||||
|
||||
def test_middleware_conf_precedence(self):
|
||||
proxy_conf = dedent("""
|
||||
[DEFAULT]
|
||||
bind_ip = 10.4.5.6
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = catch_errors copy ye-olde-proxy-server
|
||||
|
||||
[filter:copy]
|
||||
use = egg:swift#copy
|
||||
object_post_as_copy = no
|
||||
|
||||
[app:ye-olde-proxy-server]
|
||||
use = egg:swift#proxy
|
||||
object_post_as_copy = yes
|
||||
""")
|
||||
|
||||
conffile = tempfile.NamedTemporaryFile()
|
||||
conffile.write(proxy_conf)
|
||||
conffile.flush()
|
||||
|
||||
with mock.patch('swift.common.middleware.copy.get_logger',
|
||||
return_value=debug_logger('copy')):
|
||||
ssc = copy.filter_factory({
|
||||
'object_post_as_copy': 'no',
|
||||
'__file__': conffile.name
|
||||
})("no app here")
|
||||
|
||||
self.assertEqual(ssc.object_post_as_copy, False)
|
||||
self.assertFalse(ssc.logger.get_lines_for_level('warning'))
|
||||
|
||||
def _test_post_as_copy_emits_warning(self, conf):
|
||||
with mock.patch('swift.common.middleware.copy.get_logger',
|
||||
return_value=debug_logger('copy')):
|
||||
@ -1585,9 +1341,7 @@ class TestServerSideCopyMiddlewareWithEC(unittest.TestCase):
|
||||
self.app = PatchedObjControllerApp(
|
||||
None, FakeMemcache(), account_ring=FakeRing(),
|
||||
container_ring=FakeRing(), logger=self.logger)
|
||||
self.ssc = copy.filter_factory({
|
||||
'object_post_as_copy': 'yes',
|
||||
})(self.app)
|
||||
self.ssc = copy.filter_factory({})(self.app)
|
||||
self.ssc.logger = self.app.logger
|
||||
self.policy = POLICIES.default
|
||||
self.app.container_info = dict(self.container_info)
|
||||
|
@ -117,23 +117,14 @@ class TestSubRequestLogging(unittest.TestCase):
|
||||
self._test_subrequest_logged('PUT')
|
||||
self._test_subrequest_logged('DELETE')
|
||||
|
||||
def _test_subrequest_logged_POST(self, subrequest_type,
|
||||
post_as_copy=False):
|
||||
# Test that subrequests made downstream from Copy POST will be logged
|
||||
# with the request type of the subrequest as opposed to the GET/PUT.
|
||||
|
||||
app = FakeApp({'subrequest_type': subrequest_type,
|
||||
'object_post_as_copy': post_as_copy})
|
||||
def _test_subrequest_logged_POST(self, subrequest_type):
|
||||
app = FakeApp({'subrequest_type': subrequest_type})
|
||||
|
||||
hdrs = {'content-type': 'text/plain'}
|
||||
req = Request.blank(self.path, method='POST', headers=hdrs)
|
||||
|
||||
app.register('POST', self.path, HTTPOk, headers=hdrs)
|
||||
expect_lines = 2
|
||||
if post_as_copy:
|
||||
app.register('PUT', self.path, HTTPOk, headers=hdrs)
|
||||
app.register('GET', '/v1/a/c/o', HTTPOk, headers=hdrs)
|
||||
expect_lines = 4
|
||||
|
||||
req.get_response(app)
|
||||
info_log_lines = app.fake_logger.get_lines_for_level('info')
|
||||
@ -142,33 +133,17 @@ class TestSubRequestLogging(unittest.TestCase):
|
||||
|
||||
subreq_put_post = '%s %s' % (subrequest_type, SUB_PUT_POST_PATH)
|
||||
origpost = 'POST %s' % self.path
|
||||
copyget = 'GET %s' % self.path
|
||||
|
||||
if post_as_copy:
|
||||
# post_as_copy expect GET subreq, copy GET, PUT subreq, orig POST
|
||||
subreq_get = '%s %s' % (subrequest_type, SUB_GET_PATH)
|
||||
self.assertTrue(subreq_get in info_log_lines[0])
|
||||
self.assertTrue(copyget in info_log_lines[1])
|
||||
self.assertTrue(subreq_put_post in info_log_lines[2])
|
||||
self.assertTrue(origpost in info_log_lines[3])
|
||||
else:
|
||||
# fast post expect POST subreq, original POST
|
||||
self.assertTrue(subreq_put_post in info_log_lines[0])
|
||||
self.assertTrue(origpost in info_log_lines[1])
|
||||
# fast post expect POST subreq, original POST
|
||||
self.assertTrue(subreq_put_post in info_log_lines[0])
|
||||
self.assertTrue(origpost in info_log_lines[1])
|
||||
|
||||
def test_subrequest_logged_post_as_copy_with_POST_fast_post(self):
|
||||
self._test_subrequest_logged_POST('HEAD', post_as_copy=False)
|
||||
self._test_subrequest_logged_POST('GET', post_as_copy=False)
|
||||
self._test_subrequest_logged_POST('POST', post_as_copy=False)
|
||||
self._test_subrequest_logged_POST('PUT', post_as_copy=False)
|
||||
self._test_subrequest_logged_POST('DELETE', post_as_copy=False)
|
||||
|
||||
def test_subrequest_logged_post_as_copy_with_POST(self):
|
||||
self._test_subrequest_logged_POST('HEAD', post_as_copy=True)
|
||||
self._test_subrequest_logged_POST('GET', post_as_copy=True)
|
||||
self._test_subrequest_logged_POST('POST', post_as_copy=True)
|
||||
self._test_subrequest_logged_POST('PUT', post_as_copy=True)
|
||||
self._test_subrequest_logged_POST('DELETE', post_as_copy=True)
|
||||
def test_subrequest_logged_with_POST(self):
|
||||
self._test_subrequest_logged_POST('HEAD')
|
||||
self._test_subrequest_logged_POST('GET')
|
||||
self._test_subrequest_logged_POST('POST')
|
||||
self._test_subrequest_logged_POST('PUT')
|
||||
self._test_subrequest_logged_POST('DELETE')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -330,23 +330,6 @@ class VersionedWritesTestCase(VersionedWritesBaseTestCase):
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
|
||||
def test_put_object_post_as_copy(self):
|
||||
# PUTs due to a post-as-copy should NOT cause a versioning op
|
||||
self.app.register(
|
||||
'PUT', '/v1/a/c/o', swob.HTTPCreated, {}, 'passed')
|
||||
|
||||
cache = FakeCache({'sysmeta': {'versions-location': 'ver_cont'}})
|
||||
req = Request.blank(
|
||||
'/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT', 'swift.cache': cache,
|
||||
'CONTENT_LENGTH': '100',
|
||||
'swift.post_as_copy': True})
|
||||
status, headers, body = self.call_vw(req)
|
||||
self.assertEqual(status, '201 Created')
|
||||
self.assertEqual(len(self.authorized), 1)
|
||||
self.assertRequestEqual(req, self.authorized[0])
|
||||
self.assertEqual(1, self.app.call_count)
|
||||
|
||||
def test_put_first_object_success(self):
|
||||
self.app.register(
|
||||
'PUT', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||
|
@ -3192,8 +3192,6 @@ class TestReplicatedObjectController(
|
||||
|
||||
def test_POST(self):
|
||||
with save_globals():
|
||||
self.app.object_post_as_copy = False
|
||||
|
||||
def test_status_map(statuses, expected):
|
||||
set_http_connect(*statuses)
|
||||
self.app.memcache.store = {}
|
||||
@ -3218,7 +3216,6 @@ class TestReplicatedObjectController(
|
||||
def test_POST_backend_headers(self):
|
||||
# reset the router post patch_policies
|
||||
self.app.obj_controller_router = proxy_server.ObjectControllerRouter()
|
||||
self.app.object_post_as_copy = False
|
||||
self.app.sort_nodes = lambda nodes, *args, **kwargs: nodes
|
||||
backend_requests = []
|
||||
|
||||
@ -3436,7 +3433,6 @@ class TestReplicatedObjectController(
|
||||
def test_POST_meta_val_len(self):
|
||||
with save_globals():
|
||||
limit = constraints.MAX_META_VALUE_LENGTH
|
||||
self.app.object_post_as_copy = False
|
||||
ReplicatedObjectController(
|
||||
self.app, 'account', 'container', 'object')
|
||||
set_http_connect(200, 200, 202, 202, 202)
|
||||
@ -3462,7 +3458,6 @@ class TestReplicatedObjectController(
|
||||
return
|
||||
with save_globals():
|
||||
limit = constraints.MAX_META_VALUE_LENGTH
|
||||
self.app.object_post_as_copy = False
|
||||
controller = ReplicatedObjectController(
|
||||
self.app, 'account', 'container', 'object')
|
||||
set_http_connect(200, 200, 202, 202, 202)
|
||||
@ -3478,7 +3473,6 @@ class TestReplicatedObjectController(
|
||||
def test_POST_meta_key_len(self):
|
||||
with save_globals():
|
||||
limit = constraints.MAX_META_NAME_LENGTH
|
||||
self.app.object_post_as_copy = False
|
||||
set_http_connect(200, 200, 202, 202, 202)
|
||||
# acct cont obj obj obj
|
||||
req = Request.blank(
|
||||
@ -4224,7 +4218,6 @@ class TestReplicatedObjectController(
|
||||
|
||||
def test_PUT_POST_requires_container_exist(self):
|
||||
with save_globals():
|
||||
self.app.object_post_as_copy = False
|
||||
self.app.memcache = FakeMemcacheReturnsNone()
|
||||
controller = ReplicatedObjectController(
|
||||
self.app, 'account', 'container', 'object')
|
||||
@ -4837,7 +4830,6 @@ class TestReplicatedObjectController(
|
||||
called[0] = True
|
||||
return HTTPUnauthorized(request=req)
|
||||
with save_globals():
|
||||
self.app.object_post_as_copy = False
|
||||
set_http_connect(200, 200, 201, 201, 201)
|
||||
controller = ReplicatedObjectController(
|
||||
self.app, 'account', 'container', 'object')
|
||||
@ -4868,7 +4860,6 @@ class TestReplicatedObjectController(
|
||||
|
||||
def test_POST_converts_delete_after_to_delete_at(self):
|
||||
with save_globals():
|
||||
self.app.object_post_as_copy = False
|
||||
controller = ReplicatedObjectController(
|
||||
self.app, 'account', 'container', 'object')
|
||||
set_http_connect(200, 200, 202, 202, 202)
|
||||
@ -5365,7 +5356,6 @@ class TestReplicatedObjectController(
|
||||
|
||||
def test_POST_x_container_headers_with_more_container_replicas(self):
|
||||
self.app.container_ring.set_replicas(4)
|
||||
self.app.object_post_as_copy = False
|
||||
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'POST'},
|
||||
@ -6258,21 +6248,7 @@ class BaseTestECObjectController(BaseTestObjectController):
|
||||
self.ec_policy.object_ring.replica_count)
|
||||
|
||||
if method == 'POST':
|
||||
# Take care fast post here!
|
||||
orig_post_as_copy = getattr(
|
||||
_test_servers[0], 'object_post_as_copy', None)
|
||||
try:
|
||||
_test_servers[0].object_post_as_copy = False
|
||||
with mock.patch.object(
|
||||
_test_servers[0],
|
||||
'object_post_as_copy', False):
|
||||
headers = get_ring_reloaded_response(method)
|
||||
finally:
|
||||
if orig_post_as_copy is None:
|
||||
del _test_servers[0].object_post_as_copy
|
||||
else:
|
||||
_test_servers[0].object_post_as_copy = \
|
||||
orig_post_as_copy
|
||||
headers = get_ring_reloaded_response(method)
|
||||
|
||||
exp = 'HTTP/1.1 20'
|
||||
self.assertEqual(headers[:len(exp)], exp)
|
||||
|
@ -307,11 +307,6 @@ class TestObjectSysmeta(unittest.TestCase):
|
||||
# test fast-post by issuing requests to the proxy app
|
||||
self._test_sysmeta_not_updated_by_POST(self.app)
|
||||
|
||||
def test_sysmeta_not_updated_by_POST_as_copy(self):
|
||||
# test post-as-copy by issuing requests to the copy middleware app
|
||||
self.copy_app.object_post_as_copy = True
|
||||
self._test_sysmeta_not_updated_by_POST(self.copy_app)
|
||||
|
||||
def test_sysmeta_updated_by_COPY(self):
|
||||
# check sysmeta is updated by a COPY in same way as user meta by
|
||||
# issuing requests to the copy middleware app
|
||||
@ -482,8 +477,3 @@ class TestObjectSysmeta(unittest.TestCase):
|
||||
|
||||
def test_transient_sysmeta_replaced_by_PUT_or_POST(self):
|
||||
self._test_transient_sysmeta_replaced_by_PUT_or_POST(self.app)
|
||||
|
||||
def test_transient_sysmeta_replaced_by_PUT_or_POST_as_copy(self):
|
||||
# test post-as-copy by issuing requests to the copy middleware app
|
||||
self.copy_app.object_post_as_copy = True
|
||||
self._test_transient_sysmeta_replaced_by_PUT_or_POST(self.copy_app)
|
||||
|
Loading…
Reference in New Issue
Block a user