mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-31 08:39:34 +00:00
Merge branch 'master' of github.com:zalando/patroni into feature/quorum-commit
This commit is contained in:
+2
-2
@@ -229,7 +229,7 @@ class TestRestApiHandler(unittest.TestCase):
|
||||
self.assertIsNotNone(MockRestApiServer(RestApiHandler, 'GET /primary'))
|
||||
with patch.object(RestApiServer, 'query', Mock(return_value=[('', 1, '', '', '', '', False, None, None, '')])):
|
||||
self.assertIsNotNone(MockRestApiServer(RestApiHandler, 'GET /patroni'))
|
||||
with patch.object(GlobalConfig, 'is_standby_cluster', Mock(return_value=True)),\
|
||||
with patch.object(GlobalConfig, 'is_standby_cluster', Mock(return_value=True)), \
|
||||
patch.object(GlobalConfig, 'is_paused', Mock(return_value=True)):
|
||||
MockRestApiServer(RestApiHandler, 'GET /standby_leader')
|
||||
|
||||
@@ -562,7 +562,7 @@ class TestRestApiHandler(unittest.TestCase):
|
||||
request = post + '103\n\n{"leader": "postgresql1", "member": "postgresql2",' +\
|
||||
' "scheduled_at": "6016-02-15T18:13:30.568224+01:00"}'
|
||||
MockRestApiServer(RestApiHandler, request)
|
||||
with patch.object(GlobalConfig, 'is_paused', PropertyMock(return_value=True)),\
|
||||
with patch.object(GlobalConfig, 'is_paused', PropertyMock(return_value=True)), \
|
||||
patch.object(MockPatroni, 'dcs') as d:
|
||||
d.manual_failover.return_value = False
|
||||
MockRestApiServer(RestApiHandler, request)
|
||||
|
||||
@@ -155,9 +155,9 @@ class TestBootstrap(BaseTestPostgresql):
|
||||
|
||||
config = {'users': {'replicator': {'password': 'rep-pass', 'options': ['replication']}}}
|
||||
|
||||
with patch.object(Postgresql, 'is_running', Mock(return_value=False)),\
|
||||
patch.object(Postgresql, 'get_major_version', Mock(return_value=140000)),\
|
||||
patch('multiprocessing.Process', Mock(side_effect=Exception)),\
|
||||
with patch.object(Postgresql, 'is_running', Mock(return_value=False)), \
|
||||
patch.object(Postgresql, 'get_major_version', Mock(return_value=140000)), \
|
||||
patch('multiprocessing.Process', Mock(side_effect=Exception)), \
|
||||
patch('multiprocessing.get_context', Mock(side_effect=Exception), create=True):
|
||||
self.assertRaises(Exception, self.b.bootstrap, config)
|
||||
with open(os.path.join(self.p.data_dir, 'pg_hba.conf')) as f:
|
||||
@@ -185,12 +185,12 @@ class TestBootstrap(BaseTestPostgresql):
|
||||
self.assertFalse(self.b.bootstrap(config))
|
||||
|
||||
mock_cancellable_subprocess_call.return_value = 0
|
||||
with patch('multiprocessing.Process', Mock(side_effect=Exception("42"))),\
|
||||
patch('multiprocessing.get_context', Mock(side_effect=Exception("42")), create=True),\
|
||||
patch('os.path.isfile', Mock(return_value=True)),\
|
||||
patch('os.unlink', Mock()),\
|
||||
patch.object(ConfigHandler, 'save_configuration_files', Mock()),\
|
||||
patch.object(ConfigHandler, 'restore_configuration_files', Mock()),\
|
||||
with patch('multiprocessing.Process', Mock(side_effect=Exception("42"))), \
|
||||
patch('multiprocessing.get_context', Mock(side_effect=Exception("42")), create=True), \
|
||||
patch('os.path.isfile', Mock(return_value=True)), \
|
||||
patch('os.unlink', Mock()), \
|
||||
patch.object(ConfigHandler, 'save_configuration_files', Mock()), \
|
||||
patch.object(ConfigHandler, 'restore_configuration_files', Mock()), \
|
||||
patch.object(ConfigHandler, 'write_recovery_conf', Mock()):
|
||||
with self.assertRaises(Exception) as e:
|
||||
self.b.bootstrap(config)
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ class TestCitus(BaseTestPostgresql):
|
||||
'leader': 'leader', 'timeout': 30, 'cooldown': 10})
|
||||
|
||||
def test_add_task(self):
|
||||
with patch('patroni.postgresql.citus.logger.error') as mock_logger,\
|
||||
with patch('patroni.postgresql.citus.logger.error') as mock_logger, \
|
||||
patch('patroni.postgresql.citus.urlparse', Mock(side_effect=Exception)):
|
||||
self.c.add_task('', 1, None)
|
||||
mock_logger.assert_called_once()
|
||||
@@ -107,7 +107,7 @@ class TestCitus(BaseTestPostgresql):
|
||||
self.c.process_tasks()
|
||||
|
||||
self.c.add_task('after_promote', 0, 'postgres://host3:5432/postgres')
|
||||
with patch('patroni.postgresql.citus.logger.error') as mock_logger,\
|
||||
with patch('patroni.postgresql.citus.logger.error') as mock_logger, \
|
||||
patch.object(CitusHandler, 'query', Mock(side_effect=Exception)):
|
||||
self.c.process_tasks()
|
||||
mock_logger.assert_called_once()
|
||||
|
||||
@@ -21,7 +21,8 @@ class TestConfig(unittest.TestCase):
|
||||
with patch.object(Config, '_build_effective_configuration', Mock(side_effect=Exception)):
|
||||
self.assertFalse(self.config.set_dynamic_configuration({'foo': 'bar'}))
|
||||
self.assertTrue(self.config.set_dynamic_configuration({'standby_cluster': {}, 'postgresql': {
|
||||
'parameters': {'cluster_name': 1, 'wal_keep_size': 1, 'track_commit_timestamp': 1, 'wal_level': 1}}}))
|
||||
'parameters': {'cluster_name': 1, 'hot_standby': 1, 'wal_keep_size': 1,
|
||||
'track_commit_timestamp': 1, 'wal_level': 1}}}))
|
||||
|
||||
def test_reload_local_configuration(self):
|
||||
os.environ.update({
|
||||
|
||||
+5
-1
@@ -83,9 +83,13 @@ class TestCtl(unittest.TestCase):
|
||||
scheduled_at = datetime.now(tzutc) + timedelta(seconds=600)
|
||||
cluster = get_cluster_initialized_with_leader(Failover(1, 'foo', 'bar', scheduled_at))
|
||||
del cluster.members[1].data['conn_url']
|
||||
for fmt in ('pretty', 'json', 'yaml', 'tsv', 'topology'):
|
||||
for fmt in ('pretty', 'json', 'yaml', 'topology'):
|
||||
self.assertIsNone(output_members({}, cluster, name='abc', fmt=fmt))
|
||||
|
||||
with patch('click.echo') as mock_echo:
|
||||
self.assertIsNone(output_members({}, cluster, name='abc', fmt='tsv'))
|
||||
self.assertEqual(mock_echo.call_args[0][0], 'abc\tother\t\tReplica\trunning\t\tunknown')
|
||||
|
||||
@patch('patroni.ctl.get_dcs')
|
||||
@patch.object(PoolManager, 'request', Mock(return_value=MockResponse()))
|
||||
def test_switchover(self, mock_get_dcs):
|
||||
|
||||
+2
-2
@@ -172,12 +172,12 @@ class TestClient(unittest.TestCase):
|
||||
self.assertRaises(etcd.EtcdWatchTimedOut, self.client.api_execute, '/timeout', 'POST', params={'wait': 'true'})
|
||||
self.assertRaises(etcd.EtcdWatchTimedOut, self.client.api_execute, '/timeout', 'POST', params={'wait': 'true'})
|
||||
|
||||
with patch.object(EtcdClient, '_calculate_timeouts', Mock(side_effect=[(1, 1, 0), (1, 1, 0), (0, 1, 0)])),\
|
||||
with patch.object(EtcdClient, '_calculate_timeouts', Mock(side_effect=[(1, 1, 0), (1, 1, 0), (0, 1, 0)])), \
|
||||
patch.object(EtcdClient, '_load_machines_cache', Mock(side_effect=Exception)):
|
||||
self.client.http.request = Mock(side_effect=socket.error)
|
||||
self.assertRaises(etcd.EtcdException, rtry, self.client.api_execute, '/', 'GET', params={'retry': rtry})
|
||||
|
||||
with patch.object(EtcdClient, '_calculate_timeouts', Mock(side_effect=[(1, 1, 0), (1, 1, 0), (0, 1, 0)])),\
|
||||
with patch.object(EtcdClient, '_calculate_timeouts', Mock(side_effect=[(1, 1, 0), (1, 1, 0), (0, 1, 0)])), \
|
||||
patch.object(EtcdClient, '_load_machines_cache', Mock(return_value=True)):
|
||||
self.assertRaises(etcd.EtcdException, rtry, self.client.api_execute, '/', 'GET', params={'retry': rtry})
|
||||
|
||||
|
||||
+11
-4
@@ -5,8 +5,9 @@ import urllib3
|
||||
|
||||
from mock import Mock, PropertyMock, patch
|
||||
from patroni.dcs.etcd import DnsCachingResolver
|
||||
from patroni.dcs.etcd3 import PatroniEtcd3Client, Cluster, Etcd3Client, Etcd3Error, Etcd3ClientError, RetryFailedError,\
|
||||
InvalidAuthToken, Unavailable, Unknown, UnsupportedEtcdVersion, UserEmpty, AuthFailed, base64_encode, Etcd3
|
||||
from patroni.dcs.etcd3 import PatroniEtcd3Client, Cluster, Etcd3, Etcd3Client, \
|
||||
Etcd3Error, Etcd3ClientError, RetryFailedError, InvalidAuthToken, Unavailable, \
|
||||
Unknown, UnsupportedEtcdVersion, UserEmpty, AuthFailed, base64_encode
|
||||
from threading import Thread
|
||||
|
||||
from . import SleepException, MockResponse
|
||||
@@ -126,10 +127,16 @@ class TestPatroniEtcd3Client(BaseTestEtcd3):
|
||||
request = {'key': base64_encode('/patroni/test/leader')}
|
||||
mock_urlopen.return_value = MockResponse()
|
||||
mock_urlopen.return_value.content = '{"succeeded":true,"header":{"revision":"1"}}'
|
||||
self.client.call_rpc('/kv/txn', {'success': [{'request_delete_range': request}]})
|
||||
self.client.call_rpc('/kv/put', request)
|
||||
self.client.call_rpc('/kv/deleterange', request)
|
||||
|
||||
@patch.object(urllib3.PoolManager, 'urlopen')
|
||||
def test_txn(self, mock_urlopen):
|
||||
mock_urlopen.return_value = MockResponse()
|
||||
mock_urlopen.return_value.content = '{"header":{"revision":"1"}}'
|
||||
self.client.txn({'target': 'MOD', 'mod_revision': '1'},
|
||||
{'request_delete_range': {'key': base64_encode('/patroni/test/leader')}})
|
||||
|
||||
@patch('time.time', Mock(side_effect=[1, 10.9, 100]))
|
||||
def test__wait_cache(self):
|
||||
with self.kv_cache.condition:
|
||||
@@ -241,7 +248,7 @@ class TestEtcd3(BaseTestEtcd3):
|
||||
self.etcd3.update_leader(leader, '123', failsafe={'foo': 'bar'})
|
||||
self.etcd3._last_lease_refresh = 0
|
||||
self.etcd3.update_leader(leader, '124')
|
||||
with patch.object(PatroniEtcd3Client, 'lease_keepalive', Mock(return_value=True)),\
|
||||
with patch.object(PatroniEtcd3Client, 'lease_keepalive', Mock(return_value=True)), \
|
||||
patch('time.time', Mock(side_effect=[0, 100, 200, 300])):
|
||||
self.assertRaises(Etcd3Error, self.etcd3.update_leader, leader, '126')
|
||||
self.etcd3._lease = leader.session
|
||||
|
||||
+12
-6
@@ -309,7 +309,7 @@ class TestHa(PostgresInit):
|
||||
self.p.is_running = false
|
||||
self.p.controldata = lambda: {'Database cluster state': 'in production', 'Database system identifier': SYSID}
|
||||
self.assertEqual(self.ha.run_cycle(), 'doing crash recovery in a single user mode')
|
||||
with patch('patroni.async_executor.AsyncExecutor.busy', PropertyMock(return_value=True)),\
|
||||
with patch('patroni.async_executor.AsyncExecutor.busy', PropertyMock(return_value=True)), \
|
||||
patch.object(Ha, 'check_timeline', Mock(return_value=False)):
|
||||
self.ha._async_executor.schedule('doing crash recovery in a single user mode')
|
||||
self.ha.state_handler.cancellable._process = Mock()
|
||||
@@ -342,7 +342,7 @@ class TestHa(PostgresInit):
|
||||
self.ha._rewind.check_leader_is_not_in_recovery = true
|
||||
with patch.object(Rewind, 'rewind_or_reinitialize_needed_and_possible', Mock(return_value=True)):
|
||||
self.assertEqual(self.ha.run_cycle(), 'running pg_rewind from leader')
|
||||
with patch.object(Rewind, 'rewind_or_reinitialize_needed_and_possible', Mock(return_value=False)),\
|
||||
with patch.object(Rewind, 'rewind_or_reinitialize_needed_and_possible', Mock(return_value=False)), \
|
||||
patch.object(Ha, 'is_synchronous_mode', Mock(return_value=True)):
|
||||
self.p.follow = true
|
||||
self.assertEqual(self.ha.run_cycle(), 'starting as a secondary')
|
||||
@@ -377,6 +377,12 @@ class TestHa(PostgresInit):
|
||||
def test_acquire_lock_as_primary(self):
|
||||
self.assertEqual(self.ha.run_cycle(), 'acquired session lock as a leader')
|
||||
|
||||
def test_leader_race_stale_primary(self):
|
||||
with patch.object(Postgresql, 'get_primary_timeline', Mock(return_value=1)), \
|
||||
patch('patroni.ha.logger.warning') as mock_logger:
|
||||
self.assertEqual(self.ha.run_cycle(), 'demoting self because i am not the healthiest node')
|
||||
self.assertEqual(mock_logger.call_args[0][0], 'My timeline %s is behind last known cluster timeline %s')
|
||||
|
||||
def test_promoted_by_acquiring_lock(self):
|
||||
self.ha.is_healthiest_node = true
|
||||
self.p.is_leader = false
|
||||
@@ -610,7 +616,7 @@ class TestHa(PostgresInit):
|
||||
self.e.initialize = true
|
||||
self.ha.bootstrap()
|
||||
self.p.is_leader = true
|
||||
with patch.object(Watchdog, 'activate', Mock(return_value=False)),\
|
||||
with patch.object(Watchdog, 'activate', Mock(return_value=False)), \
|
||||
patch('patroni.ha.logger.error') as mock_logger:
|
||||
self.assertEqual(self.ha.post_bootstrap(), 'running post_bootstrap')
|
||||
self.assertRaises(PatroniFatalException, self.ha.post_bootstrap)
|
||||
@@ -671,9 +677,9 @@ class TestHa(PostgresInit):
|
||||
|
||||
self.ha.update_lock = false
|
||||
self.p.set_role('primary')
|
||||
with patch('patroni.async_executor.CriticalTask.cancel', Mock(return_value=False)),\
|
||||
with patch('patroni.async_executor.CriticalTask.cancel', Mock(return_value=False)), \
|
||||
patch('patroni.async_executor.CriticalTask.result',
|
||||
PropertyMock(return_value=PostmasterProcess(os.getpid())), create=True),\
|
||||
PropertyMock(return_value=PostmasterProcess(os.getpid())), create=True), \
|
||||
patch('patroni.postgresql.Postgresql.terminate_starting_postmaster') as mock_terminate:
|
||||
self.assertEqual(self.ha.run_cycle(), 'lost leader lock during restart')
|
||||
mock_terminate.assert_called()
|
||||
@@ -1537,7 +1543,7 @@ class TestHa(PostgresInit):
|
||||
self.ha.cluster.config.data.update({'synchronous_mode': 'quorum'})
|
||||
self.ha.global_config = self.ha.patroni.config.get_global_config(self.ha.cluster)
|
||||
# Test the sync node is removed from voters, added to ssn
|
||||
with patch.object(Postgresql, 'synchronous_standby_names', Mock(return_value='other')),\
|
||||
with patch.object(Postgresql, 'synchronous_standby_names', Mock(return_value='other')), \
|
||||
patch('time.sleep', Mock()):
|
||||
self.ha.run_cycle()
|
||||
self.assertEqual(mock_write_sync.call_count, 1)
|
||||
|
||||
+10
-10
@@ -8,8 +8,8 @@ import unittest
|
||||
import urllib3
|
||||
|
||||
from mock import Mock, PropertyMock, mock_open, patch
|
||||
from patroni.dcs.kubernetes import Cluster, k8s_client, k8s_config, K8sConfig, K8sConnectionFailed,\
|
||||
K8sException, K8sObject, Kubernetes, KubernetesError, KubernetesRetriableException,\
|
||||
from patroni.dcs.kubernetes import Cluster, k8s_client, k8s_config, K8sConfig, K8sConnectionFailed, \
|
||||
K8sException, K8sObject, Kubernetes, KubernetesError, KubernetesRetriableException, \
|
||||
Retry, RetryFailedError, SERVICE_HOST_ENV_NAME, SERVICE_PORT_ENV_NAME
|
||||
from threading import Thread
|
||||
from . import MockResponse, SleepException
|
||||
@@ -86,8 +86,8 @@ class TestK8sConfig(unittest.TestCase):
|
||||
with patch('os.environ', env):
|
||||
self.assertRaises(k8s_config.ConfigException, k8s_config.load_incluster_config)
|
||||
|
||||
with patch('os.environ', {SERVICE_HOST_ENV_NAME: 'a', SERVICE_PORT_ENV_NAME: '1'}),\
|
||||
patch('os.path.isfile', Mock(side_effect=[False, True, True, False, True, True, True, True])),\
|
||||
with patch('os.environ', {SERVICE_HOST_ENV_NAME: 'a', SERVICE_PORT_ENV_NAME: '1'}), \
|
||||
patch('os.path.isfile', Mock(side_effect=[False, True, True, False, True, True, True, True])), \
|
||||
patch('builtins.open', Mock(side_effect=[
|
||||
mock_open()(), mock_open(read_data='a')(), mock_open(read_data='a')(),
|
||||
mock_open()(), mock_open(read_data='a')(), mock_open(read_data='a')()])):
|
||||
@@ -98,8 +98,8 @@ class TestK8sConfig(unittest.TestCase):
|
||||
self.assertEqual(k8s_config.headers.get('authorization'), 'Bearer a')
|
||||
|
||||
def test_refresh_token(self):
|
||||
with patch('os.environ', {SERVICE_HOST_ENV_NAME: 'a', SERVICE_PORT_ENV_NAME: '1'}),\
|
||||
patch('os.path.isfile', Mock(side_effect=[True, True, False, True, True, True])),\
|
||||
with patch('os.environ', {SERVICE_HOST_ENV_NAME: 'a', SERVICE_PORT_ENV_NAME: '1'}), \
|
||||
patch('os.path.isfile', Mock(side_effect=[True, True, False, True, True, True])), \
|
||||
patch('builtins.open', Mock(side_effect=[
|
||||
mock_open(read_data='cert')(), mock_open(read_data='a')(),
|
||||
mock_open()(), mock_open(read_data='b')(), mock_open(read_data='c')()])):
|
||||
@@ -138,10 +138,10 @@ class TestK8sConfig(unittest.TestCase):
|
||||
|
||||
config["users"][0]["user"]["client-key-data"] = base64.b64encode(b'foobar').decode('utf-8')
|
||||
config["clusters"][0]["cluster"]["certificate-authority-data"] = base64.b64encode(b'foobar').decode('utf-8')
|
||||
with patch('builtins.open', mock_open(read_data=json.dumps(config))),\
|
||||
patch('os.write', Mock()), patch('os.close', Mock()),\
|
||||
patch('os.remove') as mock_remove,\
|
||||
patch('atexit.register') as mock_atexit,\
|
||||
with patch('builtins.open', mock_open(read_data=json.dumps(config))), \
|
||||
patch('os.write', Mock()), patch('os.close', Mock()), \
|
||||
patch('os.remove') as mock_remove, \
|
||||
patch('atexit.register') as mock_atexit, \
|
||||
patch('tempfile.mkstemp') as mock_mkstemp:
|
||||
mock_mkstemp.side_effect = [(3, '1.tmp'), (4, '2.tmp')]
|
||||
k8s_config.load_kube_config()
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ class TestPatroniLogger(unittest.TestCase):
|
||||
_LOG.exception('test')
|
||||
logger.start()
|
||||
|
||||
with patch.object(logging.Handler, 'format', Mock(side_effect=Exception)),\
|
||||
with patch.object(logging.Handler, 'format', Mock(side_effect=Exception)), \
|
||||
patch('_pytest.logging.LogCaptureHandler.emit', Mock()):
|
||||
logging.error('test')
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ class TestPostgresql(BaseTestPostgresql):
|
||||
|
||||
mock_read_auto = mock_open(read_data=read_data)
|
||||
mock_read_auto.return_value.__iter__ = lambda o: iter(o.readline, '')
|
||||
with patch('builtins.open', Mock(side_effect=[mock_open()(), mock_read_auto(), IOError])),\
|
||||
with patch('builtins.open', Mock(side_effect=[mock_open()(), mock_read_auto(), IOError])), \
|
||||
patch('os.chmod', Mock()):
|
||||
self.p.config.write_postgresql_conf()
|
||||
|
||||
@@ -496,8 +496,8 @@ class TestPostgresql(BaseTestPostgresql):
|
||||
self.p.remove_data_directory()
|
||||
with patch('os.path.isfile', Mock(return_value=True)):
|
||||
self.p.remove_data_directory()
|
||||
with patch('os.path.islink', Mock(side_effect=[False, False, True, True])),\
|
||||
patch('os.listdir', Mock(return_value=['12345'])),\
|
||||
with patch('os.path.islink', Mock(side_effect=[False, False, True, True])), \
|
||||
patch('os.listdir', Mock(return_value=['12345'])), \
|
||||
patch('os.path.realpath', Mock(side_effect=['../foo', '../foo_tsp'])):
|
||||
self.p.remove_data_directory()
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import tempfile
|
||||
import time
|
||||
|
||||
from mock import Mock, PropertyMock, patch
|
||||
from patroni.dcs.raft import Cluster, DynMemberSyncObj, KVStoreTTL,\
|
||||
from patroni.dcs.raft import Cluster, DynMemberSyncObj, KVStoreTTL, \
|
||||
Raft, RaftError, SyncObjUtility, TCPTransport, _TCPTransport
|
||||
from pysyncobj import SyncObjConf, FAIL_REASON
|
||||
|
||||
|
||||
@@ -65,14 +65,14 @@ class TestRewind(BaseTestPostgresql):
|
||||
|
||||
def test_pg_rewind(self):
|
||||
r = {'user': '', 'host': '', 'port': '', 'database': '', 'password': ''}
|
||||
with patch.object(Postgresql, 'major_version', PropertyMock(return_value=150000)),\
|
||||
with patch.object(Postgresql, 'major_version', PropertyMock(return_value=150000)), \
|
||||
patch.object(CancellableSubprocess, 'call', Mock(return_value=None)):
|
||||
with patch('subprocess.check_output', Mock(return_value=b'boo')):
|
||||
self.assertFalse(self.r.pg_rewind(r))
|
||||
with patch('subprocess.check_output', Mock(side_effect=Exception)):
|
||||
self.assertFalse(self.r.pg_rewind(r))
|
||||
|
||||
with patch.object(Postgresql, 'major_version', PropertyMock(return_value=120000)),\
|
||||
with patch.object(Postgresql, 'major_version', PropertyMock(return_value=120000)), \
|
||||
patch('subprocess.check_output', Mock(return_value=b'foo %f %p %r %% % %')):
|
||||
with patch.object(CancellableSubprocess, 'call', mock_cancellable_call):
|
||||
self.assertFalse(self.r.pg_rewind(r))
|
||||
@@ -91,7 +91,7 @@ class TestRewind(BaseTestPostgresql):
|
||||
'Latest checkpoint location': '0/'})):
|
||||
self.r.rewind_or_reinitialize_needed_and_possible(self.leader)
|
||||
|
||||
with patch.object(Postgresql, 'is_running', Mock(return_value=True)),\
|
||||
with patch.object(Postgresql, 'is_running', Mock(return_value=True)), \
|
||||
patch.object(MockCursor, 'fetchone',
|
||||
Mock(side_effect=[(0, 0, 1, 1, 0, 0, 0, 0, 0, None, None, None), Exception])):
|
||||
self.r.rewind_or_reinitialize_needed_and_possible(self.leader)
|
||||
|
||||
+7
-7
@@ -43,12 +43,12 @@ class TestSlotsHandler(BaseTestPostgresql):
|
||||
with mock.patch('patroni.postgresql.Postgresql._query', Mock(side_effect=psycopg.OperationalError)):
|
||||
self.s.sync_replication_slots(cluster, False)
|
||||
self.p.set_role('standby_leader')
|
||||
with patch.object(SlotsHandler, 'drop_replication_slot', Mock(return_value=(True, False))),\
|
||||
with patch.object(SlotsHandler, 'drop_replication_slot', Mock(return_value=(True, False))), \
|
||||
patch('patroni.postgresql.slots.logger.debug') as mock_debug:
|
||||
self.s.sync_replication_slots(cluster, False)
|
||||
mock_debug.assert_called_once()
|
||||
self.p.set_role('replica')
|
||||
with patch.object(Postgresql, 'is_leader', Mock(return_value=False)),\
|
||||
with patch.object(Postgresql, 'is_leader', Mock(return_value=False)), \
|
||||
patch.object(SlotsHandler, 'drop_replication_slot') as mock_drop:
|
||||
self.s.sync_replication_slots(cluster, False, paused=True)
|
||||
mock_drop.assert_not_called()
|
||||
@@ -96,8 +96,8 @@ class TestSlotsHandler(BaseTestPostgresql):
|
||||
with patch.object(SlotsHandler, 'check_logical_slots_readiness', Mock(return_value=False)):
|
||||
self.assertEqual(self.s.sync_replication_slots(self.cluster, False), [])
|
||||
self.s._schedule_load_slots = False
|
||||
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg.OperationalError)),\
|
||||
patch.object(SlotsAdvanceThread, 'schedule', Mock(return_value=(True, ['ls']))),\
|
||||
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg.OperationalError)), \
|
||||
patch.object(SlotsAdvanceThread, 'schedule', Mock(return_value=(True, ['ls']))), \
|
||||
patch.object(psycopg.OperationalError, 'diag') as mock_diag:
|
||||
type(mock_diag).sqlstate = PropertyMock(return_value='58P01')
|
||||
self.assertEqual(self.s.sync_replication_slots(self.cluster, False), ['ls'])
|
||||
@@ -119,10 +119,10 @@ class TestSlotsHandler(BaseTestPostgresql):
|
||||
@patch.object(Postgresql, 'is_leader', Mock(return_value=False))
|
||||
def test_check_logical_slots_readiness(self):
|
||||
self.s.copy_logical_slots(self.cluster, ['ls'])
|
||||
with patch.object(MockCursor, '__iter__', Mock(return_value=iter([('postgresql0', None)]))),\
|
||||
with patch.object(MockCursor, '__iter__', Mock(return_value=iter([('postgresql0', None)]))), \
|
||||
patch.object(MockCursor, 'fetchone', Mock(side_effect=Exception)):
|
||||
self.assertFalse(self.s.check_logical_slots_readiness(self.cluster, None))
|
||||
with patch.object(MockCursor, '__iter__', Mock(return_value=iter([('postgresql0', None)]))),\
|
||||
with patch.object(MockCursor, '__iter__', Mock(return_value=iter([('postgresql0', None)]))), \
|
||||
patch.object(MockCursor, 'fetchone', Mock(return_value=(False,))):
|
||||
self.assertFalse(self.s.check_logical_slots_readiness(self.cluster, None))
|
||||
with patch.object(MockCursor, '__iter__', Mock(return_value=iter([('ls', 100)]))):
|
||||
@@ -144,7 +144,7 @@ class TestSlotsHandler(BaseTestPostgresql):
|
||||
self.assertRaises(OSError, fsync_dir, 'foo')
|
||||
|
||||
def test_slots_advance_thread(self):
|
||||
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg.OperationalError)),\
|
||||
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg.OperationalError)), \
|
||||
patch.object(psycopg.OperationalError, 'diag') as mock_diag:
|
||||
type(mock_diag).sqlstate = PropertyMock(return_value='58P01')
|
||||
self.s.schedule_advance_slots({'foo': {'bar': 100}})
|
||||
|
||||
@@ -7,7 +7,7 @@ from kazoo.handlers.threading import SequentialThreadingHandler
|
||||
from kazoo.protocol.states import KeeperState, ZnodeStat
|
||||
from kazoo.retry import RetryFailedError
|
||||
from mock import Mock, PropertyMock, patch
|
||||
from patroni.dcs.zookeeper import Cluster, Leader, PatroniKazooClient,\
|
||||
from patroni.dcs.zookeeper import Cluster, Leader, PatroniKazooClient, \
|
||||
PatroniSequentialThreadingHandler, ZooKeeper, ZooKeeperError
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user