Merging multiple include files leads to validation error #380

Closed
opened 2020-12-08 12:32:38 +00:00 by jefferyto · 4 comments
Contributor

What I'm trying to do and why

My config files are split into multiple includes (as a consequence of working around #281). I'm also using includes to isolate passphrases from config files (so that only the passphrase include files need to be restricted to root access only). So I am trying to merge two include files under storage.

Steps to reproduce (if a bug)

  1. Set up a config file with something like:

    storage:
        <<: !include /etc/borgmatic.d/common/storage.yaml
        <<: !include /etc/borgamtic.d/passphrases/secret.yaml
    
  2. Run validate-borgmatic-config.

Actual behavior (if a bug)

validate-borgmatic-config returns an error:

Traceback (most recent call last):
  File "/usr/bin/validate-borgmatic-config", line 11, in <module>
    load_entry_point('borgmatic==1.5.1', 'console_scripts', 'validate-borgmatic-config')()
  File "/usr/lib/python3/dist-packages/borgmatic/commands/validate_config.py", line 45, in main
    validate.parse_configuration(config_filename, validate.schema_filename())
  File "/usr/lib/python3/dist-packages/borgmatic/config/validate.py", line 101, in parse_configuration
    config = load.load_configuration(config_filename)
  File "/usr/lib/python3/dist-packages/borgmatic/config/load.py", line 20, in load_configuration
    return yaml.load(open(filename))
  File "/usr/lib/python3/dist-packages/ruamel/yaml/main.py", line 348, in load
    return constructor.get_single_data()
  File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 113, in get_single_data
    return self.construct_document(node)
  File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 123, in construct_document
    for _dummy in generator:
  File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 723, in construct_yaml_map
    value = self.construct_mapping(node)
  File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 439, in construct_mapping
    self.flatten_mapping(node)
  File "/usr/lib/python3/dist-packages/borgmatic/config/load.py", line 59, in flatten_mapping
    super(Include_constructor, self).flatten_mapping(node)
  File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 396, in flatten_mapping
    raise DuplicateKeyError(*args)
ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping
  in "/etc/borgmatic.d/example.yaml", line 8, column 5
found duplicate key "<<"
  in "/etc/borgmatic.d/example.yaml", line 9, column 5

To suppress this check see:
   http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys

Duplicate keys will become an error in future releases, and are errors
by default when using the new API.

Expected behavior (if a bug)

I can merge multiple include files.

Other notes / implementation ideas

I've tried multiple plain !include includes, and mixing one !include and one <<: !include, but none of these validate either.

Environment

borgmatic version: 1.5.1

borgmatic installation method: Ubuntu package

Borg version: 1.1.14

Python version: 3.8.6

Database version (if applicable): N/A

operating system and version: Ubuntu 20.10

#### What I'm trying to do and why My config files are split into multiple includes (as a consequence of working around #281). I'm also using includes to isolate passphrases from config files (so that only the passphrase include files need to be restricted to root access only). So I am trying to merge two include files under `storage`. #### Steps to reproduce (if a bug) 1. Set up a config file with something like: ```yaml storage: <<: !include /etc/borgmatic.d/common/storage.yaml <<: !include /etc/borgamtic.d/passphrases/secret.yaml ``` 2. Run `validate-borgmatic-config`. #### Actual behavior (if a bug) `validate-borgmatic-config` returns an error: ``` Traceback (most recent call last): File "/usr/bin/validate-borgmatic-config", line 11, in <module> load_entry_point('borgmatic==1.5.1', 'console_scripts', 'validate-borgmatic-config')() File "/usr/lib/python3/dist-packages/borgmatic/commands/validate_config.py", line 45, in main validate.parse_configuration(config_filename, validate.schema_filename()) File "/usr/lib/python3/dist-packages/borgmatic/config/validate.py", line 101, in parse_configuration config = load.load_configuration(config_filename) File "/usr/lib/python3/dist-packages/borgmatic/config/load.py", line 20, in load_configuration return yaml.load(open(filename)) File "/usr/lib/python3/dist-packages/ruamel/yaml/main.py", line 348, in load return constructor.get_single_data() File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 113, in get_single_data return self.construct_document(node) File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 123, in construct_document for _dummy in generator: File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 723, in construct_yaml_map value = self.construct_mapping(node) File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 439, in construct_mapping self.flatten_mapping(node) File "/usr/lib/python3/dist-packages/borgmatic/config/load.py", line 59, in flatten_mapping super(Include_constructor, self).flatten_mapping(node) File "/usr/lib/python3/dist-packages/ruamel/yaml/constructor.py", line 396, in flatten_mapping raise DuplicateKeyError(*args) ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping in "/etc/borgmatic.d/example.yaml", line 8, column 5 found duplicate key "<<" in "/etc/borgmatic.d/example.yaml", line 9, column 5 To suppress this check see: http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys Duplicate keys will become an error in future releases, and are errors by default when using the new API. ``` #### Expected behavior (if a bug) I can merge multiple include files. #### Other notes / implementation ideas I've tried multiple plain `!include` includes, and mixing one `!include` and one `<<: !include`, but none of these validate either. #### Environment **borgmatic version:** 1.5.1 **borgmatic installation method:** Ubuntu package **Borg version:** 1.1.14 **Python version:** 3.8.6 **Database version (if applicable):** N/A **operating system and version:** Ubuntu 20.10
Owner

Sorry for the lengthy delay here. I think this behavior is a limitation of the YAML parsing library borgmatic uses—and possibly of YAML itself.

However, with #381 (deep merging) now implemented in master, it's possible that you'll be able to get rid of all of your per-section includes and move those to a common include for the whole file. Example:

<<: !include /etc/borgmatic.d/common/common.yaml

storage:
    <<: !include /etc/borgamtic.d/passphrases/secret.yaml

Does that seem like it'd work for your use case?

Sorry for the lengthy delay here. I think this behavior is a limitation of the YAML parsing library borgmatic uses—and possibly of YAML itself. However, with #381 (deep merging) now implemented in master, it's possible that you'll be able to get rid of all of your per-section includes and move those to a common include for the whole file. Example: ``` <<: !include /etc/borgmatic.d/common/common.yaml storage: <<: !include /etc/borgamtic.d/passphrases/secret.yaml ``` Does that seem like it'd work for your use case?
Owner

Closing for now given the work-around, but please feel free to re-open if you have additional follow-up. Thanks!

Closing for now given the work-around, but please feel free to re-open if you have additional follow-up. Thanks!
Author
Contributor

Apologies for the late reply. I haven't tried the new deep merging includes yet so I'm not sure how it interacts with other includes (my setup is more complicated than the given example).

I don't mind keeping this issue closed, though as an end user I still find it unintuitive that only one include is allowed per section.

Apologies for the late reply. I haven't tried the new deep merging includes yet so I'm not sure how it interacts with other includes (my setup is more complicated than the given example). I don't mind keeping this issue closed, though as an end user I still find it unintuitive that only one include is allowed per section.
Owner

I agree.. I'll try to document this limitation better! And feel free to reopen this ticket if the deep merging doesn't end up working for your use case.

I agree.. I'll try to document this limitation better! And feel free to reopen this ticket if the deep merging doesn't end up working for your use case.
Sign in to join this conversation.
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
borgmatic-collective/borgmatic#380
No description provided.