def test_invalid(self): # Test that not elected using defaults. with self.assertRaises(ValueError): client = stub_etcd.Client() elector = election.Elector(client, "test_basic", "/bloop", interval=-1, ttl=15) self.assertFalse(elector.master()) with self.assertRaises(ValueError): client = stub_etcd.Client() elector = election.Elector(client, "test_basic", "/bloop", interval=10, ttl=5) self.assertFalse(elector.master())
def test_check_master_process_died(self, m_exists): m_exists.return_value = False etcdv3._client = client = mock.Mock() elector = election.Elector("server-id", "/bloop", interval=5, ttl=15) # etcd3 transaction returns False because the key is no longer there. client.transaction.return_value = {} self.assertRaises(election.RestartElection, elector._check_master_process, "server-id:1234") self.assertEqual([ mock.call({ 'compare': [{ 'value': 'c2VydmVyLWlkOjEyMzQ=', 'result': 'EQUAL', 'key': 'L2Jsb29w', 'target': 'VALUE' }], 'success': [{ 'request_delete_range': { 'key': 'L2Jsb29w' } }], 'failure': [] }) ], client.transaction.mock_calls) client.failure = None self._wait_and_stop(client, elector)
def test_master_failure(self): LOG.debug("test_master_failure") client = stub_etcd.Client() client.add_read_exception(stub_etcd.EtcdKeyNotFound()) # Now become the master but fail client.add_write_exception(stub_etcd.EtcdException()) client.add_read_result(key="/bloop", value="value") client.add_read_result(key="/bloop", value=None, action="delete") # Now become the master but fail again client.add_write_exception(stub_etcd.EtcdException()) # Go back to the beginning again. client.add_read_result(key="/bloop", value="value") client.add_read_result(key="/bloop", value=None, action="delete") client.add_write_exception(None) client.add_write_exception(None) elector = election.Elector(client, "test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector) # We are no longer the master, after error. self.assertFalse(elector.master())
def test_check_master_process_still_alive(self, m_exists): m_exists.return_value = True client = mock.Mock() elector = election.Elector(client, "server-id", "/bloop", interval=5, ttl=15) elector._check_master_process("server-id:1234") self.assertEqual(client.delete.mock_calls, [])
def test_basic_election(self): # Test that not elected using defaults. LOG.debug("test_basic_election") etcdv3._client = client = stub_etcd.Client() client.add_read_result(key="/bloop", value="value") elector = election.Elector("test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector) self.assertFalse(elector.master())
def test_check_master_process_still_alive(self, m_exists): m_exists.return_value = True etcdv3._client = client = mock.Mock() elector = election.Elector("server-id", "/bloop", interval=5, ttl=15) elector._check_master_process("server-id:1234") self.assertEqual([], client.delete.mock_calls) self.assertEqual([], client.transaction.mock_calls) client.failure = None self._wait_and_stop(client, elector)
def test_fail_to_maintain(self): # Become the master after one round LOG.debug("test_become_master_first_time") etcdv3._client = client = stub_etcd.Client() client.add_read_exception(etcdv3.KeyNotFound()) client.add_write_exception(None) client.add_write_exception(e3e.ConnectionFailedError()) elector = election.Elector("test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_check_master_process_other_server(self, m_exists): m_exists.return_value = False client = mock.Mock() elector = election.Elector(client, "server-id", "/bloop", interval=5, ttl=15) elector._check_master_process("other-server:1234") self.assertEqual([], client.delete.mock_calls)
def test_initial_read_exceptions(self): LOG.debug("test_initial_read_exceptions") etcdv3._client = client = stub_etcd.Client() client.add_read_exception(e3e.Etcd3Exception()) client.add_read_exception(e3e.InternalServerError()) client.add_read_exception(e3e.ConnectionFailedError()) client.add_read_exception(e3e.PreconditionFailedError()) elector = election.Elector("test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_become_master_implausible(self): # Become the master after key vanishes LOG.debug("test_become_master_implausible") etcdv3._client = client = stub_etcd.Client() client.add_read_result(key="/bloop", value="value") client.add_read_result(key="/bloop", value="value") client.add_read_exception(etcdv3.KeyNotFound()) client.add_write_result() client.add_write_result() elector = election.Elector("test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_check_master_process_died(self, m_exists): m_exists.return_value = False client = mock.Mock() elector = election.Elector(client, "server-id", "/bloop", interval=5, ttl=15) client.delete.side_effect = stub_etcd.EtcdKeyNotFound() self.assertRaises(election.RestartElection, elector._check_master_process, "server-id:1234") self.assertEqual([mock.call("/bloop", prevValue="server-id:1234")], client.delete.mock_calls)
def test_fail_to_maintain(self): # Become the master after once round LOG.debug("test_become_master_first_time") client = stub_etcd.Client() client.add_read_exception(stub_etcd.EtcdKeyNotFound()) client.add_write_exception(None) client.add_write_exception(stub_etcd.EtcdClusterIdChanged()) elector = election.Elector(client, "test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_initial_read_exceptions(self): LOG.debug("test_initial_read_exceptions") client = stub_etcd.Client() client.add_read_exception(stub_etcd.EtcdException()) client.add_read_exception(stub_etcd.EtcdConnectionFailed()) client.add_read_exception(stub_etcd.EtcdClusterIdChanged()) client.add_read_exception(stub_etcd.EtcdEventIndexCleared()) elector = election.Elector(client, "test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_become_master_multiple_attempts(self): # Become the master after once round LOG.debug("test_become_master_multiple_circuits") for action in ["delete", "expire", "compareAndDelete", "something"]: LOG.info("Testing etcd delete event %s", action) client = stub_etcd.Client() client.add_read_result(key="/bloop", value="value") client.add_read_result(key="/bloop", value="value") client.add_read_result(key="/bloop", value=None, action=action) client.add_write_exception(None) client.add_write_exception(None) elector = election.Elector(client, "test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector)
def test_become_master_first_time(self): # Become the master after one round LOG.debug("test_become_master_first_time") etcdv3._client = client = stub_etcd.Client() client.add_read_exception(etcdv3.KeyNotFound()) client.add_write_exception(None) client.add_write_exception(None) client.add_write_exception(None) elector = election.Elector("test_basic", "/bloop", old_key="/legacy", interval=5, ttl=15) self._wait_and_stop(client, elector) client.assert_key_written("/legacy")
def test_exception_detail_logging(self): LOG.debug("test_exception_detail_logging") with mock.patch.object( log.getLogger( 'networking_calico.plugins.ml2.drivers.calico.election'), 'warning') as mock_lw: etcdv3._client = client = stub_etcd.Client() exc = e3e.Etcd3Exception(detail_text="Unauthorised user") client.add_read_exception(exc) elector = election.Elector("test_basic", "/bloop", interval=5, ttl=15) self._wait_and_stop(client, elector) # Check that Etcd3Exception detail was logged. mock_lw.assert_called_with('Failed to %s - key %s: %r:\n%s', 'read current master', '/bloop', exc, 'Unauthorised user')