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 ...@@ -41,6 +41,7 @@ import logging
import re import re
from functools import wraps from functools import wraps
import json
import six import six
from .exception import ResourceNotReady, ServerError, NotFoundError, \ from .exception import ResourceNotReady, ServerError, NotFoundError, \
...@@ -279,13 +280,18 @@ class OpenOrder(SlapRequester): ...@@ -279,13 +280,18 @@ class OpenOrder(SlapRequester):
setattr(software_instance, '_%s' % key, value) setattr(software_instance, '_%s' % key, value)
if raw_information["data"].get("text_content", None) is not None: 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: else:
setattr(software_instance, '_parameter_dict', {}) software_instance._parameter_dict = {}
setattr(software_instance, '_requested_state', raw_information["data"]['slap_state']) software_instance._requested_state = raw_information["data"]['slap_state']
setattr(software_instance, '_connection_dict', raw_information["data"]['connection_parameter_list']) software_instance._connection_dict = raw_information["data"]['connection_parameter_list']
setattr(software_instance, '_software_release_url', raw_information["data"]['url_string']) software_instance._software_release_url = raw_information["data"]['url_string']
return software_instance return software_instance
def requestComputer(self, computer_reference): def requestComputer(self, computer_reference):
......
...@@ -36,6 +36,7 @@ import logging ...@@ -36,6 +36,7 @@ import logging
from collections import OrderedDict from collections import OrderedDict
import httmock import httmock
import json
import mock import mock
import slapos.slap import slapos.slap
...@@ -1249,13 +1250,11 @@ class TestOpenOrder(SlapMixin): ...@@ -1249,13 +1250,11 @@ class TestOpenOrder(SlapMixin):
def test_getInformation(self): def test_getInformation(self):
self.slap = slapos.slap.slap() self.slap = slapos.slap.slap()
parameter_dict = { parameter_dict = {
"_": { "param1": "value1",
"param1": "value1", "param2_dict": {
"param2_dict": { "param2_param1": "",
"param2_param1": "", "param2_param2_dict": {},
"param2_param2_dict": {}, "param2_param3_dict": {"param": "value"}
"param2_param3_dict": {"param": "value"}
}
} }
} }
...@@ -1289,7 +1288,7 @@ class TestOpenOrder(SlapMixin): ...@@ -1289,7 +1288,7 @@ class TestOpenOrder(SlapMixin):
}, },
"text_content": { "text_content": {
"title": "Parameter XML", "title": "Parameter XML",
"default": dict2xml(parameter_dict), "default": dict2xml({'_':json.dumps(parameter_dict)}),
"key": "field_my_text_content", "key": "field_my_text_content",
"type": "TextAreaField" "type": "TextAreaField"
}, },
...@@ -1448,7 +1447,7 @@ class TestOpenOrder(SlapMixin): ...@@ -1448,7 +1447,7 @@ class TestOpenOrder(SlapMixin):
for key in hosting_subscription_info_dict: for key in hosting_subscription_info_dict:
if key not in link_keys: if key not in link_keys:
self.assertEqual(getattr(software_instance, '_' + key), hosting_subscription_info_dict[key]["default"]) 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._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._connection_dict, hosting_subscription_info_dict['connection_parameter_list']["default"])
self.assertEqual(software_instance._software_release_url, hosting_subscription_info_dict['url_string']["default"]) self.assertEqual(software_instance._software_release_url, hosting_subscription_info_dict['url_string']["default"])
......
...@@ -191,17 +191,20 @@ class TestUtil(unittest.TestCase): ...@@ -191,17 +191,20 @@ class TestUtil(unittest.TestCase):
""" """
xml2dict1_dict = { xml2dict1_dict = {
"_": { "_": '''{
"param1": "value1", "param1": "value1",
"param2_dict": { "param2_dict": {
"param2_param1": "", "param2_param1": "",
"param2_param2_dict": {}, "param2_param2_dict": {},
"param2_param3_dict": {"param": "value"} "param2_param3_dict": {
} "param": "value"
}
} }
}'''
} }
def test_xml2dict1(self): def test_xml2dict1(self):
self.maxDiff = None
self.assertEqual( self.assertEqual(
self.xml2dict1_dict, self.xml2dict1_dict,
slapos.util.xml2dict(self.xml2dict1_xml) slapos.util.xml2dict(self.xml2dict1_xml)
......
...@@ -33,7 +33,6 @@ import socket ...@@ -33,7 +33,6 @@ import socket
import struct import struct
import subprocess import subprocess
import sqlite3 import sqlite3
import json
from xml_marshaller.xml_marshaller import dumps, loads from xml_marshaller.xml_marshaller import dumps, loads
from lxml import etree from lxml import etree
import six import six
...@@ -163,22 +162,14 @@ else: ...@@ -163,22 +162,14 @@ else:
def dict2xml(dictionary): def dict2xml(dictionary):
instance = etree.Element('instance') 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", 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 attrib={'id': k}).text = v
return bytes2str(etree.tostring(instance, return bytes2str(etree.tostring(instance,
pretty_print=True, pretty_print=True,
...@@ -198,8 +189,6 @@ def xml2dict(xml): ...@@ -198,8 +189,6 @@ def xml2dict(xml):
else: else:
value = element.text value = element.text
result_dict[key] = value result_dict[key] = value
if len(result_dict) == 1 and '_' in result_dict:
result_dict['_'] = json.loads(result_dict['_'])
return 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