From 1fc9ff4a0b0acc8c68e14f617ede4b4640ba00b1 Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Wed, 13 Jun 2012 15:45:46 +0100 Subject: [PATCH] heat API : return response body as XML not JSON AWS API returns response as XML, this implements a new response serializer which turns dicts returned from the engine into AWS style XML responses. Ref #125. Updated following review comment. Change-Id: I8170ed814be0b5cea98761a2723e12be216374a3 Signed-off-by: Steven Hardy --- bin/heat | 14 +++++++------- heat/api/v1/stacks.py | 2 +- heat/client.py | 5 +++-- heat/common/wsgi.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/bin/heat b/bin/heat index ffb2d92a..6d71b69c 100755 --- a/bin/heat +++ b/bin/heat @@ -91,7 +91,7 @@ def template_validate(options, arguments): client = get_client(options) result = client.validate_template(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('estimatetemplatecost') @@ -188,7 +188,7 @@ def stack_create(options, arguments): c = get_client(options) result = c.create_stack(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('update') @@ -234,7 +234,7 @@ def stack_update(options, arguments): c = get_client(options) result = c.update_stack(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('delete') @@ -256,7 +256,7 @@ def stack_delete(options, arguments): c = get_client(options) result = c.delete_stack(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('describe') @@ -276,7 +276,7 @@ def stack_describe(options, arguments): c = get_client(options) result = c.describe_stacks(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('event-list') @@ -294,7 +294,7 @@ def stack_events_list(options, arguments): c = get_client(options) result = c.list_stack_events(**parameters) - print json.dumps(result, indent=2) + print result @utils.catch_error('list') @@ -306,7 +306,7 @@ def stack_list(options, arguments): ''' c = get_client(options) result = c.list_stacks() - print json.dumps(result, indent=2) + print result def get_client(options): diff --git a/heat/api/v1/stacks.py b/heat/api/v1/stacks.py index 172ac615..3807a92d 100644 --- a/heat/api/v1/stacks.py +++ b/heat/api/v1/stacks.py @@ -249,5 +249,5 @@ def create_resource(options): Stacks resource factory method. """ deserializer = wsgi.JSONRequestDeserializer() - serializer = wsgi.JSONResponseSerializer() + serializer = wsgi.XMLResponseSerializer() return wsgi.Resource(StackController(options), deserializer, serializer) diff --git a/heat/client.py b/heat/client.py index 52063356..d370a461 100644 --- a/heat/client.py +++ b/heat/client.py @@ -17,7 +17,7 @@ Client classes for callers of a heat system """ -import json +from lxml import etree import logging import os from heat.common import client as base_client @@ -44,7 +44,8 @@ class V1Client(base_client.BaseClient): params['Action'] = action res = self.do_request(method, "/", params=params) - return json.loads(res.read()) + doc = etree.fromstring(res.read()) + return etree.tostring(doc, pretty_print=True) def list_stacks(self, **kwargs): return self.stack_request("ListStacks", "GET", **kwargs) diff --git a/heat/common/wsgi.py b/heat/common/wsgi.py index 6716d0e3..e6d6f5bc 100644 --- a/heat/common/wsgi.py +++ b/heat/common/wsgi.py @@ -28,6 +28,9 @@ import os import signal import sys import time +import re +from lxml import etree + import eventlet import eventlet.greenio @@ -433,6 +436,34 @@ class JSONResponseSerializer(object): response.body = self.to_json(result) +class XMLResponseSerializer(object): + + def object_to_element(self, obj, element): + if isinstance(obj, list): + for item in obj: + subelement = etree.SubElement(element, "member") + self.object_to_element(item, subelement) + elif isinstance(obj, dict): + for key, value in obj.items(): + subelement = etree.SubElement(element, key) + self.object_to_element(value, subelement) + else: + element.text = str(obj) + + def to_xml(self, data): + # Assumption : root node is dict with single key + root = data.keys()[0] + eltree = etree.Element(root) + doc = etree.ElementTree(eltree) + self.object_to_element(data.get(root), eltree) + logging.debug("XML response : %s" % etree.tostring(eltree)) + return etree.tostring(eltree) + + def default(self, response, result): + response.content_type = 'application/xml' + response.body = self.to_xml(result) + + class Resource(object): """ WSGI app that handles (de)serialization and controller dispatch. -- 2.45.2