From dbc1b810f1175b3f0e09997067f3a222fb889c8b Mon Sep 17 00:00:00 2001 From: Inessa Vasilevskaya Date: Tue, 11 Feb 2020 18:21:32 +0100 Subject: [PATCH] answerfile: introduce answerfile.userchoices Introduced a persistent between userchoices file that will serve as a knowledge db for registered user options for a specific dialog. To register a persistent user choice you can use leapp answer command. Existing answerfile will be always updated with data from useroptions file before the workflow.run is called to ensure that users are not asked twice for the answer to the question they have already answered. Docs have been updated. Closes-Bug: https://github.com/oamg/leapp/issues/605 Closes-Bug: https://github.com/oamg/leapp/issues/606 --- docs/source/dialogs.md | 10 ++++++---- leapp/cli/upgrade/__init__.py | 22 ++++++++++++---------- leapp/config.py | 1 + 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/source/dialogs.md b/docs/source/dialogs.md index 23ae86c1c..b59f512c3 100644 --- a/docs/source/dialogs.md +++ b/docs/source/dialogs.md @@ -80,10 +80,12 @@ about potential issues is generated. If an actor containing dialog is discover d message is added to the preupgrade report file saying that for the successful upgrade the operator should record their decision in the answerfile. -As far as the dialogs are concerned, leapp remediate stage is intended specifically for answerfile management. The operator has the option to manually edit -the answerfile with editor of choice or use `leapp answer` command to fill the answerfile (usually located at -/var/log/leapp/answerfile) with choices for the discovered dialogs. After modifying the answerfile you can check -system upgradeability by rerunning leapp preupgrade. +As far as the dialogs are concerned, leapp remediate stage is intended specifically for answerfile management. +The operator has the option to manually edit the answerfile with editor of choice or use `leapp answer` command to +persistently save user options for the discovered dialogs. Choices registered with leapp answer command will have +highest priority and will override any information stored in answerfile. +After modifying the answerfile and\or registering options via leapp answer command system upgradeability can be +checked by rerunning leapp preupgrade. Leapp upgrade stage should be run only when leapp preupgrade successfully passes. In case any unanswered/bad choice dialogs are encountered the upgrade process will stop and the report file will be generated telling the operator what diff --git a/leapp/cli/upgrade/__init__.py b/leapp/cli/upgrade/__init__.py index 4f89c579f..a6ad7a34d 100644 --- a/leapp/cli/upgrade/__init__.py +++ b/leapp/cli/upgrade/__init__.py @@ -189,6 +189,7 @@ def upgrade(args): cfg = get_config() configuration = prepare_configuration(args) answerfile_path = cfg.get('report', 'answerfile') + userchoices_path = cfg.get('report', 'userchoices') if os.getuid(): raise CommandError('This command has to be run under the root user.') @@ -227,6 +228,7 @@ def upgrade(args): with beautify_actor_exception(): logger.info("Using answerfile at %s", answerfile_path) workflow.load_answerfile(answerfile_path) + workflow.load_answerfile(userchoices_path) workflow.run(context=context, skip_phases_until=skip_phases_until, skip_dialogs=True) report_errors(workflow.errors) @@ -249,6 +251,7 @@ def preupgrade(args): cfg = get_config() configuration = prepare_configuration(args) answerfile_path = cfg.get('report', 'answerfile') + userchoices_path = cfg.get('report', 'userchoices') if os.getuid(): raise CommandError('This command has to be run under the root user.') @@ -268,6 +271,7 @@ def preupgrade(args): process_whitelist_experimental(repositories, workflow, configuration, logger) with beautify_actor_exception(): workflow.load_answerfile(answerfile_path) + workflow.load_answerfile(userchoices_path) until_phase = 'ReportsPhase' logger.info('Executing workflow until phase: %s', until_phase) workflow.run(context=context, until_phase=until_phase, skip_dialogs=True) @@ -283,14 +287,13 @@ def preupgrade(args): sys.exit(1) -@command('answer', help='Manage answerfile: register user choices for specific dialog sections') -@command_opt('answerfile', help='Path to the answerfile to update') +@command('answer', help='Manage answerfile generation: register persistent user choices for specific dialog sections') @command_opt('section', action='append', metavar='dialog_sections', help='Register answer for a specific section in the answerfile') -@command_opt('add', is_flag=True, - help='If set sections will be created even if missing in original answerfile') def answer(args): - """A command to manage answerfile. Updates answerfile with userchoices""" + """A command to record user choices to the questions in the answerfile. + Saves user answer between leapp preupgrade runs. + """ cfg = get_config() if args.section: args.section = list(itertools.chain(*[i.split(',') for i in args.section])) @@ -301,15 +304,14 @@ def answer(args): for dialog_option, value in [s.split('=', 2) for s in args.section]] except ValueError: raise UsageError("A bad formatted section has been passed. Expected format is dialog.option=mychoice") - answerfile_path = args.answerfile or cfg.get('report', 'answerfile') + answerfile_path = cfg.get('report', 'answerfile') + userchoices_path = cfg.get('report', 'userchoices') answerstore = AnswerStore() answerstore.load(answerfile_path) + answerstore.load(userchoices_path) for dialog, option, value in sections: answerstore.answer(dialog, option, value) - not_updated = answerstore.update(answerfile_path, allow_missing=args.add) - if not_updated: - sys.stderr.write("WARNING: Only sections found in original userfile can be updated, ignoring {}\n".format( - ",".join(not_updated))) + answerstore.update(userchoices_path, allow_missing=True) @command('list-runs', help='List previous Leapp upgrade executions') diff --git a/leapp/config.py b/leapp/config.py index 8757dbe72..a13ff89f1 100644 --- a/leapp/config.py +++ b/leapp/config.py @@ -48,6 +48,7 @@ 'dir': '/var/log/leapp/', 'files': ','.join(_REPORTS), 'answerfile': '/var/log/leapp/answerfile', + 'userchoices': '/var/log/leapp/answerfile.userchoices' }, 'repositories': { 'repo_path': '.',