Reclass diff and list commands
diff --git a/cfg_checker/cfg_check.py b/cfg_checker/cfg_check.py
index a10d4a0..34a3102 100644
--- a/cfg_checker/cfg_check.py
+++ b/cfg_checker/cfg_check.py
@@ -1,15 +1,19 @@
 import argparse
 import os
+import reclass
 import sys
 import traceback
+
 from logging import INFO,  DEBUG
 
 import reporter
+
 from cfg_checker.common.exception import ConfigException
 from cfg_checker.common import utils, const
 from cfg_checker.common import config, logger, logger_cli, pkg_dir
 from cfg_checker.clients import salt
 
+import cfg_checker.reclass_cmp as reclass_cmp
 from cfg_checker.pkg_check import CloudPackageChecker
 from cfg_checker.network_checks import NetworkChecker
 
@@ -45,6 +49,39 @@
         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
 
@@ -84,7 +121,29 @@
 
 
 def reclass_list(args):
-    logger_cli.info("Reclass list: to be implemented")
+    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
 
@@ -93,7 +152,38 @@
     logger_cli.info("Reclass comparer (HTML report: '{}'".format(args.file))
     _filename = get_file_arg(args)
 
-    return
+    # 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():
@@ -170,11 +260,28 @@
         '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"
+    )
+
 
     #parse arguments
     try:
@@ -217,9 +324,12 @@
     try:
         config_check_entrypoint()
     except ConfigException as e:
+        logger_cli.error("\nERROR: {}".format(
+            e.message
+        ))
+
         exc_type, exc_value, exc_traceback = sys.exc_info()
-        logger_cli.error("\nERROR: {}\n\n{}".format(
-            e.message,
+        logger_cli.debug("\n{}".format(
             "".join(traceback.format_exception(
                 exc_type,
                 exc_value,
diff --git a/cfg_checker/reclass_cmp.py b/cfg_checker/reclass_cmp.py
index d644679..ee658bd 100644
--- a/cfg_checker/reclass_cmp.py
+++ b/cfg_checker/reclass_cmp.py
@@ -10,21 +10,15 @@
 from cfg_checker.common import logger, logger_cli
 
 
-global prefix_name
-global model_name_1, model_path_1
-global model_name_2, model_path_2
-
-prefix_name = "emk"
-model_name_1 = "dev"
-model_path_1 = "/Users/savex/proj/mediakind/reclass-dev"
-model_name_2 = "stg"
-model_path_2 = "/Users/savex/proj/mediakind/reclass-stg"
-
-
 class ModelComparer(object):
     """Collection of functions to compare model data.
     """
     models = {}
+    models_path = "/srv/salt/reclass"
+    model_name_1 = "source"
+    model_path_1 = os.path.join(models_path, model_name_1)
+    model_name_2 = "target"
+    model_path_2 = os.path.join(models_path, model_name_1)
 
     @staticmethod
     def load_yaml_class(fname):
@@ -73,16 +67,16 @@
         # Look Ma! I am walking the file tree with no recursion!
         for path, dirs, files in os.walk(root_path):
             # if this is a hidden folder, ignore it
-            _filders_list = path[start:].split(os.sep)
-            if any(item.startswith(".") for item in _filders_list):
+            _folders_list = path[start:].split(os.sep)
+            if any(item.startswith(".") for item in _folders_list):
                 continue
             # cut absolute part of the path and split folder names
             folders = path[start:].split(os.sep)
             subdir = {}
             # create generator of files that are not hidden
             _exts = ('.yml', '.yaml')
-            _subfiles = (file for file in files
-                         if file.endswith(_exts) and not file.startswith('.'))
+            _subfiles = (_fl for _fl in files
+                         if _fl.endswith(_exts) and not _fl.startswith('.'))
             for _file in _subfiles:
                 # cut file extension. All reclass files are '.yml'
                 _subnode = _file
@@ -124,10 +118,10 @@
                     continue
                 # check if this is an env name cluster entry
                 if dict2 is not None and \
-                        k == model_name_1 and \
-                        model_name_2 in dict2.keys():
-                    k1 = model_name_1
-                    k2 = model_name_2
+                        k == self.model_name_1 and \
+                        self.model_name_2 in dict2.keys():
+                    k1 = self.model_name_1
+                    k2 = self.model_name_2
                     if type(dict1[k1]) is dict:
                         if path == "":
                             _new_path = k1
@@ -261,8 +255,8 @@
             return _report
         # tmp report for keys
         diff_report = find_changes(
-            self.models[model_name_1],
-            self.models[model_name_2]
+            self.models[self.model_name_1],
+            self.models[self.model_name_2]
         )
         # prettify the report
         for key in diff_report.keys():
@@ -280,25 +274,25 @@
                 "param": _param_path,
             })
 
-        diff_report["diff_names"] = [model_name_1, model_name_2]
+        diff_report["diff_names"] = [self.model_name_1, self.model_name_2]
         return diff_report
 
 
-# temporary executing the parser as a main prog
-if __name__ == '__main__':
+def compare_models():
+    # Do actual compare using hardcoded model names
     mComparer = ModelComparer()
     mComparer.load_model_tree(
-        model_name_1,
-        model_path_1
+        mComparer.model_name_1,
+        mComparer.model_path_1
     )
     mComparer.load_model_tree(
-        model_name_2,
-        model_path_2
+        mComparer.model_name_2,
+        mComparer.model_path_2
     )
     diffs = mComparer.generate_model_report_tree()
 
     report_file = \
-        prefix_name + "-" + model_name_1 + "-vs-" + model_name_2 + ".html"
+        mComparer.model_name_1 + "-vs-" + mComparer.model_name_2 + ".html"
     report = reporter.ReportToFile(
         reporter.HTMLModelCompare(),
         report_file
@@ -310,3 +304,10 @@
     })
     # 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()
diff --git a/requirements.txt b/requirements.txt
index c334a77..2ac89e8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,3 +3,4 @@
 jinja2
 requests
 ipaddress
+reclass
\ No newline at end of file