remove tag and tag_ext extensions
The tag and tag_ext extensions are deprecated for removal, but are not used widely today [1]. Rather than rehoming these extensions to neutron-lib and carrying out their deprecation life-cycle for no apparent reason, this patch proposes we just remove them now. While [2] initially removed these extensions, we had to revert them with [3]. Depends-On: I295a5b84eb7fa3439561fa009b7499f94d8df4d2 [1] http://codesearch.openstack.org/?q=from%20neutron.extensions%20import%20(tag_ext%7Ctag) [2] I0d7bcd789b468b1dd3f7ea13e6751a46203d6778 [3] If16443616eee703b66d57b6422dd451a443fbc64 Change-Id: I97095453610fff114d999a526d67e78119546ff5
This commit is contained in:
parent
3ff872b913
commit
87a36cacc6
@ -30,7 +30,6 @@ scalability and HA.
|
||||
| agent | agent |
|
||||
| Subnet Allocation | subnet_allocation |
|
||||
| L3 Agent Scheduler | l3_agent_scheduler |
|
||||
| Tag support | tag |
|
||||
| Neutron external network | external-net |
|
||||
| Neutron Service Flavors | flavors |
|
||||
| Network MTU | net-mtu |
|
||||
@ -45,7 +44,6 @@ scalability and HA.
|
||||
| Resource timestamps | standard-attr-timestamp |
|
||||
| Neutron Service Type Management | service-type |
|
||||
| Router Flavor Extension | l3-flavors |
|
||||
| Tag support for resources: subnet, subnetpool, port, router | tag-ext |
|
||||
| Neutron Extra DHCP opts | extra_dhcp_opt |
|
||||
| Resource revision numbers | standard-attr-revisions |
|
||||
| Pagination support | pagination |
|
||||
|
@ -50,12 +50,7 @@ Which Resources
|
||||
---------------
|
||||
|
||||
Tag system uses standardattr mechanism so it's targeting to resources that have
|
||||
the mechanism. The system is provided by 'tag' extension, 'tag-ext'
|
||||
extension, and 'tagging' extension. The 'tag' extension supports networks only.
|
||||
The 'tag-ext' extension supports subnets, ports, routers, and subnet pools.
|
||||
The 'tagging' extension supports resources with standard attribute so it
|
||||
means that 'tag' and 'tag-ext' extensions are unnecessary now. These extensions
|
||||
will be removed. Some resources with standard attribute don't suit fit tag
|
||||
the mechanism. Some resources with standard attribute don't suit fit tag
|
||||
support usecases (e.g. security_group_rule). If new tag support resource is
|
||||
added, the resource model should inherit HasStandardAttributes and then it must
|
||||
implement the property 'api_parent' and 'tag_support'. And also the change
|
||||
|
@ -40,8 +40,6 @@ Verify operation
|
||||
| | | subnets from a subnet pool |
|
||||
| DHCP Agent Scheduler | dhcp_agent_scheduler | Schedule networks among |
|
||||
| | | dhcp agents |
|
||||
| Tag support | tag | Enables to set tag on |
|
||||
| | | resources. |
|
||||
| Neutron external network | external-net | Adds external network |
|
||||
| | | attribute to network |
|
||||
| | | resource. |
|
||||
@ -73,7 +71,6 @@ Verify operation
|
||||
| Neutron Service Type | service-type | API for retrieving service |
|
||||
| Management | | providers for Neutron |
|
||||
| | | advanced services |
|
||||
| Tag support for | tag-ext | Extends tag support to |
|
||||
| resources: subnet, | | more L2 and L3 resources. |
|
||||
| subnetpool, port, router | | |
|
||||
| Neutron Extra DHCP opts | extra_dhcp_opt | Extra options |
|
||||
|
@ -1,85 +0,0 @@
|
||||
#
|
||||
# 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 neutron_lib.api.definitions import network
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
from neutron_lib.api import faults
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import resource as api_resource
|
||||
from neutron.extensions import tagging
|
||||
|
||||
|
||||
# This extension is deprecated because tagging supports all resources
|
||||
|
||||
TAG_SUPPORTED_RESOURCES = {
|
||||
# We shouldn't add new resources here. If more resources need to be tagged,
|
||||
# we must add them in new extension.
|
||||
network.COLLECTION_NAME: network.RESOURCE_NAME,
|
||||
}
|
||||
|
||||
|
||||
class TagController(tagging.TaggingController):
|
||||
def __init__(self):
|
||||
self.plugin = directory.get_plugin(tagging.TAG_PLUGIN_TYPE)
|
||||
self.supported_resources = TAG_SUPPORTED_RESOURCES
|
||||
|
||||
|
||||
class Tag(api_extensions.ExtensionDescriptor):
|
||||
"""Extension class supporting tags."""
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "Tag support"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "tag"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Enables to set tag on resources."
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2016-01-01T00:00:00-00:00"
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
"""Returns Ext Resources."""
|
||||
exts = []
|
||||
action_status = {'index': 200, 'show': 204, 'update': 201,
|
||||
'update_all': 200, 'delete': 204, 'delete_all': 204}
|
||||
controller = api_resource.Resource(TagController(),
|
||||
faults.FAULT_MAP,
|
||||
action_status=action_status)
|
||||
collection_methods = {"delete_all": "DELETE",
|
||||
"update_all": "PUT"}
|
||||
exts = []
|
||||
for collection_name, member_name in TAG_SUPPORTED_RESOURCES.items():
|
||||
parent = {'member_name': member_name,
|
||||
'collection_name': collection_name}
|
||||
exts.append(extensions.ResourceExtension(
|
||||
tagging.TAGS, controller, parent,
|
||||
collection_methods=collection_methods))
|
||||
return exts
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version != "2.0":
|
||||
return {}
|
||||
EXTENDED_ATTRIBUTES_2_0 = {}
|
||||
for collection_name in TAG_SUPPORTED_RESOURCES:
|
||||
EXTENDED_ATTRIBUTES_2_0[collection_name] = (
|
||||
tagging.TAG_ATTRIBUTE_MAP)
|
||||
return EXTENDED_ATTRIBUTES_2_0
|
@ -1,95 +0,0 @@
|
||||
#
|
||||
# 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 neutron_lib.api.definitions import l3 as l3_apidef
|
||||
from neutron_lib.api.definitions import port as port_def
|
||||
from neutron_lib.api.definitions import subnet as subnet_def
|
||||
from neutron_lib.api.definitions import subnetpool as subnetpool_def
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
from neutron_lib.api import faults
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron.api.v2 import resource as api_resource
|
||||
from neutron.extensions import tagging
|
||||
|
||||
|
||||
# This extension is deprecated because tagging supports all resources
|
||||
|
||||
TAG_SUPPORTED_RESOURCES = {
|
||||
# We shouldn't add new resources here. If more resources need to be tagged,
|
||||
# we must add them in new extension.
|
||||
subnet_def.COLLECTION_NAME: subnet_def.RESOURCE_NAME,
|
||||
port_def.COLLECTION_NAME: port_def.RESOURCE_NAME,
|
||||
subnetpool_def.COLLECTION_NAME: subnetpool_def.RESOURCE_NAME,
|
||||
l3_apidef.ROUTERS: l3_apidef.ROUTER,
|
||||
}
|
||||
|
||||
|
||||
class TagExtController(tagging.TaggingController):
|
||||
def __init__(self):
|
||||
self.plugin = directory.get_plugin(tagging.TAG_PLUGIN_TYPE)
|
||||
self.supported_resources = TAG_SUPPORTED_RESOURCES
|
||||
|
||||
|
||||
class Tag_ext(api_extensions.ExtensionDescriptor):
|
||||
"""Extension class supporting tags for ext resources."""
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return ("Tag support for resources: %s"
|
||||
% ', '.join(TAG_SUPPORTED_RESOURCES.values()))
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "tag-ext"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Extends tag support to more L2 and L3 resources."
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2017-01-01T00:00:00-00:00"
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
"""Returns Ext Resources."""
|
||||
exts = []
|
||||
action_status = {'index': 200, 'show': 204, 'update': 201,
|
||||
'update_all': 200, 'delete': 204, 'delete_all': 204}
|
||||
controller = api_resource.Resource(TagExtController(),
|
||||
faults.FAULT_MAP,
|
||||
action_status=action_status)
|
||||
collection_methods = {"delete_all": "DELETE",
|
||||
"update_all": "PUT"}
|
||||
exts = []
|
||||
for collection_name, member_name in TAG_SUPPORTED_RESOURCES.items():
|
||||
parent = {'member_name': member_name,
|
||||
'collection_name': collection_name}
|
||||
exts.append(extensions.ResourceExtension(
|
||||
tagging.TAGS, controller, parent,
|
||||
collection_methods=collection_methods))
|
||||
return exts
|
||||
|
||||
def get_optional_extensions(self):
|
||||
return ['router']
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version != "2.0":
|
||||
return {}
|
||||
EXTENDED_ATTRIBUTES_2_0 = {}
|
||||
for collection_name in TAG_SUPPORTED_RESOURCES:
|
||||
EXTENDED_ATTRIBUTES_2_0[collection_name] = (
|
||||
tagging.TAG_ATTRIBUTE_MAP)
|
||||
return EXTENDED_ATTRIBUTES_2_0
|
@ -33,24 +33,8 @@ TAG = 'tag'
|
||||
TAGS = TAG + 's'
|
||||
MAX_TAG_LEN = 60
|
||||
TAG_PLUGIN_TYPE = 'TAG'
|
||||
# Not support resources supported by tag, tag-ext
|
||||
EXCEPTION_RESOURCES = ['networks', 'subnets', 'ports', 'subnetpools',
|
||||
'routers']
|
||||
|
||||
|
||||
# TODO(hichihara): This method is removed after tag, tag-ext extensions
|
||||
# have been removed.
|
||||
def get_tagging_supported_resources():
|
||||
# Removes some resources supported by tag, tag-ext
|
||||
parent_map = standard_attr.get_tag_resource_parent_map()
|
||||
remove_resources = [res for res in parent_map
|
||||
if res in EXCEPTION_RESOURCES]
|
||||
for resource in remove_resources:
|
||||
del parent_map[resource]
|
||||
return parent_map
|
||||
|
||||
|
||||
TAG_SUPPORTED_RESOURCES = get_tagging_supported_resources()
|
||||
TAG_SUPPORTED_RESOURCES = standard_attr.get_tag_resource_parent_map()
|
||||
TAG_ATTRIBUTE_MAP = {
|
||||
TAGS: {'allow_post': False, 'allow_put': False, 'is_visible': True}
|
||||
}
|
||||
@ -187,9 +171,7 @@ class Tagging(api_extensions.ExtensionDescriptor):
|
||||
return "2017-01-01T00:00:00-00:00"
|
||||
|
||||
def get_required_extensions(self):
|
||||
# This is needed so that depending project easily moves from old
|
||||
# extensions although this extension self can run without them.
|
||||
return ['tag', 'tag-ext']
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
|
@ -37,7 +37,7 @@ resource_model_map = standard_attr.get_standard_attr_resource_model_map()
|
||||
class TagPlugin(common_db_mixin.CommonDbMixin, tagging.TagPluginBase):
|
||||
"""Implementation of the Neutron Tag Service Plugin."""
|
||||
|
||||
supported_extension_aliases = ['tag', 'tag-ext', 'standard-attr-tag']
|
||||
supported_extension_aliases = ['standard-attr-tag']
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
inst = super(TagPlugin, cls).__new__(cls, *args, **kwargs)
|
||||
|
@ -46,7 +46,5 @@ NETWORK_API_EXTENSIONS+=",standard-attr-revisions"
|
||||
NETWORK_API_EXTENSIONS+=",standard-attr-timestamp"
|
||||
NETWORK_API_EXTENSIONS+=",standard-attr-tag"
|
||||
NETWORK_API_EXTENSIONS+=",subnet_allocation"
|
||||
NETWORK_API_EXTENSIONS+=",tag"
|
||||
NETWORK_API_EXTENSIONS+=",tag-ext"
|
||||
NETWORK_API_EXTENSIONS+=",trunk"
|
||||
NETWORK_API_EXTENSIONS+=",trunk-details"
|
||||
|
@ -1,406 +0,0 @@
|
||||
# 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 neutron_lib.api import attributes
|
||||
from neutron_lib import context
|
||||
from oslo_utils import uuidutils
|
||||
import testscenarios
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron.common import config
|
||||
import neutron.extensions
|
||||
from neutron.objects.qos import policy
|
||||
from neutron.objects import trunk
|
||||
from neutron.services.tag import tag_plugin
|
||||
from neutron.tests import fake_notifier
|
||||
from neutron.tests.unit.extensions import test_l3
|
||||
from neutron.tests.unit.extensions import test_securitygroup
|
||||
|
||||
|
||||
DB_PLUGIN_KLASS = 'neutron.tests.unit.extensions.test_tag.TestTagPlugin'
|
||||
|
||||
load_tests = testscenarios.load_tests_apply_scenarios
|
||||
extensions_path = ':'.join(neutron.extensions.__path__)
|
||||
|
||||
|
||||
class TestTagPlugin(test_securitygroup.SecurityGroupTestPlugin,
|
||||
test_l3.TestL3NatBasePlugin):
|
||||
|
||||
__native_pagination_support = True
|
||||
__native_sorting_support = True
|
||||
|
||||
supported_extension_aliases = ["external-net", "security-group"]
|
||||
|
||||
|
||||
class TestTagApiBase(test_securitygroup.SecurityGroupsTestCase,
|
||||
test_l3.L3NatTestCaseMixin):
|
||||
scenarios = [
|
||||
('Network Tag Test',
|
||||
dict(collection='networks',
|
||||
member='network')),
|
||||
('Subnet Tag Test',
|
||||
dict(collection='subnets',
|
||||
member='subnet')),
|
||||
('Port Tag Test',
|
||||
dict(collection='ports',
|
||||
member='port')),
|
||||
('Subnetpool Tag Test',
|
||||
dict(collection='subnetpools',
|
||||
member='subnetpool')),
|
||||
('Router Tag Test',
|
||||
dict(collection='routers',
|
||||
member='router')),
|
||||
('Floatingip Tag Test',
|
||||
dict(collection='floatingips',
|
||||
member='floatingip')),
|
||||
('Securitygroup Tag Test',
|
||||
dict(collection='security-groups',
|
||||
member='security_group')),
|
||||
('QoS Policy Tag Test',
|
||||
dict(collection='policies',
|
||||
member='policy')),
|
||||
('Trunk Tag Test',
|
||||
dict(collection='trunks',
|
||||
member='trunk')),
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
service_plugins = {
|
||||
'TAG': "neutron.services.tag.tag_plugin.TagPlugin",
|
||||
'router':
|
||||
"neutron.tests.unit.extensions.test_l3.TestL3NatServicePlugin"}
|
||||
super(TestTagApiBase, self).setUp(plugin=DB_PLUGIN_KLASS,
|
||||
service_plugins=service_plugins)
|
||||
plugin = tag_plugin.TagPlugin()
|
||||
l3_plugin = test_l3.TestL3NatServicePlugin()
|
||||
sec_plugin = test_securitygroup.SecurityGroupTestPlugin()
|
||||
ext_mgr = extensions.PluginAwareExtensionManager(
|
||||
extensions_path, {'router': l3_plugin, 'TAG': plugin,
|
||||
'sec': sec_plugin}
|
||||
)
|
||||
ext_mgr.extend_resources("2.0", attributes.RESOURCES)
|
||||
app = config.load_paste_app('extensions_test_app')
|
||||
self.ext_api = extensions.ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
||||
|
||||
def _is_object(self):
|
||||
return self.collection in ['policies', 'trunks']
|
||||
|
||||
def _prepare_make_resource(self):
|
||||
if self.collection == "floatingips":
|
||||
net = self._make_network(self.fmt, 'net1', True)
|
||||
self._set_net_external(net['network']['id'])
|
||||
self._make_subnet(self.fmt, net, '10.0.0.1', '10.0.0.0/24')
|
||||
info = {'network_id': net['network']['id']}
|
||||
self._make_router(self.fmt, None,
|
||||
external_gateway_info=info)
|
||||
self.net = net['network']
|
||||
|
||||
def _make_object(self):
|
||||
ctxt = context.get_admin_context()
|
||||
if self.collection == "policies":
|
||||
self.obj = policy.QosPolicy(context=ctxt,
|
||||
id=uuidutils.generate_uuid(),
|
||||
project_id='tenant', name='pol1',
|
||||
rules=[])
|
||||
elif self.collection == "trunks":
|
||||
net = self._make_network(self.fmt, 'net1', True)
|
||||
port = self._make_port(self.fmt, net['network']['id'])
|
||||
self.obj = trunk.Trunk(context=ctxt,
|
||||
id=uuidutils.generate_uuid(),
|
||||
project_id='tenant', name='',
|
||||
port_id=port['port']['id'])
|
||||
self.obj.create()
|
||||
return self.obj.id
|
||||
|
||||
def _make_resource(self):
|
||||
if self._is_object():
|
||||
return self._make_object()
|
||||
|
||||
if self.collection == "networks":
|
||||
res = self._make_network(self.fmt, 'net1', True)
|
||||
elif self.collection == "subnets":
|
||||
net = self._make_network(self.fmt, 'net1', True)
|
||||
res = self._make_subnet(self.fmt, net, '10.0.0.1', '10.0.0.0/24')
|
||||
elif self.collection == "ports":
|
||||
net = self._make_network(self.fmt, 'net1', True)
|
||||
res = self._make_port(self.fmt, net['network']['id'])
|
||||
elif self.collection == "subnetpools":
|
||||
res = self._make_subnetpool(self.fmt, ['10.0.0.0/8'],
|
||||
name='my pool', tenant_id="tenant")
|
||||
elif self.collection == "routers":
|
||||
res = self._make_router(self.fmt, None)
|
||||
elif self.collection == "floatingips":
|
||||
res = self._make_floatingip(self.fmt, self.net['id'])
|
||||
elif self.collection == "security-groups":
|
||||
res = self._make_security_group(self.fmt, 'sec1', '')
|
||||
return res[self.member]['id']
|
||||
|
||||
def _get_object_tags(self):
|
||||
ctxt = context.get_admin_context()
|
||||
res = self.obj.get_object(ctxt, id=self.resource_id)
|
||||
return res.to_dict()['tags']
|
||||
|
||||
def _get_resource_tags(self):
|
||||
if self._is_object():
|
||||
return self._get_object_tags()
|
||||
|
||||
res = self._show(self.collection, self.resource_id)
|
||||
return res[self.member]['tags']
|
||||
|
||||
def _put_tag(self, tag):
|
||||
req = self._req('PUT', self.collection, id=self.resource_id,
|
||||
subresource='tags', sub_id=tag)
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _put_tags(self, tags=None, body=None):
|
||||
if tags:
|
||||
body = {'tags': tags}
|
||||
elif body:
|
||||
body = body
|
||||
else:
|
||||
body = {}
|
||||
req = self._req('PUT', self.collection, data=body, id=self.resource_id,
|
||||
subresource='tags')
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _get_tag(self, tag):
|
||||
req = self._req('GET', self.collection, id=self.resource_id,
|
||||
subresource='tags', sub_id=tag)
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _delete_tag(self, tag):
|
||||
req = self._req('DELETE', self.collection, id=self.resource_id,
|
||||
subresource='tags', sub_id=tag)
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _delete_tags(self):
|
||||
req = self._req('DELETE', self.collection, id=self.resource_id,
|
||||
subresource='tags')
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _assertEqualTags(self, expected, actual):
|
||||
self.assertEqual(set(expected), set(actual))
|
||||
|
||||
def _get_tags_filter_objects(self, tags, tags_any, not_tags,
|
||||
not_tags_any):
|
||||
filters = {}
|
||||
if tags:
|
||||
filters['tags'] = tags
|
||||
if tags_any:
|
||||
filters['tags-any'] = tags_any
|
||||
if not_tags:
|
||||
filters['not-tags'] = not_tags
|
||||
if not_tags_any:
|
||||
filters['not-tags-any'] = not_tags_any
|
||||
|
||||
if self.collection == "policies":
|
||||
obj_class = policy.QosPolicy
|
||||
elif self.collection == "trunks":
|
||||
obj_class = trunk.Trunk
|
||||
ctxt = context.get_admin_context()
|
||||
res = obj_class.get_objects(ctxt, **filters)
|
||||
return [n.id for n in res]
|
||||
|
||||
def _make_query_string(self, tags, tags_any, not_tags, not_tags_any):
|
||||
filter_strings = []
|
||||
if tags:
|
||||
filter_strings.append("tags=" + ','.join(tags))
|
||||
if tags_any:
|
||||
filter_strings.append("tags-any=" + ','.join(tags_any))
|
||||
if not_tags:
|
||||
filter_strings.append("not-tags=" + ','.join(not_tags))
|
||||
if not_tags_any:
|
||||
filter_strings.append("not-tags-any=" + ','.join(not_tags_any))
|
||||
|
||||
return '&'.join(filter_strings)
|
||||
|
||||
def _get_tags_filter_resources(self, tags=None, tags_any=None,
|
||||
not_tags=None, not_tags_any=None):
|
||||
if self._is_object():
|
||||
return self._get_tags_filter_objects(tags, tags_any, not_tags,
|
||||
not_tags_any)
|
||||
|
||||
params = self._make_query_string(tags, tags_any, not_tags,
|
||||
not_tags_any)
|
||||
res = self._list(self.collection, query_params=params)
|
||||
return [n['id'] for n in res[self.collection.replace('-', '_')]]
|
||||
|
||||
def _test_notification_report(self, expect_notify):
|
||||
notify = set(n['event_type'] for n in fake_notifier.NOTIFICATIONS)
|
||||
duplicated_notify = expect_notify & notify
|
||||
self.assertEqual(expect_notify, duplicated_notify)
|
||||
|
||||
fake_notifier.reset()
|
||||
|
||||
|
||||
class TestResourceTagApi(TestTagApiBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestResourceTagApi, self).setUp()
|
||||
self._prepare_make_resource()
|
||||
self.resource_id = self._make_resource()
|
||||
|
||||
def test_put_tag(self):
|
||||
expect_notify = set(['tag.create.start',
|
||||
'tag.create.end'])
|
||||
res = self._put_tag('red')
|
||||
self.assertEqual(201, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['red'], tags)
|
||||
self._test_notification_report(expect_notify)
|
||||
res = self._put_tag('blue')
|
||||
self.assertEqual(201, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['red', 'blue'], tags)
|
||||
self._test_notification_report(expect_notify)
|
||||
|
||||
def test_put_tag_exists(self):
|
||||
res = self._put_tag('blue')
|
||||
self.assertEqual(201, res.status_int)
|
||||
res = self._put_tag('blue')
|
||||
self.assertEqual(201, res.status_int)
|
||||
|
||||
def test_put_tags(self):
|
||||
expect_notify = set(['tag.update.start',
|
||||
'tag.update.end'])
|
||||
res = self._put_tags(['red', 'green'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['red', 'green'], tags)
|
||||
self._test_notification_report(expect_notify)
|
||||
|
||||
def test_put_invalid_tags(self):
|
||||
res = self._put_tags()
|
||||
self.assertEqual(400, res.status_int)
|
||||
res = self._put_tags(body=7)
|
||||
self.assertEqual(400, res.status_int)
|
||||
res = self._put_tags(body={'invalid': True})
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_put_tags_replace(self):
|
||||
res = self._put_tags(['red', 'green'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['red', 'green'], tags)
|
||||
res = self._put_tags(['blue', 'red'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['blue', 'red'], tags)
|
||||
|
||||
def test_get_tag(self):
|
||||
res = self._put_tag('red')
|
||||
self.assertEqual(201, res.status_int)
|
||||
res = self._get_tag('red')
|
||||
self.assertEqual(204, res.status_int)
|
||||
|
||||
def test_get_tag_notfound(self):
|
||||
res = self._put_tag('red')
|
||||
self.assertEqual(201, res.status_int)
|
||||
res = self._get_tag('green')
|
||||
self.assertEqual(404, res.status_int)
|
||||
|
||||
def test_delete_tag(self):
|
||||
expect_notify = set(['tag.delete.start',
|
||||
'tag.delete.end'])
|
||||
res = self._put_tags(['red', 'green'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
res = self._delete_tag('red')
|
||||
self.assertEqual(204, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags(['green'], tags)
|
||||
self._test_notification_report(expect_notify)
|
||||
|
||||
def test_delete_tag_notfound(self):
|
||||
res = self._put_tags(['red', 'green'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
res = self._delete_tag('blue')
|
||||
self.assertEqual(404, res.status_int)
|
||||
|
||||
def test_delete_tags(self):
|
||||
expect_notify = set(['tag.delete_all.start',
|
||||
'tag.delete_all.end'])
|
||||
res = self._put_tags(['red', 'green'])
|
||||
self.assertEqual(200, res.status_int)
|
||||
res = self._delete_tags()
|
||||
self.assertEqual(204, res.status_int)
|
||||
tags = self._get_resource_tags()
|
||||
self._assertEqualTags([], tags)
|
||||
self._test_notification_report(expect_notify)
|
||||
|
||||
|
||||
class TestResourceTagFilter(TestTagApiBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestResourceTagFilter, self).setUp()
|
||||
self._prepare_resource_tags()
|
||||
|
||||
def _make_tags(self, resource_id, tags):
|
||||
body = {'tags': tags}
|
||||
req = self._req('PUT', self.collection, data=body, id=resource_id,
|
||||
subresource='tags')
|
||||
return req.get_response(self.ext_api)
|
||||
|
||||
def _prepare_resource_tags(self):
|
||||
self._prepare_make_resource()
|
||||
self.res1 = self._make_resource()
|
||||
self.res2 = self._make_resource()
|
||||
self.res3 = self._make_resource()
|
||||
self.res4 = self._make_resource()
|
||||
self.res5 = self._make_resource()
|
||||
self.res_ids = [self.res1, self.res2, self.res3, self.res4, self.res5]
|
||||
|
||||
self._make_tags(self.res1, ['red'])
|
||||
self._make_tags(self.res2, ['red', 'blue'])
|
||||
self._make_tags(self.res3, ['red', 'blue', 'green'])
|
||||
self._make_tags(self.res4, ['green'])
|
||||
# res5: no tags
|
||||
|
||||
def _assertEqualResources(self, expected, resources):
|
||||
actual = [n for n in resources if n in self.res_ids]
|
||||
self.assertEqual(set(expected), set(actual))
|
||||
|
||||
def test_filter_tags_single(self):
|
||||
resources = self._get_tags_filter_resources(tags=['red'])
|
||||
self._assertEqualResources([self.res1, self.res2, self.res3],
|
||||
resources)
|
||||
|
||||
def test_filter_tags_multi(self):
|
||||
resources = self._get_tags_filter_resources(tags=['red', 'blue'])
|
||||
self._assertEqualResources([self.res2, self.res3], resources)
|
||||
|
||||
def test_filter_tags_any_single(self):
|
||||
resources = self._get_tags_filter_resources(tags_any=['blue'])
|
||||
self._assertEqualResources([self.res2, self.res3], resources)
|
||||
|
||||
def test_filter_tags_any_multi(self):
|
||||
resources = self._get_tags_filter_resources(tags_any=['red', 'blue'])
|
||||
self._assertEqualResources([self.res1, self.res2, self.res3],
|
||||
resources)
|
||||
|
||||
def test_filter_not_tags_single(self):
|
||||
resources = self._get_tags_filter_resources(not_tags=['red'])
|
||||
self._assertEqualResources([self.res4, self.res5], resources)
|
||||
|
||||
def test_filter_not_tags_multi(self):
|
||||
resources = self._get_tags_filter_resources(not_tags=['red', 'blue'])
|
||||
self._assertEqualResources([self.res1, self.res4, self.res5],
|
||||
resources)
|
||||
|
||||
def test_filter_not_tags_any_single(self):
|
||||
resources = self._get_tags_filter_resources(not_tags_any=['blue'])
|
||||
self._assertEqualResources([self.res1, self.res4, self.res5],
|
||||
resources)
|
||||
|
||||
def test_filter_not_tags_any_multi(self):
|
||||
resources = self._get_tags_filter_resources(not_tags_any=['red',
|
||||
'blue'])
|
||||
self._assertEqualResources([self.res4, self.res5], resources)
|
Loading…
Reference in New Issue
Block a user