123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- import os
- import sys
- from io import StringIO
- import pytest
- from flexmock import flexmock
- from borgmatic.config import generate as module
- def test_insert_newline_before_comment_does_not_raise():
- field_name = 'foo'
- config = module.ruamel.yaml.comments.CommentedMap([(field_name, 33)])
- config.yaml_set_comment_before_after_key(key=field_name, before='Comment')
- module.insert_newline_before_comment(config, field_name)
- def test_schema_to_sample_configuration_comments_out_non_default_options():
- schema = {
- 'type': 'object',
- 'properties': dict(
- [
- ('field1', {'type': 'string', 'example': 'Example 1'}),
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ('source_directories', {'type': 'string', 'example': 'Example 3'}),
- ]
- ),
- }
- config = module.schema_to_sample_configuration(schema)
- assert config == dict(
- [
- ('field1', 'Example 1'),
- ('field2', 'Example 2'),
- ('source_directories', 'Example 3'),
- ]
- )
- assert 'COMMENT_OUT' in config.ca.items['field1'][1][-1]._value
- assert 'COMMENT_OUT' in config.ca.items['field2'][1][-1]._value
- assert 'source_directories' not in config.ca.items
- def test_schema_to_sample_configuration_comments_out_non_source_config_options():
- schema = {
- 'type': 'object',
- 'properties': dict(
- [
- ('field1', {'type': 'string', 'example': 'Example 1'}),
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ('field3', {'type': 'string', 'example': 'Example 3'}),
- ]
- ),
- }
- source_config = {'field3': 'value'}
- config = module.schema_to_sample_configuration(schema, source_config)
- assert config == dict(
- [
- ('field1', 'Example 1'),
- ('field2', 'Example 2'),
- ('field3', 'Example 3'),
- ]
- )
- assert 'COMMENT_OUT' in config.ca.items['field1'][1][-1]._value
- assert 'COMMENT_OUT' in config.ca.items['field2'][1][-1]._value
- assert 'field3' not in config.ca.items
- def test_schema_to_sample_configuration_comments_out_non_default_options_in_sequence_of_maps():
- schema = {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': dict(
- [
- ('field1', {'type': 'string', 'example': 'Example 1'}),
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ('source_directories', {'type': 'string', 'example': 'Example 3'}),
- ]
- ),
- },
- }
- config = module.schema_to_sample_configuration(schema)
- assert config == [
- dict(
- [('field1', 'Example 1'), ('field2', 'Example 2'), ('source_directories', 'Example 3')]
- )
- ]
- # The first field in a sequence does not get commented.
- assert 'field1' not in config[0].ca.items
- assert 'COMMENT_OUT' in config[0].ca.items['field2'][1][-1]._value
- assert 'source_directories' not in config[0].ca.items
- def test_schema_to_sample_configuration_comments_out_non_source_config_options_in_sequence_of_maps():
- schema = {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': dict(
- [
- ('field1', {'type': 'string', 'example': 'Example 1'}),
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ('field3', {'type': 'string', 'example': 'Example 3'}),
- ]
- ),
- },
- }
- source_config = [{'field3': 'value'}]
- config = module.schema_to_sample_configuration(schema, source_config)
- assert config == [
- dict([('field1', 'Example 1'), ('field2', 'Example 2'), ('field3', 'Example 3')])
- ]
- # The first field in a sequence does not get commented.
- assert 'field1' not in config[0].ca.items
- assert 'COMMENT_OUT' in config[0].ca.items['field2'][1][-1]._value
- assert 'field3' not in config[0].ca.items
- def test_schema_to_sample_configuration_comments_out_non_source_config_options_in_sequence_of_maps_with_different_subschemas():
- schema = {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'oneOf': [
- {
- 'properties': dict(
- [
- ('field1', {'type': 'string', 'example': 'Example 1'}),
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ]
- )
- },
- {
- 'properties': dict(
- [
- ('field2', {'type': 'string', 'example': 'Example 2'}),
- ('field3', {'type': 'string', 'example': 'Example 3'}),
- ]
- )
- },
- ],
- },
- }
- source_config = [{'field1': 'value'}, {'field3': 'value'}]
- config = module.schema_to_sample_configuration(schema, source_config)
- assert config == [
- dict([('field1', 'Example 1'), ('field2', 'Example 2'), ('field3', 'Example 3')])
- ]
- # The first field in a sequence does not get commented.
- assert 'field1' not in config[0].ca.items
- assert 'COMMENT_OUT' in config[0].ca.items['field2'][1][-1]._value
- assert 'COMMENT_OUT' in config[0].ca.items['field3'][1][-1]._value
- def test_comment_out_line_skips_blank_line():
- line = ' \n'
- assert module.comment_out_line(line) == line
- def test_comment_out_line_skips_already_commented_out_line():
- line = ' # foo'
- assert module.comment_out_line(line) == line
- def test_comment_out_line_comments_section_name():
- line = 'figgy-pudding:'
- assert module.comment_out_line(line) == '# ' + line
- def test_comment_out_line_comments_indented_option():
- line = ' enabled: true'
- assert module.comment_out_line(line) == ' # enabled: true'
- def test_comment_out_line_comments_twice_indented_option():
- line = ' - item'
- assert module.comment_out_line(line) == ' # - item'
- def test_comment_out_optional_configuration_comments_optional_config_only():
- # The "# COMMENT_OUT" comment is a sentinel used to express that the following key is optional.
- # It's stripped out of the final output.
- flexmock(module).comment_out_line = lambda line: '# ' + line
- config = '''
- # COMMENT_OUT
- foo:
- # COMMENT_OUT
- bar:
- - baz
- - quux
- repositories:
- - path: foo
- # COMMENT_OUT
- label: bar
- - path: baz
- label: quux
- # This comment should be kept.
- # COMMENT_OUT
- other: thing
- '''
- # flake8: noqa
- expected_config = '''
- # foo:
- # bar:
- # - baz
- # - quux
- repositories:
- - path: foo
- # label: bar
- - path: baz
- label: quux
- # This comment should be kept.
- # other: thing
- '''
- assert module.comment_out_optional_configuration(config.strip()) == expected_config.strip()
- def test_render_configuration_converts_configuration_to_yaml_string():
- yaml_string = module.render_configuration({'foo': 'bar'})
- assert yaml_string == 'foo: bar\n'
- def test_write_configuration_does_not_raise():
- flexmock(os.path).should_receive('exists').and_return(False)
- flexmock(os).should_receive('makedirs')
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').and_return(StringIO())
- flexmock(os).should_receive('chmod')
- module.write_configuration('config.yaml', 'config: yaml')
- def test_write_configuration_with_already_existing_file_raises():
- flexmock(os.path).should_receive('exists').and_return(True)
- with pytest.raises(FileExistsError):
- module.write_configuration('config.yaml', 'config: yaml')
- def test_write_configuration_with_already_existing_file_and_overwrite_does_not_raise():
- flexmock(os.path).should_receive('exists').and_return(True)
- module.write_configuration('/tmp/config.yaml', 'config: yaml', overwrite=True)
- def test_write_configuration_with_already_existing_directory_does_not_raise():
- flexmock(os.path).should_receive('exists').and_return(False)
- flexmock(os).should_receive('makedirs').and_raise(FileExistsError)
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').and_return(StringIO())
- flexmock(os).should_receive('chmod')
- module.write_configuration('config.yaml', 'config: yaml')
- def test_add_comments_to_configuration_sequence_of_strings_does_not_raise():
- config = module.ruamel.yaml.comments.CommentedSeq(['foo', 'bar'])
- schema = {'type': 'array', 'items': {'type': 'string'}}
- module.add_comments_to_configuration_sequence(config, schema)
- def test_add_comments_to_configuration_sequence_of_maps_does_not_raise():
- config = module.ruamel.yaml.comments.CommentedSeq(
- [module.ruamel.yaml.comments.CommentedMap([('foo', 'yo')])]
- )
- schema = {
- 'type': 'array',
- 'items': {'type': 'object', 'properties': {'foo': {'description': 'yo'}}},
- }
- module.add_comments_to_configuration_sequence(config, schema)
- def test_add_comments_to_configuration_sequence_of_maps_without_description_does_not_raise():
- config = module.ruamel.yaml.comments.CommentedSeq(
- [module.ruamel.yaml.comments.CommentedMap([('foo', 'yo')])]
- )
- schema = {'type': 'array', 'items': {'type': 'object', 'properties': {'foo': {}}}}
- module.add_comments_to_configuration_sequence(config, schema)
- def test_add_comments_to_configuration_comments_out_non_default_options():
- # Ensure that it can deal with fields both in the schema and missing from the schema.
- config = module.ruamel.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])
- schema = {
- 'type': 'object',
- 'properties': {'foo': {'description': 'Foo'}, 'bar': {'description': 'Bar'}},
- }
- module.add_comments_to_configuration_object(config, schema)
- assert 'COMMENT_OUT' in config.ca.items['foo'][1][-1]._value
- assert 'COMMENT_OUT' in config.ca.items['bar'][1][-1]._value
- assert 'baz' not in config.ca.items
- def test_add_comments_to_configuration_comments_out_non_source_config_options():
- # Ensure that it can deal with fields both in the schema and missing from the schema.
- config = module.ruamel.yaml.comments.CommentedMap(
- [('repositories', 33), ('bar', 44), ('baz', 55)]
- )
- schema = {
- 'type': 'object',
- 'properties': {
- 'repositories': {'description': 'repositories'},
- 'bar': {'description': 'Bar'},
- },
- }
- module.add_comments_to_configuration_object(config, schema)
- assert 'repositories' in config.ca.items
- assert 'COMMENT_OUT' in config.ca.items['bar'][1][-1]._value
- assert 'baz' not in config.ca.items
- def test_add_comments_to_configuration_object_with_skip_first_field_does_not_comment_out_first_option():
- config = module.ruamel.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])
- schema = {
- 'type': 'object',
- 'properties': {'foo': {'description': 'Foo'}, 'bar': {'description': 'Bar'}},
- }
- module.add_comments_to_configuration_object(config, schema, skip_first_field=True)
- assert 'foo' not in config.ca.items
- assert 'COMMENT_OUT' in config.ca.items['bar'][1][-1]._value
- assert 'baz' not in config.ca.items
- def test_add_comments_to_configuration_object_with_skip_first_field_does_not_comment_out_first_option():
- config = module.ruamel.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])
- schema = {
- 'type': 'object',
- 'properties': {'foo': {'description': 'Foo'}, 'bar': {'description': 'Bar'}},
- }
- module.add_comments_to_configuration_object(config, schema, skip_first_field=True)
- assert 'foo' not in config.ca.items
- assert 'COMMENT_OUT' in config.ca.items['bar'][1][-1]._value
- assert 'baz' not in config.ca.items
- def test_generate_sample_configuration_does_not_raise():
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').with_args('schema.yaml').and_return('')
- flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
- flexmock(load=lambda filename: {})
- )
- flexmock(module).should_receive('schema_to_sample_configuration')
- flexmock(module).should_receive('merge_source_configuration_into_destination')
- flexmock(module).should_receive('render_configuration')
- flexmock(module).should_receive('comment_out_optional_configuration')
- flexmock(module).should_receive('write_configuration')
- module.generate_sample_configuration(False, None, 'dest.yaml', 'schema.yaml')
- def test_generate_sample_configuration_with_source_filename_omits_empty_bootstrap_field():
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').with_args('schema.yaml').and_return('')
- flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
- flexmock(load=lambda filename: {})
- )
- flexmock(module.load).should_receive('load_configuration').and_return(
- {'bootstrap': {}, 'foo': 'bar'}
- )
- flexmock(module.normalize).should_receive('normalize')
- flexmock(module).should_receive('schema_to_sample_configuration').with_args(
- object, {'foo': 'bar'}
- ).once()
- flexmock(module).should_receive('merge_source_configuration_into_destination')
- flexmock(module).should_receive('render_configuration')
- flexmock(module).should_receive('comment_out_optional_configuration')
- flexmock(module).should_receive('write_configuration')
- module.generate_sample_configuration(False, 'source.yaml', 'dest.yaml', 'schema.yaml')
- def test_generate_sample_configuration_with_source_filename_keeps_non_empty_bootstrap_field():
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').with_args('schema.yaml').and_return('')
- flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
- flexmock(load=lambda filename: {})
- )
- source_config = {'bootstrap': {'stuff': 'here'}, 'foo': 'bar'}
- flexmock(module.load).should_receive('load_configuration').and_return(source_config)
- flexmock(module.normalize).should_receive('normalize')
- flexmock(module).should_receive('schema_to_sample_configuration').with_args(
- object, source_config
- ).once()
- flexmock(module).should_receive('merge_source_configuration_into_destination')
- flexmock(module).should_receive('render_configuration')
- flexmock(module).should_receive('comment_out_optional_configuration')
- flexmock(module).should_receive('write_configuration')
- module.generate_sample_configuration(False, 'source.yaml', 'dest.yaml', 'schema.yaml')
- def test_generate_sample_configuration_with_dry_run_does_not_write_file():
- builtins = flexmock(sys.modules['builtins'])
- builtins.should_receive('open').with_args('schema.yaml').and_return('')
- flexmock(module.ruamel.yaml).should_receive('YAML').and_return(
- flexmock(load=lambda filename: {})
- )
- flexmock(module).should_receive('schema_to_sample_configuration')
- flexmock(module).should_receive('merge_source_configuration_into_destination')
- flexmock(module).should_receive('render_configuration')
- flexmock(module).should_receive('comment_out_optional_configuration')
- flexmock(module).should_receive('write_configuration').never()
- module.generate_sample_configuration(True, None, 'dest.yaml', 'schema.yaml')
|