Allow testing with external zookeeper

It can be handy to test against an already running zookeeper, rather
than requiring one be installed in your test environment. Allow for
that by using the NODEPOOL_ZK_HOST environment variable.

This also gives each ZKTestCase based test a pre-existing client
connection that can be used for testing. To avoid znode path conflicts,
each connection is chroot'ed under /nodepool_test/{uniqueInt}. We
attempt to remove the {uniqueInt} znode and children as part of the
test cleanup (also removed at setUp time if cleanup fails). This will
leave a single znode for /nodepool_test, but if many tests fail for
some reason, it is easier to remove a single root node rather than
potentially many of them if we do not chroot.

Change-Id: I4fd61b16353c16bed2744e0d863ce188019430cd
This commit is contained in:
David Shrewsbury 2016-07-07 16:21:26 -04:00
parent 18f3f4c7bc
commit a0dca6ae12
3 changed files with 55 additions and 4 deletions

View File

@ -29,6 +29,7 @@ import time
import fixtures
import gear
import kazoo.client
import testresources
import testtools
@ -116,6 +117,24 @@ class ZookeeperServerFixture(fixtures.Fixture):
def setUp(self):
super(ZookeeperServerFixture, self).setUp()
if 'NODEPOOL_ZK_HOST' in os.environ:
if ':' in os.environ['NODEPOOL_ZK_HOST']:
host, port = os.environ['NODEPOOL_ZK_HOST'].split(':')
else:
host = os.environ['NODEPOOL_ZK_HOST']
port = None
self.zookeeper_host = host
if not port:
self.zookeeper_port = 2181
else:
self.zookeeper_port = int(port)
return
self.zookeeper_host = '127.0.0.1'
# Get the local port range, we're going to pick one at a time
# at random to try.
with open('/proc/sys/net/ipv4/ip_local_port_range') as f:
@ -500,4 +519,38 @@ class ZKTestCase(BaseTestCase):
super(ZKTestCase, self).setUp()
f = ZookeeperServerFixture()
self.useFixture(f)
self.zookeeper_host = f.zookeeper_host
self.zookeeper_port = f.zookeeper_port
self.chroot_path = "/nodepool_test/%s" % self.getUniqueInteger()
# Ensure the chroot path exists and clean up an pre-existing znodes
_tmp_client = kazoo.client.KazooClient(
hosts='%s:%s' % (self.zookeeper_host, self.zookeeper_port))
_tmp_client.start()
if _tmp_client.exists(self.chroot_path):
_tmp_client.delete(self.chroot_path, recursive=True)
_tmp_client.ensure_path(self.chroot_path)
_tmp_client.stop()
# Create a chroot'ed client
self.zkclient = kazoo.client.KazooClient(
hosts='%s:%s%s' % (self.zookeeper_host,
self.zookeeper_port,
self.chroot_path)
)
self.zkclient.start()
self.addCleanup(self._cleanup)
def _cleanup(self):
'''Stop the client and remove the chroot path.'''
self.zkclient.stop()
# Need a non-chroot'ed client to remove the chroot path
_tmp_client = kazoo.client.KazooClient(
hosts='%s:%s' % (self.zookeeper_host, self.zookeeper_port))
_tmp_client.start()
_tmp_client.delete(self.chroot_path, recursive=True)
_tmp_client.stop()

View File

@ -18,7 +18,6 @@ import time
import threading
import fixtures
import kazoo.client
from nodepool import builder, exceptions, fakeprovider, tests
@ -151,6 +150,4 @@ class TestNodepoolBuilder(tests.DBTestCase):
class TestZookeeper(tests.ZKTestCase):
def test_zk(self):
zk = kazoo.client.KazooClient(hosts='127.0.0.1:%s' % self.zookeeper_port)
zk.start()
zk.get('/')
self.zkclient.get('/')

View File

@ -12,6 +12,7 @@ usedevelop = True
install_command = pip install {opts} {packages}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
passenv = NODEPOOL_ZK_HOST
commands =
python setup.py testr --slowest --testr-args='{posargs}'