]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Separate out formatting for Engine API from manager
authorZane Bitter <zbitter@redhat.com>
Fri, 6 Jul 2012 12:33:19 +0000 (14:33 +0200)
committerZane Bitter <zbitter@redhat.com>
Fri, 6 Jul 2012 13:20:16 +0000 (15:20 +0200)
Change-Id: Ib5fc28bc6a3a2f1f3c0d291954e928d4fb036bbb
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/engine/api.py [new file with mode: 0644]
heat/engine/manager.py
heat/engine/parser.py
heat/tests/test_engine_api_utils.py [moved from heat/tests/test_manager.py with 85% similarity]
heat/tests/test_stacks.py

diff --git a/heat/engine/api.py b/heat/engine/api.py
new file mode 100644 (file)
index 0000000..d11c405
--- /dev/null
@@ -0,0 +1,264 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import re
+import logging
+from heat.common import utils as heat_utils
+from heat.db import api as db_api
+from heat.engine import parser
+
+
+logger = logging.getLogger('heat.engine.manager')
+
+PARAM_KEYS = (
+    PARAM_TIMEOUT,
+    PARAM_USER_KEY_re,
+    PARAM_USER_VALUE_fmt,
+) = (
+    'TimeoutInMinutes',
+    re.compile(r'Parameters\.member\.(.*?)\.ParameterKey$'),
+    'Parameters.member.%s.ParameterValue',
+)
+
+
+def extract_user_params(params):
+    '''
+    Extract a dictionary of user parameters (to e.g. a stack create command)
+    from the parameter dictionary passed through the API.
+
+    In the API parameters, each user parameter appears as two key-value pairs
+    with keys of the form:
+
+        Parameters.member.1.ParameterKey
+        Parameters.member.1.ParameterValue
+    '''
+    def get_param_pairs():
+        for k in params:
+            keymatch = PARAM_USER_KEY_re.match(k)
+            if keymatch:
+                key = params[k]
+                v = PARAM_USER_VALUE_fmt % keymatch.group(1)
+                try:
+                    value = params[v]
+                except KeyError:
+                    logger.error('Could not apply parameter %s' % key)
+
+                yield (key, value)
+
+    return dict(get_param_pairs())
+
+
+def extract_args(params):
+    '''
+    Extract any arguments passed as parameters through the API and return them
+    as a dictionary.
+    '''
+    kwargs = {}
+    try:
+        timeout_mins = int(params.get(PARAM_TIMEOUT, 0))
+    except (ValueError, TypeError):
+        logger.exception('create timeout conversion')
+    else:
+        if timeout_mins > 0:
+            kwargs['timeout_in_minutes'] = timeout_mins
+    return kwargs
+
+
+def _filter_keys(data, keys):
+    '''
+    Filter the provided data so that only the dictionary keys specified are
+    present. If keys is None, return all of the data.
+    '''
+    if keys is not None:
+        data = dict((k, v) for (k, v) in data.iteritems() if k in keys)
+
+    return data
+
+
+STACK_KEYS = (
+    STACK_NAME, STACK_ID,
+    STACK_CREATION_TIME, STACK_UPDATED_TIME, STACK_DELETION_TIME,
+    STACK_NOTIFICATION_TOPICS,
+    STACK_DESCRIPTION, STACK_TMPL_DESCRIPTION,
+    STACK_PARAMETERS, STACK_OUTPUTS,
+    STACK_STATUS, STACK_STATUS_DATA,
+    STACK_TIMEOUT,
+) = (
+    'StackName', 'StackId',
+    'CreationTime', 'LastUpdatedTime', 'DeletionTime',
+    'NotificationARNs',
+    'Description', 'TemplateDescription',
+    'Parameters', 'Outputs',
+    'StackStatus', 'StackStatusReason',
+    PARAM_TIMEOUT,
+)
+
+KEYS_STACK = (
+    STACK_NAME, STACK_ID,
+    STACK_CREATION_TIME, STACK_UPDATED_TIME,
+    STACK_NOTIFICATION_TOPICS,
+    STACK_DESCRIPTION,
+    STACK_PARAMETERS, STACK_DESCRIPTION, STACK_OUTPUTS,
+    STACK_STATUS, STACK_STATUS_DATA,
+    STACK_TIMEOUT,
+)
+KEYS_STACK_SUMMARY = (
+    STACK_CREATION_TIME, STACK_DELETION_TIME,
+    STACK_UPDATED_TIME,
+    STACK_ID, STACK_NAME,
+    STACK_TMPL_DESCRIPTION,
+    STACK_STATUS, STACK_STATUS_DATA,
+)
+
+
+STACK_OUTPUT_KEYS = (
+    OUTPUT_DESCRIPTION,
+    OUTPUT_KEY, OUTPUT_VALUE,
+) = (
+    'Description',
+    'OutputKey', 'OutputValue',
+)
+
+
+def format_stack_outputs(stack, outputs):
+    '''
+    Return a representation of the given output template for the given stack
+    that matches the API output expectations.
+    '''
+    def format_stack_output(k):
+        return {OUTPUT_DESCRIPTION: outputs[k].get('Description',
+                                                   'No description given'),
+                OUTPUT_KEY: k,
+                OUTPUT_VALUE: stack.output(k)}
+
+    return [format_stack_output(key) for key in outputs]
+
+
+def format_stack(stack, keys=None):
+    '''
+    Return a representation of the given stack that matches the API output
+    expectations.
+    '''
+    s = db_api.stack_get(stack.context, stack.id)
+    info = {
+        STACK_NAME: stack.name,
+        STACK_ID: stack.stack_id(),
+        STACK_CREATION_TIME: heat_utils.strtime(s.created_at),
+        STACK_UPDATED_TIME: heat_utils.strtime(s.updated_at),
+        STACK_NOTIFICATION_TOPICS: [],  # TODO Not implemented yet
+        STACK_PARAMETERS: stack.t[parser.PARAMETERS],
+        STACK_DESCRIPTION: stack.t[parser.DESCRIPTION],
+        STACK_TMPL_DESCRIPTION: stack.t[parser.DESCRIPTION],
+        STACK_STATUS: s.status,
+        STACK_STATUS_DATA: s.status_reason,
+    }
+
+    # only show the outputs on a completely created stack
+    if s.status == stack.CREATE_COMPLETE:
+        info[STACK_OUTPUTS] = format_stack_outputs(stack, stack.outputs)
+
+    return _filter_keys(info, keys)
+
+
+RES_KEYS = (
+    RES_DESCRIPTION, RES_UPDATED_TIME,
+    RES_NAME, RES_PHYSICAL_ID, RES_METADATA,
+    RES_STATUS, RES_STATUS_DATA, RES_TYPE,
+    RES_STACK_ID, RES_STACK_NAME,
+    RES_TIMESTAMP,
+) = (
+    'Description', 'LastUpdatedTimestamp',
+    'LogicalResourceId', 'PhysicalResourceId', 'Metadata',
+    'ResourceStatus', 'ResourceStatusReason', 'ResourceType',
+    STACK_ID, STACK_NAME,
+    'Timestamp',
+)
+
+KEYS_RESOURCE_DETAIL = (
+    RES_DESCRIPTION, RES_UPDATED_TIME,
+    RES_NAME, RES_PHYSICAL_ID, RES_METADATA,
+    RES_STATUS, RES_STATUS_DATA, RES_TYPE,
+    RES_STACK_ID, RES_STACK_NAME,
+)
+KEYS_RESOURCE = (
+    RES_DESCRIPTION,
+    RES_NAME, RES_PHYSICAL_ID,
+    RES_STATUS, RES_STATUS_DATA, RES_TYPE,
+    RES_STACK_ID, RES_STACK_NAME,
+    RES_TIMESTAMP,
+)
+KEYS_RESOURCE_SUMMARY = (
+    RES_UPDATED_TIME,
+    RES_NAME, RES_PHYSICAL_ID,
+    RES_STATUS, RES_STATUS_DATA, RES_TYPE,
+)
+
+
+def format_stack_resource(resource, keys=None):
+    '''
+    Return a representation of the given resource that matches the API output
+    expectations.
+    '''
+    rs = db_api.resource_get(resource.context, resource.id)
+    last_updated_time = rs.updated_at or rs.created_at
+    attrs = {
+        RES_DESCRIPTION: resource.parsed_template().get('Description', ''),
+        RES_UPDATED_TIME: heat_utils.strtime(last_updated_time),
+        RES_NAME: resource.name,
+        RES_PHYSICAL_ID: resource.instance_id or '',
+        RES_METADATA: rs.rsrc_metadata,
+        RES_STATUS: rs.state,
+        RES_STATUS_DATA: rs.state_description,
+        RES_TYPE: resource.t['Type'],
+        RES_STACK_ID: resource.stack.stack_id(),
+        RES_STACK_NAME: resource.stack.name,
+        RES_TIMESTAMP: heat_utils.strtime(last_updated_time),
+    }
+
+    return _filter_keys(attrs, keys)
+
+
+EVENT_KEYS = (
+    EVENT_ID,
+    EVENT_STACK_ID, EVENT_STACK_NAME,
+    EVENT_TIMESTAMP,
+    EVENT_RES_NAME, EVENT_RES_PHYSICAL_ID,
+    EVENT_RES_STATUS, EVENT_RES_STATUS_DATA, EVENT_RES_TYPE,
+    EVENT_RES_PROPERTIES,
+) = (
+    'EventId',
+    STACK_ID, STACK_NAME,
+    RES_TIMESTAMP,
+    RES_NAME, RES_PHYSICAL_ID,
+    RES_STATUS, RES_STATUS_DATA, RES_TYPE,
+    'ResourceProperties',
+)
+
+
+def format_event(event, keys=None):
+    s = event.stack
+    attrs = {
+        EVENT_ID: event.id,
+        EVENT_STACK_ID: event.stack_id,
+        EVENT_STACK_NAME: s.name,
+        EVENT_TIMESTAMP: heat_utils.strtime(event.created_at),
+        EVENT_RES_NAME: event.logical_resource_id,
+        EVENT_RES_PHYSICAL_ID: event.physical_resource_id,
+        EVENT_RES_STATUS: event.name,
+        EVENT_RES_STATUS_DATA: event.resource_status_reason,
+        EVENT_RES_TYPE: event.resource_type,
+        EVENT_RES_PROPERTIES: event.resource_properties,
+    }
+
+    return _filter_keys(attrs, keys)
index bd9d25069787e6e4507f0ee52d907801766647ef..81b630e77fb2d8942974fed199584770fcd0918b 100644 (file)
@@ -20,7 +20,6 @@ import logging
 import webob
 import json
 import urlparse
-import re
 import httplib
 import eventlet
 
@@ -29,6 +28,7 @@ from heat.db import api as db_api
 from heat.common import config
 from heat.common import utils as heat_utils
 from heat.common import context as ctxtlib
+from heat.engine import api
 from heat.engine import parser
 from heat.engine import resources
 from heat.engine import watchrule
@@ -43,37 +43,6 @@ from novaclient.exceptions import AuthorizationFailure
 logger = logging.getLogger('heat.engine.manager')
 greenpool = eventlet.GreenPool()
 
-_param_key = re.compile(r'Parameters\.member\.(.*?)\.ParameterKey$')
-
-
-def _extract_user_params(params):
-    def get_param_pairs():
-        for k in params:
-            keymatch = _param_key.match(k)
-            if keymatch:
-                key = params[k]
-                v = 'Parameters.member.%s.ParameterValue' % keymatch.group(1)
-                try:
-                    value = params[v]
-                except KeyError:
-                    logger.error('Could not apply parameter %s' % key)
-
-                yield (key, value)
-
-    return dict(get_param_pairs())
-
-
-def _extract_args(params):
-    kwargs = {}
-    try:
-        timeout_mins = int(params.get('TimeoutInMinutes', 0))
-    except (ValueError, TypeError):
-        logger.exception('create timeout conversion')
-    else:
-        if timeout_mins > 0:
-            kwargs['timeout_in_minutes'] = timeout_mins
-    return kwargs
-
 
 class EngineManager(manager.Manager):
     """
@@ -100,21 +69,15 @@ class EngineManager(manager.Manager):
 
         auth.authenticate(context)
 
-        res = {'stacks': []}
         stacks = db_api.stack_get_by_user(context)
         if stacks is None:
-            return res
-        for s in stacks:
+            stacks = []
+
+        def format_stack_summary(s):
             stack = parser.Stack.load(context, s.id)
-            mem = {}
-            mem['StackId'] = stack.stack_id()
-            mem['StackName'] = s.name
-            mem['CreationTime'] = heat_utils.strtime(s.created_at)
-            mem['TemplateDescription'] = stack.t[parser.DESCRIPTION]
-            mem['StackStatus'] = s.status
-            res['stacks'].append(mem)
+            return api.format_stack(stack, api.KEYS_STACK_SUMMARY)
 
-        return res
+        return {'stacks': [format_stack_summary(s) for s in stacks]}
 
     def show_stack(self, context, stack_name, params):
         """
@@ -125,41 +88,17 @@ class EngineManager(manager.Manager):
         """
         auth.authenticate(context)
 
-        res = {'stacks': []}
-        stacks = []
-        if not stack_name:
-            stacks = [s.name for s in db_api.stack_get_by_user(context)]
-            logging.debug("No stack name passed, got %s" % stacks)
+        if stack_name is not None:
+            s = db_api.stack_get_by_name(context, stack_name)
+            stacks = [s] if s is not None else []
         else:
-            stacks = [stack_name]
-
-        if not stacks:
-            logging.debug("No stacks found to process")
-            return res
-
-        for stack in stacks:
-            logging.debug("Processing show_stack for %s" % stack)
-            s = db_api.stack_get_by_name(context, stack)
-            if s:
-                stack = parser.Stack.load(context, s.id)
-                mem = {}
-                mem['StackId'] = stack.stack_id()
-                mem['StackName'] = s.name
-                mem['CreationTime'] = heat_utils.strtime(s.created_at)
-                mem['LastUpdatedTimestamp'] = heat_utils.strtime(s.updated_at)
-                mem['NotificationARNs'] = 'TODO'
-                mem['Parameters'] = stack.t[parser.PARAMETERS]
-                mem['Description'] = stack.t[parser.DESCRIPTION]
-                mem['StackStatus'] = s.status
-                mem['StackStatusReason'] = s.status_reason
-
-                # only show the outputs on a completely created stack
-                if s.status == stack.CREATE_COMPLETE:
-                    mem['Outputs'] = stack.get_outputs()
-
-                res['stacks'].append(mem)
-
-        return res
+            stacks = db_api.stack_get_by_user(context) or []
+
+        def format_stack_detail(s):
+            stack = parser.Stack.load(context, s.id)
+            return api.format_stack(stack, api.KEYS_STACK)
+
+        return {'stacks': [format_stack_detail(s) for s in stacks]}
 
     def create_stack(self, context, stack_name, template, params):
         """
@@ -181,7 +120,7 @@ class EngineManager(manager.Manager):
 
         tmpl = parser.Template(template)
         user_params = parser.Parameters(stack_name, tmpl,
-                                        _extract_user_params(params))
+                                        api.extract_user_params(params))
         stack = parser.Stack(context, stack_name, tmpl, user_params)
 
         response = stack.validate()
@@ -189,7 +128,7 @@ class EngineManager(manager.Manager):
             return response
 
         stack_id = stack.store()
-        greenpool.spawn_n(stack.create, **_extract_args(params))
+        greenpool.spawn_n(stack.create, **api.extract_args(params))
 
         return {'StackId': stack.stack_id()}
 
@@ -214,7 +153,7 @@ class EngineManager(manager.Manager):
         try:
             tmpl = parser.Template(template)
             user_params = parser.Parameters(stack_name, tmpl,
-                                            _extract_user_params(params))
+                                            api.extract_user_params(params))
             s = parser.Stack(context, stack_name, tmpl, user_params)
         except KeyError as ex:
             res = ('A Fn::FindInMap operation referenced '
@@ -260,20 +199,6 @@ class EngineManager(manager.Manager):
         greenpool.spawn_n(stack.delete)
         return None
 
-    # Helper for list_events.  It's here so we can use it in tests.
-    def parse_event(self, event):
-        s = event.stack
-        return {'EventId': event.id,
-                'StackId': event.stack_id,
-                'StackName': s.name,
-                'Timestamp': heat_utils.strtime(event.created_at),
-                'LogicalResourceId': event.logical_resource_id,
-                'PhysicalResourceId': event.physical_resource_id,
-                'ResourceType': event.resource_type,
-                'ResourceStatusReason': event.resource_status_reason,
-                'ResourceProperties': event.resource_properties,
-                'ResourceStatus': event.name}
-
     def list_events(self, context, stack_name, params):
         """
         The list_events method lists all events associated with a given stack.
@@ -293,7 +218,7 @@ class EngineManager(manager.Manager):
         else:
             events = db_api.event_get_all_by_user(context)
 
-        return {'events': [self.parse_event(e) for e in events]}
+        return {'events': [api.format_event(e) for e in events]}
 
     def event_create(self, context, event):
 
@@ -340,7 +265,8 @@ class EngineManager(manager.Manager):
         if resource.id is None:
             raise AttributeError('Resource not created')
 
-        return format_stack_resource(stack[resource_name])
+        return api.format_stack_resource(stack[resource_name],
+                                         api.KEYS_RESOURCE_DETAIL)
 
     def describe_stack_resources(self, context, stack_name,
                                  physical_resource_id, logical_resource_id):
@@ -360,18 +286,15 @@ class EngineManager(manager.Manager):
             raise AttributeError("The specified stack doesn't exist")
 
         stack = parser.Stack.load(context, s.id)
-        resources = []
-        for resource in stack:
-            if logical_resource_id and resource.name != logical_resource_id:
-                continue
-            formatted = format_stack_resource(resource)
-            # this API call uses Timestamp instead of LastUpdatedTimestamp
-            formatted['Timestamp'] = formatted['LastUpdatedTimestamp']
-            del formatted['LastUpdatedTimestamp']
-            del formatted['Metadata']
-            resources.append(formatted)
 
-        return resources
+        if logical_resource_id is not None:
+            name_match = lambda r: r.name == logical_resource_id
+        else:
+            name_match = lambda r: True
+
+        return [api.format_stack_resource(resource, api.KEYS_RESOURCE)
+                for resource in stack if resource.id is not None and
+                                         name_match(resource)]
 
     def list_stack_resources(self, context, stack_name):
         auth.authenticate(context)
@@ -382,17 +305,8 @@ class EngineManager(manager.Manager):
 
         stack = parser.Stack.load(context, s.id)
 
-        resources = []
-        response_keys = ('ResourceStatus', 'LogicalResourceId',
-                         'LastUpdatedTimestamp', 'PhysicalResourceId',
-                         'ResourceType')
-        for resource in stack:
-            formatted = format_stack_resource(resource)
-            for key in formatted.keys():
-                if not key in response_keys:
-                    del formatted[key]
-            resources.append(formatted)
-        return resources
+        return [api.format_stack_resource(resource, api.KEYS_RESOURCE_SUMMARY)
+                for resource in stack if resource.id is not None]
 
     def metadata_register_address(self, context, url):
         config.FLAGS.heat_metadata_server_url = url
@@ -510,23 +424,3 @@ class EngineManager(manager.Manager):
             self.run_rule(None, wr)
 
         return [None, wd.data]
-
-
-def format_stack_resource(resource):
-    """
-    Return a representation of the given resource that mathes the API output
-    expectations.
-    """
-    rs = db_api.resource_get(resource.stack.context, resource.id)
-    last_updated_time = rs.updated_at or rs.created_at
-    return {
-        'StackId': resource.stack.stack_id(),
-        'StackName': resource.stack.name,
-        'LogicalResourceId': resource.name,
-        'PhysicalResourceId': resource.instance_id or '',
-        'ResourceType': resource.t['Type'],
-        'LastUpdatedTimestamp': heat_utils.strtime(last_updated_time),
-        'Metadata': rs.rsrc_metadata,
-        'ResourceStatus': rs.state,
-        'ResourceStatusReason': rs.state_description,
-    }
index e1244a80beaea18dbf509bad8e827978d2c9e43a..555c8144b7643eaed4ccdf5257fad19956156812 100644 (file)
@@ -433,18 +433,12 @@ class Stack(object):
             db_api.stack_delete(self.context, self.id)
 
     def output(self, key):
+        '''
+        Get the value of the specified stack output.
+        '''
         value = self.outputs[key].get('Value', '')
         return self.resolve_runtime_data(value)
 
-    def get_outputs(self):
-        def output_dict(k):
-            return {'Description': self.outputs[k].get('Description',
-                                                       'No description given'),
-                    'OutputKey': k,
-                    'OutputValue': self.output(k)}
-
-        return [output_dict(key) for key in self.outputs]
-
     def restart_resource(self, resource_name):
         '''
         stop resource_name and all that depend on it
similarity index 85%
rename from heat/tests/test_manager.py
rename to heat/tests/test_engine_api_utils.py
index 39382d4091e99b204b41d6c09ac16275604c6553..453af34ac4c0d35f490aacd38c64285b72807c98 100644 (file)
@@ -17,18 +17,18 @@ import nose
 import unittest
 from nose.plugins.attrib import attr
 
-import heat.engine.manager as manager
+import heat.engine.api as api
 
 
-@attr(tag=['unit', 'manager'])
+@attr(tag=['unit', 'engine-api'])
 @attr(speed='fast')
-class managerTest(unittest.TestCase):
+class EngineApiTest(unittest.TestCase):
     def test_params_extract(self):
         p = {'Parameters.member.Foo.ParameterKey': 'foo',
              'Parameters.member.Foo.ParameterValue': 'bar',
              'Parameters.member.Blarg.ParameterKey': 'blarg',
              'Parameters.member.Blarg.ParameterValue': 'wibble'}
-        params = manager._extract_user_params(p)
+        params = api.extract_user_params(p)
         self.assertEqual(len(params), 2)
         self.assertTrue('foo' in params)
         self.assertEqual(params['foo'], 'bar')
@@ -40,7 +40,7 @@ class managerTest(unittest.TestCase):
              'Parameters.member.Foo.Bar.ParameterValue': 'bar',
              'Parameters.member.Foo.Baz.ParameterKey': 'blarg',
              'Parameters.member.Foo.Baz.ParameterValue': 'wibble'}
-        params = manager._extract_user_params(p)
+        params = api.extract_user_params(p)
         self.assertEqual(len(params), 2)
         self.assertTrue('foo' in params)
         self.assertEqual(params['foo'], 'bar')
@@ -52,7 +52,7 @@ class managerTest(unittest.TestCase):
              'Parameters.member.Foo.Bar.ParameterValue': 'bar',
              'Foo.Baz.ParameterKey': 'blarg',
              'Foo.Baz.ParameterValue': 'wibble'}
-        params = manager._extract_user_params(p)
+        params = api.extract_user_params(p)
         self.assertEqual(len(params), 1)
         self.assertTrue('foo' in params)
         self.assertEqual(params['foo'], 'bar')
@@ -60,35 +60,35 @@ class managerTest(unittest.TestCase):
     def test_params_extract_garbage_prefix(self):
         p = {'prefixParameters.member.Foo.Bar.ParameterKey': 'foo',
              'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
-        params = manager._extract_user_params(p)
+        params = api.extract_user_params(p)
         self.assertFalse(params)
 
     def test_params_extract_garbage_suffix(self):
         p = {'Parameters.member.Foo.Bar.ParameterKeysuffix': 'foo',
              'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
-        params = manager._extract_user_params(p)
+        params = api.extract_user_params(p)
         self.assertFalse(params)
 
     def test_timeout_extract(self):
         p = {'TimeoutInMinutes': '5'}
-        args = manager._extract_args(p)
+        args = api.extract_args(p)
         self.assertEqual(args['timeout_in_minutes'], 5)
 
     def test_timeout_extract_zero(self):
         p = {'TimeoutInMinutes': '0'}
-        args = manager._extract_args(p)
+        args = api.extract_args(p)
         self.assertTrue('timeout_in_minutes' not in args)
 
     def test_timeout_extract_garbage(self):
         p = {'TimeoutInMinutes': 'wibble'}
-        args = manager._extract_args(p)
+        args = api.extract_args(p)
         self.assertTrue('timeout_in_minutes' not in args)
 
     def test_timeout_extract_none(self):
         p = {'TimeoutInMinutes': None}
-        args = manager._extract_args(p)
+        args = api.extract_args(p)
         self.assertTrue('timeout_in_minutes' not in args)
 
     def test_timeout_extract_not_present(self):
-        args = manager._extract_args({})
+        args = api.extract_args({})
         self.assertTrue('timeout_in_minutes' not in args)
index 478eae0b3d81e567135accba6f68fc4bb515a767..844bbd8b35165c306926230b29963b06475efb0c 100644 (file)
@@ -33,7 +33,7 @@ from heat.engine import manager
 from heat.engine import auth
 
 
-@attr(tag=['unit', 'resource'])
+@attr(tag=['unit', 'engine-api', 'resource'])
 @attr(speed='slow')
 class stacksTest(unittest.TestCase):
     def setUp(self):
@@ -112,7 +112,10 @@ class stacksTest(unittest.TestCase):
         self.assertEqual(db_s.status, 'DELETE_COMPLETE')
 
     def test_stack_event_list(self):
-        stack = self.get_wordpress_stack('test_event_list_stack')
+        ctx = self.create_context('test_event_list_user')
+        auth.authenticate(ctx).AndReturn(True)
+
+        stack = self.get_wordpress_stack('test_event_list_stack', ctx)
         self.m.ReplayAll()
         stack.store()
         stack.create()
@@ -120,9 +123,14 @@ class stacksTest(unittest.TestCase):
         self.assertNotEqual(stack.resources['WebServer'], None)
         self.assertTrue(stack.resources['WebServer'].instance_id > 0)
 
-        m = manager.EngineManager()
-        events = db_api.event_get_all_by_stack(None, stack.id)
-        for ev in [m.parse_event(e) for e in events]:
+        man = manager.EngineManager()
+        el = man.list_events(ctx, stack.name, {})
+
+        self.assertTrue('events' in el)
+        events = el['events']
+
+        self.assertEqual(len(events), 2)
+        for ev in events:
             self.assertTrue('EventId' in ev)
             self.assertTrue(ev['EventId'] > 0)
 
@@ -174,12 +182,12 @@ class stacksTest(unittest.TestCase):
         self.assertTrue(len(sl['stacks']) > 0)
         for s in sl['stacks']:
             self.assertTrue('CreationTime' in s)
-            #self.assertTrue('LastUpdatedTime' in s)
+            self.assertTrue('LastUpdatedTime' in s)
             self.assertTrue('StackId' in s)
             self.assertNotEqual(s['StackId'], None)
             self.assertTrue('StackName' in s)
             self.assertTrue('StackStatus' in s)
-            #self.assertTrue('StackStatusReason' in s)
+            self.assertTrue('StackStatusReason' in s)
             self.assertTrue('TemplateDescription' in s)
             self.assertNotEqual(s['TemplateDescription'].find('WordPress'), -1)
 
@@ -240,7 +248,7 @@ class stacksTest(unittest.TestCase):
 
         s = sl['stacks'][0]
         self.assertTrue('CreationTime' in s)
-        #self.assertTrue('LastUpdatedTime' in s)
+        self.assertTrue('LastUpdatedTime' in s)
         self.assertTrue('StackId' in s)
         self.assertNotEqual(s['StackId'], None)
         self.assertTrue('StackName' in s)
@@ -265,7 +273,7 @@ class stacksTest(unittest.TestCase):
         r = man.describe_stack_resource(ctx, 'test_stack_res_desc',
                                         'WebServer')
 
-        #self.assertTrue('Description' in r)
+        self.assertTrue('Description' in r)
         self.assertTrue('LastUpdatedTimestamp' in r)
         self.assertTrue('StackId' in r)
         self.assertNotEqual(r['StackId'], None)
@@ -320,7 +328,7 @@ class stacksTest(unittest.TestCase):
 
         self.assertEqual(len(resources), 1)
         r = resources[0]
-        #self.assertTrue('Description' in r)
+        self.assertTrue('Description' in r)
         self.assertTrue('Timestamp' in r)
         self.assertTrue('StackId' in r)
         self.assertNotEqual(r['StackId'], None)
@@ -400,7 +408,7 @@ class stacksTest(unittest.TestCase):
         self.assertTrue('LogicalResourceId' in r)
         self.assertEqual(r['LogicalResourceId'], 'WebServer')
         self.assertTrue('ResourceStatus' in r)
-        #self.assertTrue('ResourceStatusReason' in r)
+        self.assertTrue('ResourceStatusReason' in r)
         self.assertTrue('ResourceType' in r)
 
     def test_stack_resources_list_nonexist_stack(self):