GET property which name includes resource type prefix
Currently GET call to API to retrieve property details ends with 404 error when property name includes resource type prefix. This patch extends show method to take filters as a parameter. If 'resource_type' is included in filters then the prefix of included resource type is removed from property name. This enables user to look for property name starting with prefix that comes from associated resource type. Change-Id: I3c4d96fbc9ce15016631017bf76089c338ac3cdc Closes-Bug: #1367564 DocImpact Co-Authored-By: Bartosz Fic <bartosz.fic@intel.com> Co-Authored-By: Pawel Koniszewski <pawel.koniszewski@intel.com>
This commit is contained in:
parent
2530cfa81e
commit
8b9f9836f8
@ -41,6 +41,7 @@
|
||||
"add_metadef_object":"",
|
||||
|
||||
"list_metadef_resource_types":"",
|
||||
"get_metadef_resource_type":"",
|
||||
"add_metadef_resource_type_association":"",
|
||||
|
||||
"get_metadef_property":"",
|
||||
|
@ -723,6 +723,10 @@ class MetadefResourceTypeRepoProxy(
|
||||
return [proxy_meta_resource_type(self.context, meta_resource_type) for
|
||||
meta_resource_type in meta_resource_types]
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
meta_resource_type = self.meta_resource_type_repo.get(*args, **kwargs)
|
||||
return proxy_meta_resource_type(self.context, meta_resource_type)
|
||||
|
||||
|
||||
# Metadef namespace properties classes
|
||||
def is_namespace_property_mutable(context, namespace_property):
|
||||
|
@ -580,6 +580,10 @@ class MetadefResourceTypeRepoProxy(
|
||||
self.policy.enforce(self.context, 'list_metadef_resource_types', {})
|
||||
return super(MetadefResourceTypeRepoProxy, self).list(*args, **kwargs)
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
self.policy.enforce(self.context, 'get_metadef_resource_type', {})
|
||||
return super(MetadefResourceTypeRepoProxy, self).get(*args, **kwargs)
|
||||
|
||||
def add(self, resource_type):
|
||||
self.policy.enforce(self.context,
|
||||
'add_metadef_resource_type_association', {})
|
||||
|
@ -79,8 +79,24 @@ class NamespacePropertiesController(object):
|
||||
raise webob.exc.HTTPInternalServerError()
|
||||
return namespace_properties
|
||||
|
||||
def show(self, req, namespace, property_name):
|
||||
def show(self, req, namespace, property_name, filters=None):
|
||||
try:
|
||||
if filters and filters['resource_type']:
|
||||
rs_repo = self.gateway.get_metadef_resource_type_repo(
|
||||
req.context)
|
||||
db_resource_type = rs_repo.get(filters['resource_type'],
|
||||
namespace)
|
||||
prefix = db_resource_type.prefix
|
||||
if prefix and property_name.startswith(prefix):
|
||||
property_name = property_name[len(prefix):]
|
||||
else:
|
||||
msg = (_("Property %(property_name)s does not start "
|
||||
"with the expected resource type association "
|
||||
"prefix of '%(prefix)s'.")
|
||||
% {'property_name': property_name,
|
||||
'prefix': prefix})
|
||||
raise exception.NotFound(msg)
|
||||
|
||||
prop_repo = self.gateway.get_metadef_property_repo(req.context)
|
||||
db_property = prop_repo.get(namespace, property_name)
|
||||
property = self._to_model(db_property)
|
||||
@ -185,6 +201,13 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
property_type = fromjson(PropertyType, body)
|
||||
return dict(property_type=property_type)
|
||||
|
||||
def show(self, request):
|
||||
params = request.params.copy()
|
||||
query_params = {
|
||||
'filters': params
|
||||
}
|
||||
return query_params
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
def __init__(self, schema=None):
|
||||
|
@ -628,6 +628,19 @@ class MetadefResourceTypeRepo(object):
|
||||
self._format_resource_type_to_db(resource_type)
|
||||
)
|
||||
|
||||
def get(self, resource_type, namespace):
|
||||
namespace_entity = self.meta_namespace_repo.get(namespace)
|
||||
db_resource_type = (
|
||||
self.db_api.
|
||||
metadef_resource_type_association_get(
|
||||
self.context,
|
||||
namespace,
|
||||
resource_type
|
||||
)
|
||||
)
|
||||
return self._format_resource_type_from_db(db_resource_type,
|
||||
namespace_entity)
|
||||
|
||||
def list(self, filters=None):
|
||||
namespace = filters['namespace']
|
||||
if namespace:
|
||||
|
@ -367,6 +367,10 @@ class MetadefResourceTypeRepo(object):
|
||||
self.base.add(self.resource_type_proxy_helper.unproxy(
|
||||
meta_resource_type))
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
resource_type = self.base.get(*args, **kwargs)
|
||||
return self.resource_type_proxy_helper.proxy(resource_type)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
resource_types = self.base.list(*args, **kwargs)
|
||||
return [self.resource_type_proxy_helper.proxy(resource_type)
|
||||
|
@ -55,15 +55,22 @@ class TestNamespaceProperties(functional.FunctionalTest):
|
||||
path = self._url('/v2/metadefs/namespaces')
|
||||
headers = self._headers({'content-type': 'application/json'})
|
||||
namespace_name = 'MyNamespace'
|
||||
resource_type_name = 'MyResourceType'
|
||||
resource_type_prefix = 'MyPrefix'
|
||||
data = jsonutils.dumps({
|
||||
"namespace": namespace_name,
|
||||
"display_name": "My User Friendly Namespace",
|
||||
"description": "My description",
|
||||
"visibility": "public",
|
||||
"protected": False,
|
||||
"owner": "The Test Owner"
|
||||
}
|
||||
)
|
||||
"owner": "The Test Owner",
|
||||
"resource_type_associations": [
|
||||
{
|
||||
"name": resource_type_name,
|
||||
"prefix": resource_type_prefix
|
||||
}
|
||||
]
|
||||
})
|
||||
response = requests.post(path, headers=headers, data=data)
|
||||
self.assertEqual(201, response.status_code)
|
||||
|
||||
@ -105,6 +112,30 @@ class TestNamespaceProperties(functional.FunctionalTest):
|
||||
self.assertEqual(100, property_object['minimum'])
|
||||
self.assertEqual(30000369, property_object['maximum'])
|
||||
|
||||
# Get the property with specific resource type association
|
||||
path = self._url('/v2/metadefs/namespaces/%s/properties/%s%s' % (
|
||||
namespace_name, property_name, '='.join(['?resource_type',
|
||||
resource_type_name])))
|
||||
response = requests.get(path, headers=self._headers())
|
||||
self.assertEqual(404, response.status_code)
|
||||
|
||||
# Get the property with prefix and specific resource type association
|
||||
property_name_with_prefix = ''.join([resource_type_prefix,
|
||||
property_name])
|
||||
path = self._url('/v2/metadefs/namespaces/%s/properties/%s%s' % (
|
||||
namespace_name, property_name_with_prefix, '='.join([
|
||||
'?resource_type', resource_type_name])))
|
||||
response = requests.get(path, headers=self._headers())
|
||||
self.assertEqual(200, response.status_code)
|
||||
property_object = jsonutils.loads(response.text)
|
||||
self.assertEqual("integer", property_object['type'])
|
||||
self.assertEqual("property1", property_object['title'])
|
||||
self.assertEqual("property1 description", property_object[
|
||||
'description'])
|
||||
self.assertEqual('100', property_object['default'])
|
||||
self.assertEqual(100, property_object['minimum'])
|
||||
self.assertEqual(30000369, property_object['maximum'])
|
||||
|
||||
# Returned property should match the created property
|
||||
property_object = jsonutils.loads(response.text)
|
||||
checked_keys = set([
|
||||
|
@ -38,6 +38,7 @@ NAMESPACE6 = 'Namespace6'
|
||||
PROPERTY1 = 'Property1'
|
||||
PROPERTY2 = 'Property2'
|
||||
PROPERTY3 = 'Property3'
|
||||
PROPERTY4 = 'Property4'
|
||||
|
||||
OBJECT1 = 'Object1'
|
||||
OBJECT2 = 'Object2'
|
||||
@ -46,12 +47,15 @@ OBJECT3 = 'Object3'
|
||||
RESOURCE_TYPE1 = 'ResourceType1'
|
||||
RESOURCE_TYPE2 = 'ResourceType2'
|
||||
RESOURCE_TYPE3 = 'ResourceType3'
|
||||
RESOURCE_TYPE4 = 'ResourceType4'
|
||||
|
||||
TENANT1 = '6838eb7b-6ded-434a-882c-b344c77fe8df'
|
||||
TENANT2 = '2c014f32-55eb-467d-8fcb-4bd706012f81'
|
||||
TENANT3 = '5a3e60e8-cfa9-4a9e-a90a-62b42cea92b8'
|
||||
TENANT4 = 'c6c87f25-8a94-47ed-8c83-053c25f42df4'
|
||||
|
||||
PREFIX1 = 'pref'
|
||||
|
||||
|
||||
def _db_namespace_fixture(namespace, **kwargs):
|
||||
obj = {
|
||||
@ -146,6 +150,7 @@ class TestMetadefsControllers(base.IsolatedUnitTest):
|
||||
(NAMESPACE3, _db_property_fixture(PROPERTY1)),
|
||||
(NAMESPACE3, _db_property_fixture(PROPERTY2)),
|
||||
(NAMESPACE1, _db_property_fixture(PROPERTY1)),
|
||||
(NAMESPACE6, _db_property_fixture(PROPERTY4)),
|
||||
]
|
||||
[self.db.metadef_property_create(req.context, namespace, property)
|
||||
for namespace, property in self.properties]
|
||||
@ -165,6 +170,7 @@ class TestMetadefsControllers(base.IsolatedUnitTest):
|
||||
self.resource_types = [
|
||||
_db_resource_type_fixture(RESOURCE_TYPE1),
|
||||
_db_resource_type_fixture(RESOURCE_TYPE2),
|
||||
_db_resource_type_fixture(RESOURCE_TYPE4),
|
||||
]
|
||||
[self.db.metadef_resource_type_create(req.context, resource_type)
|
||||
for resource_type in self.resource_types]
|
||||
@ -176,6 +182,8 @@ class TestMetadefsControllers(base.IsolatedUnitTest):
|
||||
(NAMESPACE3, _db_namespace_resource_type_fixture(RESOURCE_TYPE1)),
|
||||
(NAMESPACE2, _db_namespace_resource_type_fixture(RESOURCE_TYPE1)),
|
||||
(NAMESPACE2, _db_namespace_resource_type_fixture(RESOURCE_TYPE2)),
|
||||
(NAMESPACE6, _db_namespace_resource_type_fixture(RESOURCE_TYPE4,
|
||||
prefix=PREFIX1)),
|
||||
]
|
||||
[self.db.metadef_resource_type_association_create(req.context,
|
||||
namespace,
|
||||
@ -526,6 +534,25 @@ class TestMetadefsControllers(base.IsolatedUnitTest):
|
||||
output = self.property_controller.show(request, NAMESPACE3, PROPERTY1)
|
||||
self.assertEqual(output.name, PROPERTY1)
|
||||
|
||||
def test_property_show_specific_resource_type(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
output = self.property_controller.show(
|
||||
request, NAMESPACE6, ''.join([PREFIX1, PROPERTY4]),
|
||||
filters={'resource_type': RESOURCE_TYPE4})
|
||||
self.assertEqual(output.name, PROPERTY4)
|
||||
|
||||
def test_property_show_prefix_mismatch(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.property_controller.show, request, NAMESPACE6,
|
||||
PROPERTY4, filters={'resource_type': RESOURCE_TYPE4})
|
||||
|
||||
def test_property_show_non_existing_resource_type(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.property_controller.show, request, NAMESPACE2,
|
||||
PROPERTY1, filters={'resource_type': 'test'})
|
||||
|
||||
def test_property_show_non_existing(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
@ -958,10 +985,10 @@ class TestMetadefsControllers(base.IsolatedUnitTest):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
output = self.rt_controller.index(request)
|
||||
|
||||
self.assertEqual(2, len(output.resource_types))
|
||||
self.assertEqual(3, len(output.resource_types))
|
||||
actual = set([type.name for type in
|
||||
output.resource_types])
|
||||
expected = set([RESOURCE_TYPE1, RESOURCE_TYPE2])
|
||||
expected = set([RESOURCE_TYPE1, RESOURCE_TYPE2, RESOURCE_TYPE4])
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_resource_type_show(self):
|
||||
|
Loading…
Reference in New Issue
Block a user