Browse Source

When loading a configuration file that is unreadable due to file permissions, warn instead of erroring (#444).

Dan Helfman 3 years ago
parent
commit
976516d0e1
3 changed files with 26 additions and 0 deletions
  1. 3 0
      NEWS
  2. 14 0
      borgmatic/commands/borgmatic.py
  3. 9 0
      tests/unit/commands/test_borgmatic.py

+ 3 - 0
NEWS

@@ -1,5 +1,8 @@
 1.5.24.dev0
  * #431: Add "working_directory" option to support source directories with relative paths.
+ * #444: When loading a configuration file that is unreadable due to file permissions, warn instead
+   of erroring. This supports running borgmatic as a non-root user with configuration in ~/.config
+   even if there is an unreadable global configuration file in /etc.
  * #486: Fix handling of "patterns_from" and "exclude_from" options to error instead of warning when
    referencing unreadable files and "create" action is run.
  * #507: Fix Borg usage error in the "compact" action when running "borgmatic --dry-run". Now, skip

+ 14 - 0
borgmatic/commands/borgmatic.py

@@ -646,6 +646,20 @@ def load_configurations(config_filenames, overrides=None):
             configs[config_filename] = validate.parse_configuration(
                 config_filename, validate.schema_filename(), overrides
             )
+        except PermissionError:
+            logs.extend(
+                [
+                    logging.makeLogRecord(
+                        dict(
+                            levelno=logging.WARNING,
+                            levelname='WARNING',
+                            msg='{}: Insufficient permissions to read configuration file'.format(
+                                config_filename
+                            ),
+                        )
+                    ),
+                ]
+            )
         except (ValueError, OSError, validate.Validation_error) as error:
             logs.extend(
                 [

+ 9 - 0
tests/unit/commands/test_borgmatic.py

@@ -395,6 +395,15 @@ def test_load_configurations_collects_parsed_configurations():
     assert logs == []
 
 
+def test_load_configurations_logs_warning_for_permission_error():
+    flexmock(module.validate).should_receive('parse_configuration').and_raise(PermissionError)
+
+    configs, logs = tuple(module.load_configurations(('test.yaml',)))
+
+    assert configs == {}
+    assert {log.levelno for log in logs} == {logging.WARNING}
+
+
 def test_load_configurations_logs_critical_for_parse_error():
     flexmock(module.validate).should_receive('parse_configuration').and_raise(ValueError)