Commit fc2fe51d authored by Thomas Gambier's avatar Thomas Gambier 🚴🏼

fix xml2dixt and dict2xml

software releases expects _ parameter to be a string with JSON inside
not a python dict so we partially revert 2acef14b
and we do the nice printing of JSON parameters in getInformation
parent 015581b7
......@@ -41,6 +41,7 @@ import logging
import re
from functools import wraps
import json
import six
from .exception import ResourceNotReady, ServerError, NotFoundError, \
......@@ -279,13 +280,18 @@ class OpenOrder(SlapRequester):
setattr(software_instance, '_%s' % key, value)
if raw_information["data"].get("text_content", None) is not None:
setattr(software_instance, '_parameter_dict', xml2dict(unicode2str(raw_information["data"]['text_content'])))
result_dict = xml2dict(unicode2str(raw_information["data"]['text_content']))
# the '_' parameter contains a stringified JSON which is not easily readable by human
# we parse it as a dict so that it is displayed in the console as a dict (beautiful display on several lines)
if len(result_dict) == 1 and '_' in result_dict:
result_dict['_'] = json.loads(result_dict['_'])
  • Why is this decoded here ? This json encoding layer is none of the slapos layer's business. It it up to the caller to decode if it thinks it can assume the encoding of this argument.

    Because of this decoding, if I want to automatically export arguments in a way which allows them to be automatically re-imported again, then I have to duplicate the XML parsing code in order to get to the only lever which (...sadly, but this is a different topic) is actualy what slapos enforces: a string-string single-layer key-value mapping encoded in xml.

    /cc @luke @romain

Please register or sign in to reply
software_instance._parameter_dict = result_dict
else:
setattr(software_instance, '_parameter_dict', {})
software_instance._parameter_dict = {}
setattr(software_instance, '_requested_state', raw_information["data"]['slap_state'])
setattr(software_instance, '_connection_dict', raw_information["data"]['connection_parameter_list'])
setattr(software_instance, '_software_release_url', raw_information["data"]['url_string'])
software_instance._requested_state = raw_information["data"]['slap_state']
software_instance._connection_dict = raw_information["data"]['connection_parameter_list']
software_instance._software_release_url = raw_information["data"]['url_string']
return software_instance
def requestComputer(self, computer_reference):
......
......@@ -36,6 +36,7 @@ import logging
from collections import OrderedDict
import httmock
import json
import mock
import slapos.slap
......@@ -1249,13 +1250,11 @@ class TestOpenOrder(SlapMixin):
def test_getInformation(self):
self.slap = slapos.slap.slap()
parameter_dict = {
"_": {
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {"param": "value"}
}
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {"param": "value"}
}
}
......@@ -1289,7 +1288,7 @@ class TestOpenOrder(SlapMixin):
},
"text_content": {
"title": "Parameter XML",
"default": dict2xml(parameter_dict),
"default": dict2xml({'_':json.dumps(parameter_dict)}),
"key": "field_my_text_content",
"type": "TextAreaField"
},
......@@ -1448,7 +1447,7 @@ class TestOpenOrder(SlapMixin):
for key in hosting_subscription_info_dict:
if key not in link_keys:
self.assertEqual(getattr(software_instance, '_' + key), hosting_subscription_info_dict[key]["default"])
self.assertEqual(software_instance._parameter_dict, parameter_dict)
self.assertEqual(software_instance._parameter_dict, {'_': parameter_dict})
self.assertEqual(software_instance._requested_state, hosting_subscription_info_dict['slap_state']["default"])
self.assertEqual(software_instance._connection_dict, hosting_subscription_info_dict['connection_parameter_list']["default"])
self.assertEqual(software_instance._software_release_url, hosting_subscription_info_dict['url_string']["default"])
......
......@@ -191,17 +191,20 @@ class TestUtil(unittest.TestCase):
"""
xml2dict1_dict = {
"_": {
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {"param": "value"}
}
"_": '''{
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {
"param": "value"
}
}
}'''
}
def test_xml2dict1(self):
self.maxDiff = None
self.assertEqual(
self.xml2dict1_dict,
slapos.util.xml2dict(self.xml2dict1_xml)
......
......@@ -33,7 +33,6 @@ import socket
import struct
import subprocess
import sqlite3
import json
from xml_marshaller.xml_marshaller import dumps, loads
from lxml import etree
import six
......@@ -163,22 +162,14 @@ else:
def dict2xml(dictionary):
instance = etree.Element('instance')
if len(dictionary) == 1 and '_' in dictionary:
for k, v in sorted(six.iteritems(dictionary)):
if isinstance(k, bytes):
k = k.decode('utf-8')
if isinstance(v, bytes):
v = v.decode('utf-8')
elif not isinstance(v, six.text_type):
v = str(v)
etree.SubElement(instance, "parameter",
attrib={'id': '_'}).text = json.dumps(
dictionary['_'],
separators=(',', ': '),
sort_keys=True,
indent=4)
else:
for k, v in sorted(six.iteritems(dictionary)):
if isinstance(k, bytes):
k = k.decode('utf-8')
if isinstance(v, bytes):
v = v.decode('utf-8')
elif not isinstance(v, six.text_type):
v = str(v)
etree.SubElement(instance, "parameter",
attrib={'id': k}).text = v
return bytes2str(etree.tostring(instance,
pretty_print=True,
......@@ -198,8 +189,6 @@ def xml2dict(xml):
else:
value = element.text
result_dict[key] = value
if len(result_dict) == 1 and '_' in result_dict:
result_dict['_'] = json.loads(result_dict['_'])
return result_dict
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment