Refactor share metadata tests
1) Use the shares_v2_client to make metadata API requests. This allows us to test v1 proxies as well where appropriate, and actually test the supported version of the API instead of the deprecated version 2) Verify key in GET /v2/shares/<share>/metadata/{key} API the client's _parse_body helper strips out the top level key allowing us to miss bugs associated with any key changes from the server [1]. Allow for opt-in verification of the key and add this verification to the affected API. [1] https://bugs.launchpad.net/manila/+bug/1968069 Depends-On: Ib5a62599b84ba55617071f8bcd8e2a1a11b2537b Change-Id: I7b1af957f08328c642a74ff123deb78e193bbe3a Related-Bug: #1968069 Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
This commit is contained in:
parent
5203643c24
commit
8bb17fc562
|
@ -23,6 +23,7 @@ from tempest.lib.common.utils import data_utils
|
|||
from tempest.lib import exceptions
|
||||
|
||||
from manila_tempest_tests import share_exceptions
|
||||
from manila_tempest_tests import utils
|
||||
|
||||
|
||||
CONF = config.CONF
|
||||
|
@ -42,6 +43,9 @@ class SharesClient(rest_client.RestClient):
|
|||
self.share_network_id = CONF.share.share_network_id
|
||||
self.share_size = CONF.share.share_size
|
||||
|
||||
def _parse_resp(self, body, verify_top_key=None):
|
||||
return utils._parse_resp(body, verify_top_key=verify_top_key)
|
||||
|
||||
def create_share(self, share_protocol=None, size=None,
|
||||
name=None, snapshot_id=None, description=None,
|
||||
metadata=None, share_network_id=None,
|
||||
|
@ -446,7 +450,7 @@ class SharesClient(rest_client.RestClient):
|
|||
def get_metadata_item(self, share_id, key):
|
||||
resp, body = self.get("shares/%s/metadata/%s" % (share_id, key))
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
return self._parse_resp(body, verify_top_key='meta')
|
||||
|
||||
###############
|
||||
|
||||
|
|
|
@ -34,14 +34,15 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
def _verify_share_metadata(self, share, md):
|
||||
|
||||
# get metadata of share
|
||||
metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
||||
metadata = self.shares_v2_client.get_metadata(share["id"])['metadata']
|
||||
|
||||
# verify metadata
|
||||
self.assertEqual(md, metadata)
|
||||
|
||||
# verify metadata items
|
||||
for key in md:
|
||||
get_value = self.shares_client.get_metadata_item(share["id"], key)
|
||||
get_value = self.shares_v2_client.get_metadata_item(share["id"],
|
||||
key)
|
||||
self.assertEqual(md[key], get_value[key])
|
||||
|
||||
@decorators.idempotent_id('9070249f-6e94-4a38-a036-08debee547c3')
|
||||
|
@ -69,17 +70,18 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
cleanup_in_class=False)
|
||||
|
||||
# set metadata
|
||||
self.shares_client.set_metadata(share["id"], md)
|
||||
self.shares_v2_client.set_metadata(share["id"], md)
|
||||
|
||||
# verify metadata
|
||||
self._verify_share_metadata(share, md)
|
||||
|
||||
# delete metadata
|
||||
for key in md.keys():
|
||||
self.shares_client.delete_metadata(share["id"], key)
|
||||
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||
|
||||
# verify deletion of metadata
|
||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
||||
get_metadata = self.shares_v2_client.get_metadata(share["id"])[
|
||||
'metadata']
|
||||
self.assertEmpty(get_metadata)
|
||||
|
||||
@decorators.idempotent_id('4e5f8159-62b6-4d5c-f729-d8b1f029d7de')
|
||||
|
@ -93,13 +95,13 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
cleanup_in_class=False)
|
||||
|
||||
# set metadata
|
||||
self.shares_client.set_metadata(share["id"], md1)
|
||||
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||
|
||||
# verify metadata
|
||||
self._verify_share_metadata(share, md1)
|
||||
|
||||
# set metadata again
|
||||
self.shares_client.set_metadata(share["id"], md2)
|
||||
self.shares_v2_client.set_metadata(share["id"], md2)
|
||||
|
||||
# verify metadata
|
||||
md1.update(md2)
|
||||
|
@ -110,10 +112,11 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
|
||||
# delete metadata
|
||||
for key in md.keys():
|
||||
self.shares_client.delete_metadata(share["id"], key)
|
||||
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||
|
||||
# verify deletion of metadata
|
||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
||||
get_metadata = self.shares_v2_client.get_metadata(
|
||||
share["id"])['metadata']
|
||||
self.assertEmpty(get_metadata)
|
||||
|
||||
@decorators.idempotent_id('2ec70ba5-050b-3b17-c862-c149e53543c0')
|
||||
|
@ -127,13 +130,13 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
cleanup_in_class=False)
|
||||
|
||||
# set metadata
|
||||
self.shares_client.set_metadata(share["id"], md1)
|
||||
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||
|
||||
# verify metadata
|
||||
self._verify_share_metadata(share, md1)
|
||||
|
||||
# set metadata again
|
||||
self.shares_client.set_metadata(share["id"], md2)
|
||||
self.shares_v2_client.set_metadata(share["id"], md2)
|
||||
|
||||
# verify metadata
|
||||
md = {u"key9": u"value13", u"key10": u"value10",
|
||||
|
@ -142,10 +145,11 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
|
||||
# delete metadata
|
||||
for key in md.keys():
|
||||
self.shares_client.delete_metadata(share["id"], key)
|
||||
self.shares_v2_client.delete_metadata(share["id"], key)
|
||||
|
||||
# verify deletion of metadata
|
||||
get_metadata = self.shares_client.get_metadata(share["id"])['metadata']
|
||||
get_metadata = self.shares_v2_client.get_metadata(
|
||||
share["id"])['metadata']
|
||||
self.assertEmpty(get_metadata)
|
||||
|
||||
@decorators.idempotent_id('c94851f4-2559-4712-9297-9912db1da7ff')
|
||||
|
@ -160,10 +164,10 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
cleanup_in_class=False)
|
||||
|
||||
# set metadata
|
||||
self.shares_client.set_metadata(share["id"], md1)
|
||||
self.shares_v2_client.set_metadata(share["id"], md1)
|
||||
|
||||
# update metadata
|
||||
self.shares_client.update_all_metadata(share["id"], md2)
|
||||
self.shares_v2_client.update_all_metadata(share["id"], md2)
|
||||
|
||||
# verify metadata
|
||||
self._verify_share_metadata(share, md2)
|
||||
|
@ -173,9 +177,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
def test_set_metadata_min_size_key(self):
|
||||
data = {"k": "value"}
|
||||
|
||||
self.shares_client.set_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data['k'], body_get.get('k'))
|
||||
|
||||
|
@ -185,9 +189,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
max_key = "k" * 255
|
||||
data = {max_key: "value"}
|
||||
|
||||
self.shares_client.set_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertIn(max_key, body_get)
|
||||
self.assertEqual(data[max_key], body_get.get(max_key))
|
||||
|
@ -197,9 +201,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
def test_set_metadata_min_size_value(self):
|
||||
data = {"key": "v"}
|
||||
|
||||
self.shares_client.set_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data['key'], body_get['key'])
|
||||
|
||||
|
@ -209,9 +213,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
max_value = "v" * 1023
|
||||
data = {"key": max_value}
|
||||
|
||||
self.shares_client.set_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.set_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data['key'], body_get['key'])
|
||||
|
||||
|
@ -220,9 +224,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
def test_upd_metadata_min_size_key(self):
|
||||
data = {"k": "value"}
|
||||
|
||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data, body_get)
|
||||
|
||||
|
@ -232,9 +236,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
max_key = "k" * 255
|
||||
data = {max_key: "value"}
|
||||
|
||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data, body_get)
|
||||
|
||||
|
@ -243,9 +247,9 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
def test_upd_metadata_min_size_value(self):
|
||||
data = {"key": "v"}
|
||||
|
||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data, body_get)
|
||||
|
||||
|
@ -255,8 +259,8 @@ class SharesMetadataTest(base.BaseSharesMixedTest):
|
|||
max_value = "v" * 1023
|
||||
data = {"key": max_value}
|
||||
|
||||
self.shares_client.update_all_metadata(self.share["id"], data)
|
||||
self.shares_v2_client.update_all_metadata(self.share["id"], data)
|
||||
|
||||
body_get = self.shares_client.get_metadata(
|
||||
body_get = self.shares_v2_client.get_metadata(
|
||||
self.share["id"])['metadata']
|
||||
self.assertEqual(data, body_get)
|
||||
|
|
|
@ -61,14 +61,14 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_try_set_metadata_with_empty_key(self):
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.set_metadata,
|
||||
self.shares_v2_client.set_metadata,
|
||||
self.share["id"], {"": "value"})
|
||||
|
||||
@decorators.idempotent_id('759ca34d-1c87-43f3-8da2-8e1d373049ac')
|
||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_try_upd_metadata_with_empty_key(self):
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.update_all_metadata,
|
||||
self.shares_v2_client.update_all_metadata,
|
||||
self.share["id"], {"": "value"})
|
||||
|
||||
@decorators.idempotent_id('94c7ebb3-14c3-4ff1-9839-ae3acb318cd0')
|
||||
|
@ -77,7 +77,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||
too_big_key = "x" * 256
|
||||
md = {too_big_key: "value"}
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.set_metadata,
|
||||
self.shares_v2_client.set_metadata,
|
||||
self.share["id"], md)
|
||||
|
||||
@decorators.idempotent_id('33ef3047-6ca3-4547-a681-b52314382dcb')
|
||||
|
@ -86,7 +86,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||
too_big_key = "x" * 256
|
||||
md = {too_big_key: "value"}
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.update_all_metadata,
|
||||
self.shares_v2_client.update_all_metadata,
|
||||
self.share["id"], md)
|
||||
|
||||
@decorators.idempotent_id('1114970a-1b45-4c56-b20a-e13e1764e3c4')
|
||||
|
@ -95,7 +95,7 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||
too_big_value = "x" * 1024
|
||||
md = {"key": too_big_value}
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.set_metadata,
|
||||
self.shares_v2_client.set_metadata,
|
||||
self.share["id"], md)
|
||||
|
||||
@decorators.idempotent_id('c2eddcf0-cf81-4f9f-b06d-c9165ab8553e')
|
||||
|
@ -104,12 +104,12 @@ class SharesMetadataNegativeTest(base.BaseSharesMixedTest):
|
|||
too_big_value = "x" * 1024
|
||||
md = {"key": too_big_value}
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_client.update_all_metadata,
|
||||
self.shares_v2_client.update_all_metadata,
|
||||
self.share["id"], md)
|
||||
|
||||
@decorators.idempotent_id('14df3262-5a2b-4de4-b335-422329b22b07')
|
||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_try_delete_unexisting_metadata(self):
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.shares_client.delete_metadata,
|
||||
self.shares_v2_client.delete_metadata,
|
||||
self.share["id"], "wrong_key")
|
||||
|
|
|
@ -70,10 +70,10 @@ class SharesSchedulerHintsTest(base.BaseSharesMixedTest):
|
|||
self.assertEqual(backend_a, backend_b)
|
||||
|
||||
# get metadata of share
|
||||
metadata_a = self.shares_client.get_metadata(
|
||||
metadata_a = self.shares_v2_client.get_metadata(
|
||||
self.share_a["id"])['metadata']
|
||||
md_a = {"__affinity_same_host": "%s" % share_b["id"]}
|
||||
metadata_b = self.shares_client.get_metadata(
|
||||
metadata_b = self.shares_v2_client.get_metadata(
|
||||
share_b["id"])['metadata']
|
||||
md_b = {"__affinity_same_host": "%s" % self.share_a["id"]}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
|
||||
|
@ -225,3 +226,43 @@ def get_extra_headers(request_version, graduation_version):
|
|||
headers = EXPERIMENTAL
|
||||
extra_headers = True
|
||||
return headers, extra_headers
|
||||
|
||||
|
||||
def _parse_resp(body, verify_top_key=None):
|
||||
try:
|
||||
body = json.loads(body)
|
||||
except ValueError:
|
||||
return body
|
||||
|
||||
# We assume, that if the first value of the deserialized body's
|
||||
# item set is a dict or a list, that we just return the first value
|
||||
# of deserialized body.
|
||||
# Essentially "cutting out" the first placeholder element in a body
|
||||
# that looks like this:
|
||||
#
|
||||
# {
|
||||
# "users": [
|
||||
# ...
|
||||
# ]
|
||||
# }
|
||||
try:
|
||||
# Ensure there are not more than one top-level keys
|
||||
# NOTE(freerunner): Ensure, that JSON is not nullable to
|
||||
# to prevent StopIteration Exception
|
||||
if not hasattr(body, "keys") or len(body.keys()) != 1:
|
||||
return body
|
||||
# Just return the "wrapped" element
|
||||
first_key, first_item = tuple(body.items())[0]
|
||||
if isinstance(first_item, (dict, list)):
|
||||
if verify_top_key is not None:
|
||||
assert_msg = (
|
||||
"The expected top level key is '%(top_key)s' but we "
|
||||
"found '%(actual_key)s'." % {
|
||||
'top_key': verify_top_key,
|
||||
'actual_key': first_key
|
||||
})
|
||||
assert verify_top_key == first_key, assert_msg
|
||||
return first_item
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
return body
|
||||
|
|
Loading…
Reference in New Issue