mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Add cascading replication (backup from the replica) tests.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
Feature: cascading replication
|
||||
We should check that patroni can do base backup and streaming from the replica
|
||||
|
||||
Scenario: check a base backup from the replica
|
||||
Given I start postgres0
|
||||
And I start postgres1
|
||||
And replication works from postgres0 to postgres1 after 15 seconds
|
||||
And I create label with "postgres0" in postgres0 data directory
|
||||
And I create label with "postgres1" in postgres1 data directory
|
||||
And I configure and start postgres2 with a tag clonefrom postgres1
|
||||
Then replication works from postgres0 to postgres2 after 15 seconds
|
||||
And there is a label with "postgres1" in postgres2 data directory
|
||||
@@ -0,0 +1,26 @@
|
||||
from lettuce import world, steps
|
||||
|
||||
|
||||
@steps
|
||||
class CascadingReplicationSteps(object):
|
||||
|
||||
def __init__(self, environ):
|
||||
self.env = environ
|
||||
|
||||
@staticmethod
|
||||
def start_patroni_with_a_name_value_tag(step, name, tag_name, tag_value):
|
||||
'''I configure and start (\w+) with a tag (\w+) (\w+)'''
|
||||
return world.pctl.start(name, tags={tag_name: tag_value})
|
||||
|
||||
@staticmethod
|
||||
def check_label(step, content, name):
|
||||
'''There is a label with "(\w+)" in (\w+) data directory'''
|
||||
label = world.pctl.read_label(name)
|
||||
assert label == content, "{0} is not equal to {1}".format(label, content)
|
||||
|
||||
@staticmethod
|
||||
def write_label(step, content, name):
|
||||
'''I create label with "(\w+)" in (\w+) data directory'''
|
||||
world.pctl.write_label(name, content)
|
||||
|
||||
CascadingReplicationSteps(world)
|
||||
+26
-4
@@ -35,14 +35,30 @@ class PatroniController(object):
|
||||
self._patroni_path = cwd
|
||||
return self._patroni_path
|
||||
|
||||
def start(self, pg_name, max_wait_limit=15):
|
||||
def data_dir(self, pg_name):
|
||||
return os.path.join(self.patroni_path, 'data', pg_name)
|
||||
|
||||
def write_label(self, pg_name, content):
|
||||
with open(os.path.join(self.data_dir(pg_name.encode('utf-8')), 'label'), 'w') as f:
|
||||
f.write(content.encode('utf-8'))
|
||||
|
||||
def read_label(self, pg_name):
|
||||
content = None
|
||||
try:
|
||||
with open(os.path.join(self.data_dir(pg_name.encode('utf-8')), 'label'), 'r') as f:
|
||||
content = f.read()
|
||||
except IOError:
|
||||
return None
|
||||
return content.strip()
|
||||
|
||||
def start(self, pg_name, max_wait_limit=15, tags=None):
|
||||
if not self._is_running(pg_name):
|
||||
if pg_name in self._processes:
|
||||
del self._processes[pg_name]
|
||||
cwd = self.patroni_path
|
||||
self._log[pg_name] = open(os.path.join(self._output_dir, 'patroni_{0}.log'.format(pg_name)), 'a')
|
||||
|
||||
self._config[pg_name] = self._make_patroni_test_config(pg_name)
|
||||
self._config[pg_name] = self._make_patroni_test_config(pg_name, tags=tags)
|
||||
|
||||
p = subprocess.Popen(['python', 'patroni.py', self._config[pg_name]],
|
||||
stdout=self._log[pg_name], stderr=subprocess.STDOUT, cwd=cwd)
|
||||
@@ -113,7 +129,7 @@ class PatroniController(object):
|
||||
def _is_running(self, pg_name):
|
||||
return pg_name in self._processes and self._processes[pg_name].pid and (self._processes[pg_name].poll() is None)
|
||||
|
||||
def _make_patroni_test_config(self, pg_name):
|
||||
def _make_patroni_test_config(self, pg_name, tags=None):
|
||||
patroni_config_name = PatroniController.PATRONI_CONFIG.format(pg_name)
|
||||
patroni_config_path = os.path.join(self._output_dir, patroni_config_name)
|
||||
|
||||
@@ -121,6 +137,7 @@ class PatroniController(object):
|
||||
config = yaml.load(f)
|
||||
postgresql = config['postgresql']
|
||||
postgresql['name'] = pg_name.encode('utf-8')
|
||||
postgresql['data_dir'] = 'data/{0}'.format(pg_name.encode('utf-8'))
|
||||
postgresql_params = postgresql['parameters']
|
||||
postgresql_params['logging_collector'] = 'on'
|
||||
postgresql_params['log_destination'] = 'csvlog'
|
||||
@@ -129,6 +146,11 @@ class PatroniController(object):
|
||||
postgresql_params['log_statement'] = 'all'
|
||||
postgresql_params['log_min_messages'] = 'debug1'
|
||||
|
||||
if tags:
|
||||
config['tags'] = {}
|
||||
for tag_name in tags:
|
||||
config['tags'][tag_name.encode('utf-8')] = tags[tag_name].encode('utf-8')
|
||||
|
||||
with open(patroni_config_path, 'w') as f:
|
||||
yaml.dump(config, f, default_flow_style=False)
|
||||
|
||||
@@ -141,7 +163,7 @@ class PatroniController(object):
|
||||
patroni_path = self.patroni_path
|
||||
with open(os.path.join(patroni_path, PatroniController.PATRONI_CONFIG.format(pg_name)), 'r') as f:
|
||||
config = yaml.load(f)
|
||||
except OSError:
|
||||
except IOError:
|
||||
return None
|
||||
connstring = config['postgresql']['connect_address']
|
||||
if ':' in connstring:
|
||||
|
||||
Reference in New Issue
Block a user