Add rest endpoints for resource template generation.

Add api endpoints for generating a template based
on a resource implementation.

blueprint resource-template

Change-Id: Iebebad70befd1df6cd8989538cbb61350a17bc23
This commit is contained in:
Andrew Plunk 2013-07-12 09:56:07 -05:00
parent 87e02d79b8
commit 48fe2f04ba
9 changed files with 91 additions and 4 deletions

View File

@ -259,6 +259,7 @@ def map_remote_error(ex):
'StackNotFound',
'ResourceNotFound',
'ResourceNotAvailable',
'ResourceTypeNotFound',
'PhysicalResourceNotFound',
'WatchRuleNotFound',
'StackValidationFailed',

View File

@ -57,6 +57,7 @@ class FaultWrapper(wsgi.Middleware):
'ValueError': webob.exc.HTTPBadRequest,
'StackNotFound': webob.exc.HTTPNotFound,
'ResourceNotFound': webob.exc.HTTPNotFound,
'ResourceTypeNotFound': webob.exc.HTTPNotFound,
'ResourceNotAvailable': webob.exc.HTTPNotFound,
'PhysicalResourceNotFound': webob.exc.HTTPNotFound,
'InvalidTenant': webob.exc.HTTPForbidden,

View File

@ -53,6 +53,10 @@ class API(wsgi.Router):
"/resource_types",
action="list_resource_types",
conditions={'method': 'GET'})
stack_mapper.connect("generate_template",
"/resource_types/{type_name}/template",
action="generate_template",
conditions={'method': 'GET'})
# Stack collection
stack_mapper.connect("stack_index",

View File

@ -329,10 +329,14 @@ class StackController(object):
"""
Returns a list of valid resource types that may be used in a template.
"""
return {'resource_types': self.engine.list_resource_types(req.context)}
types = self.engine.list_resource_types(req.context)
return {'resource_types': types}
@util.tenant_local
def generate_template(self, req, type_name):
"""
Generates a template based on the specified type.
"""
return self.engine.generate_template(req.context, type_name)
class StackSerializer(wsgi.JSONResponseSerializer):

View File

@ -248,6 +248,10 @@ class ResourceNotFound(OpenstackException):
"in Stack %(stack_name)s.")
class ResourceTypeNotFound(OpenstackException):
message = _("The Resource Type (%(type_name)s) could not be found.")
class ResourceNotAvailable(OpenstackException):
message = _("The Resource (%(resource_name)s) is not available.")

View File

@ -383,6 +383,18 @@ class EngineService(service.Service):
"""
return list(resource.get_types())
def generate_template(self, cnxt, type_name):
"""
Generate a template based on the specified type.
arg1 -> RPC context.
arg2 -> Name of the resource type to generate a template for.
"""
try:
return \
resource.get_class(type_name).resource_to_template(type_name)
except exception.StackValidationFailed:
raise exception.ResourceTypeNotFound(type_name=type_name)
@request_context
def list_events(self, cnxt, stack_identity):
"""

View File

@ -160,6 +160,16 @@ class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy):
"""
return self.call(ctxt, self.make_msg('list_resource_types'))
def generate_template(self, ctxt, type_name):
"""
Generate a template based on the specified type.
:param ctxt: RPC context.
:param type_name: The resource type name to generate a template for.
"""
return self.call(ctxt, self.make_msg('generate_template',
type_name=type_name))
def list_events(self, ctxt, stack_identity):
"""
The list_events method lists all events associated with a given stack.

View File

@ -1138,6 +1138,42 @@ class StackControllerTest(ControllerTest, HeatTestCase):
self.assertEqual(resp.json['error']['type'], 'ServerError')
self.m.VerifyAll()
def test_generate_template(self):
req = self._get('/resource_types/TEST_TYPE/template')
engine_response = {'Type': 'TEST_TYPE'}
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'generate_template',
'args': {'type_name': 'TEST_TYPE'},
'version': self.api_version},
None).AndReturn(engine_response)
self.m.ReplayAll()
self.controller.generate_template(req, tenant_id=self.tenant,
type_name='TEST_TYPE')
self.m.VerifyAll()
def test_generate_template_not_found(self):
req = self._get('/resource_types/NOT_FOUND/template')
self.m.StubOutWithMock(rpc, 'call')
rpc.call(req.context, self.topic,
{'namespace': None,
'method': 'generate_template',
'args': {'type_name': 'NOT_FOUND'},
'version': self.api_version},
None).AndRaise(remote_error(heat_exc.ResourceTypeNotFound))
self.m.ReplayAll()
resp = request_with_middleware(fault.FaultWrapper,
self.controller.generate_template,
req, tenant_id=self.tenant,
type_name='NOT_FOUND')
self.assertEqual(resp.json['code'], 404)
self.assertEqual(resp.json['error']['type'], 'ResourceTypeNotFound')
self.m.VerifyAll()
class StackSerializerTest(HeatTestCase):
@ -1953,8 +1989,20 @@ class RoutesTest(HeatTestCase):
'list_resource_types',
'StackController',
{
'tenant_id': 'aaaa'
'tenant_id': 'aaaa',
})
self.assertRoute(
self.m,
'/aaaa/resource_types/test_type/template',
'GET',
'generate_template',
'StackController',
{
'tenant_id': 'aaaa',
'type_name': 'test_type'
})
self.assertRoute(
self.m,
'/aaaa/validate',

View File

@ -139,6 +139,9 @@ class EngineRpcAPITestCase(testtools.TestCase):
self._test_engine_api('list_stack_resources', 'call',
stack_identity=self.identity)
def test_generate_template(self):
self._test_engine_api('generate_template', 'call', type_name="TYPE")
def test_stack_suspend(self):
self._test_engine_api('stack_suspend', 'call',
stack_identity=self.identity)