Merge "Add API test for tag"
diff --git a/neutron/tests/tempest/api/test_tag.py b/neutron/tests/tempest/api/test_tag.py
new file mode 100644
index 0000000..5cf6e23
--- /dev/null
+++ b/neutron/tests/tempest/api/test_tag.py
@@ -0,0 +1,174 @@
+# 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 import exceptions as lib_exc
+from tempest import test
+
+from neutron.tests.tempest.api import base
+
+
+class TagTestJSON(base.BaseAdminNetworkTest):
+
+ @classmethod
+ @test.requires_ext(extension="tag", service="network")
+ def resource_setup(cls):
+ super(TagTestJSON, cls).resource_setup()
+ cls.res_id = cls._create_resource()
+
+ def _get_and_compare_tags(self, tags):
+ res_body = self.client.get_tags(self.resource, self.res_id)
+ self.assertItemsEqual(tags, res_body['tags'])
+
+ def _test_tag_operations(self):
+ # create and get tags
+ tags = ['red', 'blue']
+ res_body = self.client.update_tags(self.resource, self.res_id, tags)
+ self.assertItemsEqual(tags, res_body['tags'])
+ self._get_and_compare_tags(tags)
+
+ # add a tag
+ self.client.update_tag(self.resource, self.res_id, 'green')
+ self._get_and_compare_tags(['red', 'blue', 'green'])
+
+ # update tag exist
+ self.client.update_tag(self.resource, self.res_id, 'red')
+ self._get_and_compare_tags(['red', 'blue', 'green'])
+
+ # replace tags
+ tags = ['red', 'yellow', 'purple']
+ res_body = self.client.update_tags(self.resource, self.res_id, tags)
+ self.assertItemsEqual(tags, res_body['tags'])
+ self._get_and_compare_tags(tags)
+
+ # get tag
+ self.client.get_tag(self.resource, self.res_id, 'red')
+
+ # get tag not exist
+ self.assertRaises(lib_exc.NotFound, self.client.get_tag,
+ self.resource, self.res_id, 'green')
+
+ # delete tag
+ self.client.delete_tag(self.resource, self.res_id, 'red')
+ self._get_and_compare_tags(['yellow', 'purple'])
+
+ # delete tag not exist
+ self.assertRaises(lib_exc.NotFound, self.client.delete_tag,
+ self.resource, self.res_id, 'green')
+
+ # delete tags
+ self.client.delete_tags(self.resource, self.res_id)
+ self._get_and_compare_tags([])
+
+
+class TagNetworkTestJSON(TagTestJSON):
+ resource = 'networks'
+
+ @classmethod
+ def _create_resource(cls):
+ network = cls.create_network()
+ return network['id']
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('5621062d-fbfb-4437-9d69-138c78ea4188')
+ def test_network_tags(self):
+ self._test_tag_operations()
+
+
+class TagFilterTestJSON(base.BaseAdminNetworkTest):
+ credentials = ['primary', 'alt', 'admin']
+ resource = 'networks'
+
+ @classmethod
+ @test.requires_ext(extension="tag", service="network")
+ def resource_setup(cls):
+ super(TagFilterTestJSON, cls).resource_setup()
+
+ res1_id = cls._create_resource('tag-res1')
+ res2_id = cls._create_resource('tag-res2')
+ res3_id = cls._create_resource('tag-res3')
+ res4_id = cls._create_resource('tag-res4')
+ # tag-res5: a resource without tags
+ cls._create_resource('tag-res5')
+
+ cls.client.update_tags(cls.resource, res1_id, ['red'])
+ cls.client.update_tags(cls.resource, res2_id, ['red', 'blue'])
+ cls.client.update_tags(cls.resource, res3_id,
+ ['red', 'blue', 'green'])
+ cls.client.update_tags(cls.resource, res4_id, ['green'])
+
+ @classmethod
+ def setup_clients(cls):
+ super(TagFilterTestJSON, cls).setup_clients()
+ cls.client = cls.alt_manager.network_client
+
+ def _assertEqualResources(self, expected, res):
+ actual = [n['name'] for n in res if n['name'].startswith('tag-res')]
+ self.assertEqual(set(expected), set(actual))
+
+ def _test_filter_tags(self):
+ # tags single
+ filters = {'tags': 'red'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res1', 'tag-res2', 'tag-res3'], res)
+
+ # tags multi
+ filters = {'tags': 'red,blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res2', 'tag-res3'], res)
+
+ # tags-any single
+ filters = {'tags-any': 'blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res2', 'tag-res3'], res)
+
+ # tags-any multi
+ filters = {'tags-any': 'red,blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res1', 'tag-res2', 'tag-res3'], res)
+
+ # not-tags single
+ filters = {'not-tags': 'red'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res4', 'tag-res5'], res)
+
+ # not-tags multi
+ filters = {'not-tags': 'red,blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res1', 'tag-res4', 'tag-res5'], res)
+
+ # not-tags-any single
+ filters = {'not-tags-any': 'blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res1', 'tag-res4', 'tag-res5'], res)
+
+ # not-tags-any multi
+ filters = {'not-tags-any': 'red,blue'}
+ res = self._list_resource(filters)
+ self._assertEqualResources(['tag-res4', 'tag-res5'], res)
+
+
+class TagFilterNetworkTestJSON(TagFilterTestJSON):
+ resource = 'networks'
+
+ @classmethod
+ def _create_resource(cls, name):
+ res = cls.create_network(network_name=name)
+ return res['id']
+
+ def _list_resource(self, filters):
+ res = self.client.list_networks(**filters)
+ return res['networks']
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('a66b5cca-7db2-40f5-a33d-8ac9f864e53e')
+ def test_filter_network_tags(self):
+ self._test_filter_tags()
diff --git a/neutron/tests/tempest/services/network/json/network_client.py b/neutron/tests/tempest/services/network/json/network_client.py
index 3b1a9a8..6b71f02 100644
--- a/neutron/tests/tempest/services/network/json/network_client.py
+++ b/neutron/tests/tempest/services/network/json/network_client.py
@@ -895,3 +895,44 @@
body = {'extensions': self.deserialize_list(body)}
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
+
+ def get_tags(self, resource_type, resource_id):
+ uri = '%s/%s/%s/tags' % (
+ self.uri_prefix, resource_type, resource_id)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = jsonutils.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def get_tag(self, resource_type, resource_id, tag):
+ uri = '%s/%s/%s/tags/%s' % (
+ self.uri_prefix, resource_type, resource_id, tag)
+ resp, body = self.get(uri)
+ self.expected_success(204, resp.status)
+
+ def update_tag(self, resource_type, resource_id, tag):
+ uri = '%s/%s/%s/tags/%s' % (
+ self.uri_prefix, resource_type, resource_id, tag)
+ resp, body = self.put(uri, None)
+ self.expected_success(201, resp.status)
+
+ def update_tags(self, resource_type, resource_id, tags):
+ uri = '%s/%s/%s/tags' % (
+ self.uri_prefix, resource_type, resource_id)
+ req_body = jsonutils.dumps({'tags': tags})
+ resp, body = self.put(uri, req_body)
+ self.expected_success(200, resp.status)
+ body = jsonutils.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_tags(self, resource_type, resource_id):
+ uri = '%s/%s/%s/tags' % (
+ self.uri_prefix, resource_type, resource_id)
+ resp, body = self.delete(uri)
+ self.expected_success(204, resp.status)
+
+ def delete_tag(self, resource_type, resource_id, tag):
+ uri = '%s/%s/%s/tags/%s' % (
+ self.uri_prefix, resource_type, resource_id, tag)
+ resp, body = self.delete(uri)
+ self.expected_success(204, resp.status)