Merge "Add network tags client"
This commit is contained in:
commit
5bf47220a0
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Define v2.0 ``tags_client`` for the network service as a library
|
||||||
|
interface, allowing other projects to use this module as a stable
|
||||||
|
library without maintenance changes.
|
||||||
|
|
||||||
|
* tags_client(v2.0)
|
@ -83,6 +83,7 @@ class BaseNetworkTest(tempest.test.BaseTestCase):
|
|||||||
cls.os_primary.security_group_rules_client)
|
cls.os_primary.security_group_rules_client)
|
||||||
cls.network_versions_client = cls.os_primary.network_versions_client
|
cls.network_versions_client = cls.os_primary.network_versions_client
|
||||||
cls.service_providers_client = cls.os_primary.service_providers_client
|
cls.service_providers_client = cls.os_primary.service_providers_client
|
||||||
|
cls.tags_client = cls.os_primary.tags_client
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
|
90
tempest/api/network/test_tags.py
Normal file
90
tempest/api/network/test_tags.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Copyright 2017 AT&T Corporation.
|
||||||
|
# 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.api.network import base
|
||||||
|
from tempest.lib.common.utils import data_utils
|
||||||
|
from tempest.lib import decorators
|
||||||
|
from tempest.lib import exceptions as lib_exc
|
||||||
|
from tempest import test
|
||||||
|
|
||||||
|
|
||||||
|
class TagsTest(base.BaseNetworkTest):
|
||||||
|
"""Tests the following operations in the tags API:
|
||||||
|
|
||||||
|
Update all tags.
|
||||||
|
Delete all tags.
|
||||||
|
Check tag existence.
|
||||||
|
Create a tag.
|
||||||
|
List tags.
|
||||||
|
Remove a tag.
|
||||||
|
|
||||||
|
v2.0 of the Neutron API is assumed. The tag extension allows users to set
|
||||||
|
tags on their networks. The extension supports networks only.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def skip_checks(cls):
|
||||||
|
super(TagsTest, cls).skip_checks()
|
||||||
|
if not test.is_extension_enabled('tag', 'network'):
|
||||||
|
msg = "tag extension not enabled."
|
||||||
|
raise cls.skipException(msg)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resource_setup(cls):
|
||||||
|
super(TagsTest, cls).resource_setup()
|
||||||
|
cls.network = cls.create_network()
|
||||||
|
|
||||||
|
@decorators.idempotent_id('ee76bfaf-ac94-4d74-9ecc-4bbd4c583cb1')
|
||||||
|
def test_create_list_show_update_delete_tags(self):
|
||||||
|
# Validate that creating a tag on a network resource works.
|
||||||
|
tag_name = data_utils.rand_name(self.__class__.__name__ + '-Tag')
|
||||||
|
self.tags_client.create_tag('networks', self.network['id'], tag_name)
|
||||||
|
self.addCleanup(self.tags_client.delete_all_tags, 'networks',
|
||||||
|
self.network['id'])
|
||||||
|
self.tags_client.check_tag_existence('networks', self.network['id'],
|
||||||
|
tag_name)
|
||||||
|
|
||||||
|
# Validate that listing tags on a network resource works.
|
||||||
|
retrieved_tags = self.tags_client.list_tags(
|
||||||
|
'networks', self.network['id'])['tags']
|
||||||
|
self.assertEqual([tag_name], retrieved_tags)
|
||||||
|
|
||||||
|
# Generate 3 new tag names.
|
||||||
|
replace_tags = [data_utils.rand_name(
|
||||||
|
self.__class__.__name__ + '-Tag') for _ in range(3)]
|
||||||
|
|
||||||
|
# Replace the current tag with the 3 new tags and validate that the
|
||||||
|
# network resource has the 3 new tags.
|
||||||
|
updated_tags = self.tags_client.update_all_tags(
|
||||||
|
'networks', self.network['id'], replace_tags)['tags']
|
||||||
|
self.assertEqual(3, len(updated_tags))
|
||||||
|
self.assertEqual(set(replace_tags), set(updated_tags))
|
||||||
|
|
||||||
|
# Delete the first tag and check that it has been removed.
|
||||||
|
self.tags_client.delete_tag(
|
||||||
|
'networks', self.network['id'], replace_tags[0])
|
||||||
|
self.assertRaises(lib_exc.NotFound,
|
||||||
|
self.tags_client.check_tag_existence, 'networks',
|
||||||
|
self.network['id'], replace_tags[0])
|
||||||
|
for i in range(1, 3):
|
||||||
|
self.tags_client.check_tag_existence(
|
||||||
|
'networks', self.network['id'], replace_tags[i])
|
||||||
|
|
||||||
|
# Delete all the remaining tags and check that they have been removed.
|
||||||
|
self.tags_client.delete_all_tags('networks', self.network['id'])
|
||||||
|
for i in range(1, 3):
|
||||||
|
self.assertRaises(lib_exc.NotFound,
|
||||||
|
self.tags_client.check_tag_existence, 'networks',
|
||||||
|
self.network['id'], replace_tags[i])
|
@ -79,6 +79,7 @@ class Manager(clients.ServiceClients):
|
|||||||
self.security_groups_client = self.network.SecurityGroupsClient()
|
self.security_groups_client = self.network.SecurityGroupsClient()
|
||||||
self.network_versions_client = self.network.NetworkVersionsClient()
|
self.network_versions_client = self.network.NetworkVersionsClient()
|
||||||
self.service_providers_client = self.network.ServiceProvidersClient()
|
self.service_providers_client = self.network.ServiceProvidersClient()
|
||||||
|
self.tags_client = self.network.TagsClient()
|
||||||
|
|
||||||
def _set_image_clients(self):
|
def _set_image_clients(self):
|
||||||
if CONF.service_available.glance:
|
if CONF.service_available.glance:
|
||||||
|
@ -31,11 +31,12 @@ from tempest.lib.services.network.service_providers_client import \
|
|||||||
ServiceProvidersClient
|
ServiceProvidersClient
|
||||||
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
|
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
|
||||||
from tempest.lib.services.network.subnets_client import SubnetsClient
|
from tempest.lib.services.network.subnets_client import SubnetsClient
|
||||||
|
from tempest.lib.services.network.tags_client import TagsClient
|
||||||
from tempest.lib.services.network.versions_client import NetworkVersionsClient
|
from tempest.lib.services.network.versions_client import NetworkVersionsClient
|
||||||
|
|
||||||
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
|
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
|
||||||
'MeteringLabelRulesClient', 'MeteringLabelsClient',
|
'MeteringLabelRulesClient', 'MeteringLabelsClient',
|
||||||
'NetworksClient', 'PortsClient', 'QuotasClient', 'RoutersClient',
|
'NetworksClient', 'NetworkVersionsClient', 'PortsClient',
|
||||||
'SecurityGroupRulesClient', 'SecurityGroupsClient',
|
'QuotasClient', 'RoutersClient', 'SecurityGroupRulesClient',
|
||||||
'ServiceProvidersClient', 'SubnetpoolsClient', 'SubnetsClient',
|
'SecurityGroupsClient', 'ServiceProvidersClient',
|
||||||
'NetworkVersionsClient']
|
'SubnetpoolsClient', 'SubnetsClient', 'TagsClient']
|
||||||
|
88
tempest/lib/services/network/tags_client.py
Normal file
88
tempest/lib/services/network/tags_client.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Copyright 2017 AT&T Corporation.
|
||||||
|
# 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 tempest.lib.common import rest_client
|
||||||
|
from tempest.lib.services.network import base
|
||||||
|
|
||||||
|
|
||||||
|
class TagsClient(base.BaseNetworkClient):
|
||||||
|
|
||||||
|
def create_tag(self, resource_type, resource_id, tag):
|
||||||
|
"""Adds a tag on the resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#add-a-tag
|
||||||
|
"""
|
||||||
|
# NOTE(felipemonteiro): Cannot use ``update_resource`` method because
|
||||||
|
# this API requires self.put but returns 201 instead of 200 expected
|
||||||
|
# by ``update_resource``.
|
||||||
|
uri = '%s/%s/%s/tags/%s' % (
|
||||||
|
self.uri_prefix, resource_type, resource_id, tag)
|
||||||
|
resp, _ = self.put(uri, json.dumps({}))
|
||||||
|
self.expected_success(201, resp.status)
|
||||||
|
return rest_client.ResponseBody(resp)
|
||||||
|
|
||||||
|
def check_tag_existence(self, resource_type, resource_id, tag):
|
||||||
|
"""Confirm that a given tag is set on the resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#confirm-a-tag
|
||||||
|
"""
|
||||||
|
# TODO(felipemonteiro): Use the "check_resource" method in
|
||||||
|
# ``BaseNetworkClient`` once it has been implemented.
|
||||||
|
uri = '%s/%s/%s/tags/%s' % (
|
||||||
|
self.uri_prefix, resource_type, resource_id, tag)
|
||||||
|
resp, _ = self.get(uri)
|
||||||
|
self.expected_success(204, resp.status)
|
||||||
|
return rest_client.ResponseBody(resp)
|
||||||
|
|
||||||
|
def update_all_tags(self, resource_type, resource_id, tags):
|
||||||
|
"""Replace all tags on the resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#replace-all-tags
|
||||||
|
"""
|
||||||
|
uri = '/%s/%s/tags' % (resource_type, resource_id)
|
||||||
|
put_body = {"tags": tags}
|
||||||
|
return self.update_resource(uri, put_body)
|
||||||
|
|
||||||
|
def delete_tag(self, resource_type, resource_id, tag):
|
||||||
|
"""Removes a tag on the resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#remove-a-tag
|
||||||
|
"""
|
||||||
|
uri = '/%s/%s/tags/%s' % (resource_type, resource_id, tag)
|
||||||
|
return self.delete_resource(uri)
|
||||||
|
|
||||||
|
def delete_all_tags(self, resource_type, resource_id):
|
||||||
|
"""Removes all tags on the resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#remove-all-tags
|
||||||
|
"""
|
||||||
|
uri = '/%s/%s/tags' % (resource_type, resource_id)
|
||||||
|
return self.delete_resource(uri)
|
||||||
|
|
||||||
|
def list_tags(self, resource_type, resource_id):
|
||||||
|
"""Retrieves the tags for a resource.
|
||||||
|
|
||||||
|
For more information, please refer to the official API reference:
|
||||||
|
http://developer.openstack.org/api-ref/networking/v2/index.html#obtain-tag-list
|
||||||
|
"""
|
||||||
|
uri = '/%s/%s/tags' % (resource_type, resource_id)
|
||||||
|
return self.list_resources(uri)
|
123
tempest/tests/lib/services/network/test_tags_client.py
Normal file
123
tempest/tests/lib/services/network/test_tags_client.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Copyright 2017 AT&T Corporation.
|
||||||
|
# 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.network import tags_client
|
||||||
|
from tempest.tests.lib import fake_auth_provider
|
||||||
|
from tempest.tests.lib.services import base
|
||||||
|
|
||||||
|
|
||||||
|
class TestTagsClient(base.BaseServiceTest):
|
||||||
|
|
||||||
|
FAKE_TAGS = {
|
||||||
|
"tags": [
|
||||||
|
"red",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
FAKE_RESOURCE_TYPE = 'network'
|
||||||
|
|
||||||
|
FAKE_RESOURCE_ID = '7a8f904b-c1ed-4446-a87d-60440c02934b'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestTagsClient, self).setUp()
|
||||||
|
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||||
|
self.client = tags_client.TagsClient(
|
||||||
|
fake_auth, 'network', 'regionOne')
|
||||||
|
|
||||||
|
def _test_update_all_tags(self, bytes_body=False):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.update_all_tags,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.put',
|
||||||
|
self.FAKE_TAGS,
|
||||||
|
bytes_body,
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID,
|
||||||
|
tags=self.FAKE_TAGS)
|
||||||
|
|
||||||
|
def _test_check_tag_existence(self, bytes_body=False):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.check_tag_existence,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.get',
|
||||||
|
{},
|
||||||
|
bytes_body,
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID,
|
||||||
|
tag=self.FAKE_TAGS['tags'][0],
|
||||||
|
status=204)
|
||||||
|
|
||||||
|
def _test_create_tag(self, bytes_body=False):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.create_tag,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.put',
|
||||||
|
{},
|
||||||
|
bytes_body,
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID,
|
||||||
|
tag=self.FAKE_TAGS['tags'][0],
|
||||||
|
status=201)
|
||||||
|
|
||||||
|
def _test_list_tags(self, bytes_body=False):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.list_tags,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.get',
|
||||||
|
self.FAKE_TAGS,
|
||||||
|
bytes_body,
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID)
|
||||||
|
|
||||||
|
def test_update_all_tags_with_str_body(self):
|
||||||
|
self._test_update_all_tags()
|
||||||
|
|
||||||
|
def test_update_all_tags_with_bytes_body(self):
|
||||||
|
self._test_update_all_tags(bytes_body=True)
|
||||||
|
|
||||||
|
def test_delete_all_tags(self):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.delete_all_tags,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.delete',
|
||||||
|
{},
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID,
|
||||||
|
status=204)
|
||||||
|
|
||||||
|
def test_check_tag_existence_with_str_body(self):
|
||||||
|
self._test_check_tag_existence()
|
||||||
|
|
||||||
|
def test_check_tag_existence_with_bytes_body(self):
|
||||||
|
self._test_check_tag_existence(bytes_body=True)
|
||||||
|
|
||||||
|
def test_create_tag_with_str_body(self):
|
||||||
|
self._test_create_tag()
|
||||||
|
|
||||||
|
def test_create_tag_with_bytes_body(self):
|
||||||
|
self._test_create_tag(bytes_body=True)
|
||||||
|
|
||||||
|
def test_list_tags_with_str_body(self):
|
||||||
|
self._test_list_tags()
|
||||||
|
|
||||||
|
def test_list_tags_with_bytes_body(self):
|
||||||
|
self._test_list_tags(bytes_body=True)
|
||||||
|
|
||||||
|
def test_delete_tag(self):
|
||||||
|
self.check_service_client_function(
|
||||||
|
self.client.delete_tag,
|
||||||
|
'tempest.lib.common.rest_client.RestClient.delete',
|
||||||
|
{},
|
||||||
|
resource_type=self.FAKE_RESOURCE_TYPE,
|
||||||
|
resource_id=self.FAKE_RESOURCE_ID,
|
||||||
|
tag=self.FAKE_TAGS['tags'][0],
|
||||||
|
status=204)
|
Loading…
Reference in New Issue
Block a user