]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Add the ValidateTemplate API.
authorAngus Salkeld <asalkeld@redhat.com>
Wed, 28 Mar 2012 08:36:18 +0000 (19:36 +1100)
committerAngus Salkeld <asalkeld@redhat.com>
Wed, 28 Mar 2012 08:37:00 +0000 (19:37 +1100)
Implementing the validate is still a TODO.

Re: issue #1

Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
bin/heat
heat/api/v1/__init__.py
heat/api/v1/stacks.py
heat/client.py
heat/engine/api/v1/__init__.py
heat/engine/api/v1/stacks.py
heat/engine/client.py
heat/engine/parser.py

index 1791bbce5a5137f224e4879f4cbecbf91a7b33f9..3d480164a133b74868e862b1523134a7ca3af72a 100755 (executable)
--- a/bin/heat
+++ b/bin/heat
@@ -87,7 +87,18 @@ def catch_error(action):
 def template_validate(options, arguments):
     '''
     '''
-    pass
+    parameters = {}
+    if options.template_file:
+        parameters['TemplateBody'] = open(options.template_file).read()
+    elif options.template_url:
+        parameters['TemplateUrl'] = options.template_url
+    else:
+        print 'Please specify a template file or url'
+        return FAILURE
+
+    c = get_client(options)
+    result = c.validate_template(**parameters)
+    print json.dumps(result, indent=2)
 
 @catch_error('gettemplate')
 def get_template(options, arguments):
index a906f169aa9d77be3105150d0f7d9d60018291e2..8ce18894d6fea11225a9f2c15fc0cc3d6efad9e8 100644 (file)
@@ -48,5 +48,7 @@ class API(wsgi.Router):
                        action="update", conditions=dict(method=["PUT"]))
         mapper.connect("/DescribeStackEvents", controller=stacks_resource,
                        action="events_list", conditions=dict(method=["GET"]))
+        mapper.connect("/ValidateTemplate", controller=stacks_resource,
+                       action="validate_template", conditions=dict(method=["GET"]))
 
         super(API, self).__init__(mapper)
index 2e88faf204bc0527c1992b0bf188a32016439fb8..2b195e66704033684147fb606eecf95efa1e3fad 100644 (file)
@@ -123,6 +123,28 @@ class StackController(object):
 
         return c.create_stack(stack, **req.params)
 
+    def validate_template(self, req):
+
+        c = engine.get_engine_client(req.context)
+
+        try:
+            templ = self._get_template(req)
+        except socket.gaierror:
+            msg = _('Invalid Template URL')
+            return webob.exc.HTTPBadRequest(explanation=msg)
+        if templ is None:
+            msg = _("TemplateBody or TemplateUrl were not given.")
+            return webob.exc.HTTPBadRequest(explanation=msg)
+
+        try:
+            stack = json.loads(templ)
+        except ValueError:
+            msg = _("The Template must be a JSON document.")
+            return webob.exc.HTTPBadRequest(explanation=msg)
+
+        logger.info('validate_template')
+        return c.validate_template(stack, **req.params)
+
     def delete(self, req):
         """
         Returns the following information for all stacks:
index 1d75337c221f8a6af2a806a70c3a9f6d40a35b6b..fae1a3e8f1364e18a4baadab169f63fd8e72a2b0 100644 (file)
@@ -88,6 +88,14 @@ class V1Client(base_client.BaseClient):
         data = json.loads(res.read())
         return data
 
+    def validate_template(self, **kwargs):
+        params = self._extract_params(kwargs, SUPPORTED_PARAMS)
+        self._insert_common_parameters(params)
+
+        res = self.do_request("GET", "/ValidateTemplate", params=params)
+        data = json.loads(res.read())
+        return data
+
 HeatClient = V1Client
 
 
index 170f7af8b4adbdfea608e393b7bd07cf70882349..cb1960a7eb7feb18e888b2a92fece58100663cc5 100644 (file)
@@ -29,6 +29,9 @@ class API(wsgi.Router):
         mapper.resource("stack", "stacks", controller=stacks_resource,
                         collection={'detail': 'GET'})
         mapper.connect("/", controller=stacks_resource, action="index")
+        mapper.connect("/validate_template", controller=stacks_resource,
+                       action="validate_template", conditions=dict(method=["POST"]))
+
 
         events_resource = events.create_resource(conf)
         mapper.resource("event", "events", controller=events_resource,
index fb5e5945cf3a12e54422a7591bdecee461d378d2..99f82da6a809a314c82504978d0e267c34f9a706 100644 (file)
@@ -100,6 +100,18 @@ class StacksController(object):
 
         return {'stack': {'id': body['StackName']}}
 
+    def validate_template(self, req, body=None):
+
+        logger.info('validate_template')
+        if body is None:
+            msg = _("No Template provided.")
+            return webob.exc.HTTPBadRequest(explanation=msg)
+
+        s = parser.Stack('validate', body, req.params)
+        res = s.validate()
+
+        return res
+
     def delete(self, req, id):
         if not stack_db.has_key(id):
             return webob.exc.HTTPNotFound('No stack by that name')
index 4ccad480b01f75594fb799ee251b87627ed0d144..2bae31dbfd125aff535e89e37e0e964309c59464 100644 (file)
@@ -87,6 +87,20 @@ class EngineClient(BaseClient):
         data = json.loads(res.read())['stacks']
         return data
 
+    def validate_template(self, template, **kwargs):
+        """
+        Validate the template
+        """
+        headers = {
+            'Content-Type': 'application/json',
+        }
+
+        logger.info(template)
+        res = self.do_request("POST", "/validate_template", body=json.dumps(template),
+                              headers=headers, params=kwargs)
+        data = json.loads(res.read())
+        logger.info(data)
+        return data
 
     def create_stack(self, template, **kwargs):
         """
index c8757d4dc34ce6873446302dd6cda47fb5d652ce..e9fd1be9b712d86b404ae0622f1e96fe125bb7b4 100644 (file)
@@ -20,7 +20,6 @@ from heat.engine import resources
 
 logger = logging.getLogger('heat.engine.parser')
 
-
 class Stack:
     def __init__(self, stack_name, template, parms=None):
 
@@ -62,6 +61,34 @@ class Stack:
 
             self.calulate_dependancies(self.t['Resources'][r], self.resources[r])
 
+    def validate(self):
+        '''
+            If you are wondering where the actual validation is, me too.
+            it is just not obvious how to respond to validation failures.
+            http://docs.amazonwebservices.com/AWSCloudFormation/latest/APIReference/API_ValidateTemplate.html
+        '''
+        response = { 'ValidateTemplateResult': {
+                    'Description': 'bla',
+                    'Parameters': []
+                    }
+              }
+
+        for p in self.parms:
+            jp = {'member': {}}
+            res = jp['member']
+            res['NoEcho'] = 'false'
+            res['ParameterKey'] = p
+            if self.parms[p].has_key('Description'):
+                res['Description'] = self.parms[p]['Description']
+            else:
+                res['Description'] = ''
+            if self.parms[p].has_key('Default'):
+                res['DefaultValue'] = self.parms[p]['Default']
+            else:
+                res['DefaultValue'] = ''
+            response['ValidateTemplateResult']['Parameters'].append(res)
+        return response
+
     def start(self):
         # start Volumes first.
         for r in self.t['Resources']:
@@ -91,16 +118,12 @@ class Stack:
             for index, item in enumerate(s):
                 self.calulate_dependancies(item, r)
 
-
     def _apply_user_parameter(self, key, value):
-        logger.info('_apply_user_parameter %s=%s ' % (key, value))
-        if not self.t.has_key('Parameters'):
-            self.t['Parameters'] = {}
-
-        if not self.t['Parameters'].has_key(key):
-            self.t['Parameters'][key] = {}
+        logger.debug('appling user parameter %s=%s ' % (key, value))
 
-        self.t['Parameters'][key]['Value'] = value
+        if not self.parms.has_key(key):
+            self.parms[key] = {}
+        self.parms[key]['Value'] = value
 
     def _apply_user_parameters(self, parms):
         for p in parms:
@@ -111,21 +134,19 @@ class Stack:
                     value_name = 'Parameters.member.%s.ParameterValue' % s[2]
                     self._apply_user_parameter(parms[key_name], parms[value_name])
                 except:
-                    logger.error('could not apply parameter %s' % p)
-
+                    logger.error('Could not apply parameter %s' % p)
 
     def parameter_get(self, key):
         if self.parms[key] == None:
-            #print 'None Ref: %s' % key
-            return '=EMPTY='
+            logger.warn('Trying to reference parameter: %s, but it is empty' % key)
+            return ''
         elif self.parms[key].has_key('Value'):
             return self.parms[key]['Value']
         elif self.parms[key].has_key('Default'):
             return self.parms[key]['Default']
         else:
-            #print 'Missing Ref: %s' % key
-            return '=EMPTY='
-
+            logger.warn('Trying to reference parameter: %s, but no Value or Default' % key)
+            return ''
 
     def resolve_static_refs(self, s):
         '''