Module refactoring and dynamic loading
diff --git a/cfg_checker/cfg_check.py b/cfg_checker/cfg_check.py
index b8243ff..a0df7e6 100644
--- a/cfg_checker/cfg_check.py
+++ b/cfg_checker/cfg_check.py
@@ -5,15 +5,9 @@
 
 from logging import INFO,  DEBUG
 
-import reporter
+from cfg_checker.common.exception import CheckerException
+from cfg_checker.common import config, logger, logger_cli
 
-from cfg_checker.common.exception import CheckerException, ConfigException
-from cfg_checker.common import utils, const
-from cfg_checker.common import config, logger, logger_cli, pkg_dir
-
-import cfg_checker.reclass_cmp as reclass_cmp
-from cfg_checker.pkg_check import CloudPackageChecker
-from cfg_checker.network_checks import NetworkChecker
 
 pkg_dir = os.path.dirname(__file__)
 pkg_dir = os.path.normpath(pkg_dir)
@@ -40,150 +34,6 @@
     return
 
 
-def get_file_arg(args):
-    if args.file:
-        return args.file
-    else:
-        raise ConfigException("No report filename supplied")
-
-
-def get_path_arg(path):
-    if os.path.exists(path):
-        return path
-    else:
-        raise ConfigException("'{}' not exists".format(path))
-
-
-def validate_model(path):
-    logger_cli.debug("\t...validating '{}' as a model".format(path))
-    _checks = []
-    _is_folder = os.path.isdir(path)
-    logger_cli.debug("\t- folder? -> {}".format(_is_folder))
-    _checks.append(_is_folder)
-    _has_classes = os.path.isdir(os.path.join(path, "classes"))
-    logger_cli.debug("\t- has classes? -> {}".format(_has_classes))
-    _checks.append(_has_classes)
-    _has_cluster = os.path.isdir(os.path.join(path, "classes", "cluster"))
-    logger_cli.debug("\t- has classes/cluster? -> {}".format(_has_cluster))
-    _checks.append(_has_cluster)
-    _has_system = os.path.isdir(os.path.join(path, "classes", "system"))
-    logger_cli.debug("\t- has classes/system? -> {}".format(_has_system))
-    _checks.append(_has_system)
-    _has_nodes = os.path.isdir(os.path.join(path, "nodes"))
-    logger_cli.debug("\t- has nodes? -> {}".format(_has_nodes))
-    _checks.append(_has_nodes)
-    
-    logger_cli.debug("\t-> {}".format(
-        all(_checks)
-    ))
-
-    return all(_checks)
-
-
-def packages_report(args):
-    """Create package versions report
-
-    :args: - parser arguments
-    :return: - no return value
-    """
-    _filename = get_file_arg(args)
-
-    # init connection to salt and collect minion data
-    pChecker = CloudPackageChecker()
-    # collect data on installed packages
-    pChecker.collect_installed_packages()
-    # diff installed and candidates
-    # pChecker.collect_packages()
-    # report it
-    pChecker.create_html_report(_filename)
-
-
-def network_check(args):
-    logger_cli.info("# Network check (CLI output)")
-    netChecker = NetworkChecker()
-    netChecker.collect_network_info()
-    netChecker.print_network_report()
-
-    return
-
-
-def network_report(args):
-    logger_cli.info("# Network check (HTML report: '{}')".format(args.file))
-    _filename = get_file_arg(args)
-
-    netChecker = NetworkChecker()
-    netChecker.collect_network_info()
-    netChecker.create_html_report(_filename)
-
-    return
-
-
-def reclass_list(args):
-    logger_cli.info("# Reclass list")
-    _path = get_path_arg(args.models_path)
-    
-    logger_cli.info("# ...models path is '{}'".format(args.models_path))
-    
-    models = {}
-    for _folder in os.listdir(args.models_path):
-        # validate item as a model
-        _model_path = os.path.join(
-            args.models_path,
-            _folder
-        )
-        _validated = validate_model(_model_path)
-        
-        if not _validated:
-            logger_cli.info("-> '{}' not a valid model".format(_folder))
-            continue
-        else:
-            models[_folder] = _model_path
-        
-        logger_cli.info("-> '{}' at '{}'".format(_folder, _model_path))
-        
-        # TODO: collect info about the model
-
-    return
-
-
-def reclass_diff(args):
-    logger_cli.info("Reclass comparer (HTML report: '{}'".format(args.file))
-    _filename = get_file_arg(args)
-
-    # checking folder params
-    _model1 = get_path_arg(args.model1)
-    _model2 = get_path_arg(args.model2)
-    
-    # Do actual compare using hardcoded model names
-    mComparer = reclass_cmp.ModelComparer()
-
-    mComparer.model_name_1 = os.path.split(_model1)[1]
-    mComparer.model_path_1 = _model1
-    mComparer.model_name_2 = os.path.split(_model2)[1]
-    mComparer.model_path_2 = _model2
-    
-    mComparer.load_model_tree(
-        mComparer.model_name_1,
-        mComparer.model_path_1
-    )
-    mComparer.load_model_tree(
-        mComparer.model_name_2,
-        mComparer.model_path_2
-    )
-
-    diffs = mComparer.generate_model_report_tree()
-
-    report = reporter.ReportToFile(
-        reporter.HTMLModelCompare(),
-        _filename
-    )
-    logger_cli.info("# Generating report to {}".format(_filename))
-    report({
-        "nodes": {},
-        "diffs": diffs
-    })
-
-
 def config_check_entrypoint():
     """
     Main entry point. Uses nested parsers structure 
@@ -291,7 +141,7 @@
     try:
         args = parser.parse_args()
     except TypeError as e:
-        logger_cli.info("\nPlease, check arguments")
+        logger_cli.info("\n# Please, check arguments")
         return
 
     # Pass externally configured values
@@ -306,21 +156,21 @@
     # Validate the commands
     # check command
     if args.command not in commands:
-        logger_cli.info("\nPlease, type a command listed above")
+        logger_cli.info("\n# Please, type a command listed above")
         return
     elif args.type not in commands[args.command]:
         # check type
         logger_cli.info(
-            "\nPlease, select '{}' command type listed above".format(
+            "\n# Please, select '{}' command type listed above".format(
                 args.command
             )
         )
         return
     else:
         # form function name to call
-        _method_name = args.command + "_" + args.type
-        _this_module = sys.modules[__name__]
-        _method = getattr(_this_module, _method_name)
+        _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)
diff --git a/cfg_checker/cli/__init__.py b/cfg_checker/cli/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cfg_checker/cli/__init__.py
diff --git a/cfg_checker/cli/network.py b/cfg_checker/cli/network.py
new file mode 100644
index 0000000..f70c410
--- /dev/null
+++ b/cfg_checker/cli/network.py
@@ -0,0 +1,14 @@
+from cfg_checker.network.checker import NetworkChecker
+
+if __name__ == '__main__':
+    # init connection to salt and collect minion data
+    cl = NetworkChecker()
+
+    # collect data on installed packages
+    cl.collect_network_info()
+
+    # diff installed and candidates
+    # cl.collect_packages()
+
+    # report it
+    cl.create_html_report("./pkg_versions.html")
diff --git a/cfg_checker/cli/package.py b/cfg_checker/cli/package.py
new file mode 100644
index 0000000..3119385
--- /dev/null
+++ b/cfg_checker/cli/package.py
@@ -0,0 +1,15 @@
+from cfg_checker.packages.checker import CloudPackageChecker
+
+
+if __name__ == '__main__':
+    # init connection to salt and collect minion data
+    cl = CloudPackageChecker()
+
+    # collect data on installed packages
+    cl.collect_installed_packages()
+
+    # diff installed and candidates
+    # cl.collect_packages()
+
+    # report it
+    cl.create_html_report("./pkg_versions.html")
diff --git a/cfg_checker/cli/reclass.py b/cfg_checker/cli/reclass.py
new file mode 100644
index 0000000..41b863d
--- /dev/null
+++ b/cfg_checker/cli/reclass.py
@@ -0,0 +1,6 @@
+from cfg_checker.reclass.comparer import ModelComparer
+
+if __name__ == "__main__":
+    # Execute the comparison using argv params
+
+    pass
diff --git a/cfg_checker/helpers/__init__.py b/cfg_checker/helpers/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cfg_checker/helpers/__init__.py
diff --git a/cfg_checker/helpers/args_utils.py b/cfg_checker/helpers/args_utils.py
new file mode 100644
index 0000000..d7b694d
--- /dev/null
+++ b/cfg_checker/helpers/args_utils.py
@@ -0,0 +1,17 @@
+import os
+
+from cfg_checker.common.exception import ConfigException
+
+
+def get_file_arg(args):
+    if args.file:
+        return args.file
+    else:
+        raise ConfigException("No report filename supplied")
+
+
+def get_path_arg(path):
+    if os.path.exists(path):
+        return path
+    else:
+        raise ConfigException("'{}' not exists".format(path))
diff --git a/cfg_checker/modules/__init__.py b/cfg_checker/modules/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cfg_checker/modules/__init__.py
diff --git a/cfg_checker/modules/network/__init__.py b/cfg_checker/modules/network/__init__.py
new file mode 100644
index 0000000..627c7d5
--- /dev/null
+++ b/cfg_checker/modules/network/__init__.py
@@ -0,0 +1,23 @@
+import checker
+
+from cfg_checker.helpers import args_utils
+from cfg_checker.common import logger_cli
+
+def do_check(args):
+    logger_cli.info("# Network check (CLI output)")
+    netChecker = checker.NetworkChecker()
+    netChecker.collect_network_info()
+    netChecker.print_network_report()
+
+    return
+
+
+def do_report(args):
+    logger_cli.info("# Network check (HTML report: '{}')".format(args.file))
+    _filename = args_utils.get_file_arg(args)
+
+    netChecker = checker.NetworkChecker()
+    netChecker.collect_network_info()
+    netChecker.create_html_report(_filename)
+
+    return
diff --git a/cfg_checker/network_checks.py b/cfg_checker/modules/network/checker.py
similarity index 92%
rename from cfg_checker/network_checks.py
rename to cfg_checker/modules/network/checker.py
index d5bb9d5..03a48de 100644
--- a/cfg_checker/network_checks.py
+++ b/cfg_checker/modules/network/checker.py
@@ -5,8 +5,7 @@
 
 from copy import deepcopy
 
-import reporter
-
+from cfg_checker import reporter
 from cfg_checker.common import utils, const
 from cfg_checker.common import config, logger, logger_cli, pkg_dir
 from cfg_checker.common import salt_utils
@@ -128,19 +127,3 @@
             "diffs": {}
         })
         logger_cli.info("-> Done")
-
-
-if __name__ == '__main__':
-    # init connection to salt and collect minion data
-    cl = NetworkChecker()
-
-    # collect data on installed packages
-    cl.collect_network_info()
-
-    # diff installed and candidates
-    # cl.collect_packages()
-
-    # report it
-    cl.create_html_report("./pkg_versions.html")
-
-    sys.exit(0)
diff --git a/cfg_checker/modules/packages/__init__.py b/cfg_checker/modules/packages/__init__.py
new file mode 100644
index 0000000..4f1a809
--- /dev/null
+++ b/cfg_checker/modules/packages/__init__.py
@@ -0,0 +1,21 @@
+import checker
+
+from cfg_checker.helpers import args_utils
+
+
+def do_report(args):
+    """Create package versions report
+
+    :args: - parser arguments
+    :return: - no return value
+    """
+    _filename = args_utils.get_file_arg(args)
+
+    # init connection to salt and collect minion data
+    pChecker = checker.CloudPackageChecker()
+    # collect data on installed packages
+    pChecker.collect_installed_packages()
+    # diff installed and candidates
+    # pChecker.collect_packages()
+    # report it
+    pChecker.create_html_report(_filename)
diff --git a/cfg_checker/pkg_check.py b/cfg_checker/modules/packages/checker.py
similarity index 85%
rename from cfg_checker/pkg_check.py
rename to cfg_checker/modules/packages/checker.py
index e9c312e..5f48dcd 100644
--- a/cfg_checker/pkg_check.py
+++ b/cfg_checker/modules/packages/checker.py
@@ -1,11 +1,10 @@
 import json
 import os
-import sys
+#import sys
 
 from copy import deepcopy
 
-import reporter
-
+from cfg_checker import reporter
 from cfg_checker.common import utils, const
 from cfg_checker.common import config, logger, logger_cli, pkg_dir
 from cfg_checker.common import salt_utils
@@ -70,19 +69,3 @@
             "diffs": {}
         })
         logger_cli.info("-> Done")
-
-
-if __name__ == '__main__':
-    # init connection to salt and collect minion data
-    cl = CloudPackageChecker()
-
-    # collect data on installed packages
-    cl.collect_installed_packages()
-
-    # diff installed and candidates
-    # cl.collect_packages()
-
-    # report it
-    cl.create_html_report("./pkg_versions.html")
-
-    sys.exit(0)
diff --git a/cfg_checker/modules/reclass/__init__.py b/cfg_checker/modules/reclass/__init__.py
new file mode 100644
index 0000000..a695482
--- /dev/null
+++ b/cfg_checker/modules/reclass/__init__.py
@@ -0,0 +1,74 @@
+import os
+
+import comparer
+import validator
+
+from cfg_checker.common import logger_cli
+from cfg_checker.helpers import args_utils
+from cfg_checker.reports import reporter
+
+
+def do_list(args):
+    logger_cli.info("# Reclass list")
+    _path = args_utils.get_path_arg(args.models_path)
+    
+    logger_cli.info("# ...models path is '{}'".format(args.models_path))
+    
+    models = {}
+    for _folder in os.listdir(args.models_path):
+        # validate item as a model
+        _model_path = os.path.join(
+            args.models_path,
+            _folder
+        )
+        _validated = validator.basic_model_validation_by_path(_model_path)
+        
+        if not _validated:
+            logger_cli.info("-> '{}' not a valid model".format(_folder))
+            continue
+        else:
+            models[_folder] = _model_path
+        
+        logger_cli.info("-> '{}' at '{}'".format(_folder, _model_path))
+        
+        # TODO: collect info about the model
+
+    return
+
+
+def do_diff(args):
+    logger_cli.info("Reclass comparer (HTML report: '{}'".format(args.file))
+    _filename = args_utils.get_file_arg(args)
+
+    # checking folder params
+    _model1 = args_utils.get_path_arg(args.model1)
+    _model2 = args_utils.get_path_arg(args.model2)
+    
+    # Do actual compare using hardcoded model names
+    mComparer = comparer.ModelComparer()
+
+    mComparer.model_name_1 = os.path.split(_model1)[1]
+    mComparer.model_path_1 = _model1
+    mComparer.model_name_2 = os.path.split(_model2)[1]
+    mComparer.model_path_2 = _model2
+    
+    mComparer.load_model_tree(
+        mComparer.model_name_1,
+        mComparer.model_path_1
+    )
+    mComparer.load_model_tree(
+        mComparer.model_name_2,
+        mComparer.model_path_2
+    )
+
+    diffs = mComparer.generate_model_report_tree()
+
+    report = reporter.ReportToFile(
+        reporter.HTMLModelCompare(),
+        _filename
+    )
+    logger_cli.info("# Generating report to {}".format(_filename))
+    report({
+        "nodes": {},
+        "diffs": diffs
+    })
diff --git a/cfg_checker/reclass_cmp.py b/cfg_checker/modules/reclass/comparer.py
similarity index 90%
rename from cfg_checker/reclass_cmp.py
rename to cfg_checker/modules/reclass/comparer.py
index f7c34d6..5a26f29 100644
--- a/cfg_checker/reclass_cmp.py
+++ b/cfg_checker/modules/reclass/comparer.py
@@ -6,7 +6,7 @@
 import os
 import yaml
 
-import reporter
+from cfg_checker import reporter
 from cfg_checker.common import logger, logger_cli
 
 
@@ -328,44 +328,37 @@
         _diff_report["diff_names"] = [self.model_name_1, self.model_name_2]
         return _diff_report
 
+    def compare_models(self):
+        # Do actual compare using model names from the class
+        self.load_model_tree(
+            self.model_name_1,
+            self.model_path_1
+        )
+        self.load_model_tree(
+            self.model_name_2,
+            self.model_path_2
+        )
+        # Models should have similar structure to be compared
+        # classes/system
+        # classes/cluster
+        # nodes
 
-def compare_models():
-    # Do actual compare using model names from the class
-    mComparer = ModelComparer()
-    mComparer.load_model_tree(
-        mComparer.model_name_1,
-        mComparer.model_path_1
-    )
-    mComparer.load_model_tree(
-        mComparer.model_name_2,
-        mComparer.model_path_2
-    )
-    # Models should have similar structure to be compared
-    # classes/system
-    # classes/cluster
-    # nodes
-    
-    diffs = mComparer.generate_model_report_tree()
+        diffs = self.generate_model_report_tree()
 
-    report_file = \
-        mComparer.model_name_1 + "-vs-" + mComparer.model_name_2 + ".html"
-    # HTML report class is post-callable
-    report = reporter.ReportToFile(
-        reporter.HTMLModelCompare(),
-        report_file
-    )
-    logger_cli.info("...generating report to {}".format(report_file))
-    # report will have tabs for each of the comparable entities in diffs
-    report({
-        "nodes": {},
-        "all_diffs": diffs,
-    })
-    # with open("./gen_tree.json", "w+") as _out:
-    #     _out.write(json.dumps(mComparer.generate_model_report_tree))
+        report_file = \
+            self.model_name_1 + "-vs-" + self.model_name_2 + ".html"
+        # HTML report class is post-callable
+        report = reporter.ReportToFile(
+            reporter.HTMLModelCompare(),
+            report_file
+        )
+        logger_cli.info("...generating report to {}".format(report_file))
+        # report will have tabs for each of the comparable entities in diffs
+        report({
+            "nodes": {},
+            "all_diffs": diffs,
+        })
+        # with open("./gen_tree.json", "w+") as _out:
+        #     _out.write(json.dumps(mComparer.generate_model_report_tree))
 
-    return
-
-
-# temporary executing the parser as a main prog
-if __name__ == '__main__':
-    compare_models()
+        return
diff --git a/cfg_checker/modules/reclass/validator.py b/cfg_checker/modules/reclass/validator.py
new file mode 100644
index 0000000..e7d7f06
--- /dev/null
+++ b/cfg_checker/modules/reclass/validator.py
@@ -0,0 +1,28 @@
+import os
+
+from cfg_checker.common import logger_cli
+
+def basic_model_validation_by_path(path):
+    logger_cli.debug("\t...validating '{}' as a model".format(path))
+    _checks = []
+    _is_folder = os.path.isdir(path)
+    logger_cli.debug("\t- folder? -> {}".format(_is_folder))
+    _checks.append(_is_folder)
+    _has_classes = os.path.isdir(os.path.join(path, "classes"))
+    logger_cli.debug("\t- has classes? -> {}".format(_has_classes))
+    _checks.append(_has_classes)
+    _has_cluster = os.path.isdir(os.path.join(path, "classes", "cluster"))
+    logger_cli.debug("\t- has classes/cluster? -> {}".format(_has_cluster))
+    _checks.append(_has_cluster)
+    _has_system = os.path.isdir(os.path.join(path, "classes", "system"))
+    logger_cli.debug("\t- has classes/system? -> {}".format(_has_system))
+    _checks.append(_has_system)
+    _has_nodes = os.path.isdir(os.path.join(path, "nodes"))
+    logger_cli.debug("\t- has nodes? -> {}".format(_has_nodes))
+    _checks.append(_has_nodes)
+    
+    logger_cli.debug("\t-> {}".format(
+        all(_checks)
+    ))
+
+    return all(_checks)
diff --git a/cfg_checker/reports/__init__.py b/cfg_checker/reports/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cfg_checker/reports/__init__.py
diff --git a/cfg_checker/reporter.py b/cfg_checker/reports/reporter.py
similarity index 100%
rename from cfg_checker/reporter.py
rename to cfg_checker/reports/reporter.py
diff --git a/setup.py b/setup.py
index 0addf90..2661496 100644
--- a/setup.py
+++ b/setup.py
@@ -21,8 +21,12 @@
 ]
 
 entry_points = {
-    "console_scripts":
-        "mcp_checker = cfg_checker.cfg_check:cli_main"
+    "console_scripts": [
+        "mcp-checker = cfg_checker.cfg_check:cli_main",
+        "package-report = cfg_checker.cli.package",
+        "network-check = cfg_checker.cli.network",
+        "reclass-compare = cfg_checker.cli.reclass"
+    ]
 }