From 2ee75546f5f81f4a6289f8a3c0ffcf5309a450bf Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Tue, 4 Jan 2022 16:26:38 -0800 Subject: [PATCH] Add MongoDB database hook documentation. --- NEWS | 1 + README.md | 2 +- borgmatic/config/schema.yaml | 13 ++++++------- borgmatic/hooks/mongodb.py | 8 ++++---- docs/how-to/backup-your-databases.md | 28 ++++++++++++++++++++------- docs/static/mongodb.png | Bin 0 -> 12839 bytes docs/static/rsyncnet.png | Bin 7493 -> 0 bytes tests/end-to-end/test_database.py | 2 +- tests/unit/hooks/test_mongodb.py | 16 +++++++++++++-- 9 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 docs/static/mongodb.png delete mode 100644 docs/static/rsyncnet.png 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 0000000000000000000000000000000000000000..81118d9b15899a56b3f2d8e289545d06995d77b2 GIT binary patch literal 12839 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 literal 0 HcmV?d00001 diff --git a/docs/static/rsyncnet.png b/docs/static/rsyncnet.png deleted file mode 100644 index 3c027be10e5ad0abd89e893ea417efe87acb644b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7493 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