diff --git a/oslo_privsep/daemon.py b/oslo_privsep/daemon.py index 6e9d821..15a960a 100644 --- a/oslo_privsep/daemon.py +++ b/oslo_privsep/daemon.py @@ -59,6 +59,7 @@ import threading import eventlet from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import encodeutils from oslo_utils import importutils import six @@ -207,7 +208,9 @@ class _ClientChannel(comm.ClientChannel): def out_of_band(self, msg): if msg[0] == Message.LOG: # (LOG, LogRecord __dict__) - record = pylogging.makeLogRecord(msg[1]) + message = {encodeutils.safe_decode(k): v + for k, v in msg[1].items()} + record = pylogging.makeLogRecord(message) if LOG.isEnabledFor(record.levelno): LOG.logger.handle(record) else: diff --git a/oslo_privsep/tests/test_daemon.py b/oslo_privsep/tests/test_daemon.py index c5cf29a..f6e4d23 100644 --- a/oslo_privsep/tests/test_daemon.py +++ b/oslo_privsep/tests/test_daemon.py @@ -23,9 +23,11 @@ import time from oslo_log import formatters from oslo_log import log as logging from oslotest import base +import six import testtools from oslo_privsep import capabilities +from oslo_privsep import comm from oslo_privsep import daemon from oslo_privsep.tests import testctx @@ -178,3 +180,35 @@ class WithContextTest(testctx.TestContextTestCase): self.assertRaisesRegex( NameError, 'undecorated not exported', testctx.context._wrap, undecorated) + + +class ClientChannelTestCase(base.BaseTestCase): + + DICT = { + 'string_1': ('tuple_1', six.b('tuple_2')), + six.b('byte_1'): ['list_1', 'list_2'], + } + + EXPECTED = { + 'string_1': ('tuple_1', six.b('tuple_2')), + 'byte_1': ['list_1', 'list_2'], + } + + def setUp(self): + super(ClientChannelTestCase, self).setUp() + with mock.patch.object(comm.ClientChannel, '__init__'), \ + mock.patch.object(daemon._ClientChannel, 'exchange_ping'): + self.client_channel = daemon._ClientChannel(mock.ANY) + + def test_out_of_band_log_message(self): + message = [daemon.Message.LOG, self.DICT] + with mock.patch.object(pylogging, 'makeLogRecord') as mock_make_log, \ + mock.patch.object(daemon.LOG, 'isEnabledFor', + return_value=False): + self.client_channel.out_of_band(message) + mock_make_log.assert_called_once_with(self.EXPECTED) + + def test_out_of_band_not_log_message(self): + with mock.patch.object(daemon.LOG, 'warning') as mock_warning: + self.client_channel.out_of_band([daemon.Message.PING]) + mock_warning.assert_called_once()