]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat API : Move aws api common code into aws/utils.py
authorSteven Hardy <shardy@redhat.com>
Tue, 21 Aug 2012 10:52:24 +0000 (11:52 +0100)
committerSteven Hardy <shardy@redhat.com>
Tue, 21 Aug 2012 10:54:18 +0000 (11:54 +0100)
Move heat-api AWS common utility functions into a new
utils.py, so these functions can be reused by cloudwatch

Change-Id: I030d796b1048ffc4e7c40f7c8760121ab2854733
Signed-off-by: Steven Hardy <shardy@redhat.com>
heat/api/aws/utils.py [new file with mode: 0644]
heat/api/v1/stacks.py
heat/tests/test_api_aws.py [new file with mode: 0644]
heat/tests/test_api_v1.py

diff --git a/heat/api/aws/utils.py b/heat/api/aws/utils.py
new file mode 100644 (file)
index 0000000..e3b6cd3
--- /dev/null
@@ -0,0 +1,78 @@
+# 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.
+
+'''
+Helper utilities related to the AWS API implementations
+'''
+
+import re
+
+
+def format_response(action, response):
+    """
+    Format response from engine into API format
+    """
+    return {'%sResponse' % action: {'%sResult' % action: response}}
+
+
+def extract_user_params(params):
+    """
+    Extract a dictionary of user input parameters for the stack
+
+    In the AWS API parameters, each user parameter appears as two key-value
+    pairs with keys of the form below:
+
+    Parameters.member.1.ParameterKey
+    Parameters.member.1.ParameterValue
+
+    We reformat this into a normal dict here to match the heat
+    engine API expected format
+
+    Note this implemented outside of "create" as it will also be
+    used by update (and EstimateTemplateCost if appropriate..)
+    """
+    # Define the AWS key format to extract
+    PARAM_KEYS = (
+    PARAM_USER_KEY_re,
+    PARAM_USER_VALUE_fmt,
+    ) = (
+    re.compile(r'Parameters\.member\.(.*?)\.ParameterKey$'),
+    'Parameters.member.%s.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 reformat_dict_keys(keymap={}, inputdict={}):
+    '''
+    Utility function for mapping one dict format to another
+    '''
+    result = {}
+    for key in keymap:
+        result[keymap[key]] = inputdict[key]
+    return result
index 960b1387cf072b5714fb2eecd28a38e09404b004..d0b06b215246136d4fad05c762262f5711ad2dc1 100644 (file)
@@ -21,10 +21,10 @@ import json
 import os
 import socket
 import sys
-import re
 import urlparse
 import webob
 from heat.api.aws import exception
+from heat.api.aws import utils as api_utils
 from heat.common import wsgi
 from heat.common import config
 from heat.common import context
@@ -62,63 +62,6 @@ class StackController(object):
                                        str(resp['StackId'])])
         return resp
 
-    def _format_response(self, action, response):
-        """
-        Format response from engine into API format
-        """
-        return {'%sResponse' % action: {'%sResult' % action: response}}
-
-    @staticmethod
-    def _extract_user_params(params):
-        """
-        Extract a dictionary of user input parameters for the stack
-
-        In the AWS API parameters, each user parameter appears as two key-value
-        pairs with keys of the form below:
-
-        Parameters.member.1.ParameterKey
-        Parameters.member.1.ParameterValue
-
-        We reformat this into a normal dict here to match the heat
-        engine API expected format
-
-        Note this implemented outside of "create" as it will also be
-        used by update (and EstimateTemplateCost if appropriate..)
-        """
-        # Define the AWS key format to extract
-        PARAM_KEYS = (
-        PARAM_USER_KEY_re,
-        PARAM_USER_VALUE_fmt,
-        ) = (
-        re.compile(r'Parameters\.member\.(.*?)\.ParameterKey$'),
-        'Parameters.member.%s.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())
-
-    @staticmethod
-    def _reformat_dict_keys(keymap={}, inputdict={}):
-        '''
-        Utility function for mapping one dict format to another
-        '''
-        result = {}
-        for key in keymap:
-            result[keymap[key]] = inputdict[key]
-        return result
-
     def list(self, req):
         """
         Implements ListStacks API action
@@ -140,7 +83,7 @@ class StackController(object):
                 engine_api.STACK_TMPL_DESCRIPTION: 'TemplateDescription',
             }
 
-            result = self._reformat_dict_keys(keymap, s)
+            result = api_utils.reformat_dict_keys(keymap, s)
 
             # AWS docs indicate DeletionTime is ommitted for current stacks
             # This is still TODO in the engine, we don't keep data for
@@ -165,7 +108,7 @@ class StackController(object):
         res = {'StackSummaries': [format_stack_summary(s)
                                    for s in stack_list['stacks']]}
 
-        return self._format_response('ListStacks', res)
+        return api_utils.format_response('ListStacks', res)
 
     def describe(self, req):
         """
@@ -179,7 +122,7 @@ class StackController(object):
                 engine_api.OUTPUT_VALUE: 'OutputValue',
             }
 
-            return self._reformat_dict_keys(keymap, o)
+            return api_utils.reformat_dict_keys(keymap, o)
 
         def format_stack(s):
             """
@@ -200,7 +143,7 @@ class StackController(object):
                 engine_api.STACK_TIMEOUT: 'TimeoutInMinutes',
             }
 
-            result = self._reformat_dict_keys(keymap, s)
+            result = api_utils.reformat_dict_keys(keymap, s)
 
             # Reformat outputs, these are handled separately as they are
             # only present in the engine output for a completely created
@@ -239,7 +182,7 @@ class StackController(object):
 
         res = {'Stacks': [format_stack(s) for s in stack_list['stacks']]}
 
-        return self._format_response('DescribeStacks', res)
+        return api_utils.format_response('DescribeStacks', res)
 
     def _get_template(self, req):
         """
@@ -310,7 +253,7 @@ class StackController(object):
         con = req.context
 
         # Extract the stack input parameters
-        stack_parms = self._extract_user_params(req.params)
+        stack_parms = api_utils.extract_user_params(req.params)
 
         # Extract any additional arguments ("Request Parameters")
         create_args = extract_args(req.params)
@@ -340,7 +283,7 @@ class StackController(object):
         except rpc_common.RemoteError as ex:
             return exception.map_remote_error(ex)
 
-        return self._format_response(action, self._stackid_addprefix(res))
+        return api_utils.format_response(action, self._stackid_addprefix(res))
 
     def get_template(self, req):
         """
@@ -363,14 +306,15 @@ class StackController(object):
             msg = _('stack not not found')
             return exception.HeatInvalidParameterValueError(detail=msg)
 
-        return self._format_response('GetTemplate', {'TemplateBody': templ})
+        return api_utils.format_response('GetTemplate',
+                                         {'TemplateBody': templ})
 
     def estimate_template_cost(self, req):
         """
         Implements the EstimateTemplateCost API action
         Get the estimated monthly cost of a template
         """
-        return self._format_response('EstimateTemplateCost',
+        return api_utils.format_response('EstimateTemplateCost',
             {'Url': 'http://en.wikipedia.org/wiki/Gratis'})
 
     def validate_template(self, req):
@@ -423,9 +367,9 @@ class StackController(object):
             return exception.map_remote_error(ex)
 
         if res is None:
-            return self._format_response('DeleteStack', '')
+            return api_utils.format_response('DeleteStack', '')
         else:
-            return self._format_response('DeleteStack', res['Error'])
+            return api_utils.format_response('DeleteStack', res['Error'])
 
     def events_list(self, req):
         """
@@ -449,7 +393,7 @@ class StackController(object):
                 engine_api.EVENT_TIMESTAMP: 'Timestamp',
             }
 
-            result = self._reformat_dict_keys(keymap, e)
+            result = api_utils.reformat_dict_keys(keymap, e)
 
             return self._stackid_addprefix(result)
 
@@ -468,7 +412,7 @@ class StackController(object):
 
         result = [format_stack_event(e) for e in events]
 
-        return self._format_response('DescribeStackEvents',
+        return api_utils.format_response('DescribeStackEvents',
             {'StackEvents': result})
 
     def describe_stack_resource(self, req):
@@ -494,7 +438,7 @@ class StackController(object):
                 engine_api.RES_STACK_NAME: 'StackName',
             }
 
-            result = self._reformat_dict_keys(keymap, r)
+            result = api_utils.reformat_dict_keys(keymap, r)
 
             return self._stackid_addprefix(result)
 
@@ -510,7 +454,7 @@ class StackController(object):
 
         result = format_resource_detail(resource_details)
 
-        return self._format_response('DescribeStackResource',
+        return api_utils.format_response('DescribeStackResource',
             {'StackResourceDetail': result})
 
     def describe_stack_resources(self, req):
@@ -546,7 +490,7 @@ class StackController(object):
                 engine_api.RES_UPDATED_TIME: 'Timestamp',
             }
 
-            result = self._reformat_dict_keys(keymap, r)
+            result = api_utils.reformat_dict_keys(keymap, r)
 
             return self._stackid_addprefix(result)
 
@@ -568,7 +512,7 @@ class StackController(object):
 
         result = [format_stack_resource(r) for r in resources]
 
-        return self._format_response('DescribeStackResources',
+        return api_utils.format_response('DescribeStackResources',
             {'StackResources': result})
 
     def list_stack_resources(self, req):
@@ -589,7 +533,7 @@ class StackController(object):
                 engine_api.RES_TYPE: 'ResourceType',
             }
 
-            return self._reformat_dict_keys(keymap, r)
+            return api_utils.reformat_dict_keys(keymap, r)
 
         con = req.context
 
@@ -601,7 +545,7 @@ class StackController(object):
 
         summaries = [format_resource_summary(r) for r in resources]
 
-        return self._format_response('ListStackResources',
+        return api_utils.format_response('ListStackResources',
             {'StackResourceSummaries': summaries})
 
 
diff --git a/heat/tests/test_api_aws.py b/heat/tests/test_api_aws.py
new file mode 100644 (file)
index 0000000..c23407c
--- /dev/null
@@ -0,0 +1,101 @@
+# 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 sys
+import socket
+import nose
+import json
+import unittest
+from nose.plugins.attrib import attr
+
+import re
+from heat.api.aws import utils as api_utils
+
+
+@attr(tag=['unit', 'api-aws', 'AWSCommon'])
+@attr(speed='fast')
+class AWSCommon(unittest.TestCase):
+    '''
+    Tests the api/aws common componenents
+    '''
+    # The tests
+    def test_format_response(self):
+        response = api_utils.format_response("Foo", "Bar")
+        expected = {'FooResponse': {'FooResult': 'Bar'}}
+        self.assert_(response == expected)
+
+    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 = api_utils.extract_user_params(p)
+        self.assertEqual(len(params), 2)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+        self.assertTrue('blarg' in params)
+        self.assertEqual(params['blarg'], 'wibble')
+
+    def test_params_extract_dots(self):
+        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
+             'Parameters.member.Foo.Baz.ParameterKey': 'blarg',
+             'Parameters.member.Foo.Baz.ParameterValue': 'wibble'}
+        params = api_utils.extract_user_params(p)
+        self.assertEqual(len(params), 2)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+        self.assertTrue('blarg' in params)
+        self.assertEqual(params['blarg'], 'wibble')
+
+    def test_params_extract_garbage(self):
+        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
+             'Foo.Baz.ParameterKey': 'blarg',
+             'Foo.Baz.ParameterValue': 'wibble'}
+        params = api_utils.extract_user_params(p)
+        self.assertEqual(len(params), 1)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+
+    def test_params_extract_garbage_prefix(self):
+        p = {'prefixParameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
+        params = api_utils.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 = api_utils.extract_user_params(p)
+        self.assertFalse(params)
+
+    def test_reformat_dict_keys(self):
+        keymap = {"foo": "bar"}
+        data = {"foo": 123}
+        expected = {"bar": 123}
+        result = api_utils.reformat_dict_keys(keymap, data)
+        self.assertEqual(result, expected)
+
+    def setUp(self):
+        print "setup complete"
+
+    def tearDown(self):
+        print "teardown complete"
+
+
+if __name__ == '__main__':
+    sys.argv.append(__file__)
+    nose.main()
index d725909359834df98a7665b1f25119f18d20ab4f..218372da5ba6c318e0a1ddeb05f0c6636aa8031b 100644 (file)
@@ -60,11 +60,6 @@ class StackControllerTest(unittest.TestCase):
         return req
 
     # The tests
-    def test_format_response(self):
-        response = self.controller._format_response("Foo", "Bar")
-        expected = {'FooResponse': {'FooResult': 'Bar'}}
-        self.assert_(response == expected)
-
     def test_stackid_addprefix(self):
 
         # Stub socket.gethostname so it returns "ahostname"
@@ -79,59 +74,6 @@ class StackControllerTest(unittest.TestCase):
                     'StackId': 'ahostname:8000:stack/Foo/123'}
         self.assert_(response == expected)
 
-    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 = self.controller._extract_user_params(p)
-        self.assertEqual(len(params), 2)
-        self.assertTrue('foo' in params)
-        self.assertEqual(params['foo'], 'bar')
-        self.assertTrue('blarg' in params)
-        self.assertEqual(params['blarg'], 'wibble')
-
-    def test_params_extract_dots(self):
-        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
-             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
-             'Parameters.member.Foo.Baz.ParameterKey': 'blarg',
-             'Parameters.member.Foo.Baz.ParameterValue': 'wibble'}
-        params = self.controller._extract_user_params(p)
-        self.assertEqual(len(params), 2)
-        self.assertTrue('foo' in params)
-        self.assertEqual(params['foo'], 'bar')
-        self.assertTrue('blarg' in params)
-        self.assertEqual(params['blarg'], 'wibble')
-
-    def test_params_extract_garbage(self):
-        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
-             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
-             'Foo.Baz.ParameterKey': 'blarg',
-             'Foo.Baz.ParameterValue': 'wibble'}
-        params = self.controller._extract_user_params(p)
-        self.assertEqual(len(params), 1)
-        self.assertTrue('foo' in params)
-        self.assertEqual(params['foo'], 'bar')
-
-    def test_params_extract_garbage_prefix(self):
-        p = {'prefixParameters.member.Foo.Bar.ParameterKey': 'foo',
-             'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
-        params = self.controller._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 = self.controller._extract_user_params(p)
-        self.assertFalse(params)
-
-    def test_reformat_dict_keys(self):
-        keymap = {"foo": "bar"}
-        data = {"foo": 123}
-        expected = {"bar": 123}
-        result = self.controller._reformat_dict_keys(keymap, data)
-        self.assertEqual(result, expected)
-
     def test_list(self):
         # Format a dummy GET request to pass into the WSGI handler
         params = {'Action': 'ListStacks'}