Skip to content

Commit a29a46e

Browse files
committed
Allow pgbackrest clone method to use a separate configuration
Cloning from the same repository as is used from backups is usually a bad idea. Also allow specification recovery target information. Patroni will remove recovery target settings created by pgbackrest restore.
1 parent 6a10475 commit a29a46e

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

bootstrap/clone_with_pgbackrest.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,50 @@ def read_configuration():
1717
parser.add_argument('--recovery-target-time',
1818
help='the timestamp up to which recovery will proceed (including time zone)',
1919
dest='recovery_target_time_string')
20-
parser.add_argument('--dry-run', action='store_true', help='find a matching backup and build the wal-e '
21-
'command to fetch that backup without running it')
20+
parser.add_argument('--config-include-path',
21+
help='pgbackrest configuration directory')
2222
args = parser.parse_args()
2323

24-
options = namedtuple('Options', 'name datadir recovery_target_time dry_run')
24+
options = namedtuple('Options', 'name datadir recovery_target_time config_include_path')
2525
if args.recovery_target_time_string:
2626
recovery_target_time = parse(args.recovery_target_time_string)
2727
if recovery_target_time.tzinfo is None:
2828
raise Exception("recovery target time must contain a timezone")
2929
else:
3030
recovery_target_time = None
3131

32-
return options(args.scope, args.datadir, recovery_target_time, args.dry_run)
32+
return options(args.scope, args.datadir, recovery_target_time, args.config_include_path)
3333

3434
def run_clone_from_pgbackrest(options):
3535
env = os.environ.copy()
3636

3737
pg_path_argument = "--pg1-path={0}".format(options.datadir)
3838

39+
pgbackrest_command = ['/usr/bin/pgbackrest', 'restore', '--stanza=db', pg_path_argument]
40+
41+
if options.config_include_path:
42+
pgbackrest_command.extend(['--config-include-path=' + options.config_include_path])
43+
3944
if options.recovery_target_time:
4045
target_time_argument = "--target={0}".format(options.recovery_target_time)
41-
pgbackrest_command = ['/usr/bin/pgbackrest', '--stanza=db', '--type=time', target_time_argument, 'restore', pg_path_argument]
42-
else:
43-
pgbackrest_command = ['/usr/bin/pgbackrest', '--stanza=db', 'restore', pg_path_argument]
46+
pgbackrest_command.extend(['--type=time', target_time_argument])
4447

4548
logger.info("cloning cluster %s using %s", options.name, ' '.join(pgbackrest_command))
4649

47-
if not options.dry_run:
48-
ret = subprocess.call(pgbackrest_command, env=env)
49-
if ret != 0:
50-
raise Exception("pgbackrest restore exited with exit code {0}".format(ret))
50+
ret = subprocess.call(pgbackrest_command, env=env)
51+
if ret != 0:
52+
logger.error("pgbackrest restore exited with exit code {0}".format(ret))
53+
return ret
5154

5255
return 0
5356

5457
def main():
55-
options = read_configuration()
5658
try:
59+
options = read_configuration()
5760
run_clone_from_pgbackrest(options)
5861
except Exception:
5962
logger.exception("Clone with pgbackrest failed")
6063
return 1
6164

6265
if __name__ == '__main__':
63-
sys.exit(main())
66+
sys.exit(main())

scripts/configure_spilo.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,24 @@ def deep_update(a, b):
251251
{{#CLONE_WITH_PGBACKREST}}
252252
method: clone_with_pgbackrest
253253
clone_with_pgbackrest:
254-
command: python3 /scripts/clone_with_pgbackrest.py
254+
command: python3 /scripts/clone_with_pgbackrest.py
255255
--recovery-target-time="{{CLONE_TARGET_TIME}}"
256+
--config-include-path="{{CLONE_PGBACKREST_CONFIG}}"
256257
recovery_conf:
257-
restore_command: pgbackrest --stanza=db archive-get %f "%p"
258+
restore_command: pgbackrest --config-include-path="{{CLONE_PGBACKREST_CONFIG}}" --stanza=db archive-get %f "%p"
259+
recovery_target_timeline: "{{CLONE_TARGET_TIMELINE}}"
260+
{{#USE_PAUSE_AT_RECOVERY_TARGET}}
261+
recovery_target_action: pause
262+
{{/USE_PAUSE_AT_RECOVERY_TARGET}}
263+
{{^USE_PAUSE_AT_RECOVERY_TARGET}}
264+
recovery_target_action: promote
265+
{{/USE_PAUSE_AT_RECOVERY_TARGET}}
266+
{{#CLONE_TARGET_TIME}}
267+
recovery_target_time: "{{CLONE_TARGET_TIME}}"
268+
{{/CLONE_TARGET_TIME}}
269+
{{^CLONE_TARGET_INCLUSIVE}}
270+
recovery_target_inclusive: false
271+
{{/CLONE_TARGET_INCLUSIVE}}
258272
{{/CLONE_WITH_PGBACKREST}}
259273
{{#CLONE_WITH_BASEBACKUP}}
260274
method: clone_with_basebackup
@@ -673,6 +687,9 @@ def get_placeholders(provider):
673687
else:
674688
logging.warning("Clone method is set to basebackup, but no 'CLONE_SCOPE' "
675689
"or 'CLONE_HOST' or 'CLONE_USER' or 'CLONE_PASSWORD' specified")
690+
elif placeholders['CLONE_METHOD'] == 'CLONE_WITH_PGBACKREST':
691+
placeholders['CLONE_WITH_PGBACKREST'] = True
692+
placeholders.setdefault('CLONE_PGBACKREST_CONFIG', '/etc/pgbackrest/clone-conf.d')
676693
else:
677694
if set_extended_wale_placeholders(placeholders, 'STANDBY_') == 'S3':
678695
placeholders.setdefault('STANDBY_USE_WALG', 'true')

0 commit comments

Comments
 (0)