Add additional tests for PostgreSQL hook fixes (#678).

This commit is contained in:
Dan Helfman 2023-04-20 21:44:42 -07:00
parent da0f5a34f2
commit ee5c25f3bd
2 changed files with 119 additions and 8 deletions

5
NEWS
View file

@ -2,6 +2,11 @@
* #375: Restore particular PostgreSQL schemas from a database dump via "borgmatic restore --schema" * #375: Restore particular PostgreSQL schemas from a database dump via "borgmatic restore --schema"
flag. See the documentation for more information: flag. See the documentation for more information:
https://torsion.org/borgmatic/docs/how-to/backup-your-databases/#restore-particular-schemas https://torsion.org/borgmatic/docs/how-to/backup-your-databases/#restore-particular-schemas
* #678: Fix error from PostgreSQL when dumping a database with a "format" of "plain".
* #678: Fix PostgreSQL hook to support "psql_command" and "pg_restore_command" options containing
commands with arguments.
* #678: Fix calls to psql in PostgreSQL hook to ignore "~/.psqlrc", whose settings can break
database dumping.
* #684: Rename "master" development branch to "main" to use more inclusive language. You'll need to * #684: Rename "master" development branch to "main" to use more inclusive language. You'll need to
update your development checkouts accordingly. update your development checkouts accordingly.

View file

@ -76,7 +76,16 @@ def test_database_names_to_dump_with_all_and_format_lists_databases_with_hostnam
def test_database_names_to_dump_with_all_and_format_lists_databases_with_username(): def test_database_names_to_dump_with_all_and_format_lists_databases_with_username():
database = {'name': 'all', 'format': 'custom', 'username': 'postgres'} database = {'name': 'all', 'format': 'custom', 'username': 'postgres'}
flexmock(module).should_receive('execute_command_and_capture_output').with_args( flexmock(module).should_receive('execute_command_and_capture_output').with_args(
('psql', '--list', '--no-password', '--no-psqlrc', '--csv', '--tuples-only', '--username', 'postgres'), (
'psql',
'--list',
'--no-password',
'--no-psqlrc',
'--csv',
'--tuples-only',
'--username',
'postgres',
),
extra_environment=object, extra_environment=object,
).and_return('foo,test,\nbar,test,"stuff and such"') ).and_return('foo,test,\nbar,test,"stuff and such"')
@ -110,6 +119,28 @@ def test_database_names_to_dump_with_all_and_format_excludes_particular_database
) )
def test_database_names_to_dump_with_all_and_psql_command_uses_custom_command():
database = {'name': 'all', 'format': 'custom', 'psql_command': 'docker exec mycontainer psql'}
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
(
'docker',
'exec',
'mycontainer',
'psql',
'--list',
'--no-password',
'--no-psqlrc',
'--csv',
'--tuples-only',
),
extra_environment=object,
).and_return('foo,text').once()
assert module.database_names_to_dump(database, flexmock(), flexmock(), dry_run=False) == (
'foo',
)
def test_dump_databases_runs_pg_dump_for_each_database(): def test_dump_databases_runs_pg_dump_for_each_database():
databases = [{'name': 'foo'}, {'name': 'bar'}] databases = [{'name': 'foo'}, {'name': 'bar'}]
processes = [flexmock(), flexmock()] processes = [flexmock(), flexmock()]
@ -434,7 +465,16 @@ def test_restore_database_dump_runs_pg_restore():
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
flexmock(module).should_receive('execute_command').with_args( flexmock(module).should_receive('execute_command').with_args(
('psql', '--no-password', '--no-psqlrc', '--quiet', '--dbname', 'foo', '--command', 'ANALYZE'), (
'psql',
'--no-password',
'--no-psqlrc',
'--quiet',
'--dbname',
'foo',
'--command',
'ANALYZE',
),
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
@ -632,12 +672,45 @@ def test_restore_database_dump_runs_psql_for_all_database_dump():
) )
def test_restore_database_dump_runs_psql_for_plain_database_dump():
database_config = [{'name': 'foo', 'format': 'plain', 'schemas': None}]
extract_process = flexmock(stdout=flexmock())
flexmock(module).should_receive('make_extra_environment').and_return({'PGSSLMODE': 'disable'})
flexmock(module).should_receive('make_dump_path')
flexmock(module.dump).should_receive('make_database_dump_filename')
flexmock(module).should_receive('execute_command_with_processes').with_args(
('psql', '--no-password', '--no-psqlrc', '--set', 'ON_ERROR_STOP=on', '--dbname', 'foo'),
processes=[extract_process],
output_log_level=logging.DEBUG,
input_file=extract_process.stdout,
extra_environment={'PGSSLMODE': 'disable'},
).once()
flexmock(module).should_receive('execute_command').with_args(
(
'psql',
'--no-password',
'--no-psqlrc',
'--quiet',
'--dbname',
'foo',
'--command',
'ANALYZE',
),
extra_environment={'PGSSLMODE': 'disable'},
).once()
module.restore_database_dump(
database_config, 'test.yaml', {}, dry_run=False, extract_process=extract_process
)
def test_restore_database_dump_runs_non_default_pg_restore_and_psql(): def test_restore_database_dump_runs_non_default_pg_restore_and_psql():
database_config = [ database_config = [
{ {
'name': 'foo', 'name': 'foo',
'pg_restore_command': 'special_pg_restore', 'pg_restore_command': 'docker exec mycontainer pg_restore',
'psql_command': 'special_psql', 'psql_command': 'docker exec mycontainer psql',
'schemas': None, 'schemas': None,
} }
] ]
@ -648,7 +721,10 @@ def test_restore_database_dump_runs_non_default_pg_restore_and_psql():
flexmock(module.dump).should_receive('make_database_dump_filename') flexmock(module.dump).should_receive('make_database_dump_filename')
flexmock(module).should_receive('execute_command_with_processes').with_args( flexmock(module).should_receive('execute_command_with_processes').with_args(
( (
'special_pg_restore', 'docker',
'exec',
'mycontainer',
'pg_restore',
'--no-password', '--no-password',
'--if-exists', '--if-exists',
'--exit-on-error', '--exit-on-error',
@ -662,7 +738,19 @@ def test_restore_database_dump_runs_non_default_pg_restore_and_psql():
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
flexmock(module).should_receive('execute_command').with_args( flexmock(module).should_receive('execute_command').with_args(
('special_psql', '--no-password', '--no-psqlrc', '--quiet', '--dbname', 'foo', '--command', 'ANALYZE'), (
'docker',
'exec',
'mycontainer',
'psql',
'--no-password',
'--no-psqlrc',
'--quiet',
'--dbname',
'foo',
'--command',
'ANALYZE',
),
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
@ -707,7 +795,16 @@ def test_restore_database_dump_without_extract_process_restores_from_disk():
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
flexmock(module).should_receive('execute_command').with_args( flexmock(module).should_receive('execute_command').with_args(
('psql', '--no-password', '--no-psqlrc', '--quiet', '--dbname', 'foo', '--command', 'ANALYZE'), (
'psql',
'--no-password',
'--no-psqlrc',
'--quiet',
'--dbname',
'foo',
'--command',
'ANALYZE',
),
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
@ -743,7 +840,16 @@ def test_restore_database_dump_with_schemas_restores_schemas():
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()
flexmock(module).should_receive('execute_command').with_args( flexmock(module).should_receive('execute_command').with_args(
('psql', '--no-password', '--quiet', '--dbname', 'foo', '--command', 'ANALYZE'), (
'psql',
'--no-password',
'--no-psqlrc',
'--quiet',
'--dbname',
'foo',
'--command',
'ANALYZE',
),
extra_environment={'PGSSLMODE': 'disable'}, extra_environment={'PGSSLMODE': 'disable'},
).once() ).once()