From 99670fb1cc7ba7c9d8d779f13c9f7309b5d21328 Mon Sep 17 00:00:00 2001
From: Steven Hardy <shardy@redhat.com>
Date: Tue, 15 Sep 2015 12:01:05 +0100
Subject: [PATCH] Wire in files to template validate

heatclient already supplies the files map, as for create/update
but the API and RPC interfaces ignore it.  So wire in the optional
files map, which will enable moving to validation logic which
more closely aligns with the create/update code.

Change-Id: I32a4b8d8c02829398f4792fcb06783ce9233b645
Co-Authored-By: Jay Dobies <jdobies@redhat.com>
Partial-Bug: 1467573
---
 heat/api/openstack/v1/stacks.py                  | 3 ++-
 heat/engine/service.py                           | 7 ++++---
 heat/rpc/client.py                               | 8 ++++++--
 heat/tests/api/cfn/test_api_cfn_v1.py            | 4 +++-
 heat/tests/api/openstack_v1/test_stacks.py       | 8 ++++++--
 heat/tests/engine/service/test_service_engine.py | 2 +-
 heat/tests/test_rpc_client.py                    | 3 ++-
 7 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py
index 2ff26327d1..04d8265b5f 100644
--- a/heat/api/openstack/v1/stacks.py
+++ b/heat/api/openstack/v1/stacks.py
@@ -511,7 +511,8 @@ class StackController(object):
 
         result = self.rpc_client.validate_template(req.context,
                                                    data.template(),
-                                                   data.environment())
+                                                   data.environment(),
+                                                   files=data.files())
 
         if 'Error' in result:
             raise exc.HTTPBadRequest(result['Error'])
diff --git a/heat/engine/service.py b/heat/engine/service.py
index 54d58a6762..1a162ebdd0 100644
--- a/heat/engine/service.py
+++ b/heat/engine/service.py
@@ -273,7 +273,7 @@ class EngineService(service.Service):
     by the RPC caller.
     """
 
-    RPC_API_VERSION = '1.16'
+    RPC_API_VERSION = '1.17'
 
     def __init__(self, host, topic):
         super(EngineService, self).__init__()
@@ -927,7 +927,7 @@ class EngineService(service.Service):
                                                 engine_id=engine_id)
 
     @context.request_context
-    def validate_template(self, cnxt, template, params=None):
+    def validate_template(self, cnxt, template, params=None, files=None):
         """
         The validate_template method uses the stack parser to check
         the validity of a template.
@@ -935,13 +935,14 @@ class EngineService(service.Service):
         :param cnxt: RPC context.
         :param template: Template of stack you want to create.
         :param params: Stack Input Params
+        :param files: Files referenced from the template
         """
         LOG.info(_LI('validate_template'))
         if template is None:
             msg = _("No Template provided.")
             return webob.exc.HTTPBadRequest(explanation=msg)
 
-        tmpl = templatem.Template(template)
+        tmpl = templatem.Template(template, files=files)
 
         # validate overall template
         try:
diff --git a/heat/rpc/client.py b/heat/rpc/client.py
index 5526674d2f..670e2eb85b 100644
--- a/heat/rpc/client.py
+++ b/heat/rpc/client.py
@@ -37,6 +37,7 @@ class EngineClient(object):
         1.14 - Add cancel_with_rollback option to stack_cancel_update
         1.15 - Add preview_update_stack() call
         1.16 - Adds version, type_name to list_resource_types()
+        1.17 - Add files to validate_template
     '''
 
     BASE_RPC_API_VERSION = '1.0'
@@ -292,7 +293,7 @@ class EngineClient(object):
                                        ),
                          version='1.15')
 
-    def validate_template(self, ctxt, template, params=None):
+    def validate_template(self, ctxt, template, params=None, files=None):
         """
         The validate_template method uses the stack parser to check
         the validity of a template.
@@ -300,10 +301,13 @@ class EngineClient(object):
         :param ctxt: RPC context.
         :param template: Template of stack you want to create.
         :param params: Stack Input Params/Environment
+        :param files: files referenced from the environment/template.
         """
         return self.call(ctxt, self.make_msg('validate_template',
                                              template=template,
-                                             params=params))
+                                             params=params,
+                                             files=files),
+                         version='1.17')
 
     def authenticated_to_backend(self, ctxt):
         """
diff --git a/heat/tests/api/cfn/test_api_cfn_v1.py b/heat/tests/api/cfn/test_api_cfn_v1.py
index c0fce4f18a..a8a9a57617 100644
--- a/heat/tests/api/cfn/test_api_cfn_v1.py
+++ b/heat/tests/api/cfn/test_api_cfn_v1.py
@@ -1073,7 +1073,9 @@ class CfnStackControllerTest(common.HeatTestCase):
         self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
         rpc_client.EngineClient.call(
             dummy_req.context,
-            ('validate_template', {'template': json_template, 'params': None})
+            ('validate_template', {'template': json_template, 'params': None,
+                                   'files': None}),
+            version='1.17'
         ).AndReturn(response)
         self.m.ReplayAll()
 
diff --git a/heat/tests/api/openstack_v1/test_stacks.py b/heat/tests/api/openstack_v1/test_stacks.py
index e1ecf4eeed..cfdca8e283 100644
--- a/heat/tests/api/openstack_v1/test_stacks.py
+++ b/heat/tests/api/openstack_v1/test_stacks.py
@@ -2000,7 +2000,9 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
               'params': {'parameters': {},
                          'encrypted_param_names': [],
                          'parameter_defaults': {},
-                         'resource_registry': {}}})
+                         'resource_registry': {}},
+              'files': {}}),
+            version='1.17'
         ).AndReturn(engine_response)
         self.m.ReplayAll()
 
@@ -2025,7 +2027,9 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
               'params': {'parameters': {},
                          'encrypted_param_names': [],
                          'parameter_defaults': {},
-                         'resource_registry': {}}})
+                         'resource_registry': {}},
+              'files': {}}),
+            version='1.17'
         ).AndReturn({'Error': 'fubar'})
         self.m.ReplayAll()
 
diff --git a/heat/tests/engine/service/test_service_engine.py b/heat/tests/engine/service/test_service_engine.py
index fb586736d4..17fb4b1af7 100644
--- a/heat/tests/engine/service/test_service_engine.py
+++ b/heat/tests/engine/service/test_service_engine.py
@@ -39,7 +39,7 @@ class ServiceEngineTest(common.HeatTestCase):
 
     def test_make_sure_rpc_version(self):
         self.assertEqual(
-            '1.16',
+            '1.17',
             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 '
diff --git a/heat/tests/test_rpc_client.py b/heat/tests/test_rpc_client.py
index 9bb5879b48..683ee369e5 100644
--- a/heat/tests/test_rpc_client.py
+++ b/heat/tests/test_rpc_client.py
@@ -198,7 +198,8 @@ class EngineRpcAPITestCase(common.HeatTestCase):
     def test_validate_template(self):
         self._test_engine_api('validate_template', 'call',
                               template={u'Foo': u'bar'},
-                              params={u'Egg': u'spam'})
+                              params={u'Egg': u'spam'},
+                              files=None)
 
     def test_list_resource_types(self):
         self._test_engine_api('list_resource_types',