config-dump: Allow dumping config for multi compose

Clone the main config, all referenced parts and included variants or
comps files.

This requires a new argument: destination directory to which to write
the copied files.

JIRA: COMPOSE-3289
Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
Lubomír Sedlář 2019-05-21 15:25:35 +02:00
parent 33471c38bb
commit 217fcd6c02
1 changed files with 116 additions and 21 deletions

View File

@ -7,8 +7,11 @@ import argparse
import json import json
import os import os
import re import re
import shutil
import sys import sys
from six.moves import configparser
import kobo.conf import kobo.conf
import pungi.checks import pungi.checks
import pungi.util import pungi.util
@ -40,6 +43,93 @@ def validate_definition(value):
return value return value
def dump_multi_config(conf_file, dest, **kwargs):
"""Given a multi compose config, clone it and all referenced files to a
given directory.
"""
parser = configparser.RawConfigParser()
parser.read(conf_file)
pungi.util.makedirs(dest)
basedir = os.path.dirname(conf_file)
def copy_local_files(config):
"""Helper function called on all loaded Pungi configs that copies local
variants or comps files (unless specified by absolute path).
"""
for opt in "comps_file", "variants_file":
val = config.get(opt)
if isinstance(val, str) and val[0] != "/":
shutil.copy2(os.path.join(basedir, val), dest)
for section in parser.sections():
if section == "general":
continue
file_path = parser.get(section, "config")
dest_file = os.path.splitext(os.path.join(dest, file_path))[0] + ".json"
with open(dest_file, "w") as fh:
if not process_file(
[os.path.join(basedir, file_path)],
out=fh,
callback=copy_local_files,
**kwargs
):
return False
parser.set(section, "config", os.path.basename(dest_file))
with open(os.path.join(dest, os.path.basename(conf_file)), "w") as fh:
parser.write(fh)
return True
def process_file(
sources,
out=sys.stdout,
callback=None,
defines=None,
just_dump=False,
event=None,
offline=False,
):
"""Load Pungi config file, validate it, optionally resolve Git references,
and dump created JSON to a given stream.
:param callable callback: a callable to call with parsed config
:param dict defines: mapping of values to define before parsing the config
:param bool just_dump: skip validation and adding default values
:param int event: Koji event to hardcode into the config
:param bool offline: skip resolving Git references
:returns: False if validation failed, True otherwise
"""
conf = kobo.conf.PyConfigParser()
conf.load_from_dict(defines or {})
for source in sources:
load_source(source, conf)
if not just_dump:
errors, _ = pungi.checks.validate(conf, offline=offline)
if errors:
for error in errors:
print(error, file=sys.stderr)
return False
if event:
conf["koji_event"] = event
# Clean up defines from the final final config. We don't want to keep them
# as they would cause warnings during validation.
for key in defines:
del conf[key]
if callback:
callback(conf)
json.dump(conf, out, sort_keys=True, indent=4)
return True
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
@ -84,34 +174,39 @@ def main():
group.add_argument( group.add_argument(
"--offline", action="store_true", help="Do not resolve git references." "--offline", action="store_true", help="Do not resolve git references."
) )
parser.add_argument(
"--multi",
metavar="DIR",
help=(
"Treat source as config for pungi-orchestrate and store dump into "
"given directory."
),
)
args = parser.parse_args() args = parser.parse_args()
defines = dict(var.split("=", 1) for var in args.define) defines = dict(var.split("=", 1) for var in args.define)
conf = kobo.conf.PyConfigParser() if args.multi:
conf.load_from_dict(defines) if len(args.sources) > 1:
parser.error("Only one multi config can be specified.")
for source in args.sources: return dump_multi_config(
load_source(source, conf) args.sources[0],
dest=args.multi,
defines=defines,
just_dump=args.just_dump,
event=args.freeze_event,
offline=args.offline,
)
if not args.just_dump: return process_file(
errors, _ = pungi.checks.validate(conf, offline=args.offline) args.sources,
if errors: defines=defines,
for error in errors: just_dump=args.just_dump,
print(error, file=sys.stderr) event=args.freeze_event,
return False offline=args.offline,
)
if args.freeze_event:
conf["koji_event"] = args.freeze_event
# Clean up defines from the final final config. We don't want to keep them
# as they would cause warnings during validation.
for key in defines:
del conf[key]
json.dump(conf, sys.stdout, sort_keys=True, indent=4)
return True
if __name__ == "__main__": if __name__ == "__main__":