]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Add rest endpoints for resource template generation.
authorAndrew Plunk <andrew.plunk@rackspace.com>
Fri, 12 Jul 2013 14:56:07 +0000 (09:56 -0500)
committerAndrew Plunk <andrew.plunk@rackspace.com>
Fri, 26 Jul 2013 15:53:39 +0000 (10:53 -0500)
Add api endpoints for generating a template based
on a resource implementation.

blueprint resource-template

Change-Id: Iebebad70befd1df6cd8989538cbb61350a17bc23

heat/api/aws/exception.py
heat/api/middleware/fault.py
heat/api/openstack/v1/__init__.py
heat/api/openstack/v1/stacks.py
heat/common/exception.py
heat/engine/service.py
heat/rpc/client.py
heat/tests/test_api_openstack_v1.py
heat/tests/test_rpc_client.py

index c10907704755ad6190e62ea165e62aab16d07738..a0207b67381f13bc11fd041716161d7d7d408b52 100644 (file)
@@ -259,6 +259,7 @@ def map_remote_error(ex):
             'StackNotFound',
             'ResourceNotFound',
             'ResourceNotAvailable',
+            'ResourceTypeNotFound',
             'PhysicalResourceNotFound',
             'WatchRuleNotFound',
             'StackValidationFailed',
index 370fe49536a5cbef759049544a862bc3c72d157a..9df7ae60e5a5a93fca052e801f330860b9751516 100644 (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,
index b0898f1f70cc3f7678e67affb4459b4f98f08dda..a1ab038f1c000b87d2091c49fddc6af43f4f7449 100644 (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",
index d7bb53d376568147191ca1e6955ebd1b098e13d7..617f25a3fe6d52ab0d8caca26c8f194bffdd631c 100644 (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):
index 0fc68e9a4ed84302879487b0fbe5547bed09e3c4..eb236a5a38e462d28ca9edc5d5449bc3381e1b26 100644 (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.")
 
index d91423ad27864c3217ccaa6b86d8cede134b303e..add8e1a895f1b55d6dfc16baa3ca1b032f4ba133 100644 (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):
         """
index dba3c4ff87b05c10d21c70f33b8ffe88e6ad0b8f..c0a32300b0f84ef8d6f35f911a76b16e28098d6a 100644 (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.
index ce38c4eb3cccb228845e9433484e60f482a8d3c0..db0275a28bc653f66ca14fcda717d28736867a83 100644 (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',
index 3b25f7fbda9850592ac4d13a60ab75218e38e021..93a1bbe3220fd1a3980d3c520d7026db7624f1e3 100644 (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)