Refactor memcache config and MemcacheRing loading
The loading and creation of the Memcache ring in the middleware is rather interesting. It not only reads the config file, but also may look for a `/etc/swift/memcache.conf`. Further, we are know are looking at using the MemcacheRing client in more places. So this patch moves the config reading from the middleware and into a `load_memcache` helper method in swift/common/memcached.py. Drive-by: cleanup unused stuff in middleware test module Change-Id: I028722facfbe3ff8092b6bdcc931887a169cc49a
This commit is contained in:
parent
51730f1273
commit
a8516e1510
@ -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…
x
Reference in New Issue
Block a user