Merge "Add network tags client"

This commit is contained in:
Jenkins 2017-06-16 05:13:39 +00:00 committed by Gerrit Code Review
commit 5bf47220a0
7 changed files with 316 additions and 4 deletions

View File

@ -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)

View File

@ -83,6 +83,7 @@ class BaseNetworkTest(tempest.test.BaseTestCase):
cls.os_primary.security_group_rules_client)
cls.network_versions_client = cls.os_primary.network_versions_client
cls.service_providers_client = cls.os_primary.service_providers_client
cls.tags_client = cls.os_primary.tags_client
@classmethod
def resource_setup(cls):

View 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])

View File

@ -79,6 +79,7 @@ class Manager(clients.ServiceClients):
self.security_groups_client = self.network.SecurityGroupsClient()
self.network_versions_client = self.network.NetworkVersionsClient()
self.service_providers_client = self.network.ServiceProvidersClient()
self.tags_client = self.network.TagsClient()
def _set_image_clients(self):
if CONF.service_available.glance:

View File

@ -31,11 +31,12 @@ from tempest.lib.services.network.service_providers_client import \
ServiceProvidersClient
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
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
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
'MeteringLabelRulesClient', 'MeteringLabelsClient',
'NetworksClient', 'PortsClient', 'QuotasClient', 'RoutersClient',
'SecurityGroupRulesClient', 'SecurityGroupsClient',
'ServiceProvidersClient', 'SubnetpoolsClient', 'SubnetsClient',
'NetworkVersionsClient']
'NetworksClient', 'NetworkVersionsClient', 'PortsClient',
'QuotasClient', 'RoutersClient', 'SecurityGroupRulesClient',
'SecurityGroupsClient', 'ServiceProvidersClient',
'SubnetpoolsClient', 'SubnetsClient', 'TagsClient']

View 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)

View 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)