Merge "utils: move publisher-only utils functions in publisher"

This commit is contained in:
Zuul 2018-01-30 03:46:13 +00:00 committed by Gerrit Code Review
commit 120a32bf50
4 changed files with 82 additions and 82 deletions

View File

@ -22,7 +22,6 @@ from oslo_config import cfg
from oslo_utils import secretutils
import six
from ceilometer import utils
OPTS = [
cfg.StrOpt('telemetry_secret',
@ -40,6 +39,42 @@ OPTS = [
]
def decode_unicode(input):
"""Decode the unicode of the message, and encode it into utf-8."""
if isinstance(input, dict):
temp = {}
# If the input data is a dict, create an equivalent dict with a
# predictable insertion order to avoid inconsistencies in the
# message signature computation for equivalent payloads modulo
# ordering
for key, value in sorted(six.iteritems(input)):
temp[decode_unicode(key)] = decode_unicode(value)
return temp
elif isinstance(input, (tuple, list)):
# When doing a pair of JSON encode/decode operations to the tuple,
# the tuple would become list. So we have to generate the value as
# list here.
return [decode_unicode(element) for element in input]
elif isinstance(input, six.text_type):
return input.encode('utf-8')
elif six.PY3 and isinstance(input, six.binary_type):
return input.decode('utf-8')
else:
return input
def recursive_keypairs(d, separator=':'):
"""Generator that produces sequence of keypairs for nested dictionaries."""
for name, value in sorted(six.iteritems(d)):
if isinstance(value, dict):
for subname, subvalue in recursive_keypairs(value, separator):
yield ('%s%s%s' % (name, separator, subname), subvalue)
elif isinstance(value, (tuple, list)):
yield name, decode_unicode(value)
else:
yield name, value
def compute_signature(message, secret):
"""Return the signature for a message dictionary."""
if not secret:
@ -48,7 +83,7 @@ def compute_signature(message, secret):
if isinstance(secret, six.text_type):
secret = secret.encode('utf-8')
digest_maker = hmac.new(secret, b'', hashlib.sha256)
for name, value in utils.recursive_keypairs(message):
for name, value in recursive_keypairs(message):
if name == 'message_signature':
# Skip any existing signature value, which would not have
# been part of the original message.

View File

@ -121,3 +121,48 @@ class TestSignature(base.BaseTestCase):
def test_verify_no_secret(self):
data = {'a': 'A', 'b': 'B'}
self.assertTrue(utils.verify_signature(data, ''))
class TestUtils(base.BaseTestCase):
def test_recursive_keypairs(self):
data = {'a': 'A', 'b': 'B',
'nested': {'a': 'A', 'b': 'B'}}
pairs = list(utils.recursive_keypairs(data))
self.assertEqual([('a', 'A'), ('b', 'B'),
('nested:a', 'A'), ('nested:b', 'B')],
pairs)
def test_recursive_keypairs_with_separator(self):
data = {'a': 'A',
'b': 'B',
'nested': {'a': 'A',
'b': 'B',
},
}
separator = '.'
pairs = list(utils.recursive_keypairs(data, separator))
self.assertEqual([('a', 'A'),
('b', 'B'),
('nested.a', 'A'),
('nested.b', 'B')],
pairs)
def test_recursive_keypairs_with_list_of_dict(self):
small = 1
big = 1 << 64
expected = [('a', 'A'),
('b', 'B'),
('nested:list', [{small: 99, big: 42}])]
data = {'a': 'A',
'b': 'B',
'nested': {'list': [{small: 99, big: 42}]}}
pairs = list(utils.recursive_keypairs(data))
self.assertEqual(len(expected), len(pairs))
for k, v in pairs:
# the keys 1 and 1<<64 cause a hash collision on 64bit platforms
if k == 'nested:list':
self.assertIn(v,
[[{small: 99, big: 42}],
[{big: 42, small: 99}]])
else:
self.assertIn((k, v), expected)

View File

@ -22,49 +22,6 @@ from ceilometer import utils
class TestUtils(base.BaseTestCase):
def test_recursive_keypairs(self):
data = {'a': 'A', 'b': 'B',
'nested': {'a': 'A', 'b': 'B'}}
pairs = list(utils.recursive_keypairs(data))
self.assertEqual([('a', 'A'), ('b', 'B'),
('nested:a', 'A'), ('nested:b', 'B')],
pairs)
def test_recursive_keypairs_with_separator(self):
data = {'a': 'A',
'b': 'B',
'nested': {'a': 'A',
'b': 'B',
},
}
separator = '.'
pairs = list(utils.recursive_keypairs(data, separator))
self.assertEqual([('a', 'A'),
('b', 'B'),
('nested.a', 'A'),
('nested.b', 'B')],
pairs)
def test_recursive_keypairs_with_list_of_dict(self):
small = 1
big = 1 << 64
expected = [('a', 'A'),
('b', 'B'),
('nested:list', [{small: 99, big: 42}])]
data = {'a': 'A',
'b': 'B',
'nested': {'list': [{small: 99, big: 42}]}}
pairs = list(utils.recursive_keypairs(data))
self.assertEqual(len(expected), len(pairs))
for k, v in pairs:
# the keys 1 and 1<<64 cause a hash collision on 64bit platforms
if k == 'nested:list':
self.assertIn(v,
[[{small: 99, big: 42}],
[{big: 42, small: 99}]])
else:
self.assertIn((k, v), expected)
def test_hash_of_set(self):
x = ['a', 'b']
y = ['a', 'b', 'a']

View File

@ -22,7 +22,6 @@ import threading
from oslo_concurrency import processutils
from oslo_config import cfg
import six
ROOTWRAP_CONF = "/etc/ceilometer/rootwrap.conf"
@ -51,42 +50,6 @@ def execute(*cmd, **kwargs):
return processutils.execute(*cmd, **kwargs)
def decode_unicode(input):
"""Decode the unicode of the message, and encode it into utf-8."""
if isinstance(input, dict):
temp = {}
# If the input data is a dict, create an equivalent dict with a
# predictable insertion order to avoid inconsistencies in the
# message signature computation for equivalent payloads modulo
# ordering
for key, value in sorted(six.iteritems(input)):
temp[decode_unicode(key)] = decode_unicode(value)
return temp
elif isinstance(input, (tuple, list)):
# When doing a pair of JSON encode/decode operations to the tuple,
# the tuple would become list. So we have to generate the value as
# list here.
return [decode_unicode(element) for element in input]
elif isinstance(input, six.text_type):
return input.encode('utf-8')
elif six.PY3 and isinstance(input, six.binary_type):
return input.decode('utf-8')
else:
return input
def recursive_keypairs(d, separator=':'):
"""Generator that produces sequence of keypairs for nested dictionaries."""
for name, value in sorted(six.iteritems(d)):
if isinstance(value, dict):
for subname, subvalue in recursive_keypairs(value, separator):
yield ('%s%s%s' % (name, separator, subname), subvalue)
elif isinstance(value, (tuple, list)):
yield name, decode_unicode(value)
else:
yield name, value
def hash_of_set(s):
return str(hash(frozenset(s)))