Add namespace tags client and tests
As in the doc following, there are namespace tags apis, this patch
is to add them to the code.
[doc]http://developer.openstack.org/api-ref/image/v2/metadefs-index.html
Change-Id: I92b2c58d11828eafd9f876a46581279bb9b26e3d
diff --git a/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
index 9d1a003..eaab1f0 100644
--- a/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
+++ b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
@@ -6,4 +6,5 @@
there are some apis are not included, add them.
* namespace_objects_client(v2)
+ * namespace_tags_client(v2)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 23bd628..cd4f820 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -143,6 +143,7 @@
cls.resource_types_client = cls.os.resource_types_client
cls.namespace_properties_client = cls.os.namespace_properties_client
cls.namespace_objects_client = cls.os.namespace_objects_client
+ cls.namespace_tags_client = cls.os.namespace_tags_client
cls.schemas_client = cls.os.schemas_client
def create_namespace(cls, namespace_name=None, visibility='public',
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_tags.py b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
new file mode 100644
index 0000000..186d9c8
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
@@ -0,0 +1,90 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.image import base
+from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest import test
+
+
+class MetadataNamespaceTagsTest(base.BaseV2ImageTest):
+ """Test the Metadata definition namespace tags basic functionality"""
+
+ tags = [
+ {
+ "name": "sample-tag1"
+ },
+ {
+ "name": "sample-tag2"
+ },
+ {
+ "name": "sample-tag3"
+ }
+ ]
+ tag_list = ["sample-tag1", "sample-tag2", "sample-tag3"]
+
+ def _create_namespace_tags(self, namespace):
+ # Create a namespace
+ namespace_tags = self.namespace_tags_client.create_namespace_tags(
+ namespace['namespace'], tags=self.tags)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.namespace_tags_client.delete_namespace_tags,
+ namespace['namespace'])
+ return namespace_tags
+
+ @test.idempotent_id('a2a3765e-3a6d-4f6d-a3a7-3cc3476aa876')
+ def test_create_list_delete_namespace_tags(self):
+ # Create a namespace
+ namespace = self.create_namespace()
+ self._create_namespace_tags(namespace)
+ # List namespace tags
+ body = self.namespace_tags_client.list_namespace_tags(
+ namespace['namespace'])
+ self.assertTrue(3, len(body['tags']))
+ self.assertIn(body['tags'][0]['name'], self.tag_list)
+ self.assertIn(body['tags'][1]['name'], self.tag_list)
+ self.assertIn(body['tags'][2]['name'], self.tag_list)
+ # Delete all tag definitions
+ self.namespace_tags_client.delete_namespace_tags(
+ namespace['namespace'])
+ body = self.namespace_tags_client.list_namespace_tags(
+ namespace['namespace'])
+ self.assertEqual([], body['tags'])
+
+ @test.idempotent_id('a2a3765e-1a2c-3f6d-a3a7-3cc3466ab875')
+ def test_create_update_delete_tag(self):
+ # Create a namespace
+ namespace = self.create_namespace()
+ self._create_namespace_tags(namespace)
+ # Create a tag
+ tag_name = data_utils.rand_name('tag_name')
+ self.namespace_tags_client.create_namespace_tag(
+ namespace=namespace['namespace'], tag_name=tag_name)
+
+ body = self.namespace_tags_client.show_namespace_tag(
+ namespace['namespace'], tag_name)
+ self.assertEqual(tag_name, body['name'])
+ # Update tag definition
+ update_tag_definition = data_utils.rand_name('update-tag')
+ body = self.namespace_tags_client.update_namespace_tag(
+ namespace['namespace'], tag_name=tag_name,
+ name=update_tag_definition)
+ self.assertEqual(update_tag_definition, body['name'])
+ # Delete tag definition
+ self.namespace_tags_client.delete_namespace_tag(
+ namespace['namespace'], update_tag_definition)
+ # List namespace tags and validate deletion
+ namespace_tags = [
+ namespace_tag['name'] for namespace_tag in
+ self.namespace_tags_client.list_namespace_tags(
+ namespace['namespace'])['tags']]
+ self.assertNotIn(update_tag_definition, namespace_tags)
diff --git a/tempest/clients.py b/tempest/clients.py
index 8093a72..a4306d8 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -132,6 +132,8 @@
self.schemas_client = self.image_v2.SchemasClient()
self.namespace_properties_client = \
self.image_v2.NamespacePropertiesClient()
+ self.namespace_tags_client = \
+ self.image_v2.NamespaceTagsClient()
def _set_compute_clients(self):
self.agents_client = self.compute.AgentsClient()
diff --git a/tempest/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index a35ce17..7d973e5 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -19,11 +19,13 @@
NamespaceObjectsClient
from tempest.lib.services.image.v2.namespace_properties_client import \
NamespacePropertiesClient
+from tempest.lib.services.image.v2.namespace_tags_client import \
+ NamespaceTagsClient
from tempest.lib.services.image.v2.namespaces_client import NamespacesClient
from tempest.lib.services.image.v2.resource_types_client import \
ResourceTypesClient
from tempest.lib.services.image.v2.schemas_client import SchemasClient
__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespaceObjectsClient',
- 'NamespacePropertiesClient', 'NamespacesClient',
- 'ResourceTypesClient', 'SchemasClient']
+ 'NamespacePropertiesClient', 'NamespaceTagsClient',
+ 'NamespacesClient', 'ResourceTypesClient', 'SchemasClient']
diff --git a/tempest/lib/services/image/v2/namespace_tags_client.py b/tempest/lib/services/image/v2/namespace_tags_client.py
new file mode 100644
index 0000000..ac8b569
--- /dev/null
+++ b/tempest/lib/services/image/v2/namespace_tags_client.py
@@ -0,0 +1,119 @@
+# Copyright 2016 EasyStack.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class NamespaceTagsClient(rest_client.RestClient):
+ api_version = "v2"
+
+ def create_namespace_tag(self, namespace, tag_name):
+ """Adds a tag to the list of namespace tag definitions.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-tag-definition
+ """
+ url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+ tag_name)
+ resp, body = self.post(url, None)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_namespace_tag(self, namespace, tag_name):
+ """Gets a definition for a tag.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#get_tag_definition
+ """
+ url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+ tag_name)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_namespace_tag(self, namespace, tag_name, **kwargs):
+ """Renames a tag definition.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#update-tag-definition
+ """
+ url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+ tag_name)
+ data = json.dumps(kwargs)
+ resp, body = self.put(url, data)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_namespace_tag(self, namespace, tag_name):
+ """Deletes a tag definition within a namespace.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#delete-tag-definition
+ """
+ url = 'metadefs/namespaces/%s/tags/%s' % (namespace, tag_name)
+ resp, _ = self.delete(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def create_namespace_tags(self, namespace, **kwargs):
+ """Creates one or more tag definitions in a namespace.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-tags
+ """
+ url = 'metadefs/namespaces/%s/tags' % namespace
+ data = json.dumps(kwargs)
+ resp, body = self.post(url, data)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_namespace_tags(self, namespace, **params):
+ """Lists the tag definitions within a namespace.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#list-tags
+ """
+ url = 'metadefs/namespaces/%s/tags' % namespace
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_namespace_tags(self, namespace):
+ """Deletes all tag definitions within a namespace.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#delete-all-tag-definitions
+ """
+ url = 'metadefs/namespaces/%s/tags' % namespace
+ resp, _ = self.delete(url)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py b/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py
new file mode 100644
index 0000000..2faa5be
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py
@@ -0,0 +1,126 @@
+# Copyright 2016 EasyStack. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.image.v2 import namespace_tags_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestNamespaceTagsClient(base.BaseServiceTest):
+ FAKE_CREATE_SHOW_TAGS = {
+ "created_at": "2015-05-09T01:12:31Z",
+ "name": "added-sample-tag",
+ "updated_at": "2015-05-09T01:12:31Z"
+ }
+
+ FAKE_LIST_TAGS = {
+ "tags": [
+ {
+ "name": "sample-tag1"
+ },
+ {
+ "name": "sample-tag2"
+ },
+ {
+ "name": "sample-tag3"
+ }
+ ]
+ }
+
+ FAKE_UPDATE_TAGS = {"name": "new-tag-name"}
+
+ def setUp(self):
+ super(TestNamespaceTagsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = namespace_tags_client.NamespaceTagsClient(
+ fake_auth, 'image', 'regionOne')
+
+ def _test_create_namespace_tags(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_namespace_tags,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_SHOW_TAGS,
+ bytes_body, status=201,
+ namespace="OS::Compute::Hypervisor",
+ tags=[{"name": "sample-tag1"},
+ {"name": "sample-tag2"},
+ {"name": "sample-tag3"}])
+
+ def _test_list_namespace_tags(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_namespace_tags,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_LIST_TAGS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor")
+
+ def _test_create_namespace_tag_definition(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_namespace_tag,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ self.FAKE_CREATE_SHOW_TAGS,
+ bytes_body,
+ status=201,
+ namespace="OS::Compute::Hypervisor",
+ tag_name="added-sample-tag")
+
+ def _test_show_namespace_tag_definition(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_namespace_tag,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_CREATE_SHOW_TAGS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor",
+ tag_name="added-sample-tag")
+
+ def _test_update_namespace_tag_definition(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_namespace_tag,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ self.FAKE_UPDATE_OBJECTS,
+ bytes_body,
+ namespace="OS::Compute::Hypervisor",
+ tag_name="added-sample-tag",
+ name="new-tag-name")
+
+ def test_create_namespace_tags_with_str_body(self):
+ self._test_create_namespace_tags()
+
+ def test_create_namespace_tags_with_bytes_body(self):
+ self._test_create_namespace_tags(bytes_body=True)
+
+ def test_list_namespace_tags_with_str_body(self):
+ self._test_list_namespace_tags()
+
+ def test_list_namespace_tags_with_bytes_body(self):
+ self._test_list_namespace_tags(bytes_body=True)
+
+ def test_create_namespace_tag_with_str_body(self):
+ self._test_create_namespace_tag_definition()
+
+ def test_create_namespace_tag_with_bytes_body(self):
+ self._test_create_namespace_tag_definition(bytes_body=True)
+
+ def test_show_namespace_tag_with_str_body(self):
+ self._test_show_namespace_tag_definition()
+
+ def test_show_namespace_tag_with_bytes_body(self):
+ self._test_show_namespace_tag_definition(bytes_body=True)
+
+ def test_delete_all_namespace_tags(self):
+ self.check_service_client_function(
+ self.client.delete_namespace_tags,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {}, status=200,
+ namespace="OS::Compute::Hypervisor")