# 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']))
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):
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,
})
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
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,
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)
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):
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
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()
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()
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')
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,