diff --git a/heat/api/cfn/v1/__init__.py b/heat/api/cfn/v1/__init__.py index 9d259a7cd8..bfe6d32c34 100644 --- a/heat/api/cfn/v1/__init__.py +++ b/heat/api/cfn/v1/__init__.py @@ -18,6 +18,7 @@ import routes from webob import Request from heat.api.cfn.v1 import stacks +from heat.api.cfn.v1 import waitcondition from heat.common import wsgi from heat.openstack.common import log as logging @@ -70,4 +71,13 @@ class API(wsgi.Router): mapper.connect("/", controller=stacks_resource, action="index") + # Add controller which handles waitcondition notifications + # 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', + controller=waitcondition_controller, + action='update_waitcondition', + conditions=dict(method=['PUT'])) + super(API, self).__init__(mapper) diff --git a/heat/api/cfn/v1/waitcondition.py b/heat/api/cfn/v1/waitcondition.py new file mode 100644 index 0000000000..f8bd2c479f --- /dev/null +++ b/heat/api/cfn/v1/waitcondition.py @@ -0,0 +1,71 @@ +# 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 json + +from webob.exc import Response + +from heat.common import wsgi +from heat.common import context +from heat.engine import rpcapi as engine_rpcapi +from heat.openstack.common import rpc + + +def json_response(http_status, data): + """Create a JSON response with a specific HTTP code.""" + response = Response(json.dumps(data)) + response.status = http_status + response.content_type = 'application/json' + return response + + +def json_error(http_status, message): + """Create a JSON error response.""" + body = {'error': message} + return json_response(http_status, body) + + +class WaitConditionController: + def __init__(self, options): + self.options = options + self.engine_rpcapi = engine_rpcapi.EngineAPI() + + def update_waitcondition(self, req, body, stack_id, resource_name): + con = req.context + [error, metadata] = self.engine_rpcapi.metadata_update(con, + stack_id=stack_id, + resource_name=resource_name, + metadata=body) + if error: + if error == 'stack': + return json_error(404, + 'The stack "%s" does not exist.' % stack_id) + else: + return json_error(404, + 'The resource "%s" does not exist.' % resource_name) + return json_response(201, { + 'resource': resource_name, + 'metadata': body, + }) + + +def create_resource(options): + """ + Stacks resource factory method. + """ + deserializer = wsgi.JSONRequestDeserializer() + serializer = wsgi.JSONResponseSerializer() + return wsgi.Resource(WaitConditionController(options), deserializer, + serializer)