瀏覽代碼

When running the "rcreate" action and the repository already exists but with a different encryption mode than requested, error (#840).

Dan Helfman 1 年之前
父節點
當前提交
a08c7fc77a
共有 3 個文件被更改,包括 48 次插入9 次删除
  1. 2 0
      NEWS
  2. 22 8
      borgmatic/borg/rcreate.py
  3. 24 1
      tests/unit/borg/test_rcreate.py

+ 2 - 0
NEWS

@@ -12,6 +12,8 @@
    https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#apprise-hook
  * #839: Document a potentially breaking shell quoting edge case within error hooks:
    https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#error-hooks
+ * #840: When running the "rcreate" action and the repository already exists but with a different
+   encryption mode than requested, error.
  * Switch from Drone to Gitea Actions for continuous integration.
  * Rename scripts/run-end-to-end-dev-tests to scripts/run-end-to-end-tests and use it in both dev
    and CI for better dev-CI parity.

+ 22 - 8
borgmatic/borg/rcreate.py

@@ -1,4 +1,5 @@
 import argparse
+import json
 import logging
 import subprocess
 
@@ -31,17 +32,30 @@ def create_repository(
     version, a Borg encryption mode, the path to another repo whose key material should be reused,
     whether the repository should be append-only, and the storage quota to use, create the
     repository. If the repository already exists, then log and skip creation.
+
+    Raise ValueError if the requested encryption mode does not match that of the repository.
+    Raise json.decoder.JSONDecodeError if the "borg info" JSON outputcannot be decoded.
+    Raise subprocess.CalledProcessError if "borg info" returns an error exit code.
     '''
     try:
-        rinfo.display_repository_info(
-            repository_path,
-            config,
-            local_borg_version,
-            argparse.Namespace(json=True),
-            global_arguments,
-            local_path,
-            remote_path,
+        info_data = json.loads(
+            rinfo.display_repository_info(
+                repository_path,
+                config,
+                local_borg_version,
+                argparse.Namespace(json=True),
+                global_arguments,
+                local_path,
+                remote_path,
+            )
         )
+        repository_encryption_mode = info_data.get('encryption', {}).get('mode')
+
+        if repository_encryption_mode != encryption_mode:
+            raise ValueError(
+                f'Requested encryption mode "{encryption_mode}" does not match existing repository encryption mode "{repository_encryption_mode}"'
+            )
+
         logger.info(f'{repository_path}: Repository already exists. Skipping creation.')
         return
     except subprocess.CalledProcessError as error:

+ 24 - 1
tests/unit/borg/test_rcreate.py

@@ -13,7 +13,9 @@ RCREATE_COMMAND = ('borg', 'rcreate', '--encryption', 'repokey')
 
 
 def insert_rinfo_command_found_mock():
-    flexmock(module.rinfo).should_receive('display_repository_info')
+    flexmock(module.rinfo).should_receive('display_repository_info').and_return(
+        '{"encryption": {"mode": "repokey"}}'
+    )
 
 
 def insert_rinfo_command_not_found_mock():
@@ -120,6 +122,27 @@ def test_create_repository_skips_creation_when_repository_already_exists():
     )
 
 
+def test_create_repository_errors_when_repository_with_differing_encryption_mode_already_exists():
+    insert_rinfo_command_found_mock()
+    flexmock(module.feature).should_receive('available').and_return(True)
+    flexmock(module.flags).should_receive('make_repository_flags').and_return(
+        (
+            '--repo',
+            'repo',
+        )
+    )
+
+    with pytest.raises(ValueError):
+        module.create_repository(
+            dry_run=False,
+            repository_path='repo',
+            config={},
+            local_borg_version='2.3.4',
+            global_arguments=flexmock(log_json=False),
+            encryption_mode='repokey-blake2',
+        )
+
+
 def test_create_repository_raises_for_unknown_rinfo_command_error():
     flexmock(module.rinfo).should_receive('display_repository_info').and_raise(
         subprocess.CalledProcessError(RINFO_SOME_UNKNOWN_EXIT_CODE, [])