blob: 566a49848f44985bb3df0219e74eaa9816ae9e2b [file] [log] [blame]
Alexbab1efe2019-04-23 18:51:23 -05001import pkgutil
Alex265f45e2019-04-23 18:51:23 -05002import sys
3import traceback
4
Alex9a4ad212020-10-01 18:04:25 -05005from cfg_checker.cli.arguments import add_global_arguments
6from cfg_checker.common import logger, logger_cli
7from cfg_checker.common.exception import CheckerException, \
8 CommandNotSupportedException
9from cfg_checker.common.settings import CheckerConfiguration
Alexbab1efe2019-04-23 18:51:23 -050010from cfg_checker.helpers.args_utils import MyParser
Alex265f45e2019-04-23 18:51:23 -050011
Alexbab1efe2019-04-23 18:51:23 -050012main_pkg_name = __name__.split('.')[0]
13mods_package_name = "modules"
14mods_import_path = main_pkg_name + '.' + mods_package_name
15mods_prefix = mods_import_path + '.'
Alex265f45e2019-04-23 18:51:23 -050016
Alexbab1efe2019-04-23 18:51:23 -050017commands = {}
Alex9a4ad212020-10-01 18:04:25 -050018supports = {}
Alexac2a2732020-09-11 11:00:26 -050019parsers_inits = {}
Alexbab1efe2019-04-23 18:51:23 -050020parsers = {}
21helps = {}
22# Pure dynamic magic, loading all 'do_*' methods from available modules
23_m = __import__(mods_import_path, fromlist=[main_pkg_name])
24for _imp, modName, isMod in pkgutil.iter_modules(_m.__path__, mods_prefix):
25 # iterate all packages, add to dict
26 if isMod:
27 # load module
28 _p = _imp.find_module(modName).load_module(modName)
29 # create a shortname
30 mod_name = modName.split('.')[-1]
31 # A package! Create it and add commands
32 commands[mod_name] = \
33 [_n[3:] for _n in dir(_p) if _n.startswith("do_")]
Alex9a4ad212020-10-01 18:04:25 -050034 supports[mod_name] = _p.supported_envs
Alexac2a2732020-09-11 11:00:26 -050035 parsers_inits[mod_name] = getattr(_p, 'init_parser')
36 parsers[mod_name] = {}
Alexbab1efe2019-04-23 18:51:23 -050037 helps[mod_name] = getattr(_p, 'command_help')
Alex265f45e2019-04-23 18:51:23 -050038
39
Alex9a4ad212020-10-01 18:04:25 -050040def execute_command(args, command, config):
Alex265f45e2019-04-23 18:51:23 -050041 # Validate the commands
Alexcf91b182019-05-31 11:57:07 -050042 # check commands
Alexac2a2732020-09-11 11:00:26 -050043 if command not in commands:
Alexac2a2732020-09-11 11:00:26 -050044 logger_cli.info("\n# Please, type a command listed above")
45 return 1
Alexcf91b182019-05-31 11:57:07 -050046 if not hasattr(args, 'type') or not args.type:
Alexac2a2732020-09-11 11:00:26 -050047 parsers[command].print_help()
Alexcf91b182019-05-31 11:57:07 -050048 logger_cli.info("\n# Please, type a command listed above")
Alex3bc95f62020-03-05 17:00:04 -060049 return 1
Alexd0391d42019-05-21 18:48:55 -050050 _type = args.type.replace("-", "_") if "-" in args.type else args.type
Alexac2a2732020-09-11 11:00:26 -050051 if _type not in commands[command]:
Alex265f45e2019-04-23 18:51:23 -050052 # check type
53 logger_cli.info(
54 "\n# Please, select '{}' command type listed above".format(
55 command
56 )
57 )
Alex3bc95f62020-03-05 17:00:04 -060058 return 1
Alex265f45e2019-04-23 18:51:23 -050059 else:
Alex9a4ad212020-10-01 18:04:25 -050060 # check if command is supported
61 if len(
62 set(supports[command]).intersection(set(config.detected_envs))
63 ) < 1:
64 raise CommandNotSupportedException(
65 "'{}' is not supported on any of the currently "
66 "detected environments: {}".format(
67 command,
68 ",".join(config.detected_envs)
69 )
70 )
71 return 1
72
Alex265f45e2019-04-23 18:51:23 -050073 # form function name to call
Alexd0391d42019-05-21 18:48:55 -050074 _method_name = "do_" + _type
Alex265f45e2019-04-23 18:51:23 -050075 _target_module = __import__(
Alexbab1efe2019-04-23 18:51:23 -050076 mods_prefix + command,
Alex265f45e2019-04-23 18:51:23 -050077 fromlist=[""]
78 )
79 _method = getattr(_target_module, _method_name)
80
81 # Execute the command
82 try:
Alex9a4ad212020-10-01 18:04:25 -050083 # Compatibility between entrypoints
84 if not hasattr(args, 'command'):
85 args.command = command
86 _method(args, config)
Alex265f45e2019-04-23 18:51:23 -050087 return 0
Alex9a4ad212020-10-01 18:04:25 -050088 except CommandNotSupportedException as e:
89 logger_cli.error("\n{}".format(e.message))
90 return 1
Alex265f45e2019-04-23 18:51:23 -050091 except CheckerException as e:
Alex9a4ad212020-10-01 18:04:25 -050092 logger_cli.error("\n{}".format(e.message))
Alex265f45e2019-04-23 18:51:23 -050093
94 exc_type, exc_value, exc_traceback = sys.exc_info()
95 logger_cli.debug("\n{}".format(
96 "".join(traceback.format_exception(
97 exc_type,
98 exc_value,
99 exc_traceback
100 ))
101 ))
102 return 1
Alexbab1efe2019-04-23 18:51:23 -0500103
104
105def cli_command(_title, _name):
106 my_parser = MyParser(_title)
Alexac2a2732020-09-11 11:00:26 -0500107 parsers[_name] = parsers_inits[_name](my_parser)
Alexbab1efe2019-04-23 18:51:23 -0500108
109 # parse arguments
110 try:
Alex9a4ad212020-10-01 18:04:25 -0500111 add_global_arguments(my_parser)
Alexd0391d42019-05-21 18:48:55 -0500112 args, unknown = my_parser.parse_known_args()
Alexbab1efe2019-04-23 18:51:23 -0500113 except TypeError:
114 logger_cli.info("\n# Please, check arguments")
Alex3bc95f62020-03-05 17:00:04 -0600115 sys.exit(1)
Alexbab1efe2019-04-23 18:51:23 -0500116
Alexd0391d42019-05-21 18:48:55 -0500117 if unknown:
118 logger_cli.error(
119 "# Unexpected arguments: {}".format(
120 ", ".join(["'{}'".format(a) for a in unknown])
121 )
122 )
123 sys.exit(1)
124
Alex9a4ad212020-10-01 18:04:25 -0500125 # Init the config
126 config = CheckerConfiguration(args)
127
Alexbab1efe2019-04-23 18:51:23 -0500128 # force use of sudo
129 config.ssh_uses_sudo = True
130
131 # Execute the command
Alex9a4ad212020-10-01 18:04:25 -0500132 try:
133 result = execute_command(args, _name, config)
134 logger.debug(result)
135 except CommandNotSupportedException as e:
136 logger_cli.error("\nERROR: {}".format(
137 e.message
138 ))
Alexbab1efe2019-04-23 18:51:23 -0500139 sys.exit(result)