Browse Source

code review

Divyansh Singh 2 years ago
parent
commit
903507bd03

+ 9 - 9
borgmatic/config/schema.yaml

@@ -938,24 +938,24 @@ properties:
                     required: ['path','name']
                     required: ['path','name']
                     additionalProperties: false
                     additionalProperties: false
                     properties:
                     properties:
+                        name:
+                            type: string
+                            description: |
+                                This is used to tag the database dump file 
+                                with a name. It is not the path to the database 
+                                file itself. The name "all" has no special 
+                                meaning for SQLite databases.
+                            example: users
                         path:
                         path:
                             type: string
                             type: string
                             description: |
                             description: |
                                 Path to the SQLite database file to dump. If
                                 Path to the SQLite database file to dump. If
                                 relative, it is relative to the current working
                                 relative, it is relative to the current working
-                                directory. If absolute, it is relative to the
-                                root of the filesystem. Note that using this
+                                directory. Note that using this
                                 database hook implicitly enables both
                                 database hook implicitly enables both
                                 read_special and one_file_system (see above) to
                                 read_special and one_file_system (see above) to
                                 support dump and restore streaming.
                                 support dump and restore streaming.
                             example: /var/lib/sqlite/users.db
                             example: /var/lib/sqlite/users.db
-                        name:
-                            type: string
-                            description: |
-                                This is used to tag the database dump file with
-                                a name. It is not used to identify the database
-                                file itself.
-                            example: users
             mongodb_databases:
             mongodb_databases:
                 type: array
                 type: array
                 items:
                 items:

+ 7 - 9
borgmatic/hooks/sqlite.py

@@ -17,7 +17,7 @@ def make_dump_path(location_config):  # pragma: no cover
     )
     )
 
 
 
 
-def dump_databases(databases, log_prefix, location_config, dry_run):  # pragma: no cover
+def dump_databases(databases, log_prefix, location_config, dry_run):
     '''
     '''
     Dump the given SQLite3 databases to a file. The databases are supplied as a sequence of
     Dump the given SQLite3 databases to a file. The databases are supplied as a sequence of
     configuration dicts, as per the configuration schema. Use the given log prefix in any log
     configuration dicts, as per the configuration schema. Use the given log prefix in any log
@@ -29,11 +29,13 @@ def dump_databases(databases, log_prefix, location_config, dry_run):  # pragma:
 
 
     logger.info('{}: Dumping SQLite databases{}'.format(log_prefix, dry_run_label))
     logger.info('{}: Dumping SQLite databases{}'.format(log_prefix, dry_run_label))
 
 
+    if databases[0]['name'] == 'all':
+        logger.warning('The "all" database name has no meaning for SQLite3 databases')
+
     for database in databases:
     for database in databases:
         database_path = database['path']
         database_path = database['path']
-        database_filename = database['name']
         dump_path = make_dump_path(location_config)
         dump_path = make_dump_path(location_config)
-        dump_filename = dump.make_database_dump_filename(dump_path, database_filename)
+        dump_filename = dump.make_database_dump_filename(dump_path, database['name'])
         if os.path.exists(dump_filename):
         if os.path.exists(dump_filename):
             logger.warning(
             logger.warning(
                 f'{log_prefix}: Skipping duplicate dump of SQLite database at {database_path} to {dump_filename}'
                 f'{log_prefix}: Skipping duplicate dump of SQLite database at {database_path} to {dump_filename}'
@@ -98,13 +100,9 @@ def restore_database_dump(database_config, log_prefix, location_config, dry_run,
     if dry_run:
     if dry_run:
         return
         return
 
 
-    remove_command = (
-        'rm',
-        database_path,
-    )
     try:
     try:
-        execute_command(remove_command, shell=True)
-    except CalledProcessError:
+        execute_command(('rm', database_path), shell=True)
+    except CalledProcessError:  # pragma: no cover
         logger.info(f'{log_prefix}: Database does not exist at {database_path}, skipping removal')
         logger.info(f'{log_prefix}: Database does not exist at {database_path}, skipping removal')
 
 
     restore_command = (
     restore_command = (

+ 4 - 5
docs/how-to/backup-your-databases.md

@@ -28,8 +28,8 @@ hooks:
     mongodb_databases:
     mongodb_databases:
         - name: messages
         - name: messages
     sqlite_databases:
     sqlite_databases:
-        - path: /var/lib/sqlite3/mydb.sqlite
         - name: mydb
         - name: mydb
+          path: /var/lib/sqlite3/mydb.sqlite          
 ```
 ```
 
 
 As part of each backup, borgmatic streams a database dump for each configured
 As part of each backup, borgmatic streams a database dump for each configured
@@ -78,8 +78,8 @@ hooks:
           authentication_database: mongousers
           authentication_database: mongousers
           options: "--ssl"
           options: "--ssl"
     sqlite_databases:
     sqlite_databases:
-        - path: /var/lib/sqlite3/mydb.sqlite
         - name: mydb
         - name: mydb
+          path: /var/lib/sqlite3/mydb.sqlite
 ```
 ```
 
 
 See your [borgmatic configuration
 See your [borgmatic configuration
@@ -103,8 +103,7 @@ hooks:
 ```
 ```
 
 
 Note that you may need to use a `username` of the `postgres` superuser for
 Note that you may need to use a `username` of the `postgres` superuser for
-this to work with PostgreSQL. Also, the `all` database name is not supported
-for SQLite databases.
+this to work with PostgreSQL.
 
 
 <span class="minilink minilink-addedin">New in version 1.7.6</span> With
 <span class="minilink minilink-addedin">New in version 1.7.6</span> With
 PostgreSQL and MySQL, you can optionally dump "all" databases to separate
 PostgreSQL and MySQL, you can optionally dump "all" databases to separate
@@ -161,7 +160,7 @@ bring back any missing configuration files in order to restore a database.
 
 
 ## Supported databases
 ## Supported databases
 
 
-As of now, borgmatic supports PostgreSQL, MySQL/MariaDB, MongoDB databases and SQLite databases
+As of now, borgmatic supports PostgreSQL, MySQL/MariaDB, MongoDB and SQLite databases
 directly. But see below about general-purpose preparation and cleanup hooks as
 directly. But see below about general-purpose preparation and cleanup hooks as
 a work-around with other database systems. Also, please [file a
 a work-around with other database systems. Also, please [file a
 ticket](https://torsion.org/borgmatic/#issues) for additional database systems
 ticket](https://torsion.org/borgmatic/#issues) for additional database systems

+ 30 - 16
tests/unit/hooks/test_sqlite.py

@@ -10,12 +10,10 @@ def test_dump_databases_logs_and_skips_if_dump_already_exists():
     databases = [{'path': '/path/to/database', 'name': 'database'}]
     databases = [{'path': '/path/to/database', 'name': 'database'}]
 
 
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
-    flexmock(module).should_receive('dump.make_database_dump_filename').and_return(
+    flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
         '/path/to/dump/database'
         '/path/to/dump/database'
     )
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
     flexmock(module.os.path).should_receive('exists').and_return(True)
-    flexmock(logging).should_receive('info')
-    flexmock(logging).should_receive('warning')
 
 
     assert module.dump_databases(databases, 'test.yaml', {}, dry_run=False) == []
     assert module.dump_databases(databases, 'test.yaml', {}, dry_run=False) == []
 
 
@@ -25,34 +23,49 @@ def test_dump_databases_dumps_each_database():
         {'path': '/path/to/database1', 'name': 'database1'},
         {'path': '/path/to/database1', 'name': 'database1'},
         {'path': '/path/to/database2', 'name': 'database2'},
         {'path': '/path/to/database2', 'name': 'database2'},
     ]
     ]
+    processes = [flexmock(), flexmock()]
 
 
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
-    flexmock(module).should_receive('dump.make_database_dump_filename').and_return(
+    flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
         '/path/to/dump/database'
         '/path/to/dump/database'
     )
     )
     flexmock(module.os.path).should_receive('exists').and_return(False)
     flexmock(module.os.path).should_receive('exists').and_return(False)
-    flexmock(logging).should_receive('info')
-    flexmock(logging).should_receive('warning')
-    flexmock(module).should_receive('dump.create_parent_directory_for_dump')
-    flexmock(module).should_receive('execute_command').and_return('process')
+    flexmock(module.dump).should_receive('create_parent_directory_for_dump')
+    flexmock(module).should_receive('execute_command').and_return(processes[0]).and_return(
+        processes[1]
+    )
+
+    assert module.dump_databases(databases, 'test.yaml', {}, dry_run=False) == processes
 
 
-    assert module.dump_databases(databases, 'test.yaml', {}, dry_run=False) == [
-        'process',
-        'process',
+
+def test_dumping_database_with_name_all_warns_and_dumps_all_databases():
+    databases = [
+        {'path': '/path/to/database1', 'name': 'all'},
     ]
     ]
+    processes = [flexmock()]
+
+    flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
+    flexmock(logging).should_receive('warning')
+    flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
+        '/path/to/dump/database'
+    )
+    flexmock(module.os.path).should_receive('exists').and_return(False)
+    flexmock(module.dump).should_receive('create_parent_directory_for_dump')
+    flexmock(module).should_receive('execute_command').and_return(processes[0])
+
+    assert module.dump_databases(databases, 'test.yaml', {}, dry_run=False) == processes
 
 
 
 
 def test_dump_databases_does_not_dump_if_dry_run():
 def test_dump_databases_does_not_dump_if_dry_run():
     databases = [{'path': '/path/to/database', 'name': 'database'}]
     databases = [{'path': '/path/to/database', 'name': 'database'}]
 
 
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
     flexmock(module).should_receive('make_dump_path').and_return('/path/to/dump')
-    flexmock(module).should_receive('dump.make_database_dump_filename').and_return(
+    flexmock(module.dump).should_receive('make_database_dump_filename').and_return(
         '/path/to/dump/database'
         '/path/to/dump/database'
     )
     )
     flexmock(module.os.path).should_receive('exists').and_return(False)
     flexmock(module.os.path).should_receive('exists').and_return(False)
-    flexmock(logging).should_receive('info')
-    flexmock(logging).should_receive('warning')
-    flexmock(module).should_receive('dump.create_parent_directory_for_dump')
+    flexmock(module.dump).should_receive('create_parent_directory_for_dump').never()
+    flexmock(module).should_receive('execute_command').never()
 
 
     assert module.dump_databases(databases, 'test.yaml', {}, dry_run=True) == []
     assert module.dump_databases(databases, 'test.yaml', {}, dry_run=True) == []
 
 
@@ -61,7 +74,8 @@ def test_restore_database_dump_restores_database():
     database_config = [{'path': '/path/to/database', 'name': 'database'}]
     database_config = [{'path': '/path/to/database', 'name': 'database'}]
     extract_process = flexmock(stdout=flexmock())
     extract_process = flexmock(stdout=flexmock())
 
 
-    flexmock(module).should_receive('execute_command_with_processes').and_return('process')
+    flexmock(module).should_receive('execute_command_with_processes').once()
+    flexmock(module).should_receive('execute_command').once()
 
 
     module.restore_database_dump(
     module.restore_database_dump(
         database_config, 'test.yaml', {}, dry_run=False, extract_process=extract_process
         database_config, 'test.yaml', {}, dry_run=False, extract_process=extract_process