diff --git a/scripts/leappinspector/completion/_leapp-inspector b/scripts/leappinspector/completion/_leapp-inspector index 15873de..149647c 100644 --- a/scripts/leappinspector/completion/_leapp-inspector +++ b/scripts/leappinspector/completion/_leapp-inspector @@ -32,7 +32,7 @@ _leapp_inspector_phases_list() { _leapp_inspector_subcommands() { command -v leapp-inspector >/dev/null || { - _describe 'commands' (help actors messages executions interactive inspecion) + _describe 'commands' (help actors messages executions interactive inspecion config-data) return } @@ -126,6 +126,11 @@ _leapp_inspector_subcommands() { '(-h --help)'{-h,--help}'[show help message and exit]' \ "--paranoid[set inspection to the paranoid mode]" ;; + config-data) + _arguments \ + '(-h --help)'{-h,--help}'[show help message and exit]' \ + '(-f --format)'{-f,--format}'[output format to use]' \ + ;; *) _arguments \ '(-h --help)'{-h,--help}'[show help message and exit]' diff --git a/scripts/leappinspector/completion/leapp-inspector.bash b/scripts/leappinspector/completion/leapp-inspector.bash index 9b73e76..f77dc9b 100644 --- a/scripts/leappinspector/completion/leapp-inspector.bash +++ b/scripts/leappinspector/completion/leapp-inspector.bash @@ -2,7 +2,7 @@ _get_subcommands() { # if the leapp-inspector command is not available, return predefined # set of subcommands command -v leapp-inspector >/dev/null || { - echo help actors messages executions interactive inspecion + echo help actors messages executions interactive inspecion config-data return } leapp-inspector help \ @@ -204,6 +204,9 @@ _leapp_inspector_complete () { inspection) _handle_subcmd_inspection ;; + config-data) + COMPREPLY=( $(compgen -W "-h --help -f --format" -- "$cur") ) + ;; *) COMPREPLY=( $(compgen -W "-h --help" -- "$cur") ) ;; diff --git a/scripts/leappinspector/leapp-inspector b/scripts/leappinspector/leapp-inspector index 7bafa0e..7b091e3 100755 --- a/scripts/leappinspector/leapp-inspector +++ b/scripts/leappinspector/leapp-inspector @@ -2,13 +2,14 @@ import argparse import errno +import itertools import json import os import re import socket import sqlite3 import sys -import itertools +import yaml from collections.abc import Mapping, Iterable try: from json.decoder import JSONDecodeError @@ -21,8 +22,6 @@ except ImportError: # for Python2 (we do not want to make dependency on the six library) from ConfigParser import SafeConfigParser as ConfigParser -from pprint import pprint as pp - """ ============= DISCLAIMER ================== The code is not stabilized yet! Read: it's under heavy development! @@ -523,6 +522,29 @@ class LeappDatabase(Database): """ return self.get_messages(msg_type="Report") + def get_config_data(self): + """ + Get information about dialogs for the current context. + """ + if not self._user_version_satisfied(4): # configs introduced in ver 4 + return [] + + # The way this is implemented in the framework, at the time of this + # commit, there can be any TEXT put into actor_config_data.config. + # leapp-repository generally only puts there a JSON with a single top + # level "dict" with sections being the keys + cmd = ( + "SELECT acd.config FROM actor_config ac" + " JOIN actor_config_data acd ON ac.actor_config_hash = acd.hash" + " WHERE ac.context = '{context}'" + ).format(context=self._context) + + # The framework also doesn't ensure that the hash is computed from the + # config, let's return all the rows though, the caller can then warn if + # there are multiple for some reason + results = self.execute(cmd).fetchall() + + return [json.loads(row['config']) for row in results] class Color(object): reset = "\033[0m" if sys.stdout.isatty() else "" @@ -801,6 +823,15 @@ class LeappDataPrinter(LeappDatabase): return json_data return json.dumps(json_data, indent=4, sort_keys=True) + @staticmethod + def format_json_data(data, recursive=False): + """ + :param data: Data in JSON format + :param resursive: Whether to expand nested JSON strings in values + """ + # this is just a public wrapper of _fmt_msg_data to hide the stack argument + return LeappDataPrinter._fmt_msg_data(data, recursive) + @staticmethod def print_message(msg, recursive=False): for i in ("stamp", "actor", "phase", "type"): @@ -890,7 +921,7 @@ class LeappDataPrinter(LeappDatabase): return LeappDataPrinter.format_dict(ans) - def format_config(config): + def format_config_schema(config): config_fmt = [ ("Class", "class_name", "", None, False), ("Section", "section", "", None, False), @@ -902,12 +933,9 @@ class LeappDataPrinter(LeappDatabase): return LeappDataPrinter.format_dict(config, fmt=config_fmt) - def format_config(config): - return recursive_format_dict(config) - def format_config_schemas(t): if show_config: - return LeappDataPrinter.format_list(t, fmt=format_config, **list_style) + return LeappDataPrinter.format_list(t, fmt=format_config_schema, **list_style) return "[OPTIMIZED OUT]" @@ -928,7 +956,6 @@ class LeappDataPrinter(LeappDatabase): ("Phase", "phase", "", None, False), ("Tags", "tags", None, pretty_list, True), ("Config Schemas", "config_schemas", None, format_config_schemas, show_config), - ("Config", "config", None, format_config, True), ("Consumes", "consumes", None, pretty_list, True), ("Produces", "produces", None, pretty_list, True), ("Produced", "msgs", None, pretty_list, True), @@ -1507,6 +1534,38 @@ class ActorsCLI(SubCommandBaseClass): ) +class ConfigDataCLI(SubCommandBaseClass): + + name = "config-data" + help_short_str = "Print actor config data (not schemas)" + + def set_arguments(self): + self.subparser.add_argument( + "-f", + "--format", + dest="format", + default='json', + choices=("json", "yaml"), + help="output format to use", + ) + + def process(self): + self.LeappDataPrinter._print_header("Actor Configs Data") + configs = self.LeappDataPrinter.get_config_data() + if len(configs) > 1: + print("WARNING: Multiple entries found for the same config hash, possibly a bug?") + for config in configs: + if self.cmdline.format == 'json': + formatted = LeappDataPrinter.format_json_data(json.dumps(config), recursive=False) + print(formatted) + elif self.cmdline.format == 'yaml': + formatted = yaml.dump(config, sort_keys=False) + print(formatted) + else: + # shouldn't be allowed by arg parser + raise ValueError("Unexpected value for format: {}".format(self.cmdline.format)) + + class ExecutionsCLI(SubCommandBaseClass): name = "executions" @@ -1650,6 +1709,7 @@ def set_default_subcommands(cli): cli.add_subcommand(ExecutionsCLI) cli.add_subcommand(InteractiveCLI) cli.add_subcommand(InspectionCLI) + cli.add_subcommand(ConfigDataCLI) if __name__ == '__main__':