Commit 40ef5503 authored by Thomas Gambier's avatar Thomas Gambier 🚴🏼

Fixes for "slapos service info"

 * xml2dict and dict2xml support the JSON format of parameter dict
 * since xml2dict doesn't support unicode, we convert unicode to str in
getInformation

See merge request !198
parents c5c597de 583ebce5
...@@ -46,7 +46,7 @@ import six ...@@ -46,7 +46,7 @@ import six
from .exception import ResourceNotReady, ServerError, NotFoundError, \ from .exception import ResourceNotReady, ServerError, NotFoundError, \
ConnectionError ConnectionError
from .hateoas import SlapHateoasNavigator, ConnectionHelper from .hateoas import SlapHateoasNavigator, ConnectionHelper
from slapos.util import loads, dumps, bytes2str, xml2dict, dict2xml, calculate_dict_hash from slapos.util import loads, dumps, bytes2str, unicode2str, xml2dict, dict2xml, calculate_dict_hash
from xml.sax import saxutils from xml.sax import saxutils
from zope.interface import implementer from zope.interface import implementer
...@@ -279,7 +279,7 @@ class OpenOrder(SlapRequester): ...@@ -279,7 +279,7 @@ 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(raw_information["data"]['text_content'])) setattr(software_instance, '_parameter_dict', xml2dict(unicode2str(raw_information["data"]['text_content'])))
else: else:
setattr(software_instance, '_parameter_dict', {}) setattr(software_instance, '_parameter_dict', {})
......
...@@ -402,7 +402,7 @@ class TestCliNode(CliMixin): ...@@ -402,7 +402,7 @@ class TestCliNode(CliMixin):
class TestCliList(CliMixin): class TestCliList(CliMixin):
def test_list(self): def test_list(self):
""" """
Test "slapos list" command output. Test "slapos service list" command output.
""" """
return_value = { return_value = {
'instance1': slapos.slap.SoftwareInstance(_title='instance1', _software_release_url='SR1'), 'instance1': slapos.slap.SoftwareInstance(_title='instance1', _software_release_url='SR1'),
...@@ -424,7 +424,7 @@ class TestCliList(CliMixin): ...@@ -424,7 +424,7 @@ class TestCliList(CliMixin):
class TestCliInfo(CliMixin): class TestCliInfo(CliMixin):
def test_info(self, _): def test_info(self, _):
""" """
Test "slapos info" command output. Test "slapos service info" command output.
""" """
setattr(self.conf, 'reference', 'instance1') setattr(self.conf, 'reference', 'instance1')
instance = slapos.slap.SoftwareInstance( instance = slapos.slap.SoftwareInstance(
...@@ -444,7 +444,7 @@ class TestCliInfo(CliMixin): ...@@ -444,7 +444,7 @@ class TestCliInfo(CliMixin):
def test_unknownReference(self, _): def test_unknownReference(self, _):
""" """
Test "slapos info" command output in case reference Test "slapos service info" command output in case reference
of service is not known. of service is not known.
""" """
setattr(self.conf, 'reference', 'instance1') setattr(self.conf, 'reference', 'instance1')
...@@ -456,7 +456,7 @@ class TestCliInfo(CliMixin): ...@@ -456,7 +456,7 @@ class TestCliInfo(CliMixin):
class TestCliComputerList(CliMixin): class TestCliComputerList(CliMixin):
def test_computer_list(self): def test_computer_list(self):
""" """
Test "slapos list" command output. Test "slapos computer list" command output.
""" """
return_value = { return_value = {
'computer1': slapos.slap.hateoas.TempDocument(title='computer1', _reference='COMP-1'), 'computer1': slapos.slap.hateoas.TempDocument(title='computer1', _reference='COMP-1'),
...@@ -492,8 +492,8 @@ class TestComputerCliInfo(CliMixin): ...@@ -492,8 +492,8 @@ class TestComputerCliInfo(CliMixin):
def test_computer_unknownReference(self, _): def test_computer_unknownReference(self, _):
""" """
Test "slapos info" command output in case reference Test "slapos computer info" command output in case reference
of service is not known. of computer is not known.
""" """
setattr(self.conf, 'reference', 'COMP-0') setattr(self.conf, 'reference', 'COMP-0')
with patch.object(slapos.slap.Computer, 'getInformation', side_effect=raiseNotFoundError): with patch.object(slapos.slap.Computer, 'getInformation', side_effect=raiseNotFoundError):
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
############################################################################## ##############################################################################
import os import os
import slapos.util import slapos.util
from slapos.util import string_to_boolean from slapos.util import string_to_boolean, unicode2str
import tempfile import tempfile
import unittest import unittest
import shutil import shutil
...@@ -120,7 +120,7 @@ class TestUtil(unittest.TestCase): ...@@ -120,7 +120,7 @@ class TestUtil(unittest.TestCase):
for value in [True, False, 1, '1', 't', 'tru', 'truelle', 'f', 'fals', 'falsey']: for value in [True, False, 1, '1', 't', 'tru', 'truelle', 'f', 'fals', 'falsey']:
self.assertRaises(ValueError, string_to_boolean, value) self.assertRaises(ValueError, string_to_boolean, value)
xml2dict_xml = slapos.util.bytes2str(b"""<?xml version='1.0' encoding='utf-8'?> xml2dict0_xml = slapos.util.bytes2str(b"""<?xml version='1.0' encoding='utf-8'?>
<instance> <instance>
<parameter id="badstr">\xc5\x81</parameter> <parameter id="badstr">\xc5\x81</parameter>
<parameter id="badu">\xc5\x81</parameter> <parameter id="badu">\xc5\x81</parameter>
...@@ -134,7 +134,7 @@ class TestUtil(unittest.TestCase): ...@@ -134,7 +134,7 @@ class TestUtil(unittest.TestCase):
</instance> </instance>
""") """)
xml2dict_indict = { xml2dict0_indict = {
u'ukey': u'ustr', u'ukey': u'ustr',
'key': 'str', 'key': 'str',
'int': 1, 'int': 1,
...@@ -146,7 +146,7 @@ class TestUtil(unittest.TestCase): ...@@ -146,7 +146,7 @@ class TestUtil(unittest.TestCase):
'badu': u'\u0141' 'badu': u'\u0141'
} }
xml2dict_outdict = { xml2dict0_outdict = {
'badstr': u'\u0141', 'badstr': u'\u0141',
'badu': u'\u0141', 'badu': u'\u0141',
'emptystr': None, 'emptystr': None,
...@@ -157,17 +157,61 @@ class TestUtil(unittest.TestCase): ...@@ -157,17 +157,61 @@ class TestUtil(unittest.TestCase):
'none': 'None', 'none': 'None',
'ukey': 'ustr'} 'ukey': 'ustr'}
def test_xml2dict(self): def test_xml2dict0(self):
self.assertEqual( self.assertEqual(
self.xml2dict_outdict, dict,
slapos.util.xml2dict(self.xml2dict_xml) type(slapos.util.xml2dict(self.xml2dict0_xml))
)
self.assertEqual(
self.xml2dict0_outdict,
slapos.util.xml2dict(self.xml2dict0_xml)
)
def test_dict2xml0(self):
self.maxDiff = None
self.assertEqual(
self.xml2dict0_xml,
slapos.util.dict2xml(self.xml2dict0_indict)
)
xml2dict1_xml = """<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="_">{
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {
"param": "value"
}
}
}</parameter>
</instance>
"""
xml2dict1_dict = {
"_": {
"param1": "value1",
"param2_dict": {
"param2_param1": "",
"param2_param2_dict": {},
"param2_param3_dict": {"param": "value"}
}
}
}
def test_xml2dict1(self):
self.assertEqual(
self.xml2dict1_dict,
slapos.util.xml2dict(self.xml2dict1_xml)
) )
def test_dict2xml(self): def test_dict2xml1(self):
self.maxDiff = None self.maxDiff = None
self.assertEqual( self.assertEqual(
self.xml2dict_xml, self.xml2dict1_xml,
slapos.util.dict2xml(self.xml2dict_indict) slapos.util.dict2xml(self.xml2dict1_dict)
) )
......
...@@ -33,6 +33,7 @@ import socket ...@@ -33,6 +33,7 @@ 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
...@@ -162,14 +163,22 @@ else: ...@@ -162,14 +163,22 @@ else:
def dict2xml(dictionary): def dict2xml(dictionary):
instance = etree.Element('instance') instance = etree.Element('instance')
for k, v in sorted(six.iteritems(dictionary)): if len(dictionary) == 1 and '_' in 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,
...@@ -189,6 +198,8 @@ def xml2dict(xml): ...@@ -189,6 +198,8 @@ 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