summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Fic <bartosz.fic@intel.com>2014-10-08 10:47:31 +0200
committerNikhil Komawar <nikhilskomawar@gmail.com>2014-10-09 09:48:15 -0400
commit6b0c7ed29ec1e716e704e19112d9ee24553faf19 (patch)
tree4fffd6b8a6086c63bca3c7757cde65495cfdeb7e
parent9eff67b8fff812acdbf787f2dc119761f3cf3153 (diff)
downloadglance-6b0c7ed29ec1e716e704e19112d9ee24553faf19.tar.gz
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>
-rw-r--r--etc/policy.json1
-rw-r--r--glance/api/authorization.py4
-rw-r--r--glance/api/policy.py4
-rw-r--r--glance/api/v2/metadef_properties.py25
-rw-r--r--glance/db/__init__.py13
-rw-r--r--glance/domain/proxy.py4
-rw-r--r--glance/tests/functional/v2/test_metadef_properties.py37
-rw-r--r--glance/tests/unit/v2/test_metadef_resources.py31
8 files changed, 113 insertions, 6 deletions
diff --git a/etc/policy.json b/etc/policy.json
index e72363f6d..325f00b21 100644
--- a/etc/policy.json
+++ b/etc/policy.json
@@ -41,6 +41,7 @@
"add_metadef_object":"",
"list_metadef_resource_types":"",
+ "get_metadef_resource_type":"",
"add_metadef_resource_type_association":"",
"get_metadef_property":"",
diff --git a/glance/api/authorization.py b/glance/api/authorization.py
index ea8d1d494..149ff55a7 100644
--- a/glance/api/authorization.py
+++ b/glance/api/authorization.py
@@ -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):
diff --git a/glance/api/policy.py b/glance/api/policy.py
index a557290d0..0bc8d5651 100644
--- a/glance/api/policy.py
+++ b/glance/api/policy.py
@@ -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', {})
diff --git a/glance/api/v2/metadef_properties.py b/glance/api/v2/metadef_properties.py
index 06787e193..65097ea81 100644
--- a/glance/api/v2/metadef_properties.py
+++ b/glance/api/v2/metadef_properties.py
@@ -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):
diff --git a/glance/db/__init__.py b/glance/db/__init__.py
index fd0b84cfa..1a80044cd 100644
--- a/glance/db/__init__.py
+++ b/glance/db/__init__.py
@@ -626,6 +626,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:
diff --git a/glance/domain/proxy.py b/glance/domain/proxy.py
index 7a1667bc3..5a91d343d 100644
--- a/glance/domain/proxy.py
+++ b/glance/domain/proxy.py
@@ -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)
diff --git a/glance/tests/functional/v2/test_metadef_properties.py b/glance/tests/functional/v2/test_metadef_properties.py
index 7983cf253..b5e791b69 100644
--- a/glance/tests/functional/v2/test_metadef_properties.py
+++ b/glance/tests/functional/v2/test_metadef_properties.py
@@ -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([
diff --git a/glance/tests/unit/v2/test_metadef_resources.py b/glance/tests/unit/v2/test_metadef_resources.py
index 87aff8a08..9334fe239 100644
--- a/glance/tests/unit/v2/test_metadef_resources.py
+++ b/glance/tests/unit/v2/test_metadef_resources.py
@@ -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):