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