Commit 57b1ee3e authored by Léo-Paul Géneau's avatar Léo-Paul Géneau 👾

Raise error when serialization type is unkown

See merge request !436
parent 2ca595a8
...@@ -40,7 +40,8 @@ from slapos.cli.config import ClientConfigCommand ...@@ -40,7 +40,8 @@ from slapos.cli.config import ClientConfigCommand
from slapos.client import (ClientConfig, _getSoftwareReleaseFromSoftwareString, from slapos.client import (ClientConfig, _getSoftwareReleaseFromSoftwareString,
init) init)
from slapos.slap import ResourceNotReady from slapos.slap import ResourceNotReady
from slapos.util import SoftwareReleaseSchema, SoftwareReleaseSerialisation from slapos.util import (SoftwareReleaseSchema, SoftwareReleaseSerialisation,
UndefinedSerializationError)
try: try:
from typing import IO, Dict from typing import IO, Dict
...@@ -158,10 +159,10 @@ def do_request(logger, conf, local): ...@@ -158,10 +159,10 @@ def do_request(logger, conf, local):
conf.software_url = local[conf.software_url] conf.software_url = local[conf.software_url]
software_schema = SoftwareReleaseSchema(conf.software_url, conf.type) software_schema = SoftwareReleaseSchema(conf.software_url, conf.type)
software_schema_serialisation = software_schema.getSerialisation()
parameters = conf.parameters parameters = conf.parameters
if conf.parameters_file: if conf.parameters_file:
parameters = getParametersFromFile(conf.parameters_file, software_schema_serialisation) # getSerialisation must throw an exception if serialization cannot be found
parameters = getParametersFromFile(conf.parameters_file, software_schema.getSerialisation())
try: try:
partition = local['slap'].registerOpenOrder().request( partition = local['slap'].registerOpenOrder().request(
software_release=conf.software_url, software_release=conf.software_url,
...@@ -175,9 +176,12 @@ def do_request(logger, conf, local): ...@@ -175,9 +176,12 @@ def do_request(logger, conf, local):
logger.info('Instance requested.\nState is : %s.', partition.getState()) logger.info('Instance requested.\nState is : %s.', partition.getState())
logger.info('Connection parameters of instance are:') logger.info('Connection parameters of instance are:')
connection_parameter_dict = partition.getConnectionParameterDict() connection_parameter_dict = partition.getConnectionParameterDict()
if software_schema_serialisation == SoftwareReleaseSerialisation.JsonInXml: try:
if '_' in connection_parameter_dict: if software_schema.getSerialisation() == SoftwareReleaseSerialisation.JsonInXml:
connection_parameter_dict = json.loads(connection_parameter_dict['_']) if '_' in connection_parameter_dict:
connection_parameter_dict = json.loads(connection_parameter_dict['_'])
except UndefinedSerializationError:
pass
logger.info(StrPrettyPrinter().pformat(connection_parameter_dict)) logger.info(StrPrettyPrinter().pformat(connection_parameter_dict))
logger.info('You can rerun the command to get up-to-date information.') logger.info('You can rerun the command to get up-to-date information.')
except ResourceNotReady: except ResourceNotReady:
......
...@@ -49,8 +49,9 @@ import six ...@@ -49,8 +49,9 @@ 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 (SoftwareReleaseSchema, bytes2str, calculate_dict_hash, from slapos.util import (SoftwareReleaseSchema, UndefinedSerializationError,
dict2xml, dumps, loads, unicode2str, xml2dict) bytes2str, calculate_dict_hash, dict2xml, dumps, loads,
unicode2str, xml2dict)
from xml.sax import saxutils from xml.sax import saxutils
from zope.interface import implementer from zope.interface import implementer
...@@ -100,6 +101,11 @@ class SlapRequester(SlapDocument): ...@@ -100,6 +101,11 @@ class SlapRequester(SlapDocument):
"Request parameters do not validate against schema definition:\n{e}".format(e=e), "Request parameters do not validate against schema definition:\n{e}".format(e=e),
UserWarning, UserWarning,
) )
except UndefinedSerializationError as e:
warnings.warn(
"No serialization type found:\n{e}".format(e=e),
UserWarning,
)
except Exception as e: except Exception as e:
# note that we intentionally catch wide exceptions, so that if anything # note that we intentionally catch wide exceptions, so that if anything
# is wrong with fetching the schema or the schema itself this does not # is wrong with fetching the schema or the schema itself this does not
......
...@@ -40,7 +40,7 @@ import pkg_resources ...@@ -40,7 +40,7 @@ import pkg_resources
from contextlib import contextmanager from contextlib import contextmanager
from mock import patch, create_autospec from mock import patch, create_autospec
import mock import mock
from slapos.util import sqlite_connect, bytes2str from slapos.util import sqlite_connect, bytes2str, UndefinedSerializationError
from slapos.slap.slap import DEFAULT_SOFTWARE_TYPE from slapos.slap.slap import DEFAULT_SOFTWARE_TYPE
import slapos.cli.console import slapos.cli.console
...@@ -906,23 +906,22 @@ class TestCliRequest(CliMixin): ...@@ -906,23 +906,22 @@ class TestCliRequest(CliMixin):
]) ])
class TestCliRequestParametersFileJson(CliMixin): class TestCliRequestParameterFile(CliMixin):
"""Request with --parameter-file, with a .json file. """Request with --parameter-file, with a .json file.
""" """
expected_partition_parameter_kw = {'foo': ['bar']} expected_partition_parameter_kw = {'foo': ['bar']}
def _makeParameterFile(self): def _makeParameterFile(self):
f = tempfile.NamedTemporaryFile(suffix='.json', mode='w', delete=False) f = tempfile.NamedTemporaryFile(
suffix=self.parameter_file_suffix,
mode='w', delete=False,
)
self.addCleanup(os.unlink, f.name) self.addCleanup(os.unlink, f.name)
f.write(textwrap.dedent('''\ f.write(textwrap.dedent(self.parameter_file_content))
{
"foo": ["bar"]
}
'''))
f.flush() f.flush()
return f.name return f.name
def test_request_parameters_file(self): def _request_parameters_file_setup(self):
self.conf.reference = 'instance reference' self.conf.reference = 'instance reference'
self.conf.software_url = 'software URL' self.conf.software_url = 'software URL'
self.conf.parameters = None self.conf.parameters = None
...@@ -934,28 +933,66 @@ class TestCliRequestParametersFileJson(CliMixin): ...@@ -934,28 +933,66 @@ class TestCliRequestParametersFileJson(CliMixin):
self.conf.state = None self.conf.state = None
self.conf.slave = False self.conf.slave = False
with patch.object(
slapos.slap.slap,
'registerOpenOrder',
return_value=mock.create_autospec(slapos.slap.OpenOrder)) as registerOpenOrder:
slapos.cli.request.do_request(self.logger, self.conf, self.local)
registerOpenOrder().request.assert_called_once_with( class TestCliRequestParameterFileUndefinedSerialization(TestCliRequestParameterFile):
software_release='software URL', """Request with --parameter-file, without defining serialization type.
partition_reference='instance reference', """
partition_parameter_kw=self.expected_partition_parameter_kw, parameter_file_suffix = ''
software_type=None, parameter_file_content = '''\
filter_kw={'computer_guid': 'COMP-1234'}, {
state=None, "foo": ["bar"]
shared=False, }
) '''
self.logger.info.assert_any_call(
'Requesting %s as instance of %s...', def test_request_parameters_file(self):
'instance reference', self._request_parameters_file_setup()
'software URL', self.assertRaises(
UndefinedSerializationError,
slapos.cli.request.do_request,
self.logger,
self.conf,
self.local,
) )
class TestCliRequestParametersFileJson(TestCliRequestParameterFile):
"""Request with --parameter-file, with a .json file.
"""
parameter_file_suffix = '.json'
parameter_file_content = '''\
{
"foo": ["bar"]
}
'''
serialization = 'xml'
def test_request_parameters_file(self):
self._request_parameters_file_setup()
with mock.patch(
'slapos.cli.request.SoftwareReleaseSchema.getSerialisation',
return_value=self.serialization):
with patch.object(
slapos.slap.slap,
'registerOpenOrder',
return_value=mock.create_autospec(slapos.slap.OpenOrder)) as registerOpenOrder:
slapos.cli.request.do_request(self.logger, self.conf, self.local)
registerOpenOrder().request.assert_called_once_with(
software_release='software URL',
partition_reference='instance reference',
partition_parameter_kw=self.expected_partition_parameter_kw,
software_type=None,
filter_kw={'computer_guid': 'COMP-1234'},
state=None,
shared=False,
)
self.logger.info.assert_any_call(
'Requesting %s as instance of %s...',
'instance reference',
'software URL',
)
class TestCliRequestParametersFileJsonJsonInXMLSerialisation( class TestCliRequestParametersFileJsonJsonInXMLSerialisation(
TestCliRequestParametersFileJson): TestCliRequestParametersFileJson):
"""Request with --parameter-file, with a .json file and a software using """Request with --parameter-file, with a .json file and a software using
...@@ -963,68 +1000,40 @@ class TestCliRequestParametersFileJsonJsonInXMLSerialisation( ...@@ -963,68 +1000,40 @@ class TestCliRequestParametersFileJsonJsonInXMLSerialisation(
serialised with {'_': json.dumps(params)} serialised with {'_': json.dumps(params)}
""" """
expected_partition_parameter_kw = {"_": "{\"foo\": [\"bar\"]}"} expected_partition_parameter_kw = {"_": "{\"foo\": [\"bar\"]}"}
serialization = 'json-in-xml'
def test_request_parameters_file(self):
with mock.patch(
'slapos.cli.request.SoftwareReleaseSchema.getSerialisation',
return_value='json-in-xml'):
super(TestCliRequestParametersFileJsonJsonInXMLSerialisation,
self).test_request_parameters_file()
class TestCliRequestParametersFileJsonJsonInXMLSerialisationAlreadySerialised( class TestCliRequestParametersFileJsonJsonInXMLSerialisationAlreadySerialised(
TestCliRequestParametersFileJson): TestCliRequestParametersFileJsonJsonInXMLSerialisation):
"""Request with --parameter-file, with a .json file and a software using """Request with --parameter-file, with a .json file and a software using
json-in-xml for serialisation and parameters already serialised with json-in-xml for serialisation and parameters already serialised with
{'_': json.dumps(params)}. In that case, parameters are not serialized one {'_': json.dumps(params)}. In that case, parameters are not serialized one
more time. more time.
""" """
expected_partition_parameter_kw = {"_": "{\"foo\": [\"bar\"]}"} expected_partition_parameter_kw = {"_": "{\"foo\": [\"bar\"]}"}
parameter_file_content = r'''
def _makeParameterFile(self): {"_": "{\"foo\": [\"bar\"]}"}
f = tempfile.NamedTemporaryFile(suffix='.json', mode='w', delete=False) '''
self.addCleanup(os.unlink, f.name)
f.write(textwrap.dedent(r'''
{"_": "{\"foo\": [\"bar\"]}"}
'''))
f.flush()
return f.name
def test_request_parameters_file(self):
with mock.patch(
'slapos.cli.request.SoftwareReleaseSchema.getSerialisation',
return_value='json-in-xml'):
super(
TestCliRequestParametersFileJsonJsonInXMLSerialisationAlreadySerialised,
self).test_request_parameters_file()
class TestCliRequestParametersFileYaml(TestCliRequestParametersFileJson): class TestCliRequestParametersFileYaml(TestCliRequestParametersFileJson):
"""Request with --parameter-file, with a .yaml file. This behaves like json. """Request with --parameter-file, with a .yaml file. This behaves like json.
""" """
def _makeParameterFile(self): parameter_file_content = '''\
f = tempfile.NamedTemporaryFile(suffix='.yaml', mode='w', delete=False) foo:
self.addCleanup(os.unlink, f.name) - bar
f.write(textwrap.dedent('''\ '''
foo: parameter_file_suffix = '.yaml'
- bar
'''))
f.flush()
return f.name
class TestCliRequestParametersFileXml(TestCliRequestParametersFileJson): class TestCliRequestParametersFileXml(TestCliRequestParametersFileJson):
"""Request with --parameter-file, with a .xml file """Request with --parameter-file, with a .xml file
""" """
expected_partition_parameter_kw = {'foo': 'bar'} expected_partition_parameter_kw = {'foo': 'bar'}
def _makeParameterFile(self): parameter_file_content = '''\
f = tempfile.NamedTemporaryFile(suffix='.xml', mode='w', delete=False) <?xml version="1.0" encoding="utf-8"?>
f.write(textwrap.dedent('''\ <instance>
<?xml version="1.0" encoding="utf-8"?> <parameter id="foo">bar</parameter>
<instance> </instance>
<parameter id="foo">bar</parameter> '''
</instance> parameter_file_suffix = '.xml'
'''))
f.flush()
self.addCleanup(os.unlink, f.name)
return f.name
...@@ -70,6 +70,11 @@ _ALLOWED_CLASS_SET = frozenset(( ...@@ -70,6 +70,11 @@ _ALLOWED_CLASS_SET = frozenset((
)) ))
class UndefinedSerializationError(ValueError):
"""Raised when the serialization type is not found"""
pass
class SafeXMLMarshaller(Marshaller): class SafeXMLMarshaller(Marshaller):
def m_instance(self, value, kw): def m_instance(self, value, kw):
cls = value.__class__ cls = value.__class__
...@@ -393,14 +398,14 @@ class SoftwareReleaseSchema(object): ...@@ -393,14 +398,14 @@ class SoftwareReleaseSchema(object):
return software_schema['software-type'].get(software_type) return software_schema['software-type'].get(software_type)
def getSerialisation(self): def getSerialisation(self):
# type: () -> Optional[SoftwareReleaseSerialisation] # type: () -> SoftwareReleaseSerialisation
"""Returns the serialisation method used for parameters. """Returns the serialisation method used for parameters.
""" """
software_schema = self.getSoftwareTypeSchema() software_schema = self.getSoftwareTypeSchema()
if software_schema is None or 'serialisation' not in software_schema: if software_schema is None or 'serialisation' not in software_schema:
software_schema = self.getSoftwareSchema() software_schema = self.getSoftwareSchema()
if software_schema is None: if software_schema is None:
return None raise UndefinedSerializationError
return SoftwareReleaseSerialisation(software_schema['serialisation']) return SoftwareReleaseSerialisation(software_schema['serialisation'])
def getInstanceRequestParameterSchemaURL(self): def getInstanceRequestParameterSchemaURL(self):
......
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