summaryrefslogtreecommitdiff
path: root/test/functional/test_object_versioning.py
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2020-06-18 09:41:46 -0700
committerTim Burke <tim.burke@gmail.com>2020-06-18 09:41:46 -0700
commit481f126e6b59689599f438e5d27f7328f5b3e813 (patch)
tree14212db13aee782e95ffd36993d74c6bf35df0cb /test/functional/test_object_versioning.py
parentb3fd0bd9d82160305a821e742b2cd968036911b2 (diff)
parent51a587ed8dd5700b558ad26d70dcb7facc0f91e4 (diff)
downloadswift-481f126e6b59689599f438e5d27f7328f5b3e813.tar.gz
Merge remote-tracking branch 'gerrit/master' into feature/losffeature/losf
Change-Id: If9d7c63f3c4c15fbccff31e2b77a6911bb95972a
Diffstat (limited to 'test/functional/test_object_versioning.py')
-rw-r--r--test/functional/test_object_versioning.py106
1 files changed, 88 insertions, 18 deletions
diff --git a/test/functional/test_object_versioning.py b/test/functional/test_object_versioning.py
index ebfca68f6..d7db187c0 100644
--- a/test/functional/test_object_versioning.py
+++ b/test/functional/test_object_versioning.py
@@ -26,6 +26,7 @@ from six.moves.urllib.parse import quote, unquote
import test.functional as tf
+from swift.common.swob import normalize_etag
from swift.common.utils import MD5_OF_EMPTY_STRING, config_true_value
from swift.common.middleware.versioned_writes.object_versioning import \
DELETE_MARKER_CONTENT_TYPE
@@ -331,6 +332,80 @@ class TestObjectVersioning(TestObjectVersioningBase):
# listing, though, we'll only ever have the two entries.
self.assertTotalVersions(container, 2)
+ def test_get_if_match(self):
+ body = b'data'
+ oname = Utils.create_name()
+ obj = self.env.unversioned_container.file(oname)
+ resp = obj.write(body, return_resp=True)
+ etag = resp.getheader('etag')
+ self.assertEqual(md5(body).hexdigest(), normalize_etag(etag))
+
+ # un-versioned object is cool with with if-match
+ self.assertEqual(body, obj.read(hdrs={'if-match': etag}))
+ with self.assertRaises(ResponseError) as cm:
+ obj.read(hdrs={'if-match': 'not-the-etag'})
+ self.assertEqual(412, cm.exception.status)
+
+ v_obj = self.env.container.file(oname)
+ resp = v_obj.write(body, return_resp=True)
+ self.assertEqual(resp.getheader('etag'), etag)
+
+ # versioned object is too with with if-match
+ self.assertEqual(body, v_obj.read(hdrs={
+ 'if-match': normalize_etag(etag)}))
+ # works quoted, too
+ self.assertEqual(body, v_obj.read(hdrs={
+ 'if-match': '"%s"' % normalize_etag(etag)}))
+ with self.assertRaises(ResponseError) as cm:
+ v_obj.read(hdrs={'if-match': 'not-the-etag'})
+ self.assertEqual(412, cm.exception.status)
+
+ def test_container_acls(self):
+ if tf.skip3:
+ raise SkipTest('Username3 not set')
+
+ obj = self.env.container.file(Utils.create_name())
+ resp = obj.write(b"data", return_resp=True)
+ version_id = resp.getheader('x-object-version-id')
+ self.assertIsNotNone(version_id)
+
+ with self.assertRaises(ResponseError) as cm:
+ obj.read(hdrs={'X-Auth-Token': self.env.conn3.storage_token})
+ self.assertEqual(403, cm.exception.status)
+
+ # Container ACLs work more or less like they always have
+ self.env.container.update_metadata(
+ hdrs={'X-Container-Read': self.env.conn3.user_acl})
+ self.assertEqual(b"data", obj.read(hdrs={
+ 'X-Auth-Token': self.env.conn3.storage_token}))
+
+ # But the version-specifc GET still requires a swift owner
+ with self.assertRaises(ResponseError) as cm:
+ obj.read(hdrs={'X-Auth-Token': self.env.conn3.storage_token},
+ parms={'version-id': version_id})
+ self.assertEqual(403, cm.exception.status)
+
+ # If it's pointing to a symlink that points elsewhere, that still needs
+ # to be authed
+ tgt_name = Utils.create_name()
+ self.env.unversioned_container.file(tgt_name).write(b'link')
+ sym_tgt_header = quote(unquote('%s/%s' % (
+ self.env.unversioned_container.name, tgt_name)))
+ obj.write(hdrs={'X-Symlink-Target': sym_tgt_header})
+
+ # So, user1's good...
+ self.assertEqual(b'link', obj.read())
+ # ...but user3 can't
+ with self.assertRaises(ResponseError) as cm:
+ obj.read(hdrs={'X-Auth-Token': self.env.conn3.storage_token})
+ self.assertEqual(403, cm.exception.status)
+
+ # unless we add the acl to the unversioned_container
+ self.env.unversioned_container.update_metadata(
+ hdrs={'X-Container-Read': self.env.conn3.user_acl})
+ self.assertEqual(b'link', obj.read(
+ hdrs={'X-Auth-Token': self.env.conn3.storage_token}))
+
def _test_overwriting_setup(self, obj_name=None):
# sanity
container = self.env.container
@@ -919,13 +994,13 @@ class TestObjectVersioning(TestObjectVersioningBase):
'Content-Type': 'text/jibberish32'
}, return_resp=True)
v1_version_id = resp.getheader('x-object-version-id')
- v1_etag = resp.getheader('etag')
+ v1_etag = normalize_etag(resp.getheader('etag'))
resp = obj.write(b'version2', hdrs={
'Content-Type': 'text/jibberish33'
}, return_resp=True)
v2_version_id = resp.getheader('x-object-version-id')
- v2_etag = resp.getheader('etag')
+ v2_etag = normalize_etag(resp.getheader('etag'))
# sanity
self.assertEqual(b'version2', obj.read())
@@ -992,7 +1067,7 @@ class TestObjectVersioning(TestObjectVersioningBase):
self.assertEqual(b'version1', obj.read())
obj_info = obj.info()
self.assertEqual('text/jibberish32', obj_info['content_type'])
- self.assertEqual(v1_etag, obj_info['etag'])
+ self.assertEqual(v1_etag, normalize_etag(obj_info['etag']))
def test_delete_with_version_api_old_object(self):
versioned_obj_name = Utils.create_name()
@@ -2308,7 +2383,7 @@ class TestSloWithVersioning(TestObjectVersioningBase):
expected = {
'bytes': file_info['content_length'],
'content_type': 'application/octet-stream',
- 'hash': manifest_info['etag'],
+ 'hash': normalize_etag(manifest_info['etag']),
'name': 'my-slo-manifest',
'slo_etag': file_info['etag'],
'version_symlink': True,
@@ -2340,7 +2415,7 @@ class TestSloWithVersioning(TestObjectVersioningBase):
expected = {
'bytes': file_info['content_length'],
'content_type': 'application/octet-stream',
- 'hash': manifest_info['etag'],
+ 'hash': normalize_etag(manifest_info['etag']),
'name': 'my-slo-manifest',
'slo_etag': file_info['etag'],
'version_symlink': True,
@@ -2688,16 +2763,11 @@ class TestVersioningContainerTempurl(TestObjectVersioningBase):
obj.write(b"version2")
# get v2 object (reading from versions container)
- # cross container tempurl does not work for container tempurl key
- try:
- obj.read(parms=get_parms, cfg={'no_auth_token': True})
- except ResponseError as e:
- self.assertEqual(e.status, 401)
- else:
- self.fail('request did not error')
- try:
- obj.info(parms=get_parms, cfg={'no_auth_token': True})
- except ResponseError as e:
- self.assertEqual(e.status, 401)
- else:
- self.fail('request did not error')
+ # versioning symlink allows us to bypass the normal
+ # container-tempurl-key scoping
+ contents = obj.read(parms=get_parms, cfg={'no_auth_token': True})
+ self.assert_status([200])
+ self.assertEqual(contents, b"version2")
+ # HEAD works, too
+ obj.info(parms=get_parms, cfg={'no_auth_token': True})
+ self.assert_status([200])