diff --git a/NEWS b/NEWS index f4278c0b0..96663dae5 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ 1.5.22.dev0 + * #288: Database dump hooks for MongoDB. * #470: Move mysqldump options to the beginning of the command due to MySQL bug 30994. * #471: When command-line configuration override produces a parse error, error cleanly instead of tracebacking. diff --git a/README.md b/README.md index 9a37cfc2c..3d282dcfd 100644 --- a/README.md +++ b/README.md @@ -65,11 +65,11 @@ borgmatic is powered by [Borg Backup](https://www.borgbackup.org/). PostgreSQL      MySQL      MariaDB      +MongoDB      Healthchecks      Cronitor      Cronhub      PagerDuty      -rsync.net      BorgBase      diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index c211da47c..8b747a72b 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -798,7 +798,7 @@ properties: port: type: integer description: Port to connect to. Defaults to 27017. - example: 27017 + example: 27018 username: type: string description: | @@ -811,15 +811,14 @@ properties: Password with which to connect to the database. Skip it if no authentication is needed. example: trustsome1 - auth_db: + authentication_database: type: string description: | Authentication database where the specified - username has been created. - If no authentication database is specified, - the databse provided in "name" will be used. - If "name" is "all", the "admin" database will - be used. + username exists. If no authentication database + is specified, the database provided in "name" + is used. If "name" is "all", the "admin" + database is used. example: admin format: type: string diff --git a/borgmatic/hooks/mongodb.py b/borgmatic/hooks/mongodb.py index e06fd026f..feb4955d6 100644 --- a/borgmatic/hooks/mongodb.py +++ b/borgmatic/hooks/mongodb.py @@ -72,8 +72,8 @@ def build_dump_command(database, dump_filename, dump_format): command.extend(('--username', database['username'])) if 'password' in database: command.extend(('--password', database['password'])) - if 'auth_db' in database: - command.extend(('--authenticationDatabase', database['auth_db'])) + if 'authentication_database' in database: + command.extend(('--authenticationDatabase', database['authentication_database'])) if not all_databases: command.extend(('--db', database['name'])) if 'options' in database: @@ -157,6 +157,6 @@ def build_restore_command(extract_process, database, dump_filename): command.extend(('--username', database['username'])) if 'password' in database: command.extend(('--password', database['password'])) - if 'auth_db' in database: - command.extend(('--authenticationDatabase', database['auth_db'])) + if 'authentication_database' in database: + command.extend(('--authenticationDatabase', database['authentication_database'])) return command diff --git a/docs/how-to/backup-your-databases.md b/docs/how-to/backup-your-databases.md index 19fa23d30..7eca0c626 100644 --- a/docs/how-to/backup-your-databases.md +++ b/docs/how-to/backup-your-databases.md @@ -15,7 +15,8 @@ consistent snapshot that is more suited for backups. Fortunately, borgmatic includes built-in support for creating database dumps prior to running backups. For example, here is everything you need to dump and -backup a couple of local PostgreSQL databases and a MySQL/MariaDB database: +backup a couple of local PostgreSQL databases, a MySQL/MariaDB database, and a +MongoDB database: ```yaml hooks: @@ -24,12 +25,15 @@ hooks: - name: orders mysql_databases: - name: posts + mongodb_databases: + - name: messages ``` As part of each backup, borgmatic streams a database dump for each configured database directly to Borg, so it's included in the backup without consuming -additional disk space. (The one exception is PostgreSQL's "directory" dump -format, which can't stream and therefore does consume temporary disk space.) +additional disk space. (The exceptions are the PostgreSQL/MongoDB "directory" +dump formats, which can't stream and therefore do consume temporary disk +space.) To support this, borgmatic creates temporary named pipes in `~/.borgmatic` by default. To customize this path, set the `borgmatic_source_directory` option @@ -59,6 +63,14 @@ hooks: username: root password: trustsome1 options: "--skip-comments" + mongodb_databases: + - name: messages + hostname: database3.example.org + port: 27018 + username: dbuser + password: trustsome1 + authentication_database: mongousers + options: "--ssl" ``` If you want to dump all databases on a host, use `all` for the database name: @@ -69,13 +81,15 @@ hooks: - name: all mysql_databases: - name: all + mongodb_databases: + - name: all ``` Note that you may need to use a `username` of the `postgres` superuser for this to work with PostgreSQL. If you would like to backup databases only and not source directories, you can -specify an empty `source_directories` value because it is a mandatory field: +specify an empty `source_directories` value (as it is a mandatory field): ```yaml location: @@ -97,7 +111,7 @@ bring back any missing configuration files in order to restore a database. ## Supported databases -As of now, borgmatic supports PostgreSQL and MySQL/MariaDB databases +As of now, borgmatic supports PostgreSQL, MySQL/MariaDB, and MongoDB databases directly. But see below about general-purpose preparation and cleanup hooks as a work-around with other database systems. Also, please [file a ticket](https://torsion.org/borgmatic/#issues) for additional database systems @@ -196,8 +210,8 @@ that may not be exhaustive. If you prefer to restore a database without the help of borgmatic, first [extract](https://torsion.org/borgmatic/docs/how-to/extract-a-backup/) an archive containing a database dump, and then manually restore the dump file -found within the extracted `~/.borgmatic/` path (e.g. with `pg_restore` or -`mysql` commands). +found within the extracted `~/.borgmatic/` path (e.g. with `pg_restore`, +`mysql`, or `mongorestore`, commands). ## Preparation and cleanup hooks diff --git a/docs/static/mongodb.png b/docs/static/mongodb.png new file mode 100644 index 000000000..81118d9b1 Binary files /dev/null and b/docs/static/mongodb.png differ diff --git a/docs/static/rsyncnet.png b/docs/static/rsyncnet.png deleted file mode 100644 index 3c027be10..000000000 Binary files a/docs/static/rsyncnet.png and /dev/null differ diff --git a/tests/end-to-end/test_database.py b/tests/end-to-end/test_database.py index 57e4219c4..c7f6366df 100644 --- a/tests/end-to-end/test_database.py +++ b/tests/end-to-end/test_database.py @@ -52,7 +52,7 @@ hooks: hostname: mongodb username: root password: test - auth_db: admin + authentication_database: admin - name: all hostname: mongodb username: root diff --git a/tests/unit/hooks/test_mongodb.py b/tests/unit/hooks/test_mongodb.py index 377962e41..cc4ae4c4f 100644 --- a/tests/unit/hooks/test_mongodb.py +++ b/tests/unit/hooks/test_mongodb.py @@ -67,7 +67,14 @@ def test_dump_databases_runs_mongodump_with_hostname_and_port(): def test_dump_databases_runs_mongodump_with_username_and_password(): - databases = [{'name': 'foo', 'username': 'mongo', 'password': 'trustsome1', 'auth_db': "admin"}] + databases = [ + { + 'name': 'foo', + 'username': 'mongo', + 'password': 'trustsome1', + 'authentication_database': "admin", + } + ] process = flexmock() flexmock(module).should_receive('make_dump_path').and_return('') flexmock(module.dump).should_receive('make_database_dump_filename').and_return( @@ -216,7 +223,12 @@ def test_restore_database_dump_runs_pg_restore_with_hostname_and_port(): def test_restore_database_dump_runs_pg_restore_with_username_and_password(): database_config = [ - {'name': 'foo', 'username': 'mongo', 'password': 'trustsome1', 'auth_db': 'admin'} + { + 'name': 'foo', + 'username': 'mongo', + 'password': 'trustsome1', + 'authentication_database': 'admin', + } ] extract_process = flexmock(stdout=flexmock())