convert.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import os
  2. from ruamel import yaml
  3. from borgmatic.config import generate
  4. def _convert_section(source_section_config, section_schema):
  5. '''
  6. Given a legacy Parsed_config instance for a single section, convert it to its corresponding
  7. yaml.comments.CommentedMap representation in preparation for actual serialization to YAML.
  8. Where integer types exist in the given section schema, convert their values to integers.
  9. '''
  10. destination_section_config = yaml.comments.CommentedMap(
  11. [
  12. (
  13. option_name,
  14. int(option_value)
  15. if section_schema['properties'].get(option_name, {}).get('type') == 'integer'
  16. else option_value,
  17. )
  18. for option_name, option_value in source_section_config.items()
  19. ]
  20. )
  21. return destination_section_config
  22. def convert_legacy_parsed_config(source_config, source_excludes, schema):
  23. '''
  24. Given a legacy Parsed_config instance loaded from an INI-style config file and a list of exclude
  25. patterns, convert them to a corresponding yaml.comments.CommentedMap representation in
  26. preparation for serialization to a single YAML config file.
  27. Additionally, use the given schema as a source of helpful comments to include within the
  28. returned CommentedMap.
  29. '''
  30. destination_config = yaml.comments.CommentedMap(
  31. [
  32. (section_name, _convert_section(section_config, schema['properties'][section_name]))
  33. for section_name, section_config in source_config._asdict().items()
  34. ]
  35. )
  36. # Split space-separated values into actual lists, make "repository" into a list, and merge in
  37. # excludes.
  38. location = destination_config['location']
  39. location['source_directories'] = source_config.location['source_directories'].split(' ')
  40. location['repositories'] = [location.pop('repository')]
  41. location['exclude_patterns'] = source_excludes
  42. if source_config.consistency.get('checks'):
  43. destination_config['consistency']['checks'] = source_config.consistency['checks'].split(' ')
  44. # Add comments to each section, and then add comments to the fields in each section.
  45. generate.add_comments_to_configuration_object(destination_config, schema)
  46. for section_name, section_config in destination_config.items():
  47. generate.add_comments_to_configuration_object(
  48. section_config, schema['properties'][section_name], indent=generate.INDENT
  49. )
  50. return destination_config
  51. class Legacy_configuration_not_upgraded(FileNotFoundError):
  52. def __init__(self):
  53. super(Legacy_configuration_not_upgraded, self).__init__(
  54. '''borgmatic changed its configuration file format in version 1.1.0 from INI-style
  55. to YAML. This better supports validation, and has a more natural way to express
  56. lists of values. To upgrade your existing configuration, run:
  57. sudo upgrade-borgmatic-config
  58. That will generate a new YAML configuration file at /etc/borgmatic/config.yaml
  59. (by default) using the values from both your existing configuration and excludes
  60. files. The new version of borgmatic will consume the YAML configuration file
  61. instead of the old one.'''
  62. )
  63. def guard_configuration_upgraded(source_config_filename, destination_config_filenames):
  64. '''
  65. If legacy source configuration exists but no destination upgraded configs do, raise
  66. Legacy_configuration_not_upgraded.
  67. The idea is that we want to alert the user about upgrading their config if they haven't already.
  68. '''
  69. destination_config_exists = any(
  70. os.path.exists(filename) for filename in destination_config_filenames
  71. )
  72. if os.path.exists(source_config_filename) and not destination_config_exists:
  73. raise Legacy_configuration_not_upgraded()