Merge "Add dummy API definitions for extension subresources"
This commit is contained in:
@@ -12,6 +12,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# A declaration of a dummy neutron extension: this may have a number of
|
||||
# constants being defined, and their aim is to document as much about
|
||||
# the extension as possible.
|
||||
|
||||
# The alias of the extension.
|
||||
ALIAS = 'dummy'
|
||||
|
||||
@@ -20,38 +24,47 @@ ALIAS = 'dummy'
|
||||
LABEL = 'DUMMY'
|
||||
|
||||
# Whether or not this extension is simply signaling behavior to the user
|
||||
# or it actively modifies the attribute map.
|
||||
# or it actively modifies the attribute map (mandatory).
|
||||
IS_SHIM_EXTENSION = False
|
||||
|
||||
# Whether the extension is marking the adoption of standardattr model for
|
||||
# legacy resources, or introducing new standardattr attributes. False or
|
||||
# None if the standardattr model is adopted since the introduction of
|
||||
# resource extension.
|
||||
# resource extension (mandatory).
|
||||
# If this is True, the alias for the extension should be prefixed with
|
||||
# 'standard-attr-'.
|
||||
IS_STANDARD_ATTR_EXTENSION = False
|
||||
|
||||
# The name of the extension.
|
||||
# The name of the extension (mandatory).
|
||||
NAME = 'Foo Extension'
|
||||
|
||||
# A prefix for API resources. An empty prefix means that the API is going
|
||||
# to be exposed at the v2/ level as any other core resource.
|
||||
# to be exposed at the v2/ level as any other core resource (mandatory).
|
||||
API_PREFIX = ''
|
||||
|
||||
# The description of the extension.
|
||||
# The description of the extension (mandatory).
|
||||
DESCRIPTION = "Provides support for foo"
|
||||
|
||||
# A timestamp of when the extension was introduced.
|
||||
# A timestamp of when the extension was introduced (mandatory).
|
||||
UPDATED_TIMESTAMP = "2000-00-01T00:00:00-00:00"
|
||||
|
||||
# The name of the resource.
|
||||
# The specific resources and/or attributes for the extension (optional).
|
||||
# In case of simple extensions, with single resource, the string constants
|
||||
# RESOURCE_NAME and COLLECTION_NAME can be used, otherwise string literals
|
||||
# can be used instead.
|
||||
|
||||
# The name of the resource introduced or being extended
|
||||
# (in case it is defined by another extension, or it is
|
||||
# a core resource).
|
||||
RESOURCE_NAME = 'foo'
|
||||
|
||||
# The plural for the resource.
|
||||
# The plural for the resource introduced or being extended
|
||||
# (in case it is defined by another extension, or it is a
|
||||
# core resource).
|
||||
COLLECTION_NAME = 'fooes'
|
||||
|
||||
# The resource attribute map for the extension. It is effectively the
|
||||
# bulk of the API contract alongside ACTION_MAP
|
||||
# bulk of the API contract alongside ACTION_MAP (mandatory).
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
COLLECTION_NAME: {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
@@ -60,8 +73,26 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
}
|
||||
}
|
||||
|
||||
# The subresource attribute map for the extension. It adds child resources
|
||||
# to main extension's resource. The subresource map must have a parent and
|
||||
# a parameters entry. If an extension does not need such a map, None can
|
||||
# be specified (mandatory). For example:
|
||||
SUB_RESOURCE_ATTRIBUTE_MAP = {
|
||||
'subfoo': {
|
||||
'parent': {
|
||||
'collection_name': COLLECTION_NAME,
|
||||
'member_name': RESOURCE_NAME},
|
||||
'parameters': {
|
||||
'id': {'allow_post': False, 'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
'primary_key': True},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# The action map: it associates verbs with methods to be performed on
|
||||
# the API resource. For example:
|
||||
# the API resource (mandatory). For example:
|
||||
#
|
||||
# ACTION_MAP = {
|
||||
# RESOURCE_NAME: {
|
||||
@@ -73,11 +104,11 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
ACTION_MAP = {
|
||||
}
|
||||
|
||||
# The list of required extensions.
|
||||
# The list of required extensions (mandatory).
|
||||
REQUIRED_EXTENSIONS = [
|
||||
]
|
||||
|
||||
# The list of optional extensions.
|
||||
# The list of optional extensions (mandatory).
|
||||
OPTIONAL_EXTENSIONS = [
|
||||
]
|
||||
|
||||
|
||||
@@ -77,6 +77,9 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
},
|
||||
}
|
||||
|
||||
# The subresource attribute map for the extension.
|
||||
SUB_RESOURCE_ATTRIBUTE_MAP = None
|
||||
|
||||
# The action map.
|
||||
ACTION_MAP = {
|
||||
TRUNK: {
|
||||
|
||||
@@ -40,18 +40,27 @@ DESCRIPTION = "Expose trunk port details"
|
||||
# A timestamp of when the extension was introduced.
|
||||
TIMESTAMP = "2016-01-01T10:00:00-00:00"
|
||||
|
||||
# The name of the resource introduced or being extended.
|
||||
RESOURCE_NAME = 'port'
|
||||
|
||||
# The plural for the resource introduced or being extended.
|
||||
COLLECTION_NAME = 'ports'
|
||||
|
||||
# The specific resources and/or attributes for the extension (optional).
|
||||
TRUNK_DETAILS = 'trunk_details'
|
||||
|
||||
# The resource attribute map for the extension.
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
'ports': {TRUNK_DETAILS: {'allow_post': False, 'allow_put': False,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True,
|
||||
'required_by_policy': True}},
|
||||
COLLECTION_NAME: {TRUNK_DETAILS: {'allow_post': False, 'allow_put': False,
|
||||
'default': constants.ATTR_NOT_SPECIFIED,
|
||||
'is_visible': True,
|
||||
'enforce_policy': True,
|
||||
'required_by_policy': True}},
|
||||
}
|
||||
|
||||
# The subresource attribute map for the extension.
|
||||
SUB_RESOURCE_ATTRIBUTE_MAP = None
|
||||
|
||||
# The action map.
|
||||
ACTION_MAP = None
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ class DefinitionBaseTestCase(test_base.BaseTestCase):
|
||||
|
||||
extension_module = None
|
||||
extension_resources = ()
|
||||
extension_subresources = ()
|
||||
extension_attributes = ()
|
||||
|
||||
def setUp(self):
|
||||
@@ -73,6 +74,7 @@ class DefinitionBaseTestCase(test_base.BaseTestCase):
|
||||
self.name = self.extension_module.NAME
|
||||
self.description = self.extension_module.DESCRIPTION
|
||||
self.resource_map = self.extension_module.RESOURCE_ATTRIBUTE_MAP
|
||||
self.subresource_map = self.extension_module.SUB_RESOURCE_ATTRIBUTE_MAP
|
||||
self.action_map = self.extension_module.ACTION_MAP
|
||||
self.required_extensions = self.extension_module.REQUIRED_EXTENSIONS
|
||||
self.optional_extensions = self.extension_module.OPTIONAL_EXTENSIONS
|
||||
@@ -100,19 +102,40 @@ class DefinitionBaseTestCase(test_base.BaseTestCase):
|
||||
self.assertIn(
|
||||
resource, base.KNOWN_RESOURCES + self.extension_resources,
|
||||
'Resource is unknown, check for typos.')
|
||||
for attribute in self.resource_map[resource].keys():
|
||||
self.assertIn(
|
||||
attribute,
|
||||
base.KNOWN_ATTRIBUTES + self.extension_attributes,
|
||||
'Attribute is unknown, check for typos.')
|
||||
for keyword in self.resource_map[resource][attribute]:
|
||||
self.assertIn(keyword, base.KNOWN_KEYWORDS,
|
||||
'Keyword is unknown, check for typos.')
|
||||
value = self.resource_map[resource][attribute][keyword]
|
||||
assert_f = ASSERT_FUNCTIONS[keyword]
|
||||
assert_f(self, attribute,
|
||||
self.resource_map[resource][attribute],
|
||||
keyword, value)
|
||||
self.assertParams(self.resource_map[resource])
|
||||
|
||||
def assertParams(self, resource):
|
||||
for attribute in resource.keys():
|
||||
self.assertIn(
|
||||
attribute,
|
||||
base.KNOWN_ATTRIBUTES + self.extension_attributes,
|
||||
'Attribute is unknown, check for typos.')
|
||||
for keyword in resource[attribute]:
|
||||
self.assertIn(keyword, base.KNOWN_KEYWORDS,
|
||||
'Keyword is unknown, check for typos.')
|
||||
value = resource[attribute][keyword]
|
||||
assert_f = ASSERT_FUNCTIONS[keyword]
|
||||
assert_f(self, attribute,
|
||||
resource[attribute],
|
||||
keyword, value)
|
||||
|
||||
def test_subresource_map(self):
|
||||
if not self.subresource_map:
|
||||
self.skipTest('API extension has no subresource map.')
|
||||
for subresource in self.subresource_map:
|
||||
self.assertIn(
|
||||
subresource, self.extension_subresources,
|
||||
'Sub-resource is unknown, check for typos.')
|
||||
for attribute in self.subresource_map[subresource]:
|
||||
self.assertIn(attribute, ('parent', 'parameters'))
|
||||
self.assertIn(
|
||||
self.subresource_map[subresource]['parent']['collection_name'],
|
||||
base.KNOWN_RESOURCES + self.extension_resources,
|
||||
'Sub-resource parent is unknown, check for typos.')
|
||||
self.assertIn('member_name',
|
||||
self.subresource_map[subresource]['parent'],
|
||||
'Incorrect parent definition, check for typos.')
|
||||
self.assertParams(self.subresource_map[subresource]['parameters'])
|
||||
|
||||
def test_action_map(self):
|
||||
if not self.action_map:
|
||||
|
||||
@@ -17,3 +17,4 @@ from neutron_lib.tests.unit.api.definitions import base
|
||||
class _DummyDefinitionTestCase(base.DefinitionBaseTestCase):
|
||||
extension_module = _dummy
|
||||
extension_resources = (_dummy.COLLECTION_NAME,)
|
||||
extension_subresources = ('subfoo',)
|
||||
|
||||
@@ -16,4 +16,5 @@ from neutron_lib.tests.unit.api.definitions import base
|
||||
|
||||
class TrunkDetailsDefinitionTestCase(base.DefinitionBaseTestCase):
|
||||
extension_module = trunk_details
|
||||
extension_resource = (trunk_details.COLLECTION_NAME,)
|
||||
extension_attributes = (trunk_details.TRUNK_DETAILS,)
|
||||
|
||||
Reference in New Issue
Block a user