When writing config, make containing directory if necessary. Also default to tighter permissions.
This commit is contained in:
parent
f98558546c
commit
61f88228b0
4 changed files with 27 additions and 7 deletions
|
@ -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())
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -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)])
|
||||||
|
|
Loading…
Reference in a new issue