]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat engine : convert WaitConditionHandle URL to ARN format
authorSteven Hardy <shardy@redhat.com>
Tue, 4 Dec 2012 16:33:51 +0000 (16:33 +0000)
committerSteven Hardy <shardy@redhat.com>
Tue, 11 Dec 2012 16:06:57 +0000 (16:06 +0000)
Convert the WaitConditionHandle URL format to use the ARN format,
the resulting URL will be similar to the AWS format

fixes bug 1087799

Signed-off-by: Steven Hardy <shardy@redhat.com>
Change-Id: I04b1f6cd913c54c9f4fa82cc1e76be22a19fe2ea

heat/api/cfn/v1/__init__.py
heat/api/cfn/v1/waitcondition.py
heat/engine/resources/wait_condition.py
heat/tests/test_waitcondition.py

index bfe6d32c34066bc269b85cae1b838daf8def3f1a..fa33bfd5e038c9c4e50c2a90be842e98f7e7a0e3 100644 (file)
@@ -75,7 +75,7 @@ class API(wsgi.Router):
         # This is not part of the main CFN API spec, hence handle it
         # separately via a different path
         waitcondition_controller = waitcondition.create_resource(conf)
-        mapper.connect('/waitcondition/:stack_id/resources/:resource_name',
+        mapper.connect('/waitcondition/{arn:.*}',
                        controller=waitcondition_controller,
                        action='update_waitcondition',
                        conditions=dict(method=['PUT']))
index 9f93e1cde4bfefec80501f85bf2eaedf71443e49..a428d971351cd424eac632b7d0cdc52a80fd0c60 100644 (file)
@@ -21,6 +21,7 @@ from heat.common import wsgi
 from heat.common import context
 from heat.rpc import client as rpc_client
 from heat.openstack.common import rpc
+from heat.common import identifier
 
 
 def json_response(http_status, data):
@@ -42,21 +43,23 @@ class WaitConditionController:
         self.options = options
         self.engine = rpc_client.EngineClient()
 
-    def update_waitcondition(self, req, body, stack_id, resource_name):
+    def update_waitcondition(self, req, body, arn):
         con = req.context
+        identity = identifier.ResourceIdentifier.from_arn(arn)
         [error, metadata] = self.engine.metadata_update(con,
-                                 stack_id=stack_id,
-                                 resource_name=resource_name,
+                                 stack_id=identity.stack_id,
+                                 resource_name=identity.resource_name,
                                  metadata=body)
         if error:
             if error == 'stack':
                 return json_error(404,
-                        'The stack "%s" does not exist.' % stack_id)
+                        'The stack "%s" does not exist.' % identity.stack_id)
             else:
                 return json_error(404,
-                        'The resource "%s" does not exist.' % resource_name)
+                        'The resource "%s" does not exist.' %
+                        identity.resource_name)
         return json_response(201, {
-            'resource': resource_name,
+            'resource': identity.resource_name,
             'metadata': body,
         })
 
index aa42f6f526c319c5d196d21596e740362a412ceb..23c07e011f99ac321e74bfee47d01e67eee8f20b 100644 (file)
@@ -19,6 +19,7 @@ import urllib
 import urlparse
 
 from heat.common import exception
+from heat.common import identifier
 from heat.engine import resource
 
 from heat.openstack.common import log as logging
@@ -59,9 +60,14 @@ class WaitConditionHandle(resource.Resource):
         Also see boto/auth.py::QuerySignatureV2AuthHandler
         """
         host_url = urlparse.urlparse(cfg.CONF.heat_waitcondition_server_url)
+        # Note the WSGI spec apparently means that the webob request we end up
+        # prcessing in the CFN API (ec2token.py) has an unquoted path, so we
+        # need to calculate the signature with the path component unquoted, but
+        # ensure the actual URL contains the quoted version...
+        unquoted_path = urllib.unquote(host_url.path + path)
         request = {'host': host_url.netloc.lower(),
                    'verb': 'PUT',
-                   'path': host_url.path + path,
+                   'path': unquoted_path,
                    'params': {'SignatureMethod': 'HmacSHA256',
                               'SignatureVersion': '2',
                               'AWSAccessKeyId': credentials.access,
@@ -100,7 +106,7 @@ class WaitConditionHandle(resource.Resource):
         Override the default resource FnGetRefId so we return the signed URL
         '''
         if self.resource_id:
-            urlpath = '/%s/resources/%s' % (self.stack.id, self.name)
+            urlpath = self.identifier().arn_url_path()
             ec2_creds = self.keystone().get_ec2_keypair(self.resource_id)
             signed_url = self._sign_url(ec2_creds, urlpath)
             return unicode(signed_url)
@@ -148,7 +154,8 @@ class WaitCondition(resource.Resource):
     def _get_handle_resource_id(self):
         if self.resource_id is None:
             handle_url = self.properties['Handle']
-            self.resource_id = handle_url.split('/')[-1].split('?')[0]
+            handle_id = identifier.ResourceIdentifier.from_arn_url(handle_url)
+            self.resource_id_set(handle_id.resource_name)
         return self.resource_id
 
     def _get_status_reason(self, handle):
index 6179804eef811e9abaa8c1711f507fc015ad6e15..03d0a6c23b4be869c9275f30633ffd9f8c9b2fb0 100644 (file)
@@ -27,6 +27,7 @@ from heat.tests import fakes
 
 import heat.db as db_api
 from heat.common import template_format
+from heat.common import identifier
 from heat.engine import parser
 from heat.engine.resources import wait_condition as wc
 from heat.common import context
@@ -99,6 +100,11 @@ class WaitConditionTest(unittest.TestCase):
         self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
         wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fc)
 
+        id = identifier.ResourceIdentifier('test_tenant', stack.name,
+                                           stack.id, '', 'WaitHandle')
+        self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
+        wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
+
         self.m.ReplayAll()
 
         stack.create()
@@ -130,6 +136,11 @@ class WaitConditionTest(unittest.TestCase):
         self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
         wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fc)
 
+        id = identifier.ResourceIdentifier('test_tenant', stack.name,
+                                           stack.id, '', 'WaitHandle')
+        self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
+        wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
+
         self.m.ReplayAll()
 
         stack.create()
@@ -186,6 +197,11 @@ class WaitConditionHandleTest(unittest.TestCase):
         self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone')
         wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fc)
 
+        id = identifier.ResourceIdentifier('test_tenant', stack.name,
+                                           stack.id, '', 'WaitHandle')
+        self.m.StubOutWithMock(wc.WaitConditionHandle, 'identifier')
+        wc.WaitConditionHandle.identifier().MultipleTimes().AndReturn(id)
+
         # Stub time to a fixed value so we can get an expected signature
         t = time.gmtime(1354196977)
         self.m.StubOutWithMock(time, 'gmtime')
@@ -198,14 +214,18 @@ class WaitConditionHandleTest(unittest.TestCase):
         self.assertEqual(resource.state, 'CREATE_COMPLETE')
 
         expected_url = "".join(
-                       ["http://127.0.0.1:8000/v1/waitcondition/STACKABCD1234",
-                       "/resources/WaitHandle",
-                       "?Timestamp=2012-11-29T13%3A49%3A37Z",
-                       "&SignatureMethod=HmacSHA256",
-                       "&AWSAccessKeyId=4567",
-                       "&SignatureVersion=2",
-                       "&Signature=",
-                       "%2BY5r9xvxTzTrRkz%2Br5T1wGeFwoU1wTh2c5u8a2sCurQ%3D"])
+                       ['http://127.0.0.1:8000/v1/waitcondition/',
+                        'arn%3Aopenstack%3Aheat%3A%3Atest_tenant%3Astacks%2F',
+                        'test_stack2%2FSTACKABCD1234%2Fresources%2F',
+                        'WaitHandle?',
+                        'Timestamp=2012-11-29T13%3A49%3A37Z&',
+                        'SignatureMethod=HmacSHA256&',
+                        'AWSAccessKeyId=4567&',
+                        'SignatureVersion=2&',
+                        'Signature=',
+                        'ePyTwmC%2F1kSigeo%2Fha7kP8Avvb45G9Y7WOQWe4F%2BnXM%3D'
+                       ])
+
         self.assertEqual(expected_url, resource.FnGetRefId())
 
         self.assertEqual(resource.UPDATE_REPLACE,