mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-01-27 10:20:10 +00:00
Rename create_replica_method to create_replica_methods
To make it clear that it's actually an array
This commit is contained in:
@@ -131,7 +131,7 @@ PostgreSQL
|
||||
- **pg\_ctl\_timeout**: How long should pg_ctl wait when doing ``start``, ``stop`` or ``restart``. Default value is 60 seconds.
|
||||
- **use\_pg\_rewind**: try to use pg\_rewind on the former leader when it joins cluster as a replica.
|
||||
- **remove\_data\_directory\_on\_rewind\_failure**: If this option is enabled, Patroni will remove postgres data directory and recreate replica. Otherwise it will try to follow the new leader. Default value is **false**.
|
||||
- **replica\_method**: for each create_replica_method other than basebackup, you would add a configuration section of the same name. At a minimum, this should include "command" with a full path to the actual script to be executed. Other configuration parameters will be passed along to the script in the form "parameter=value".
|
||||
- **replica\_method**: for each create_replica_methods other than basebackup, you would add a configuration section of the same name. At a minimum, this should include "command" with a full path to the actual script to be executed. Other configuration parameters will be passed along to the script in the form "parameter=value".
|
||||
|
||||
REST API
|
||||
--------
|
||||
|
||||
@@ -68,7 +68,7 @@ scripts to clone a new replica. Those are configured in the ``postgresql`` confi
|
||||
.. code:: YAML
|
||||
|
||||
postgresql:
|
||||
create_replica_method:
|
||||
create_replica_methods:
|
||||
- wal_e
|
||||
- basebackup
|
||||
wal_e:
|
||||
@@ -80,7 +80,7 @@ scripts to clone a new replica. Those are configured in the ``postgresql`` confi
|
||||
max-rate: '100M'
|
||||
|
||||
|
||||
The ``create_replica_method`` defines available replica creation methods and the order of executing them. Patroni will
|
||||
The ``create_replica_methods`` defines available replica creation methods and the order of executing them. Patroni will
|
||||
stop on the first one that returns 0. Each method should define a separate section in the configuration file, listing the command
|
||||
to execute and any custom parameters that should be passed to that command. All parameters will be passed in a
|
||||
``--name=value`` format. Besides user-defined parameters, Patroni supplies a couple of cluster-specific ones:
|
||||
@@ -99,8 +99,9 @@ A special ``no_master`` parameter, if defined, allows Patroni to call the replic
|
||||
running master or replicas. In that case, an empty string will be passed in a connection string. This is useful for
|
||||
restoring the formerly running cluster from the binary backup.
|
||||
|
||||
A ``basebackup`` method is a special case: it will be used if ``create_replica_method`` is empty, although it is possible
|
||||
to list it explicitly among the ``create_replica_method`` methods. This method initializes a new replica with the
|
||||
A ``basebackup`` method is a special case: it will be used if
|
||||
``create_replica_methods`` is empty, although it is possible
|
||||
to list it explicitly among the ``create_replica_methods`` methods. This method initializes a new replica with the
|
||||
``pg_basebackup``, the base backup is taken from the master unless there are replicas with ``clonefrom`` tag, in which case one
|
||||
of such replicas will be used as the origin for pg_basebackup. It works without any configuration; however, it is
|
||||
possible to specify a ``basebackup`` configuration section. Same rules as with the other method configuration apply,
|
||||
|
||||
@@ -180,6 +180,11 @@ class Postgresql(object):
|
||||
if self._replace_pg_hba():
|
||||
self.reload()
|
||||
|
||||
@property
|
||||
def _create_replica_methods(self):
|
||||
return (self.config.get('create_replica_methods', []) or
|
||||
self.config.get('create_replica_method', []))
|
||||
|
||||
@property
|
||||
def _configuration_to_save(self):
|
||||
configuration = [os.path.basename(self._postgresql_conf)]
|
||||
@@ -638,7 +643,7 @@ class Postgresql(object):
|
||||
""" go through the replication methods to see if there are ones
|
||||
that does not require a working replication connection.
|
||||
"""
|
||||
replica_methods = self.config.get('create_replica_method', [])
|
||||
replica_methods = self._create_replica_methods
|
||||
return any(self.replica_method_can_work_without_replication_connection(method) for method in replica_methods)
|
||||
|
||||
def create_replica(self, clone_member):
|
||||
@@ -653,7 +658,7 @@ class Postgresql(object):
|
||||
|
||||
# get list of replica methods from config.
|
||||
# If there is no configuration key, or no value is specified, use basebackup
|
||||
replica_methods = self.config.get('create_replica_method') or ['basebackup']
|
||||
replica_methods = self._create_replica_methods or ['basebackup']
|
||||
|
||||
if clone_member and clone_member.conn_url:
|
||||
r = clone_member.conn_kwargs(self._replication)
|
||||
@@ -1622,7 +1627,7 @@ $$""".format(name, ' '.join(options)), name, password, password)
|
||||
|
||||
def basebackup(self, conn_url, env, options):
|
||||
# creates a replica data dir using pg_basebackup.
|
||||
# this is the default, built-in create_replica_method
|
||||
# this is the default, built-in create_replica_methods
|
||||
# tries twice, then returns failure (as 1)
|
||||
# uses "stream" as the xlog-method to avoid sync issues
|
||||
# supports additional user-supplied options, those are not validated
|
||||
|
||||
@@ -420,14 +420,14 @@ class TestPostgresql(unittest.TestCase):
|
||||
def test_create_replica(self, mock_cancellable_subprocess_call):
|
||||
self.p.delete_trigger_file = Mock(side_effect=OSError)
|
||||
|
||||
self.p.config['create_replica_method'] = ['wale', 'basebackup']
|
||||
self.p.config['create_replica_methods'] = ['wale', 'basebackup']
|
||||
self.p.config['wale'] = {'command': 'foo'}
|
||||
mock_cancellable_subprocess_call.return_value = 0
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
del self.p.config['wale']
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
|
||||
self.p.config['create_replica_method'] = ['basebackup']
|
||||
self.p.config['create_replica_methods'] = ['basebackup']
|
||||
self.p.config['basebackup'] = [{'max_rate': '100M'}, 'no-sync']
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
|
||||
@@ -448,7 +448,7 @@ class TestPostgresql(unittest.TestCase):
|
||||
self.p.config['basebackup'] = {"foo": "bar"}
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
|
||||
self.p.config['create_replica_method'] = ['wale', 'basebackup']
|
||||
self.p.config['create_replica_methods'] = ['wale', 'basebackup']
|
||||
del self.p.config['basebackup']
|
||||
mock_cancellable_subprocess_call.return_value = 1
|
||||
self.assertEquals(self.p.create_replica(self.leader), 1)
|
||||
@@ -465,6 +465,31 @@ class TestPostgresql(unittest.TestCase):
|
||||
self.p.cancel()
|
||||
self.assertEquals(self.p.create_replica(self.leader), 1)
|
||||
|
||||
@patch('time.sleep', Mock())
|
||||
@patch.object(Postgresql, 'cancellable_subprocess_call')
|
||||
@patch.object(Postgresql, 'remove_data_directory', Mock(return_value=True))
|
||||
def test_create_replica_old_format(self, mock_cancellable_subprocess_call):
|
||||
""" The same test as before but with old 'create_replica_method'
|
||||
to test backward compatibility
|
||||
"""
|
||||
self.p.delete_trigger_file = Mock(side_effect=OSError)
|
||||
|
||||
self.p.config['create_replica_method'] = ['wale', 'basebackup']
|
||||
self.p.config['wale'] = {'command': 'foo'}
|
||||
mock_cancellable_subprocess_call.return_value = 0
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
del self.p.config['wale']
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
|
||||
self.p.config['create_replica_method'] = ['basebackup']
|
||||
self.p.config['basebackup'] = [{'max_rate': '100M'}, 'no-sync']
|
||||
self.assertEquals(self.p.create_replica(self.leader), 0)
|
||||
|
||||
self.p.config['create_replica_method'] = ['wale', 'basebackup']
|
||||
del self.p.config['basebackup']
|
||||
mock_cancellable_subprocess_call.return_value = 1
|
||||
self.assertEquals(self.p.create_replica(self.leader), 1)
|
||||
|
||||
def test_basebackup(self):
|
||||
self.p.cancel()
|
||||
self.p.basebackup(None, None, {'foo': 'bar'})
|
||||
|
||||
Reference in New Issue
Block a user