blob: 00e40d258861a50334f793d9e7d5f15f8f7605fa [file] [log] [blame]
import argparse
import os
import sys
import traceback
from logging import DEBUG, INFO
from cfg_checker.common import config, logger, logger_cli
from cfg_checker.common.exception import CheckerException
pkg_dir = os.path.dirname(__file__)
pkg_dir = os.path.normpath(pkg_dir)
commands = {
'packages': ['report'],
'network': ['check', 'report'],
'reclass': ['list', 'diff']
}
class MyParser(argparse.ArgumentParser):
def error(self, message):
sys.stderr.write('Error: {0}\n\n'.format(message))
self.print_help()
def help_message():
print"""
Please, use following examples to generate info reports:\n
cfg_checker packages report\n
cfg_checker network check\n
cfg_checker network report\n
"""
return
def config_check_entrypoint():
"""
Main entry point. Uses nested parsers structure
with a default function to execute the comand
:return: - no return value
"""
# Main entrypoint
parser = MyParser(prog="# Mirantis Cloud configuration checker")
# Parsers (each parser can have own arguments)
# - subparsers (command)
# |- pkg_parser
# | - pkg_subparsers (type)
# | - pkg_report_parser (default func - pkg_check)
# |- net_parser
# | - net_subparsers (type)
# | - net_check_parser (default func - net_check)
# | - net_report_parser (default func - net_report)
# - reclass_parser
# - reclass_list (default func - reclass_list)
# - reclass_compare (default func - reclass_diff)
parser.add_argument(
"-d",
"--debug",
action="store_true", default=False,
help="Set CLI logging level to DEBUG"
)
parser.add_argument(
'-s',
'--sudo',
action='store_true', default=True,
help="Use sudo for getting salt creds"
)
subparsers = parser.add_subparsers(dest='command')
# packages
pkg_parser = subparsers.add_parser(
'packages',
help="Package versions check (Candidate vs Installed)"
)
pkg_subparsers = pkg_parser.add_subparsers(dest='type')
pkg_report_parser = pkg_subparsers.add_parser(
'report',
help="Report package versions to HTML file"
)
pkg_report_parser.add_argument(
'--full',
action="store_true", default=False,
help="HTML report will have all of the packages, not just errors"
)
pkg_report_parser.add_argument(
'--html',
metavar='packages_html_filename',
help="HTML filename to save report"
)
pkg_report_parser.add_argument(
'--csv',
metavar='packages_csv_filename',
help="CSV filename to save report"
)
# networking
net_parser = subparsers.add_parser(
'network',
help="Network infrastructure checks and reports"
)
net_subparsers = net_parser.add_subparsers(dest='type')
net_check_parser = net_subparsers.add_parser(
'check',
help="Do network check and print the result"
)
net_check_parser.add_argument(
'--detailed',
action="store_true", default=False,
help="Print error details after summary"
)
net_report_parser = net_subparsers.add_parser(
'report',
help="Generate network check report"
)
net_report_parser.add_argument(
'--html',
metavar='network_html_filename',
help="HTML filename to save report"
)
# reclass
reclass_parser = subparsers.add_parser(
'reclass',
help="Reclass related checks and reports"
)
reclass_subparsers = reclass_parser.add_subparsers(dest='type')
reclass_list_parser = reclass_subparsers.add_parser(
'list',
help="List models available to compare"
)
reclass_list_parser.add_argument(
"-p",
"--models-path",
default="/srv/salt/",
help="Global path to search models in"
)
reclass_diff_parser = reclass_subparsers.add_parser(
'diff',
help="List models available to compare"
)
reclass_diff_parser.add_argument(
"--model1",
required=True,
help="Model A <path>. Model name is the folder name"
)
reclass_diff_parser.add_argument(
"--model2",
required=True,
help="Model B <path>. Model name is the folder name"
)
reclass_diff_parser.add_argument(
'--html',
metavar='reclass_html_filename',
help="HTML filename to save report"
)
# parse arguments
try:
args = parser.parse_args()
except TypeError:
logger_cli.info("\n# Please, check arguments")
return
# Pass externally configured values
config.ssh_uses_sudo = args.sudo
# Handle options
if args.debug:
logger_cli.setLevel(DEBUG)
else:
logger_cli.setLevel(INFO)
# Validate the commands
# check command
if args.command not in commands:
logger_cli.info("\n# Please, type a command listed above")
return
elif args.type not in commands[args.command]:
# check type
logger_cli.info(
"\n# Please, select '{}' command type listed above".format(
args.command
)
)
return
else:
# form function name to call
_method_name = "do_" + args.type
_target_module = __import__(
"cfg_checker.modules."+args.command,
fromlist=[""]
)
_method = getattr(_target_module, _method_name)
# Execute the command
result = _method(args)
logger.debug(result)
def cli_main():
try:
config_check_entrypoint()
except CheckerException as e:
logger_cli.error("\nERROR: {}".format(
e.message
))
exc_type, exc_value, exc_traceback = sys.exc_info()
logger_cli.debug("\n{}".format(
"".join(traceback.format_exception(
exc_type,
exc_value,
exc_traceback
))
))
if __name__ == '__main__':
cli_main()