When writing config, make containing directory if necessary. Also default to tighter permissions.

This commit is contained in:
Dan Helfman 2017-07-10 15:20:50 -07:00
parent f98558546c
commit 61f88228b0
4 changed files with 27 additions and 7 deletions

View file

@ -42,7 +42,7 @@ def parse_arguments(*arguments):
def main(): # pragma: no cover def main(): # pragma: no cover
try: try:
# TODO: Detect whether only legacy config is present. If so, inform the user about how to # TODO: Detect whether only legacy config is present. If so, inform the user about how to
# upgrade, then exet. # upgrade, then exit.
args = parse_arguments(*sys.argv[1:]) args = parse_arguments(*sys.argv[1:])
config = parse_configuration(args.config_filename, schema_filename()) config = parse_configuration(args.config_filename, schema_filename())

View file

@ -87,8 +87,11 @@ def main(): # pragma: no cover
destination_config = convert.convert_legacy_parsed_config(source_config, source_excludes, schema) destination_config = convert.convert_legacy_parsed_config(source_config, source_excludes, schema)
generate.write_configuration(args.destination_config_filename, destination_config) generate.write_configuration(
os.chmod(args.destination_config_filename, source_config_file_mode) args.destination_config_filename,
destination_config,
mode=source_config_file_mode,
)
# TODO: As a backstop, check that the written config can actually be read and parsed, and # TODO: As a backstop, check that the written config can actually be read and parsed, and
# that it matches the destination config data structure that was written. # that it matches the destination config data structure that was written.

View file

@ -40,17 +40,24 @@ def _schema_to_sample_configuration(schema, level=0):
return config return config
def write_configuration(config_filename, config): def write_configuration(config_filename, config, mode=0o600):
''' '''
Given a target config filename and a config data structure of nested OrderedDicts, write out the Given a target config filename and a config data structure of nested OrderedDicts, write out the
config to file as YAML. config to file as YAML. Create any containing directories as needed.
''' '''
if os.path.exists(config_filename): if os.path.exists(config_filename):
raise FileExistsError('{} already exists. Aborting.'.format(config_filename)) raise FileExistsError('{} already exists. Aborting.'.format(config_filename))
try:
os.makedirs(os.path.dirname(config_filename), mode=0o700)
except FileExistsError:
pass
with open(config_filename, 'w') as config_file: with open(config_filename, 'w') as config_file:
config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT)) config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT))
os.chmod(config_filename, mode)
def add_comments_to_configuration(config, schema, indent=0): def add_comments_to_configuration(config, schema, indent=0):
''' '''

View file

@ -18,21 +18,31 @@ def test_insert_newline_before_comment_does_not_raise():
def test_write_configuration_does_not_raise(): def test_write_configuration_does_not_raise():
flexmock(os.path).should_receive('exists').and_return(False) flexmock(os.path).should_receive('exists').and_return(False)
flexmock(os).should_receive('makedirs')
builtins = flexmock(sys.modules['builtins']) builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').and_return(StringIO()) builtins.should_receive('open').and_return(StringIO())
flexmock(os).should_receive('chmod')
module.write_configuration('config.yaml', {}) module.write_configuration('config.yaml', {})
def test_write_configuration_with_already_existing_file_raises(): def test_write_configuration_with_already_existing_file_raises():
flexmock(os.path).should_receive('exists').and_return(True) flexmock(os.path).should_receive('exists').and_return(True)
builtins = flexmock(sys.modules['builtins'])
builtins.should_receive('open').and_return(StringIO())
with pytest.raises(FileExistsError): with pytest.raises(FileExistsError):
module.write_configuration('config.yaml', {}) module.write_configuration('config.yaml', {})
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', {})
def test_add_comments_to_configuration_does_not_raise(): def test_add_comments_to_configuration_does_not_raise():
# Ensure that it can deal with fields both in the schema and missing from the schema. # Ensure that it can deal with fields both in the schema and missing from the schema.
config = module.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)]) config = module.yaml.comments.CommentedMap([('foo', 33), ('bar', 44), ('baz', 55)])