Merge "Functional tests migration for metadef APIs"

This commit is contained in:
Zuul
2025-08-07 16:20:00 +00:00
committed by Gerrit Code Review
6 changed files with 391 additions and 487 deletions

View File

@@ -12,12 +12,11 @@
# limitations under the License. # limitations under the License.
from oslo_utils.fixture import uuidsentinel as uuids from oslo_utils.fixture import uuidsentinel as uuids
import requests
from glance.tests import functional from glance.tests import functional
class MetadefFunctionalTestBase(functional.FunctionalTest): class MetadefFunctionalTestBase(functional.SynchronousAPIBase):
"""A basic set of assertions and utilities for testing the metadef API.""" """A basic set of assertions and utilities for testing the metadef API."""
def setUp(self): def setUp(self):
@@ -61,4 +60,5 @@ class MetadefFunctionalTestBase(functional.FunctionalTest):
:returns: a dictionary of the namespace in the response :returns: a dictionary of the namespace in the response
""" """
return requests.post(path, headers=headers, json=namespace).json()
return self.api_post(path, headers, json=namespace)

View File

@@ -16,7 +16,6 @@
import http.client as http import http.client as http
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import requests
from glance.tests.functional.v2 import metadef_base from glance.tests.functional.v2 import metadef_base
@@ -25,27 +24,24 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
def setUp(self): def setUp(self):
super(TestNamespaces, self).setUp() super(TestNamespaces, self).setUp()
self.cleanup() self.start_server(enable_cache=False)
self.api_server.deployment_flavor = 'noauth'
self.start_servers(**self.__dict__.copy())
def test_namespace_lifecycle(self): def test_namespace_lifecycle(self):
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace # Create a namespace
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
namespace_name = 'MyNamespace' namespace_name = 'MyNamespace'
data = jsonutils.dumps({ data = {
"namespace": namespace_name, "namespace": namespace_name,
"display_name": "My User Friendly Namespace", "display_name": "My User Friendly Namespace",
"description": "My description" "description": "My description"
} }
) response = self.api_post(path, headers=headers, json=data)
response = requests.post(path, headers=headers, data=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
namespace_loc_header = response.headers['Location'] namespace_loc_header = response.headers['Location']
@@ -80,11 +76,11 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(namespace[key], value, key) self.assertEqual(namespace[key], value, key)
# Attempt to insert a duplicate # Attempt to insert a duplicate
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Get the namespace using the returned Location header # Get the namespace using the returned Location header
response = requests.get(namespace_loc_header, headers=self._headers()) response = self.api_get(namespace_loc_header, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
namespace = jsonutils.loads(response.text) namespace = jsonutils.loads(response.text)
self.assertEqual(namespace_name, namespace['namespace']) self.assertEqual(namespace_name, namespace['namespace'])
@@ -94,21 +90,19 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
self.assertFalse(namespace['protected']) self.assertFalse(namespace['protected'])
# The namespace should be mutable # The namespace should be mutable
path = self._url('/v2/metadefs/namespaces/%s' % namespace_name) path = '/v2/metadefs/namespaces/%s' % namespace_name
media_type = 'application/json' media_type = 'application/json'
headers = self._headers({'content-type': media_type}) headers = self._headers({'content-type': media_type})
namespace_name = "MyNamespace-UPDATED" namespace_name = "MyNamespace-UPDATED"
data = jsonutils.dumps( data = {
{ "namespace": namespace_name,
"namespace": namespace_name, "display_name": "display_name-UPDATED",
"display_name": "display_name-UPDATED", "description": "description-UPDATED",
"description": "description-UPDATED", "visibility": "private", # Not changed
"visibility": "private", # Not changed "protected": True,
"protected": True, "owner": self.tenant2
"owner": self.tenant2 }
} response = self.api_put(path, headers=headers, json=data)
)
response = requests.put(path, headers=headers, data=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned namespace should reflect the changes # Returned namespace should reflect the changes
@@ -121,8 +115,8 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(self.tenant2, namespace['owner']) self.assertEqual(self.tenant2, namespace['owner'])
# Updates should persist across requests # Updates should persist across requests
path = self._url('/v2/metadefs/namespaces/%s' % namespace_name) path = '/v2/metadefs/namespaces/%s' % namespace_name
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
namespace = jsonutils.loads(response.text) namespace = jsonutils.loads(response.text)
self.assertEqual('MyNamespace-UPDATED', namespace['namespace']) self.assertEqual('MyNamespace-UPDATED', namespace['namespace'])
@@ -133,12 +127,12 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(self.tenant2, namespace['owner']) self.assertEqual(self.tenant2, namespace['owner'])
# Deletion should not work on protected namespaces # Deletion should not work on protected namespaces
path = self._url('/v2/metadefs/namespaces/%s' % namespace_name) path = '/v2/metadefs/namespaces/%s' % namespace_name
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Unprotect namespace for deletion # Unprotect namespace for deletion
path = self._url('/v2/metadefs/namespaces/%s' % namespace_name) path = '/v2/metadefs/namespaces/%s' % namespace_name
media_type = 'application/json' media_type = 'application/json'
headers = self._headers({'content-type': media_type}) headers = self._headers({'content-type': media_type})
doc = { doc = {
@@ -149,87 +143,26 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
"protected": False, "protected": False,
"owner": self.tenant2 "owner": self.tenant2
} }
data = jsonutils.dumps(doc) response = self.api_put(path, headers=headers, json=doc)
response = requests.put(path, headers=headers, data=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Deletion should work. Deleting namespace MyNamespace # Deletion should work. Deleting namespace MyNamespace
path = self._url('/v2/metadefs/namespaces/%s' % namespace_name) path = '/v2/metadefs/namespaces/%s' % namespace_name
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
def test_metadef_dont_accept_illegal_bodies(self):
# Namespace should not exist
path = self._url('/v2/metadefs/namespaces/bodytest')
response = requests.get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace
path = self._url('/v2/metadefs/namespaces')
headers = self._headers({'content-type': 'application/json'})
namespace_name = 'bodytest'
data = jsonutils.dumps({
"namespace": namespace_name,
"display_name": "My User Friendly Namespace",
"description": "My description"
}
)
response = requests.post(path, headers=headers, data=data)
self.assertEqual(http.CREATED, response.status_code)
# Test all the urls that supply data
data_urls = [
'/v2/schemas/metadefs/namespace',
'/v2/schemas/metadefs/namespaces',
'/v2/schemas/metadefs/resource_type',
'/v2/schemas/metadefs/resource_types',
'/v2/schemas/metadefs/property',
'/v2/schemas/metadefs/properties',
'/v2/schemas/metadefs/object',
'/v2/schemas/metadefs/objects',
'/v2/schemas/metadefs/tag',
'/v2/schemas/metadefs/tags',
'/v2/metadefs/resource_types',
]
for value in data_urls:
path = self._url(value)
data = jsonutils.dumps(["body"])
response = requests.get(path, headers=self._headers(), data=data)
self.assertEqual(http.BAD_REQUEST, response.status_code)
# Put the namespace into the url
test_urls = [
('/v2/metadefs/namespaces/%s/resource_types', 'get'),
('/v2/metadefs/namespaces/%s/resource_types/type', 'delete'),
('/v2/metadefs/namespaces/%s', 'get'),
('/v2/metadefs/namespaces/%s', 'delete'),
('/v2/metadefs/namespaces/%s/objects/name', 'get'),
('/v2/metadefs/namespaces/%s/objects/name', 'delete'),
('/v2/metadefs/namespaces/%s/properties', 'get'),
('/v2/metadefs/namespaces/%s/tags/test', 'get'),
('/v2/metadefs/namespaces/%s/tags/test', 'post'),
('/v2/metadefs/namespaces/%s/tags/test', 'delete'),
]
for link, method in test_urls:
path = self._url(link % namespace_name)
data = jsonutils.dumps(["body"])
response = getattr(requests, method)(
path, headers=self._headers(), data=data)
self.assertEqual(http.BAD_REQUEST, response.status_code)
def _update_namespace(self, path, headers, data): def _update_namespace(self, path, headers, data):
# The namespace should be mutable # The namespace should be mutable
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned namespace should reflect the changes # Returned namespace should reflect the changes
namespace = response.json() namespace = jsonutils.loads(response.text)
expected_namespace = { expected_namespace = {
"namespace": data['namespace'], "namespace": data['namespace'],
"display_name": data['display_name'], "display_name": data['display_name'],
@@ -245,10 +178,10 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(namespace, expected_namespace) self.assertEqual(namespace, expected_namespace)
# Updates should persist across requests # Updates should persist across requests
path = self._url('/v2/metadefs/namespaces/%s' % namespace['namespace']) path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
namespace = response.json() namespace = jsonutils.loads(response.text)
namespace.pop('created_at') namespace.pop('created_at')
namespace.pop('updated_at') namespace.pop('updated_at')
self.assertEqual(namespace, expected_namespace) self.assertEqual(namespace, expected_namespace)
@@ -257,7 +190,7 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
def test_role_based_namespace_lifecycle(self): def test_role_based_namespace_lifecycle(self):
# Create public and private namespaces for tenant1 and tenant2 # Create public and private namespaces for tenant1 and tenant2
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
tenant_namespaces = dict() tenant_namespaces = dict()
for tenant in [self.tenant1, self.tenant2]: for tenant in [self.tenant1, self.tenant2]:
@@ -272,6 +205,7 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
} }
namespace = self.create_namespace(path, headers, namespace = self.create_namespace(path, headers,
namespace_data) namespace_data)
namespace = jsonutils.loads(namespace.text)
self.assertNamespacesEqual(namespace, namespace_data) self.assertNamespacesEqual(namespace, namespace_data)
tenant_namespaces.setdefault(tenant, list()) tenant_namespaces.setdefault(tenant, list())
tenant_namespaces[tenant].append(namespace) tenant_namespaces[tenant].append(namespace)
@@ -294,12 +228,12 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
# Check Tenant 1 and Tenant 2 will be able to see total 3 namespaces # Check Tenant 1 and Tenant 2 will be able to see total 3 namespaces
# (two of own and 1 public of other tenant) # (two of own and 1 public of other tenant)
for tenant in [self.tenant1, self.tenant2]: for tenant in [self.tenant1, self.tenant2]:
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'X-Tenant-Id': tenant, headers = self._headers({'X-Tenant-Id': tenant,
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
namespaces = response.json()['namespaces'] namespaces = jsonutils.loads(response.text)['namespaces']
expected_namespaces = _get_expected_namespaces(tenant) expected_namespaces = _get_expected_namespaces(tenant)
self.assertEqual(sorted(x['namespace'] for x in namespaces), self.assertEqual(sorted(x['namespace'] for x in namespaces),
sorted(expected_namespaces)) sorted(expected_namespaces))
@@ -308,10 +242,8 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
headers = self._headers({'X-Tenant-Id': tenant, headers = self._headers({'X-Tenant-Id': tenant,
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for namespace in namespaces: for namespace in namespaces:
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace']) response = self.api_get(path, headers=headers)
headers = headers
response = requests.get(path, headers=headers)
if namespace['visibility'] == 'public': if namespace['visibility'] == 'public':
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
else: else:
@@ -338,14 +270,13 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
"protected": True, # changed "protected": True, # changed
"owner": namespace["owner"] # Not changed "owner": namespace["owner"] # Not changed
} }
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace'])
headers = self._headers({ headers = self._headers({
'X-Tenant-Id': namespace['owner'], 'X-Tenant-Id': namespace['owner'],
}) })
# Update namespace should fail with non admin role # Update namespace should fail with non admin role
headers['X-Roles'] = "reader,member" headers['X-Roles'] = "reader,member"
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Should work with admin role # Should work with admin role
@@ -353,16 +284,14 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
namespace = self._update_namespace(path, headers, data) namespace = self._update_namespace(path, headers, data)
# Deletion should fail as namespaces are protected now # Deletion should fail as namespaces are protected now
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace'])
headers['X-Roles'] = "admin" headers['X-Roles'] = "admin"
response = requests.delete(path, headers=headers) response = self.api_delete(path, headers=headers)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Deletion should not be allowed for non admin roles # Deletion should not be allowed for non admin roles
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace']) response = self.api_delete(
response = requests.delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace['owner'] 'X-Tenant-Id': namespace['owner']
@@ -372,29 +301,26 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
# Unprotect the namespaces before deletion # Unprotect the namespaces before deletion
headers = self._headers() headers = self._headers()
for namespace in total_ns: for namespace in total_ns:
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace'])
headers = headers
data = { data = {
"namespace": namespace['namespace'], "namespace": namespace['namespace'],
"protected": False, "protected": False,
} }
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
# Get updated namespace set again # Get updated namespace set again
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
self.assertFalse(namespace['protected']) self.assertFalse(namespace['protected'])
namespaces = response.json()['namespaces'] namespaces = jsonutils.loads(response.text)['namespaces']
# Verify that deletion is not allowed for unprotected namespaces with # Verify that deletion is not allowed for unprotected namespaces with
# non admin role # non admin role
for namespace in namespaces: for namespace in namespaces:
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace']) response = self.api_delete(
response = requests.delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace['owner'] 'X-Tenant-Id': namespace['owner']
@@ -403,13 +329,11 @@ class TestNamespaces(metadef_base.MetadefFunctionalTestBase):
# Delete namespaces of all tenants # Delete namespaces of all tenants
for namespace in total_ns: for namespace in total_ns:
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace']) response = self.api_delete(path, headers=headers)
response = requests.delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Deleted namespace should not be returned # Deleted namespace should not be returned
path = self._url( path = '/v2/metadefs/namespaces/%s' % namespace['namespace']
'/v2/metadefs/namespaces/%s' % namespace['namespace']) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)

View File

@@ -16,7 +16,6 @@
import http.client as http import http.client as http
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import requests
from glance.tests.functional.v2 import metadef_base from glance.tests.functional.v2 import metadef_base
@@ -25,21 +24,19 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
def setUp(self): def setUp(self):
super(TestMetadefObjects, self).setUp() super(TestMetadefObjects, self).setUp()
self.cleanup() self.start_server(enable_cache=False)
self.api_server.deployment_flavor = 'noauth'
self.start_servers(**self.__dict__.copy())
def test_metadata_objects_lifecycle(self): def test_metadata_objects_lifecycle(self):
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace # Create a namespace
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
namespace_name = 'MyNamespace' namespace_name = 'MyNamespace'
data = jsonutils.dumps({ data = {
"namespace": namespace_name, "namespace": namespace_name,
"display_name": "My User Friendly Namespace", "display_name": "My User Friendly Namespace",
"description": "My description", "description": "My description",
@@ -47,58 +44,55 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
"protected": False, "protected": False,
"owner": "The Test Owner" "owner": "The Test Owner"
} }
) response = self.api_post(path, headers=headers, json=data)
response = requests.post(path, headers=headers, data=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Metadata objects should not exist # Metadata objects should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace/objects/object1') path = '/v2/metadefs/namespaces/MyNamespace/objects/object1'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a object # Create a object
path = self._url('/v2/metadefs/namespaces/MyNamespace/objects') path = '/v2/metadefs/namespaces/MyNamespace/objects'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
metadata_object_name = "object1" metadata_object_name = "object1"
data = jsonutils.dumps( data = {
{ "name": metadata_object_name,
"name": metadata_object_name, "description": "object1 description.",
"description": "object1 description.", "required": [
"required": [ "property1"
"property1" ],
], "properties": {
"properties": { "property1": {
"property1": { "type": "integer",
"type": "integer", "title": "property1",
"title": "property1", "description": "property1 description",
"description": "property1 description", "operators": ["<all-in>"],
"operators": ["<all-in>"], "default": 100,
"default": 100, "minimum": 100,
"minimum": 100, "maximum": 30000369
"maximum": 30000369 },
}, "property2": {
"property2": { "type": "string",
"type": "string", "title": "property2",
"title": "property2", "description": "property2 description ",
"description": "property2 description ", "default": "value2",
"default": "value2", "minLength": 2,
"minLength": 2, "maxLength": 50
"maxLength": 50
}
} }
} }
) }
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Attempt to insert a duplicate # Attempt to insert a duplicate
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Get the metadata object created above # Get the metadata object created above
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace_name, metadata_object_name)) namespace_name, metadata_object_name)
response = requests.get(path, response = self.api_get(path,
headers=self._headers()) headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
metadata_object = jsonutils.loads(response.text) metadata_object = jsonutils.loads(response.text)
@@ -166,40 +160,38 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
) )
# The metadata_object should be mutable # The metadata_object should be mutable
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace_name, metadata_object_name)) namespace_name, metadata_object_name)
media_type = 'application/json' media_type = 'application/json'
headers = self._headers({'content-type': media_type}) headers = self._headers({'content-type': media_type})
metadata_object_name = "object1-UPDATED" metadata_object_name = "object1-UPDATED"
data = jsonutils.dumps( data = {
{ "name": metadata_object_name,
"name": metadata_object_name, "description": "desc-UPDATED",
"description": "desc-UPDATED", "required": [
"required": [ "property2"
"property2" ],
], "properties": {
"properties": { 'property1': {
'property1': { 'type': 'integer',
'type': 'integer', "title": "property1",
"title": "property1", 'description': 'p1 desc-UPDATED',
'description': 'p1 desc-UPDATED', 'default': 500,
'default': 500, 'minimum': 500,
'minimum': 500, 'maximum': 1369
'maximum': 1369 },
}, "property2": {
"property2": { "type": "string",
"type": "string", "title": "property2",
"title": "property2", "description": "p2 desc-UPDATED",
"description": "p2 desc-UPDATED", 'operators': ['<or>'],
'operators': ['<or>'], "default": "value2-UPDATED",
"default": "value2-UPDATED", "minLength": 5,
"minLength": 5, "maxLength": 150
"maxLength": 150
}
} }
} }
) }
response = requests.put(path, headers=headers, data=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned metadata_object should reflect the changes # Returned metadata_object should reflect the changes
@@ -222,9 +214,9 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(150, updated_property2['maxLength']) self.assertEqual(150, updated_property2['maxLength'])
# Updates should persist across requests # Updates should persist across requests
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace_name, metadata_object_name)) namespace_name, metadata_object_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(200, response.status_code) self.assertEqual(200, response.status_code)
self.assertEqual('object1-UPDATED', metadata_object['name']) self.assertEqual('object1-UPDATED', metadata_object['name'])
self.assertEqual('desc-UPDATED', metadata_object['description']) self.assertEqual('desc-UPDATED', metadata_object['description'])
@@ -244,15 +236,15 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(150, updated_property2['maxLength']) self.assertEqual(150, updated_property2['maxLength'])
# Deletion of metadata_object object1 # Deletion of metadata_object object1
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace_name, metadata_object_name)) namespace_name, metadata_object_name)
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# metadata_object object1 should not exist # metadata_object object1 should not exist
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace_name, metadata_object_name)) namespace_name, metadata_object_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
def _create_object(self, namespaces): def _create_object(self, namespaces):
@@ -273,11 +265,11 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
}, },
} }
} }
path = self._url('/v2/metadefs/namespaces/%s/objects' % path = ('/v2/metadefs/namespaces/%s/'
namespace['namespace']) 'objects') % namespace['namespace']
response = requests.post(path, headers=headers, json=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
obj_metadata = response.json() obj_metadata = jsonutils.loads(response.text)
metadef_objects = dict() metadef_objects = dict()
metadef_objects[namespace['namespace']] = obj_metadata['name'] metadef_objects[namespace['namespace']] = obj_metadata['name']
objects.append(metadef_objects) objects.append(metadef_objects)
@@ -285,7 +277,7 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
return objects return objects
def _update_object(self, path, headers, data, namespace): def _update_object(self, path, headers, data, namespace):
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
expected_object = { expected_object = {
@@ -298,21 +290,21 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
data['name']) data['name'])
} }
# Returned metadata_object should reflect the changes # Returned metadata_object should reflect the changes
metadata_object = response.json() metadata_object = jsonutils.loads(response.text)
metadata_object.pop('created_at') metadata_object.pop('created_at')
metadata_object.pop('updated_at') metadata_object.pop('updated_at')
self.assertEqual(metadata_object, expected_object) self.assertEqual(metadata_object, expected_object)
# Updates should persist across requests # Updates should persist across requests
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
metadata_object = response.json() metadata_object = jsonutils.loads(response.text)
metadata_object.pop('created_at') metadata_object.pop('created_at')
metadata_object.pop('updated_at') metadata_object.pop('updated_at')
self.assertEqual(metadata_object, expected_object) self.assertEqual(metadata_object, expected_object)
def test_role_base_metadata_objects_lifecycle(self): def test_role_base_metadata_objects_lifecycle(self):
# Create public and private namespaces for tenant1 and tenant2 # Create public and private namespaces for tenant1 and tenant2
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
tenant1_namespaces = [] tenant1_namespaces = []
tenant2_namespaces = [] tenant2_namespaces = []
@@ -328,6 +320,7 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
} }
namespace = self.create_namespace(path, headers, namespace = self.create_namespace(path, headers,
namespace_data) namespace_data)
namespace = jsonutils.loads(namespace.text)
self.assertNamespacesEqual(namespace, namespace_data) self.assertNamespacesEqual(namespace, namespace_data)
if tenant == self.tenant1: if tenant == self.tenant1:
tenant1_namespaces.append(namespace) tenant1_namespaces.append(namespace)
@@ -344,10 +337,9 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for obj in objects: for obj in objects:
for namespace, object_name in obj.items(): for namespace, object_name in obj.items():
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace, object_name)) namespace, object_name)
headers = headers response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
if namespace.split('_')[1] == 'public': if namespace.split('_')[1] == 'public':
expected = http.OK expected = http.OK
else: else:
@@ -355,12 +347,11 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
path = self._url( path = '/v2/metadefs/namespaces/%s/objects' % namespace
'/v2/metadefs/namespaces/%s/objects' % namespace) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
if expected == http.OK: if expected == http.OK:
resp_objs = response.json()['objects'] resp_objs = jsonutils.loads(response.text)['objects']
self.assertEqual( self.assertEqual(
sorted(obj.values()), sorted(obj.values()),
sorted([x['name'] for x in resp_objs])) sorted([x['name'] for x in resp_objs]))
@@ -392,10 +383,10 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
} }
} }
# Update object should fail with non admin role # Update object should fail with non admin role
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace, object_name)) namespace, object_name)
headers['X-Roles'] = "reader,member" headers['X-Roles'] = "reader,member"
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Should work with admin role # Should work with admin role
@@ -406,9 +397,9 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
# Delete object should not be allowed to non admin role # Delete object should not be allowed to non admin role
for obj in total_objects: for obj in total_objects:
for namespace, object_name in obj.items(): for namespace, object_name in obj.items():
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace, object_name)) namespace, object_name)
response = requests.delete( response = self.api_delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace.split('_')[0] 'X-Tenant-Id': namespace.split('_')[0]
@@ -419,11 +410,11 @@ class TestMetadefObjects(metadef_base.MetadefFunctionalTestBase):
headers = self._headers() headers = self._headers()
for obj in total_objects: for obj in total_objects:
for namespace, object_name in obj.items(): for namespace, object_name in obj.items():
path = self._url('/v2/metadefs/namespaces/%s/objects/%s' % path = '/v2/metadefs/namespaces/%s/objects/%s' % (
(namespace, object_name)) namespace, object_name)
response = requests.delete(path, headers=headers) response = self.api_delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Deleted objects should not be exist # Deleted objects should not exist
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)

View File

@@ -16,7 +16,6 @@
import http.client as http import http.client as http
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import requests
from glance.tests.functional.v2 import metadef_base from glance.tests.functional.v2 import metadef_base
@@ -25,23 +24,21 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
def setUp(self): def setUp(self):
super(TestNamespaceProperties, self).setUp() super(TestNamespaceProperties, self).setUp()
self.cleanup() self.start_server(enable_cache=False)
self.api_server.deployment_flavor = 'noauth'
self.start_servers(**self.__dict__.copy())
def test_properties_lifecycle(self): def test_properties_lifecycle(self):
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace # Create a namespace
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
namespace_name = 'MyNamespace' namespace_name = 'MyNamespace'
resource_type_name = 'MyResourceType' resource_type_name = 'MyResourceType'
resource_type_prefix = 'MyPrefix' resource_type_prefix = 'MyPrefix'
data = jsonutils.dumps({ data = {
"namespace": namespace_name, "namespace": namespace_name,
"display_name": "My User Friendly Namespace", "display_name": "My User Friendly Namespace",
"description": "My description", "description": "My description",
@@ -54,43 +51,40 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
"prefix": resource_type_prefix "prefix": resource_type_prefix
} }
] ]
}) }
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Property1 should not exist # Property1 should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace/properties' path = '/v2/metadefs/namespaces/MyNamespace/properties/property1'
'/property1') response = self.api_get(path, headers=self._headers())
response = requests.get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a property # Create a property
path = self._url('/v2/metadefs/namespaces/MyNamespace/properties') path = '/v2/metadefs/namespaces/MyNamespace/properties'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
property_name = "property1" property_name = "property1"
data = jsonutils.dumps( data = {
{ "name": property_name,
"name": property_name, "type": "integer",
"type": "integer", "title": "property1",
"title": "property1", "description": "property1 description",
"description": "property1 description", "default": 100,
"default": 100, "minimum": 100,
"minimum": 100, "maximum": 30000369,
"maximum": 30000369, "readonly": False,
"readonly": False, }
} response = self.api_post(path, headers=headers, json=data)
)
response = requests.post(path, headers=headers, data=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Attempt to insert a duplicate # Attempt to insert a duplicate
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Get the property created above # Get the property created above
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace_name, property_name)) namespace_name, property_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
property_object = jsonutils.loads(response.text) property_object = jsonutils.loads(response.text)
self.assertEqual("integer", property_object['type']) self.assertEqual("integer", property_object['type'])
@@ -102,19 +96,19 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(30000369, property_object['maximum']) self.assertEqual(30000369, property_object['maximum'])
# Get the property with specific resource type association # Get the property with specific resource type association
path = self._url('/v2/metadefs/namespaces/%s/properties/%s%s' % ( path = '/v2/metadefs/namespaces/%s/properties/%s%s' % (
namespace_name, property_name, '='.join(['?resource_type', namespace_name, property_name, '='.join(['?resource_type',
resource_type_name]))) resource_type_name]))
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Get the property with prefix and specific resource type association # Get the property with prefix and specific resource type association
property_name_with_prefix = ''.join([resource_type_prefix, property_name_with_prefix = ''.join([resource_type_prefix,
property_name]) property_name])
path = self._url('/v2/metadefs/namespaces/%s/properties/%s%s' % ( path = '/v2/metadefs/namespaces/%s/properties/%s%s' % (
namespace_name, property_name_with_prefix, '='.join([ namespace_name, property_name_with_prefix, '='.join([
'?resource_type', resource_type_name]))) '?resource_type', resource_type_name]))
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
property_object = jsonutils.loads(response.text) property_object = jsonutils.loads(response.text)
self.assertEqual("integer", property_object['type']) self.assertEqual("integer", property_object['type'])
@@ -153,25 +147,23 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(property_object[key], value, key) self.assertEqual(property_object[key], value, key)
# The property should be mutable # The property should be mutable
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace_name, property_name)) namespace_name, property_name)
media_type = 'application/json' media_type = 'application/json'
headers = self._headers({'content-type': media_type}) headers = self._headers({'content-type': media_type})
property_name = "property1-UPDATED" property_name = "property1-UPDATED"
data = jsonutils.dumps( data = {
{ "name": property_name,
"name": property_name, "type": "string",
"type": "string", "title": "string property",
"title": "string property", "description": "desc-UPDATED",
"description": "desc-UPDATED", "operators": ["<or>"],
"operators": ["<or>"], "default": "value-UPDATED",
"default": "value-UPDATED", "minLength": 5,
"minLength": 5, "maxLength": 10,
"maxLength": 10, "readonly": True,
"readonly": True, }
} response = self.api_put(path, headers=headers, json=data)
)
response = requests.put(path, headers=headers, data=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned property should reflect the changes # Returned property should reflect the changes
@@ -185,9 +177,10 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
self.assertTrue(property_object['readonly']) self.assertTrue(property_object['readonly'])
# Updates should persist across requests # Updates should persist across requests
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace_name, property_name)) namespace_name, property_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
property_object = jsonutils.loads(response.text)
self.assertEqual('string', property_object['type']) self.assertEqual('string', property_object['type'])
self.assertEqual('desc-UPDATED', property_object['description']) self.assertEqual('desc-UPDATED', property_object['description'])
self.assertEqual('value-UPDATED', property_object['default']) self.assertEqual('value-UPDATED', property_object['default'])
@@ -196,15 +189,15 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(10, property_object['maxLength']) self.assertEqual(10, property_object['maxLength'])
# Deletion of property property1 # Deletion of property property1
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace_name, property_name)) namespace_name, property_name)
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# property1 should not exist # property1 should not exist
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace_name, property_name)) namespace_name, property_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
def _create_properties(self, namespaces): def _create_properties(self, namespaces):
@@ -217,11 +210,11 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
"title": "property", "title": "property",
"description": "property description", "description": "property description",
} }
path = self._url('/v2/metadefs/namespaces/%s/properties' % path = ('/v2/metadefs/namespaces/%s/'
namespace['namespace']) 'properties') % namespace['namespace']
response = requests.post(path, headers=headers, json=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
prop_metadata = response.json() prop_metadata = jsonutils.loads(response.text)
metadef_property = dict() metadef_property = dict()
metadef_property[namespace['namespace']] = prop_metadata['name'] metadef_property[namespace['namespace']] = prop_metadata['name']
properties.append(metadef_property) properties.append(metadef_property)
@@ -230,22 +223,23 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
def _update_property(self, path, headers, data): def _update_property(self, path, headers, data):
# The property should be mutable # The property should be mutable
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned property should reflect the changes # Returned property should reflect the changes
property_object = response.json() property_object = jsonutils.loads(response.text)
self.assertEqual('string', property_object['type']) self.assertEqual('string', property_object['type'])
self.assertEqual(data['description'], property_object['description']) self.assertEqual(data['description'], property_object['description'])
# Updates should persist across requests # Updates should persist across requests
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
property_object = jsonutils.loads(response.text)
self.assertEqual('string', property_object['type']) self.assertEqual('string', property_object['type'])
self.assertEqual(data['description'], property_object['description']) self.assertEqual(data['description'], property_object['description'])
def test_role_base_metadata_properties_lifecycle(self): def test_role_base_metadata_properties_lifecycle(self):
# Create public and private namespaces for tenant1 and tenant2 # Create public and private namespaces for tenant1 and tenant2
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
tenant1_namespaces = [] tenant1_namespaces = []
tenant2_namespaces = [] tenant2_namespaces = []
@@ -261,6 +255,7 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
} }
namespace = self.create_namespace(path, headers, namespace = self.create_namespace(path, headers,
namespace_data) namespace_data)
namespace = jsonutils.loads(namespace.text)
self.assertNamespacesEqual(namespace, namespace_data) self.assertNamespacesEqual(namespace, namespace_data)
if tenant == self.tenant1: if tenant == self.tenant1:
tenant1_namespaces.append(namespace) tenant1_namespaces.append(namespace)
@@ -277,10 +272,9 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for prop in properties: for prop in properties:
for namespace, property_name in prop.items(): for namespace, property_name in prop.items():
path = \ path = '/v2/metadefs/namespaces/%s/properties/%s' % (
self._url('/v2/metadefs/namespaces/%s/properties/%s' % namespace, property_name)
(namespace, property_name)) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
if namespace.split('_')[1] == 'public': if namespace.split('_')[1] == 'public':
expected = http.OK expected = http.OK
else: else:
@@ -291,12 +285,12 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
# Make sure the same holds for listing # Make sure the same holds for listing
path = self._url( path = '/v2/metadefs/namespaces/%s/properties' % namespace
'/v2/metadefs/namespaces/%s/properties' % namespace) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
if expected == http.OK: if expected == http.OK:
resp_props = response.json()['properties'].values() resp_props = jsonutils.loads(
response.text)['properties'].values()
self.assertEqual( self.assertEqual(
sorted(prop.values()), sorted(prop.values()),
sorted([x['name'] sorted([x['name']
@@ -320,12 +314,12 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
"title": "string property", "title": "string property",
"description": "desc-UPDATED", "description": "desc-UPDATED",
} }
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace, property_name)) namespace, property_name)
# Update property should fail with non admin role # Update property should fail with non admin role
headers['X-Roles'] = "reader,member" headers['X-Roles'] = "reader,member"
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Should work with admin role # Should work with admin role
@@ -336,9 +330,9 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
# Delete property should not be allowed to non admin role # Delete property should not be allowed to non admin role
for prop in total_properties: for prop in total_properties:
for namespace, property_name in prop.items(): for namespace, property_name in prop.items():
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace, property_name)) namespace, property_name)
response = requests.delete( response = self.api_delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace.split('_')[0] 'X-Tenant-Id': namespace.split('_')[0]
@@ -349,11 +343,11 @@ class TestNamespaceProperties(metadef_base.MetadefFunctionalTestBase):
headers = self._headers() headers = self._headers()
for prop in total_properties: for prop in total_properties:
for namespace, property_name in prop.items(): for namespace, property_name in prop.items():
path = self._url('/v2/metadefs/namespaces/%s/properties/%s' % path = '/v2/metadefs/namespaces/%s/properties/%s' % (
(namespace, property_name)) namespace, property_name)
response = requests.delete(path, headers=headers) response = self.api_delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Deleted property should not be exist # Deleted property should not exist
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)

View File

@@ -16,7 +16,6 @@
import http.client as http import http.client as http
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import requests
from glance.tests.functional.v2 import metadef_base from glance.tests.functional.v2 import metadef_base
@@ -25,61 +24,55 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
def setUp(self): def setUp(self):
super(TestMetadefResourceTypes, self).setUp() super(TestMetadefResourceTypes, self).setUp()
self.cleanup() self.start_server(enable_cache=False)
self.api_server.deployment_flavor = 'noauth'
self.start_servers(**self.__dict__.copy())
def test_metadef_resource_types_lifecycle(self): def test_metadef_resource_types_lifecycle(self):
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace # Create a namespace
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
namespace_name = 'MyNamespace' namespace_name = 'MyNamespace'
data = jsonutils.dumps({ data = {
"namespace": namespace_name, "namespace": namespace_name,
"display_name": "My User Friendly Namespace", "display_name": "My User Friendly Namespace",
"description": "My description", "description": "My description",
"visibility": "public", "visibility": "public",
"protected": False, "protected": False,
"owner": "The Test Owner" "owner": "The Test Owner"
}) }
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Resource type should not exist # Resource type should not exist
path = self._url('/v2/metadefs/namespaces/%s/resource_types' % path = '/v2/metadefs/namespaces/%s/resource_types' % (namespace_name)
(namespace_name)) response = self.api_get(path, headers=self._headers())
response = requests.get(path, headers=self._headers())
metadef_resource_type = jsonutils.loads(response.text) metadef_resource_type = jsonutils.loads(response.text)
self.assertEqual( self.assertEqual(
0, len(metadef_resource_type['resource_type_associations'])) 0, len(metadef_resource_type['resource_type_associations']))
# Create a resource type # Create a resource type
path = self._url('/v2/metadefs/namespaces/MyNamespace/resource_types') path = '/v2/metadefs/namespaces/MyNamespace/resource_types'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
metadef_resource_type_name = "resource_type1" metadef_resource_type_name = "resource_type1"
data = jsonutils.dumps( data = {
{ "name": "resource_type1",
"name": "resource_type1", "prefix": "hw_",
"prefix": "hw_", "properties_target": "image",
"properties_target": "image", }
} response = self.api_post(path, headers=headers, json=data)
)
response = requests.post(path, headers=headers, data=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Attempt to insert a duplicate # Attempt to insert a duplicate
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Get the metadef resource type created above # Get the metadef resource type created above
path = self._url('/v2/metadefs/namespaces/%s/resource_types' % path = '/v2/metadefs/namespaces/%s/resource_types' % (namespace_name)
(namespace_name)) response = self.api_get(path,
response = requests.get(path,
headers=self._headers()) headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
metadef_resource_type = jsonutils.loads(response.text) metadef_resource_type = jsonutils.loads(response.text)
@@ -118,15 +111,14 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
value, key) value, key)
# Deassociate of metadef resource type resource_type1 # Deassociate of metadef resource type resource_type1
path = self._url('/v2/metadefs/namespaces/%s/resource_types/%s' % path = '/v2/metadefs/namespaces/%s/resource_types/%s' % (
(namespace_name, metadef_resource_type_name)) namespace_name, metadef_resource_type_name)
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# resource_type1 should not exist # resource_type1 should not exist
path = self._url('/v2/metadefs/namespaces/%s/resource_types' % path = '/v2/metadefs/namespaces/%s/resource_types' % (namespace_name)
(namespace_name)) response = self.api_get(path, headers=self._headers())
response = requests.get(path, headers=self._headers())
metadef_resource_type = jsonutils.loads(response.text) metadef_resource_type = jsonutils.loads(response.text)
self.assertEqual( self.assertEqual(
0, len(metadef_resource_type['resource_type_associations'])) 0, len(metadef_resource_type['resource_type_associations']))
@@ -140,11 +132,11 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
"prefix": "hw_", "prefix": "hw_",
"properties_target": "image" "properties_target": "image"
} }
path = self._url('/v2/metadefs/namespaces/%s/resource_types' % path = ('/v2/metadefs/namespaces/%s/'
(namespace['namespace'])) 'resource_types') % (namespace['namespace'])
response = requests.post(path, headers=headers, json=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
rs_type = response.json() rs_type = jsonutils.loads(response.text)
resource_type = dict() resource_type = dict()
resource_type[namespace['namespace']] = rs_type['name'] resource_type[namespace['namespace']] = rs_type['name']
resource_types.append(resource_type) resource_types.append(resource_type)
@@ -153,7 +145,7 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
def test_role_base_metadef_resource_types_lifecycle(self): def test_role_base_metadef_resource_types_lifecycle(self):
# Create public and private namespaces for tenant1 and tenant2 # Create public and private namespaces for tenant1 and tenant2
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
tenant1_namespaces = [] tenant1_namespaces = []
tenant2_namespaces = [] tenant2_namespaces = []
@@ -169,6 +161,7 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
} }
namespace = self.create_namespace(path, headers, namespace = self.create_namespace(path, headers,
namespace_data) namespace_data)
namespace = jsonutils.loads(namespace.text)
self.assertNamespacesEqual(namespace, namespace_data) self.assertNamespacesEqual(namespace, namespace_data)
if tenant == self.tenant1: if tenant == self.tenant1:
tenant1_namespaces.append(namespace) tenant1_namespaces.append(namespace)
@@ -185,9 +178,9 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
headers = self._headers({'X-Tenant-Id': tenant, headers = self._headers({'X-Tenant-Id': tenant,
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for namespace in namespaces: for namespace in namespaces:
path = self._url('/v2/metadefs/namespaces/%s/resource_types' % path = ('/v2/metadefs/namespaces/%s/'
(namespace['namespace'])) 'resource_types') % (namespace['namespace'])
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
if namespace['visibility'] == 'public': if namespace['visibility'] == 'public':
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
else: else:
@@ -195,12 +188,12 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
def _check_resource_types(tenant, total_rs_types): def _check_resource_types(tenant, total_rs_types):
# Resource types are visible across tenants for all users # Resource types are visible across tenants for all users
path = self._url('/v2/metadefs/resource_types') path = '/v2/metadefs/resource_types'
headers = self._headers({'X-Tenant-Id': tenant, headers = self._headers({'X-Tenant-Id': tenant,
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
metadef_resource_type = response.json() metadef_resource_type = jsonutils.loads(response.text)
# The resource types list count should be same as the total # The resource types list count should be same as the total
# resource types created across the tenants. # resource types created across the tenants.
@@ -227,10 +220,9 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
# Disassociate resource type should not be allowed to non admin role # Disassociate resource type should not be allowed to non admin role
for resource_type in total_resource_types: for resource_type in total_resource_types:
for namespace, rs_type in resource_type.items(): for namespace, rs_type in resource_type.items():
path = \ path = '/v2/metadefs/namespaces/%s/resource_types/%s' % (
self._url('/v2/metadefs/namespaces/%s/resource_types/%s' % namespace, rs_type)
(namespace, rs_type)) response = self.api_delete(
response = requests.delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace.split('_')[0] 'X-Tenant-Id': namespace.split('_')[0]
@@ -241,19 +233,17 @@ class TestMetadefResourceTypes(metadef_base.MetadefFunctionalTestBase):
headers = self._headers() headers = self._headers()
for resource_type in total_resource_types: for resource_type in total_resource_types:
for namespace, rs_type in resource_type.items(): for namespace, rs_type in resource_type.items():
path = \ path = '/v2/metadefs/namespaces/%s/resource_types/%s' % (
self._url('/v2/metadefs/namespaces/%s/resource_types/%s' % namespace, rs_type)
(namespace, rs_type)) response = self.api_delete(path, headers=headers)
response = requests.delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Disassociated resource type should not be exist # Disassociated resource type should not be exist
# When the specified resource type is not associated with given # When the specified resource type is not associated with given
# namespace then it returns empty list in response instead of # namespace then it returns empty list in response instead of
# raising not found error # raising not found error
path = self._url( path = '/v2/metadefs/namespaces/%s/resource_types' % namespace
'/v2/metadefs/namespaces/%s/resource_types' % namespace) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers) metadef_resource_type = jsonutils.loads(response.text)
metadef_resource_type = response.json()
self.assertEqual( self.assertEqual(
[], metadef_resource_type['resource_type_associations']) [], metadef_resource_type['resource_type_associations'])

View File

@@ -16,7 +16,6 @@
import http.client as http import http.client as http
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import requests
from glance.tests.functional.v2 import metadef_base from glance.tests.functional.v2 import metadef_base
@@ -25,52 +24,49 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
def setUp(self): def setUp(self):
super(TestMetadefTags, self).setUp() super(TestMetadefTags, self).setUp()
self.cleanup() self.start_server(enable_cache=False)
self.api_server.deployment_flavor = 'noauth'
self.start_servers(**self.__dict__.copy())
def test_metadata_tags_lifecycle(self): def test_metadata_tags_lifecycle(self):
# Namespace should not exist # Namespace should not exist
path = self._url('/v2/metadefs/namespaces/MyNamespace') path = '/v2/metadefs/namespaces/MyNamespace'
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create a namespace # Create a namespace
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
namespace_name = 'MyNamespace' namespace_name = 'MyNamespace'
data = jsonutils.dumps({ data = {
"namespace": namespace_name, "namespace": namespace_name,
"display_name": "My User Friendly Namespace", "display_name": "My User Friendly Namespace",
"description": "My description", "description": "My description",
"visibility": "public", "visibility": "public",
"protected": False, "protected": False,
"owner": "The Test Owner"} "owner": "The Test Owner"
) }
response = requests.post(path, headers=headers, data=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Metadata tag should not exist # Metadata tag should not exist
metadata_tag_name = "tag1" metadata_tag_name = "tag1"
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace_name, metadata_tag_name)) namespace_name, metadata_tag_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create the metadata tag # Create the metadata tag
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
response = requests.post(path, headers=headers) response = self.api_post(path, headers=headers)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Get the metadata tag created above # Get the metadata tag created above
response = requests.get(path, response = self.api_get(path,
headers=self._headers()) headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
metadata_tag = jsonutils.loads(response.text) metadata_tag = jsonutils.loads(response.text)
self.assertEqual(metadata_tag_name, metadata_tag['name']) self.assertEqual(metadata_tag_name, metadata_tag['name'])
# Returned tag should match the created tag # Returned tag should match the created tag
metadata_tag = jsonutils.loads(response.text)
checked_keys = set([ checked_keys = set([
'name', 'name',
'created_at', 'created_at',
@@ -91,21 +87,19 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
# Try to create a duplicate metadata tag # Try to create a duplicate metadata tag
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
response = requests.post(path, headers=headers) response = self.api_post(path, headers=headers)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# The metadata_tag should be mutable # The metadata_tag should be mutable
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace_name, metadata_tag_name)) namespace_name, metadata_tag_name)
media_type = 'application/json' media_type = 'application/json'
headers = self._headers({'content-type': media_type}) headers = self._headers({'content-type': media_type})
metadata_tag_name = "tag1-UPDATED" metadata_tag_name = "tag1-UPDATED"
data = jsonutils.dumps( data = {
{ "name": metadata_tag_name
"name": metadata_tag_name }
} response = self.api_put(path, headers=headers, json=data)
)
response = requests.put(path, headers=headers, data=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned metadata_tag should reflect the changes # Returned metadata_tag should reflect the changes
@@ -113,79 +107,93 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
self.assertEqual('tag1-UPDATED', metadata_tag['name']) self.assertEqual('tag1-UPDATED', metadata_tag['name'])
# Updates should persist across requests # Updates should persist across requests
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace_name, metadata_tag_name)) namespace_name, metadata_tag_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
self.assertEqual('tag1-UPDATED', metadata_tag['name']) self.assertEqual('tag1-UPDATED', metadata_tag['name'])
# Deletion of metadata_tag_name # Deletion of metadata_tag_name
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace_name, metadata_tag_name)) namespace_name, metadata_tag_name)
response = requests.delete(path, headers=self._headers()) response = self.api_delete(path, headers=self._headers())
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# metadata_tag_name should not exist # metadata_tag_name should not exist
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace_name, metadata_tag_name)) namespace_name, metadata_tag_name)
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create multiple tags. # Create multiple tags.
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % namespace_name
(namespace_name))
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
data = jsonutils.dumps( data = {
{"tags": [{"name": "tag1"}, {"name": "tag2"}, {"name": "tag3"}]} "tags": [
) {"name": "tag1"},
response = requests.post(path, headers=headers, data=data) {"name": "tag2"},
{"name": "tag3"}
]
}
response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# List out the three new tags. # List out the three new tags.
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
tags = jsonutils.loads(response.text)['tags'] tags = jsonutils.loads(response.text)['tags']
self.assertEqual(3, len(tags)) self.assertEqual(3, len(tags))
# Attempt to create bogus duplicate tag4 # Attempt to create bogus duplicate tag4
data = jsonutils.dumps( data = {
{"tags": [{"name": "tag4"}, {"name": "tag5"}, {"name": "tag4"}]} "tags": [
) {"name": "tag4"},
response = requests.post(path, headers=headers, data=data) {"name": "tag5"},
{"name": "tag4"}
]
}
response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Verify the previous 3 still exist # Verify the previous 3 still exist
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
tags = jsonutils.loads(response.text)['tags'] tags = jsonutils.loads(response.text)['tags']
self.assertEqual(3, len(tags)) self.assertEqual(3, len(tags))
# Create new tags and append to existing tags. # Create new tags and append to existing tags.
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % namespace_name
(namespace_name))
headers = self._headers({'content-type': 'application/json', headers = self._headers({'content-type': 'application/json',
'X-Openstack-Append': 'True'}) 'X-Openstack-Append': 'True'})
data = jsonutils.dumps( data = {
{"tags": [{"name": "tag4"}, {"name": "tag5"}, {"name": "tag6"}]} "tags": [
) {"name": "tag4"},
response = requests.post(path, headers=headers, data=data) {"name": "tag5"},
{"name": "tag6"}
]
}
response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# List out all six tags. # List out all six tags.
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
tags = jsonutils.loads(response.text)['tags'] tags = jsonutils.loads(response.text)['tags']
self.assertEqual(6, len(tags)) self.assertEqual(6, len(tags))
# Attempt to create duplicate existing tag6 # Attempt to create duplicate existing tag6
data = jsonutils.dumps( data = {
{"tags": [{"name": "tag6"}, {"name": "tag7"}, {"name": "tag8"}]} "tags": [
) {"name": "tag6"},
response = requests.post(path, headers=headers, data=data) {"name": "tag7"},
{"name": "tag8"}
]
}
response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.CONFLICT, response.status_code) self.assertEqual(http.CONFLICT, response.status_code)
# Verify the previous 6 still exist # Verify the previous 6 still exist
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
tags = jsonutils.loads(response.text)['tags'] tags = jsonutils.loads(response.text)['tags']
self.assertEqual(6, len(tags)) self.assertEqual(6, len(tags))
@@ -195,11 +203,11 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
for namespace in namespaces: for namespace in namespaces:
headers = self._headers({'X-Tenant-Id': namespace['owner']}) headers = self._headers({'X-Tenant-Id': namespace['owner']})
tag_name = "tag_of_%s" % (namespace['namespace']) tag_name = "tag_of_%s" % (namespace['namespace'])
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace['namespace'], tag_name)) namespace['namespace'], tag_name)
response = requests.post(path, headers=headers) response = self.api_post(path, headers=headers)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
tag_metadata = response.json() tag_metadata = jsonutils.loads(response.text)
metadef_tags = dict() metadef_tags = dict()
metadef_tags[namespace['namespace']] = tag_metadata['name'] metadef_tags[namespace['namespace']] = tag_metadata['name']
tags.append(metadef_tags) tags.append(metadef_tags)
@@ -208,20 +216,20 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
def _update_tags(self, path, headers, data): def _update_tags(self, path, headers, data):
# The tag should be mutable # The tag should be mutable
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.OK, response.status_code, response.text) self.assertEqual(http.OK, response.status_code, response.text)
# Returned metadata_tag should reflect the changes # Returned metadata_tag should reflect the changes
metadata_tag = response.json() metadata_tag = jsonutils.loads(response.text)
self.assertEqual(data['name'], metadata_tag['name']) self.assertEqual(data['name'], metadata_tag['name'])
# Updates should persist across requests # Updates should persist across requests
response = requests.get(path, headers=self._headers()) response = self.api_get(path, headers=self._headers())
self.assertEqual(http.OK, response.status_code) self.assertEqual(http.OK, response.status_code)
self.assertEqual(data['name'], metadata_tag['name']) self.assertEqual(data['name'], metadata_tag['name'])
def test_role_base_metadata_tags_lifecycle(self): def test_role_base_metadata_tags_lifecycle(self):
# Create public and private namespaces for tenant1 and tenant2 # Create public and private namespaces for tenant1 and tenant2
path = self._url('/v2/metadefs/namespaces') path = '/v2/metadefs/namespaces'
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
tenant1_namespaces = [] tenant1_namespaces = []
tenant2_namespaces = [] tenant2_namespaces = []
@@ -237,6 +245,7 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
} }
namespace = self.create_namespace(path, headers, namespace = self.create_namespace(path, headers,
namespace_data) namespace_data)
namespace = jsonutils.loads(namespace.text)
self.assertNamespacesEqual(namespace, namespace_data) self.assertNamespacesEqual(namespace, namespace_data)
if tenant == self.tenant1: if tenant == self.tenant1:
tenant1_namespaces.append(namespace) tenant1_namespaces.append(namespace)
@@ -253,9 +262,9 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for tag in tags: for tag in tags:
for namespace, tag_name in tag.items(): for namespace, tag_name in tag.items():
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace, tag_name)) namespace, tag_name)
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
if namespace.split('_')[1] == 'public': if namespace.split('_')[1] == 'public':
expected = http.OK expected = http.OK
else: else:
@@ -266,12 +275,11 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
# Make sure the same holds for listing # Make sure the same holds for listing
path = self._url( path = '/v2/metadefs/namespaces/%s/tags' % namespace
'/v2/metadefs/namespaces/%s/tags' % namespace) response = self.api_get(path, headers=headers)
response = requests.get(path, headers=headers)
self.assertEqual(expected, response.status_code) self.assertEqual(expected, response.status_code)
if expected == http.OK: if expected == http.OK:
resp_props = response.json()['tags'] resp_props = jsonutils.loads(response.text)['tags']
self.assertEqual( self.assertEqual(
sorted(tag.values()), sorted(tag.values()),
sorted([x['name'] sorted([x['name']
@@ -291,12 +299,12 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
for namespace, tag_name in tag.items(): for namespace, tag_name in tag.items():
data = { data = {
"name": tag_name} "name": tag_name}
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace, tag_name)) namespace, tag_name)
# Update tag should fail with non admin role # Update tag should fail with non admin role
headers['X-Roles'] = "reader,member" headers['X-Roles'] = "reader,member"
response = requests.put(path, headers=headers, json=data) response = self.api_put(path, headers=headers, json=data)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Should work with admin role # Should work with admin role
@@ -307,9 +315,9 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
# Delete tags should not be allowed to non admin role # Delete tags should not be allowed to non admin role
for tag in total_tags: for tag in total_tags:
for namespace, tag_name in tag.items(): for namespace, tag_name in tag.items():
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace, tag_name)) namespace, tag_name)
response = requests.delete( response = self.api_delete(
path, headers=self._headers({ path, headers=self._headers({
'X-Roles': 'reader,member', 'X-Roles': 'reader,member',
'X-Tenant-Id': namespace.split('_')[0] 'X-Tenant-Id': namespace.split('_')[0]
@@ -320,13 +328,13 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
headers = self._headers() headers = self._headers()
for tag in total_tags: for tag in total_tags:
for namespace, tag_name in tag.items(): for namespace, tag_name in tag.items():
path = self._url('/v2/metadefs/namespaces/%s/tags/%s' % path = '/v2/metadefs/namespaces/%s/tags/%s' % (
(namespace, tag_name)) namespace, tag_name)
response = requests.delete(path, headers=headers) response = self.api_delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)
# Deleted tags should not be exist # Deleted tags should not exist
response = requests.get(path, headers=headers) response = self.api_get(path, headers=headers)
self.assertEqual(http.NOT_FOUND, response.status_code) self.assertEqual(http.NOT_FOUND, response.status_code)
# Create multiple tags should not be allowed to non admin role # Create multiple tags should not be allowed to non admin role
@@ -336,32 +344,29 @@ class TestMetadefTags(metadef_base.MetadefFunctionalTestBase):
"tags": [{"name": "tag1"}, {"name": "tag2"}, {"name": "tag3"}] "tags": [{"name": "tag1"}, {"name": "tag2"}, {"name": "tag3"}]
} }
for namespace in tenant1_namespaces: for namespace in tenant1_namespaces:
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % (
(namespace['namespace'])) namespace['namespace'])
response = requests.post(path, headers=headers, json=data) response = self.api_post(path, headers=headers, json=data)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Create multiple tags. # Create multiple tags.
headers = self._headers({'content-type': 'application/json'}) headers = self._headers({'content-type': 'application/json'})
for namespace in tenant1_namespaces: for namespace in tenant1_namespaces:
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % (namespace['namespace'])
(namespace['namespace'])) response = self.api_post(path, headers=headers, json=data)
response = requests.post(path, headers=headers, json=data)
self.assertEqual(http.CREATED, response.status_code) self.assertEqual(http.CREATED, response.status_code)
# Delete multiple tags should not be allowed with non admin role # Delete multiple tags should not be allowed with non admin role
headers = self._headers({'content-type': 'application/json', headers = self._headers({'content-type': 'application/json',
'X-Roles': 'reader,member'}) 'X-Roles': 'reader,member'})
for namespace in tenant1_namespaces: for namespace in tenant1_namespaces:
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % (namespace['namespace'])
(namespace['namespace'])) response = self.api_delete(path, headers=headers)
response = requests.delete(path, headers=headers)
self.assertEqual(http.FORBIDDEN, response.status_code) self.assertEqual(http.FORBIDDEN, response.status_code)
# Delete multiple tags created above created tags # Delete multiple tags created above created tags
headers = self._headers() headers = self._headers()
for namespace in tenant1_namespaces: for namespace in tenant1_namespaces:
path = self._url('/v2/metadefs/namespaces/%s/tags' % path = '/v2/metadefs/namespaces/%s/tags' % (namespace['namespace'])
(namespace['namespace'])) response = self.api_delete(path, headers=headers)
response = requests.delete(path, headers=headers)
self.assertEqual(http.NO_CONTENT, response.status_code) self.assertEqual(http.NO_CONTENT, response.status_code)