Add to resource-type-list returning description

Add to resource-type-list command ability to return
resource description.

@APIImpact
@DocImpact

Change-Id: Ia92699e5ca60a891e9704c468e447e1053be7609
Closes-bug: #1558049
This commit is contained in:
Peter Razumovsky 2016-04-18 15:36:48 +03:00
parent f3033f65ef
commit 42bfc8a282
12 changed files with 113 additions and 30 deletions

View File

@ -1577,4 +1577,15 @@ updated_time_3:
in: body
required: true
type: string
with_description:
description: |
Either display resource type's description or not. Default is ``false``
in: query
required: false
type: boolean
resource_description:
description: |
Displays resource type's description.
in: body
required: false
type: string

View File

@ -28,6 +28,7 @@ Request
- name: name
- version: version
- support_status: support_status
- with_description: with_description
Response Parameters
@ -38,7 +39,7 @@ Response Parameters
- template_versions: template_versions
- type: type
- version: version
- description: resource_description
Response Example

View File

@ -624,12 +624,22 @@ class StackController(object):
support_status = req.params.get('support_status')
type_name = req.params.get('name')
version = req.params.get('version')
if req.params.get('with_description') is not None:
with_description = self._extract_bool_param(
'with_description',
req.params.get('with_description'))
else:
# Add backward compatibility support for case when heatclient
# version is lower than version with this parameter.
with_description = False
return {
'resource_types':
self.rpc_client.list_resource_types(req.context,
support_status=support_status,
type_name=type_name,
heat_version=version)}
self.rpc_client.list_resource_types(
req.context,
support_status=support_status,
type_name=type_name,
heat_version=version,
with_description=with_description)}
@util.policy_enforce
def list_template_versions(self, req):

View File

@ -573,3 +573,10 @@ def format_snapshot(snapshot):
rpc_api.SNAPSHOT_CREATION_TIME: snapshot.created_at.isoformat(),
}
return result
def build_resource_description(docstring):
if docstring is not None:
return '\n'.join(map(lambda x: x.strip(), docstring.split('\n')))
else:
return _('No description given')

View File

@ -574,7 +574,8 @@ class ResourceRegistry(object):
cnxt=None,
support_status=None,
type_name=None,
version=None):
version=None,
with_description=False):
"""Return a list of valid resource types."""
# validate the support status
@ -627,7 +628,21 @@ class ResourceRegistry(object):
return (version is None or
cls.get_class().support_status.version == version)
return [name for name, cls in six.iteritems(self._registry)
def resource_description(name, cls, with_description):
if not with_description:
return name
if cls.description == 'Plugin':
rsrc = cls.value
elif cls.description == 'Template':
rsrc = cls.get_class()
else:
rsrc = None
return {
'resource_type': name,
'description': rsrc.__doc__}
return [resource_description(name, cls, with_description)
for name, cls in six.iteritems(self._registry)
if (is_resource(name) and
name_matches(name) and
status_matches(cls) and
@ -723,11 +738,13 @@ class Environment(object):
cnxt=None,
support_status=None,
type_name=None,
version=None):
version=None,
with_description=False):
return self.registry.get_types(cnxt,
support_status=support_status,
type_name=type_name,
version=version)
version=version,
with_description=with_description)
def get_resource_info(self, resource_type, resource_name=None,
registry_type=None, ignore=None):

View File

@ -36,7 +36,8 @@ def generate_class_from_template(name, data, param_defaults):
props, attrs = TemplateResource.get_schemas(tmpl, param_defaults)
cls = type(name, (TemplateResource,),
{'properties_schema': props,
'attributes_schema': attrs})
'attributes_schema': attrs,
'__doc__': tmpl.t.get(tmpl.get_section_name('Description'))})
return cls

View File

@ -298,7 +298,7 @@ class EngineService(service.Service):
by the RPC caller.
"""
RPC_API_VERSION = '1.29'
RPC_API_VERSION = '1.30'
def __init__(self, host, topic):
super(EngineService, self).__init__()
@ -1432,18 +1432,27 @@ class EngineService(service.Service):
cnxt,
support_status=None,
type_name=None,
heat_version=None):
heat_version=None,
with_description=False):
"""Get a list of supported resource types.
:param cnxt: RPC context.
:param support_status: Support status of resource type
:param type_name: Resource type's name (regular expression allowed)
:param heat_version: Heat version
:param with_description: Either return resource type description or not
"""
return resources.global_env().get_types(cnxt,
support_status=support_status,
type_name=type_name,
version=heat_version)
result = resources.global_env().get_types(
cnxt,
support_status=support_status,
type_name=type_name,
version=heat_version,
with_description=with_description)
if with_description:
for resource_type in result:
resource_type['description'] = api.build_resource_description(
resource_type['description'])
return result
def list_template_versions(self, cnxt):
mgr = templatem._get_template_extension_manager()

View File

@ -50,6 +50,7 @@ class EngineClient(object):
1.27 - Add check_software_deployment
1.28 - Add environment_show call
1.29 - Add template_id to create_stack/update_stack
1.30 - Add possibility to resource_type_* return descriptions
"""
BASE_RPC_API_VERSION = '1.0'
@ -431,19 +432,23 @@ class EngineClient(object):
ctxt,
support_status=None,
type_name=None,
heat_version=None):
heat_version=None,
with_description=False):
"""Get a list of valid resource types.
:param ctxt: RPC context.
:param support_status: Support status of resource type
:param type_name: Resource type's name (regular expression allowed)
:param version: Heat version
:param heat_version: Heat version
:param with_description: Either return resource type description or not
"""
return self.call(ctxt, self.make_msg('list_resource_types',
support_status=support_status,
type_name=type_name,
heat_version=heat_version),
version='1.16')
return self.call(ctxt,
self.make_msg('list_resource_types',
support_status=support_status,
type_name=type_name,
heat_version=heat_version,
with_description=with_description),
version='1.30')
def list_template_versions(self, ctxt):
"""Get a list of available template versions.

View File

@ -2449,9 +2449,10 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
{
'support_status': None,
'type_name': None,
'heat_version': None
'heat_version': None,
'with_description': False
}),
version="1.16"
version="1.30"
).AndReturn(engine_response)
self.m.ReplayAll()
response = self.controller.list_resource_types(req,
@ -2471,9 +2472,10 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
{
'support_status': None,
'type_name': None,
'heat_version': None
'heat_version': None,
'with_description': False
}),
version="1.16"
version="1.30"
).AndRaise(tools.to_remote_error(error))
self.m.ReplayAll()

View File

@ -40,7 +40,7 @@ class ServiceEngineTest(common.HeatTestCase):
def test_make_sure_rpc_version(self):
self.assertEqual(
'1.29',
'1.30',
service.EngineService.RPC_API_VERSION,
('RPC version is changed, please update this test to new version '
'and make sure additional test cases are added for RPC APIs '

View File

@ -65,6 +65,25 @@ class ResourceTypeTest(common.HeatTestCase):
# Check for a known resource, not listed
self.assertNotIn('OS::Nova::Server', resources)
@mock.patch.object(res.Resource, 'is_service_available')
def test_list_resource_types_with_descr(self, mock_is_service_available):
mock_is_service_available.return_value = True
resources = self.eng.list_resource_types(self.ctx,
with_description=True)
self.assertIsInstance(resources, list)
description = ("Heat Template Resource for Designate Domain.\n\n"
"Designate provides DNS-as-a-Service services for "
"OpenStack. So, domain\nis a realm with an "
"identification string, unique in DNS.\n")
self.assertIn({'resource_type': 'OS::Designate::Domain',
'description': description}, resources)
self.assertIn({'resource_type': 'AWS::RDS::DBInstance',
'description': 'Builtin AWS::RDS::DBInstance'},
resources)
self.assertIn({'resource_type': 'AWS::EC2::Instance',
'description': 'No description given'},
resources)
def test_resource_schema(self):
type_name = 'ResourceWithPropsType'
expected = {

View File

@ -222,7 +222,8 @@ class EngineRpcAPITestCase(common.HeatTestCase):
support_status=None,
type_name=None,
heat_version=None,
version='1.16')
with_description=False,
version='1.30')
def test_resource_schema(self):
self._test_engine_api('resource_schema', 'call', type_name="TYPE")