Merge "Refactor memcache config and MemcacheRing loading"
This commit is contained in:
commit
32600ee56b
@ -44,18 +44,20 @@ version is at:
|
||||
http://github.com/memcached/memcached/blob/1.4.2/doc/protocol.txt
|
||||
"""
|
||||
|
||||
import os
|
||||
import six
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from bisect import bisect
|
||||
|
||||
from eventlet.green import socket
|
||||
from eventlet.green import socket, ssl
|
||||
from eventlet.pools import Pool
|
||||
from eventlet import Timeout
|
||||
from six.moves import range
|
||||
from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError
|
||||
from swift.common import utils
|
||||
from swift.common.utils import md5, human_readable
|
||||
from swift.common.utils import md5, human_readable, config_true_value
|
||||
|
||||
DEFAULT_MEMCACHED_PORT = 11211
|
||||
|
||||
@ -204,6 +206,10 @@ class MemcacheRing(object):
|
||||
self.logger = logger
|
||||
self.item_size_warning_threshold = item_size_warning_threshold
|
||||
|
||||
@property
|
||||
def memcache_servers(self):
|
||||
return list(self._client_cache.keys())
|
||||
|
||||
def _exception_occurred(self, server, e, action='talking',
|
||||
sock=None, fp=None, got_connection=True):
|
||||
if isinstance(e, Timeout):
|
||||
@ -554,3 +560,96 @@ class MemcacheRing(object):
|
||||
return values
|
||||
except (Exception, Timeout) as e:
|
||||
self._exception_occurred(server, e, sock=sock, fp=fp)
|
||||
|
||||
|
||||
def load_memcache(conf, logger):
|
||||
"""
|
||||
Build a MemcacheRing object from the given config. It will also use the
|
||||
passed in logger.
|
||||
|
||||
:param conf: a dict, the config options
|
||||
:param logger: a logger
|
||||
"""
|
||||
memcache_servers = conf.get('memcache_servers')
|
||||
try:
|
||||
# Originally, while we documented using memcache_max_connections
|
||||
# we only accepted max_connections
|
||||
max_conns = int(conf.get('memcache_max_connections',
|
||||
conf.get('max_connections', 0)))
|
||||
except ValueError:
|
||||
max_conns = 0
|
||||
|
||||
memcache_options = {}
|
||||
if (not memcache_servers
|
||||
or max_conns <= 0):
|
||||
path = os.path.join(conf.get('swift_dir', '/etc/swift'),
|
||||
'memcache.conf')
|
||||
memcache_conf = ConfigParser()
|
||||
if memcache_conf.read(path):
|
||||
# if memcache.conf exists we'll start with those base options
|
||||
try:
|
||||
memcache_options = dict(memcache_conf.items('memcache'))
|
||||
except NoSectionError:
|
||||
pass
|
||||
|
||||
if not memcache_servers:
|
||||
try:
|
||||
memcache_servers = \
|
||||
memcache_conf.get('memcache', 'memcache_servers')
|
||||
except (NoSectionError, NoOptionError):
|
||||
pass
|
||||
if max_conns <= 0:
|
||||
try:
|
||||
new_max_conns = \
|
||||
memcache_conf.get('memcache',
|
||||
'memcache_max_connections')
|
||||
max_conns = int(new_max_conns)
|
||||
except (NoSectionError, NoOptionError, ValueError):
|
||||
pass
|
||||
|
||||
# while memcache.conf options are the base for the memcache
|
||||
# middleware, if you set the same option also in the filter
|
||||
# section of the proxy config it is more specific.
|
||||
memcache_options.update(conf)
|
||||
connect_timeout = float(memcache_options.get(
|
||||
'connect_timeout', CONN_TIMEOUT))
|
||||
pool_timeout = float(memcache_options.get(
|
||||
'pool_timeout', POOL_TIMEOUT))
|
||||
tries = int(memcache_options.get('tries', TRY_COUNT))
|
||||
io_timeout = float(memcache_options.get('io_timeout', IO_TIMEOUT))
|
||||
if config_true_value(memcache_options.get('tls_enabled', 'false')):
|
||||
tls_cafile = memcache_options.get('tls_cafile')
|
||||
tls_certfile = memcache_options.get('tls_certfile')
|
||||
tls_keyfile = memcache_options.get('tls_keyfile')
|
||||
tls_context = ssl.create_default_context(
|
||||
cafile=tls_cafile)
|
||||
if tls_certfile:
|
||||
tls_context.load_cert_chain(tls_certfile, tls_keyfile)
|
||||
else:
|
||||
tls_context = None
|
||||
error_suppression_interval = float(memcache_options.get(
|
||||
'error_suppression_interval', ERROR_LIMIT_TIME))
|
||||
error_suppression_limit = float(memcache_options.get(
|
||||
'error_suppression_limit', ERROR_LIMIT_COUNT))
|
||||
item_size_warning_threshold = int(memcache_options.get(
|
||||
'item_size_warning_threshold', DEFAULT_ITEM_SIZE_WARNING_THRESHOLD))
|
||||
|
||||
if not memcache_servers:
|
||||
memcache_servers = '127.0.0.1:11211'
|
||||
if max_conns <= 0:
|
||||
max_conns = 2
|
||||
|
||||
return MemcacheRing(
|
||||
[s.strip() for s in memcache_servers.split(',')
|
||||
if s.strip()],
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
tries=tries,
|
||||
io_timeout=io_timeout,
|
||||
max_conns=max_conns,
|
||||
tls_context=tls_context,
|
||||
logger=logger,
|
||||
error_limit_count=error_suppression_limit,
|
||||
error_limit_time=error_suppression_interval,
|
||||
error_limit_duration=error_suppression_interval,
|
||||
item_size_warning_threshold=item_size_warning_threshold)
|
||||
|
@ -13,15 +13,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
|
||||
from eventlet.green import ssl
|
||||
from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError
|
||||
|
||||
from swift.common.memcached import (
|
||||
MemcacheRing, CONN_TIMEOUT, POOL_TIMEOUT, IO_TIMEOUT, TRY_COUNT,
|
||||
ERROR_LIMIT_COUNT, ERROR_LIMIT_TIME, DEFAULT_ITEM_SIZE_WARNING_THRESHOLD)
|
||||
from swift.common.utils import get_logger, config_true_value
|
||||
from swift.common.memcached import load_memcache
|
||||
from swift.common.utils import get_logger
|
||||
|
||||
|
||||
class MemcacheMiddleware(object):
|
||||
@ -32,90 +25,7 @@ class MemcacheMiddleware(object):
|
||||
def __init__(self, app, conf):
|
||||
self.app = app
|
||||
self.logger = get_logger(conf, log_route='memcache')
|
||||
self.memcache_servers = conf.get('memcache_servers')
|
||||
try:
|
||||
# Originally, while we documented using memcache_max_connections
|
||||
# we only accepted max_connections
|
||||
max_conns = int(conf.get('memcache_max_connections',
|
||||
conf.get('max_connections', 0)))
|
||||
except ValueError:
|
||||
max_conns = 0
|
||||
|
||||
memcache_options = {}
|
||||
if (not self.memcache_servers
|
||||
or max_conns <= 0):
|
||||
path = os.path.join(conf.get('swift_dir', '/etc/swift'),
|
||||
'memcache.conf')
|
||||
memcache_conf = ConfigParser()
|
||||
if memcache_conf.read(path):
|
||||
# if memcache.conf exists we'll start with those base options
|
||||
try:
|
||||
memcache_options = dict(memcache_conf.items('memcache'))
|
||||
except NoSectionError:
|
||||
pass
|
||||
|
||||
if not self.memcache_servers:
|
||||
try:
|
||||
self.memcache_servers = \
|
||||
memcache_conf.get('memcache', 'memcache_servers')
|
||||
except (NoSectionError, NoOptionError):
|
||||
pass
|
||||
if max_conns <= 0:
|
||||
try:
|
||||
new_max_conns = \
|
||||
memcache_conf.get('memcache',
|
||||
'memcache_max_connections')
|
||||
max_conns = int(new_max_conns)
|
||||
except (NoSectionError, NoOptionError, ValueError):
|
||||
pass
|
||||
|
||||
# while memcache.conf options are the base for the memcache
|
||||
# middleware, if you set the same option also in the filter
|
||||
# section of the proxy config it is more specific.
|
||||
memcache_options.update(conf)
|
||||
connect_timeout = float(memcache_options.get(
|
||||
'connect_timeout', CONN_TIMEOUT))
|
||||
pool_timeout = float(memcache_options.get(
|
||||
'pool_timeout', POOL_TIMEOUT))
|
||||
tries = int(memcache_options.get('tries', TRY_COUNT))
|
||||
io_timeout = float(memcache_options.get('io_timeout', IO_TIMEOUT))
|
||||
if config_true_value(memcache_options.get('tls_enabled', 'false')):
|
||||
tls_cafile = memcache_options.get('tls_cafile')
|
||||
tls_certfile = memcache_options.get('tls_certfile')
|
||||
tls_keyfile = memcache_options.get('tls_keyfile')
|
||||
self.tls_context = ssl.create_default_context(
|
||||
cafile=tls_cafile)
|
||||
if tls_certfile:
|
||||
self.tls_context.load_cert_chain(tls_certfile,
|
||||
tls_keyfile)
|
||||
else:
|
||||
self.tls_context = None
|
||||
error_suppression_interval = float(memcache_options.get(
|
||||
'error_suppression_interval', ERROR_LIMIT_TIME))
|
||||
error_suppression_limit = float(memcache_options.get(
|
||||
'error_suppression_limit', ERROR_LIMIT_COUNT))
|
||||
item_size_warning_threshold = int(memcache_options.get(
|
||||
'item_size_warning_threshold',
|
||||
DEFAULT_ITEM_SIZE_WARNING_THRESHOLD))
|
||||
|
||||
if not self.memcache_servers:
|
||||
self.memcache_servers = '127.0.0.1:11211'
|
||||
if max_conns <= 0:
|
||||
max_conns = 2
|
||||
|
||||
self.memcache = MemcacheRing(
|
||||
[s.strip() for s in self.memcache_servers.split(',') if s.strip()],
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
tries=tries,
|
||||
io_timeout=io_timeout,
|
||||
max_conns=max_conns,
|
||||
tls_context=self.tls_context,
|
||||
logger=self.logger,
|
||||
error_limit_count=error_suppression_limit,
|
||||
error_limit_time=error_suppression_interval,
|
||||
error_limit_duration=error_suppression_interval,
|
||||
item_size_warning_threshold=item_size_warning_threshold)
|
||||
self.memcache = load_memcache(conf, self.logger)
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
env['swift.cache'] = self.memcache
|
||||
|
@ -19,7 +19,6 @@ import unittest
|
||||
|
||||
from eventlet.green import ssl
|
||||
import mock
|
||||
from six.moves.configparser import NoSectionError, NoOptionError
|
||||
|
||||
from swift.common.middleware import memcache
|
||||
from swift.common.memcached import MemcacheRing
|
||||
@ -34,63 +33,6 @@ class FakeApp(object):
|
||||
return env
|
||||
|
||||
|
||||
class ExcConfigParser(object):
|
||||
|
||||
def read(self, path):
|
||||
raise RuntimeError('read called with %r' % path)
|
||||
|
||||
|
||||
class EmptyConfigParser(object):
|
||||
|
||||
def read(self, path):
|
||||
return False
|
||||
|
||||
|
||||
def get_config_parser(memcache_servers='1.2.3.4:5',
|
||||
memcache_max_connections='4',
|
||||
section='memcache',
|
||||
item_size_warning_threshold='75'):
|
||||
_srvs = memcache_servers
|
||||
_maxc = memcache_max_connections
|
||||
_section = section
|
||||
_warn_threshold = item_size_warning_threshold
|
||||
|
||||
class SetConfigParser(object):
|
||||
|
||||
def items(self, section_name):
|
||||
if section_name != section:
|
||||
raise NoSectionError(section_name)
|
||||
return {
|
||||
'memcache_servers': memcache_servers,
|
||||
'memcache_max_connections': memcache_max_connections
|
||||
}
|
||||
|
||||
def read(self, path):
|
||||
return True
|
||||
|
||||
def get(self, section, option):
|
||||
if _section == section:
|
||||
if option == 'memcache_servers':
|
||||
if _srvs == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _srvs
|
||||
elif option in ('memcache_max_connections',
|
||||
'max_connections'):
|
||||
if _maxc == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _maxc
|
||||
elif option == 'item_size_warning_threshold':
|
||||
if _warn_threshold == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _warn_threshold
|
||||
else:
|
||||
raise NoOptionError(option, section)
|
||||
else:
|
||||
raise NoSectionError(option)
|
||||
|
||||
return SetConfigParser
|
||||
|
||||
|
||||
def start_response(*args):
|
||||
pass
|
||||
|
||||
@ -106,165 +48,13 @@ class TestCacheMiddleware(unittest.TestCase):
|
||||
self.assertTrue('swift.cache' in resp)
|
||||
self.assertTrue(isinstance(resp['swift.cache'], MemcacheRing))
|
||||
|
||||
def test_conf_default_read(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', ExcConfigParser):
|
||||
for d in ({},
|
||||
{'memcache_servers': '6.7.8.9:10'},
|
||||
{'memcache_max_connections': '30'},
|
||||
{'item_size_warning_threshold': 75},
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'item_size_warning_threshold': '75'},
|
||||
{'item_size_warning_threshold': '75',
|
||||
'memcache_max_connections': '30'},
|
||||
):
|
||||
with self.assertRaises(RuntimeError) as catcher:
|
||||
memcache.MemcacheMiddleware(FakeApp(), d)
|
||||
self.assertEqual(
|
||||
str(catcher.exception),
|
||||
"read called with '/etc/swift/memcache.conf'")
|
||||
|
||||
def test_conf_set_no_read(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', ExcConfigParser):
|
||||
memcache.MemcacheMiddleware(
|
||||
FakeApp(), {'memcache_servers': '1.2.3.4:5',
|
||||
'memcache_max_connections': '30',
|
||||
'item_size_warning_threshold': '80'})
|
||||
|
||||
def test_conf_default(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', EmptyConfigParser):
|
||||
app = memcache.MemcacheMiddleware(FakeApp(), {})
|
||||
self.assertEqual(app.memcache_servers, '127.0.0.1:11211')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
self.assertEqual(app.memcache.item_size_warning_threshold, -1)
|
||||
|
||||
def test_conf_inline(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'memcache_max_connections': '5',
|
||||
'item_size_warning_threshold': '75'})
|
||||
self.assertEqual(app.memcache_servers, '6.7.8.9:10')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['6.7.8.9:10'].max_size, 5)
|
||||
self.assertEqual(app.memcache.item_size_warning_threshold, 75)
|
||||
|
||||
def test_conf_inline_ratelimiting(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'error_suppression_limit': '5',
|
||||
'error_suppression_interval': '2.5'})
|
||||
self.assertEqual(app.memcache._error_limit_count, 5)
|
||||
self.assertEqual(app.memcache._error_limit_time, 2.5)
|
||||
self.assertEqual(app.memcache._error_limit_duration, 2.5)
|
||||
|
||||
def test_conf_inline_tls(self):
|
||||
fake_context = mock.Mock()
|
||||
with mock.patch.object(ssl, 'create_default_context',
|
||||
return_value=fake_context):
|
||||
with mock.patch.object(memcache, 'ConfigParser',
|
||||
get_config_parser()):
|
||||
memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'tls_enabled': 'true',
|
||||
'tls_cafile': 'cafile',
|
||||
'tls_certfile': 'certfile',
|
||||
'tls_keyfile': 'keyfile'})
|
||||
ssl.create_default_context.assert_called_with(cafile='cafile')
|
||||
fake_context.load_cert_chain.assert_called_with('certfile',
|
||||
'keyfile')
|
||||
|
||||
def test_conf_extra_no_section(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser',
|
||||
get_config_parser(section='foobar')):
|
||||
app = memcache.MemcacheMiddleware(FakeApp(), {})
|
||||
self.assertEqual(app.memcache_servers, '127.0.0.1:11211')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
|
||||
def test_conf_extra_no_option(self):
|
||||
replacement_parser = get_config_parser(
|
||||
memcache_servers='error',
|
||||
memcache_max_connections='error')
|
||||
with mock.patch.object(memcache, 'ConfigParser', replacement_parser):
|
||||
app = memcache.MemcacheMiddleware(FakeApp(), {})
|
||||
self.assertEqual(app.memcache_servers, '127.0.0.1:11211')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
|
||||
def test_conf_inline_other_max_conn(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'max_connections': '5'})
|
||||
self.assertEqual(app.memcache_servers, '6.7.8.9:10')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['6.7.8.9:10'].max_size, 5)
|
||||
|
||||
def test_conf_inline_bad_max_conn(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'max_connections': 'bad42'})
|
||||
self.assertEqual(app.memcache_servers, '6.7.8.9:10')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['6.7.8.9:10'].max_size, 4)
|
||||
|
||||
def test_conf_inline_bad_item_warning_threshold(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
with self.assertRaises(ValueError) as err:
|
||||
memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'memcache_serialization_support': '0',
|
||||
'item_size_warning_threshold': 'bad42'})
|
||||
self.assertIn('invalid literal for int() with base 10:',
|
||||
str(err.exception))
|
||||
|
||||
def test_conf_from_extra_conf(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(FakeApp(), {})
|
||||
self.assertEqual(app.memcache_servers, '1.2.3.4:5')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['1.2.3.4:5'].max_size, 4)
|
||||
|
||||
def test_conf_from_extra_conf_bad_max_conn(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser(
|
||||
memcache_max_connections='bad42')):
|
||||
app = memcache.MemcacheMiddleware(FakeApp(), {})
|
||||
self.assertEqual(app.memcache_servers, '1.2.3.4:5')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['1.2.3.4:5'].max_size, 2)
|
||||
|
||||
def test_conf_from_inline_and_maxc_from_extra_conf(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10'})
|
||||
self.assertEqual(app.memcache_servers, '6.7.8.9:10')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['6.7.8.9:10'].max_size, 4)
|
||||
|
||||
def test_conf_from_inline_and_sers_from_extra_conf(self):
|
||||
with mock.patch.object(memcache, 'ConfigParser', get_config_parser()):
|
||||
app = memcache.MemcacheMiddleware(
|
||||
FakeApp(),
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'memcache_max_connections': '42'})
|
||||
self.assertEqual(app.memcache_servers, '6.7.8.9:10')
|
||||
self.assertEqual(
|
||||
app.memcache._client_cache['6.7.8.9:10'].max_size, 42)
|
||||
|
||||
def test_filter_factory(self):
|
||||
factory = memcache.filter_factory({'max_connections': '3'},
|
||||
memcache_servers='10.10.10.10:10')
|
||||
thefilter = factory('myapp')
|
||||
self.assertEqual(thefilter.app, 'myapp')
|
||||
self.assertEqual(thefilter.memcache_servers, '10.10.10.10:10')
|
||||
self.assertEqual(thefilter.memcache.memcache_servers,
|
||||
['10.10.10.10:10'])
|
||||
self.assertEqual(
|
||||
thefilter.memcache._client_cache['10.10.10.10:10'].max_size, 3)
|
||||
|
||||
|
@ -27,9 +27,11 @@ from uuid import uuid4
|
||||
import os
|
||||
|
||||
import mock
|
||||
from six.moves.configparser import NoSectionError, NoOptionError
|
||||
|
||||
from eventlet import GreenPool, sleep, Queue
|
||||
from eventlet.pools import Pool
|
||||
from eventlet.green import ssl
|
||||
|
||||
from swift.common import memcached
|
||||
from swift.common.memcached import MemcacheConnectionError
|
||||
@ -1047,5 +1049,229 @@ class TestMemcached(unittest.TestCase):
|
||||
do_test('1' * 2048576, 1000000, True)
|
||||
|
||||
|
||||
class ExcConfigParser(object):
|
||||
|
||||
def read(self, path):
|
||||
raise Exception('read called with %r' % path)
|
||||
|
||||
|
||||
class EmptyConfigParser(object):
|
||||
|
||||
def read(self, path):
|
||||
return False
|
||||
|
||||
|
||||
def get_config_parser(memcache_servers='1.2.3.4:5',
|
||||
memcache_max_connections='4',
|
||||
section='memcache',
|
||||
item_size_warning_threshold='75'):
|
||||
_srvs = memcache_servers
|
||||
_maxc = memcache_max_connections
|
||||
_section = section
|
||||
_warn_threshold = item_size_warning_threshold
|
||||
|
||||
class SetConfigParser(object):
|
||||
|
||||
def items(self, section_name):
|
||||
if section_name != section:
|
||||
raise NoSectionError(section_name)
|
||||
return {
|
||||
'memcache_servers': memcache_servers,
|
||||
'memcache_max_connections': memcache_max_connections
|
||||
}
|
||||
|
||||
def read(self, path):
|
||||
return True
|
||||
|
||||
def get(self, section, option):
|
||||
if _section == section:
|
||||
if option == 'memcache_servers':
|
||||
if _srvs == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _srvs
|
||||
elif option in ('memcache_max_connections',
|
||||
'max_connections'):
|
||||
if _maxc == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _maxc
|
||||
elif option == 'item_size_warning_threshold':
|
||||
if _warn_threshold == 'error':
|
||||
raise NoOptionError(option, section)
|
||||
return _warn_threshold
|
||||
else:
|
||||
raise NoOptionError(option, section)
|
||||
else:
|
||||
raise NoSectionError(option)
|
||||
|
||||
return SetConfigParser
|
||||
|
||||
|
||||
def start_response(*args):
|
||||
pass
|
||||
|
||||
|
||||
class TestLoadMemcache(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.logger = debug_logger()
|
||||
|
||||
def test_conf_default_read(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', ExcConfigParser):
|
||||
for d in ({},
|
||||
{'memcache_servers': '6.7.8.9:10'},
|
||||
{'memcache_max_connections': '30'},
|
||||
{'item_size_warning_threshold': 75},
|
||||
{'memcache_servers': '6.7.8.9:10',
|
||||
'item_size_warning_threshold': '75'},
|
||||
{'item_size_warning_threshold': '75',
|
||||
'memcache_max_connections': '30'},
|
||||
):
|
||||
with self.assertRaises(Exception) as catcher:
|
||||
memcached.load_memcache(d, self.logger)
|
||||
self.assertEqual(
|
||||
str(catcher.exception),
|
||||
"read called with '/etc/swift/memcache.conf'")
|
||||
|
||||
def test_conf_set_no_read(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', ExcConfigParser):
|
||||
exc = None
|
||||
try:
|
||||
memcached.load_memcache({
|
||||
'memcache_servers': '1.2.3.4:5',
|
||||
'memcache_max_connections': '30',
|
||||
'item_size_warning_threshold': '80'
|
||||
|
||||
}, self.logger)
|
||||
except Exception as err:
|
||||
exc = err
|
||||
self.assertIsNone(exc)
|
||||
|
||||
def test_conf_default(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', EmptyConfigParser):
|
||||
memcache = memcached.load_memcache({}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['127.0.0.1:11211'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
self.assertEqual(memcache.item_size_warning_threshold, -1)
|
||||
|
||||
def test_conf_inline(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10',
|
||||
'memcache_max_connections': '5',
|
||||
'item_size_warning_threshold': '75'
|
||||
}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['6.7.8.9:10'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['6.7.8.9:10'].max_size, 5)
|
||||
self.assertEqual(memcache.item_size_warning_threshold, 75)
|
||||
|
||||
def test_conf_inline_ratelimiting(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'error_suppression_limit': '5',
|
||||
'error_suppression_interval': '2.5',
|
||||
}, self.logger)
|
||||
self.assertEqual(memcache._error_limit_count, 5)
|
||||
self.assertEqual(memcache._error_limit_time, 2.5)
|
||||
self.assertEqual(memcache._error_limit_duration, 2.5)
|
||||
|
||||
def test_conf_inline_tls(self):
|
||||
fake_context = mock.Mock()
|
||||
with mock.patch.object(ssl, 'create_default_context',
|
||||
return_value=fake_context):
|
||||
with mock.patch.object(memcached, 'ConfigParser',
|
||||
get_config_parser()):
|
||||
memcached.load_memcache({
|
||||
'tls_enabled': 'true',
|
||||
'tls_cafile': 'cafile',
|
||||
'tls_certfile': 'certfile',
|
||||
'tls_keyfile': 'keyfile',
|
||||
}, self.logger)
|
||||
ssl.create_default_context.assert_called_with(cafile='cafile')
|
||||
fake_context.load_cert_chain.assert_called_with('certfile',
|
||||
'keyfile')
|
||||
|
||||
def test_conf_extra_no_section(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser',
|
||||
get_config_parser(section='foobar')):
|
||||
memcache = memcached.load_memcache({}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['127.0.0.1:11211'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
|
||||
def test_conf_extra_no_option(self):
|
||||
replacement_parser = get_config_parser(
|
||||
memcache_servers='error',
|
||||
memcache_max_connections='error')
|
||||
with mock.patch.object(memcached, 'ConfigParser', replacement_parser):
|
||||
memcache = memcached.load_memcache({}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['127.0.0.1:11211'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['127.0.0.1:11211'].max_size, 2)
|
||||
|
||||
def test_conf_inline_other_max_conn(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10',
|
||||
'max_connections': '5'
|
||||
}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['6.7.8.9:10'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['6.7.8.9:10'].max_size, 5)
|
||||
|
||||
def test_conf_inline_bad_max_conn(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10',
|
||||
'max_connections': 'bad42',
|
||||
}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['6.7.8.9:10'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['6.7.8.9:10'].max_size, 4)
|
||||
|
||||
def test_conf_inline_bad_item_warning_threshold(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
with self.assertRaises(ValueError) as err:
|
||||
memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10',
|
||||
'item_size_warning_threshold': 'bad42',
|
||||
}, self.logger)
|
||||
self.assertIn('invalid literal for int() with base 10:',
|
||||
str(err.exception))
|
||||
|
||||
def test_conf_from_extra_conf(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['1.2.3.4:5'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['1.2.3.4:5'].max_size, 4)
|
||||
|
||||
def test_conf_from_extra_conf_bad_max_conn(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser(
|
||||
memcache_max_connections='bad42')):
|
||||
memcache = memcached.load_memcache({}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['1.2.3.4:5'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['1.2.3.4:5'].max_size, 2)
|
||||
|
||||
def test_conf_from_inline_and_maxc_from_extra_conf(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10'}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['6.7.8.9:10'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['6.7.8.9:10'].max_size, 4)
|
||||
|
||||
def test_conf_from_inline_and_sers_from_extra_conf(self):
|
||||
with mock.patch.object(memcached, 'ConfigParser', get_config_parser()):
|
||||
memcache = memcached.load_memcache({
|
||||
'memcache_servers': '6.7.8.9:10',
|
||||
'memcache_max_connections': '42',
|
||||
}, self.logger)
|
||||
self.assertEqual(memcache.memcache_servers, ['6.7.8.9:10'])
|
||||
self.assertEqual(
|
||||
memcache._client_cache['6.7.8.9:10'].max_size, 42)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user