Refactor modules execution
diff --git a/ci_checker/__init__.py b/cfg_checker/__init__.py
similarity index 100%
rename from ci_checker/__init__.py
rename to cfg_checker/__init__.py
diff --git a/cfg_checker/cfg_check.py b/cfg_checker/cfg_check.py
new file mode 100644
index 0000000..9260f30
--- /dev/null
+++ b/cfg_checker/cfg_check.py
@@ -0,0 +1,112 @@
+import argparse
+import os
+import sys
+
+import reporter
+from cfg_checker.common import utils, const
+from cfg_checker.common import config, logger, logger_cli, pkg_dir
+from cfg_checker.clients import salt
+
+from cfg_checker.pkg_check import CloudPackageChecker
+
+pkg_dir = os.path.dirname(__file__)
+pkg_dir = os.path.normpath(pkg_dir)
+
+
+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 pkg_check(args):
+ # create package versions report
+ _filename = args.file
+ # 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 net_check(args):
+ print("This is net check routine")
+
+ return
+
+
+def net_report(args):
+ print("This is net check routine")
+
+ return
+
+
+def config_check_entrypoint():
+ # Main entrypointр
+ parser = MyParser(prog="Cloud configuration checker")
+ 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(
+ '-f',
+ '--file',
+ help="HTML filename to save report"
+ )
+
+ # networking
+ net_parser = subparsers.add_parser(
+ 'network',
+ help="Network infrastructure checks"
+ )
+ 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.set_defaults(func=net_check)
+
+ net_report_parser = net_subparsers.add_parser(
+ 'report',
+ help="Generate network check report"
+ )
+ net_report_parser.add_argument(
+ '-f',
+ '--file',
+ help="HTML filename to save report"
+ )
+ net_report_parser.set_defaults(func=net_report)
+
+ #parse arguments
+ args = parser.parse_args()
+
+ # Execute the command
+ result = args.func(args)
+
+ logger.debug(result)
+ return
+
+if __name__ == '__main__':
+ config_check_entrypoint()
diff --git a/cfg_checker/clients/__init__.py b/cfg_checker/clients/__init__.py
new file mode 100644
index 0000000..3e1f55c
--- /dev/null
+++ b/cfg_checker/clients/__init__.py
@@ -0,0 +1,29 @@
+from cfg_checker.common.salt_utils import SaltRemote
+from cfg_checker.common import logger
+
+# instance of the salt client
+salt = None
+
+
+def get_salt_remote(config):
+ """Singleton-like creation of instance
+
+ Arguments:
+ config {base_config} -- an instance to base_config
+ with creds and params
+
+ Returns:
+ SaltRemote -- instance of salt client
+ """
+
+ global salt
+ logger.info("Creating salt remote instance")
+ # create it once
+ if salt is None:
+ salt = SaltRemote(config)
+ # do most expensive operation with no strict timeout possible
+ # all nodes that answer ping
+ salt.nodes_active = salt.get_active_nodes()
+
+ # return once required
+ return salt
diff --git a/cfg_checker/common/__init__.py b/cfg_checker/common/__init__.py
new file mode 100644
index 0000000..297ace6
--- /dev/null
+++ b/cfg_checker/common/__init__.py
@@ -0,0 +1,13 @@
+import os
+import const
+
+from settings import pkg_dir, config
+from other import Utils
+from log import logger, logger_cli
+
+
+utils = Utils()
+const = const
+logger = logger
+logger_cli = logger_cli
+config = config
\ No newline at end of file
diff --git a/ci_checker/common/const.py b/cfg_checker/common/const.py
similarity index 100%
rename from ci_checker/common/const.py
rename to cfg_checker/common/const.py
diff --git a/ci_checker/common/exception.py b/cfg_checker/common/exception.py
similarity index 85%
rename from ci_checker/common/exception.py
rename to cfg_checker/common/exception.py
index 82e2432..bc7cefe 100644
--- a/ci_checker/common/exception.py
+++ b/cfg_checker/common/exception.py
@@ -1,11 +1,11 @@
from exceptions import Exception
-class CiCheckerBaseExceptions(Exception):
+class CheckerBaseExceptions(Exception):
pass
-class CheckerException(CiCheckerBaseExceptions):
+class CheckerException(CheckerBaseExceptions):
def __init__(self, message, *args, **kwargs):
super(CheckerException, self).__init__(message, *args, **kwargs)
# get the trace
diff --git a/ci_checker/common/log.py b/cfg_checker/common/log.py
similarity index 85%
rename from ci_checker/common/log.py
rename to cfg_checker/common/log.py
index 78f5ab3..af52cac 100644
--- a/ci_checker/common/log.py
+++ b/cfg_checker/common/log.py
@@ -1,5 +1,11 @@
+import os
import logging
+pkg_dir = os.path.dirname(__file__)
+pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
+pkg_dir = os.path.normpath(pkg_dir)
+pkg_dir = os.path.abspath(pkg_dir)
+
def color_me(color):
RESET_SEQ = "\033[0m"
@@ -78,3 +84,12 @@
logger_cli.addHandler(sh)
return logger, logger_cli
+
+# init instances of logger to be used by all other modules
+logger, logger_cli = setup_loggers(
+ 'cfg_checker',
+ log_fname=os.path.join(
+ pkg_dir,
+ os.getenv('LOGFILE', 'cfg_checker.log')
+ )
+)
diff --git a/ci_checker/common/other.py b/cfg_checker/common/other.py
similarity index 89%
rename from ci_checker/common/other.py
rename to cfg_checker/common/other.py
index 14003ea..97030bb 100644
--- a/ci_checker/common/other.py
+++ b/cfg_checker/common/other.py
@@ -1,13 +1,14 @@
import os
import re
-from ci_checker.common.const import all_roles_map
+from cfg_checker.common.const import all_roles_map
-from ci_checker.common.exception import ConfigException
+from cfg_checker.common.exception import ConfigException
-PKG_DIR = os.path.dirname(__file__)
-PKG_DIR = os.path.join(PKG_DIR, os.pardir, os.pardir)
-PKG_DIR = os.path.normpath(PKG_DIR)
+pkg_dir = os.path.dirname(__file__)
+pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
+pkg_dir = os.path.normpath(pkg_dir)
+pkg_dir = os.path.abspath(pkg_dir)
class Utils(object):
@@ -74,7 +75,7 @@
try:
if not nodes_list:
return []
- with open(os.path.join(PKG_DIR, nodes_list)) as _f:
+ with open(os.path.join(pkg_dir, nodes_list)) as _f:
_list.extend(_f.read().splitlines())
except IOError as e:
raise ConfigException("Error while loading file, '{}': "
diff --git a/ci_checker/common/salt_utils.py b/cfg_checker/common/salt_utils.py
similarity index 98%
rename from ci_checker/common/salt_utils.py
rename to cfg_checker/common/salt_utils.py
index cbf0321..ba1233b 100644
--- a/ci_checker/common/salt_utils.py
+++ b/cfg_checker/common/salt_utils.py
@@ -5,8 +5,7 @@
import requests
import time
-from ci_checker.common.base_settings import base_config as config
-from ci_checker.common import logger
+from cfg_checker.common import logger, config
def list_to_target_string(node_list, separator):
diff --git a/cfg_checker/common/settings.py b/cfg_checker/common/settings.py
new file mode 100644
index 0000000..cea1f0c
--- /dev/null
+++ b/cfg_checker/common/settings.py
@@ -0,0 +1,107 @@
+import os
+
+from exception import ConfigException
+from log import logger
+from other import utils
+
+pkg_dir = os.path.dirname(__file__)
+pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
+pkg_dir = os.path.normpath(pkg_dir)
+pkg_dir = os.path.abspath(pkg_dir)
+
+_default_work_folder = os.path.normpath(pkg_dir)
+
+
+class CheckerConfiguration(object):
+ def _init_values(self):
+ """Load values from environment variables or put default ones
+ """
+
+ self.name = "CheckerConfig"
+ self.working_folder = os.environ.get(
+ 'CFG_TESTS_WORK_DIR',
+ _default_work_folder
+ )
+ self.date_format = "%Y-%m-%d %H:%M:%S.%f%z"
+ self.default_tz = "UTC"
+
+ self.salt_host = os.environ.get('SALT_URL', None)
+ self.salt_port = os.environ.get('SALT_PORT', '6969')
+ self.salt_user = os.environ.get('SALT_USER', 'salt')
+ self.salt_pass = os.environ.get('SALT_PASSWORD', None)
+ self.salt_timeout = os.environ.get('SALT_TIMEOUT', 30)
+ self.salt_file_root = os.environ.get('SALT_FILE_ROOT', None)
+ self.salt_scripts_folder = os.environ.get(
+ 'SALT_SCRIPTS_FOLDER',
+ 'cfg_checker_scripts'
+ )
+ self.all_nodes = utils.get_nodes_list(
+ os.environ.get('CFG_ALL_NODES', None),
+ os.environ.get('SALT_NODE_LIST_FILE', None)
+ )
+ self.skip_nodes = utils.node_string_to_list(os.environ.get(
+ 'CFG_SKIP_NODES',
+ None
+ ))
+
+ @staticmethod
+ def _init_env(env_name=None):
+ """[summary]
+
+ Keyword Arguments:
+ env_name {str} -- environment name to search configuration
+ files in etc/<env_name>.env (default: {None})
+
+ Raises:
+ ConfigException -- on IO error when loading env file
+ ConfigException -- on env file failed validation
+ """
+ # load env file as init os.environment with its values
+ if env_name is None:
+ _env_name = 'default'
+ else:
+ _env_name = env_name
+ _config_path = os.path.join(pkg_dir, 'etc', _env_name + '.env')
+ if os.path.isfile(_config_path):
+ with open(_config_path) as _f:
+ _list = _f.read().splitlines()
+ logger.debug("Loading env vars from '{}'".format(_config_path))
+ else:
+ raise ConfigException(
+ "Failed to load enviroment vars from '{}'".format(
+ _config_path
+ )
+ )
+ for index in range(len(_list)):
+ _line = _list[index]
+ # skip comments
+ if _line.strip().startswith('#'):
+ continue
+ # validate
+ _errors = []
+ if _line.find('=') < 0 or _line.count('=') > 1:
+ _errors.append("Line {}: {}".format(index, _line))
+ else:
+ # save values
+ _t = _line.split('=')
+ _key, _value = _t[0], _t[1]
+ os.environ[_key] = _value
+ # if there was errors, report them
+ if _errors:
+ raise ConfigException(
+ "Environment file failed validation in lines: {}".format(
+ "\n".join(_errors)
+ )
+ )
+ else:
+ logger.debug("Loaded total of '{}' vars".format(len(_list)))
+
+ def __init__(self):
+ """Base configuration class. Only values that are common for all scripts
+ """
+ _env = os.getenv('SALT_ENV', None)
+ self._init_env(_env)
+ self._init_values()
+
+
+config = CheckerConfiguration()
diff --git a/ci_checker/pkg_check.py b/cfg_checker/pkg_check.py
similarity index 91%
rename from ci_checker/pkg_check.py
rename to cfg_checker/pkg_check.py
index dd1efc1..34907c5 100644
--- a/ci_checker/pkg_check.py
+++ b/cfg_checker/pkg_check.py
@@ -4,11 +4,11 @@
from copy import deepcopy
-import common.const as const
import reporter
-from ci_checker.common import utils
-from ci_checker.common import base_config, logger, logger_cli, PKG_DIR
-from ci_checker.common import salt_utils
+
+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
node_tmpl = {
'role': '',
@@ -20,7 +20,7 @@
class CloudPackageChecker(object):
- _config = base_config
+ _config = config
def __init__(self):
logger_cli.info("Collecting nodes for package check")
@@ -173,16 +173,17 @@
})
-# init connection to salt and collect minion data
-cl = CloudPackageChecker()
+if __name__ == '__main__':
+ # init connection to salt and collect minion data
+ cl = CloudPackageChecker()
-# collect data on installed packages
-cl.collect_installed_packages()
+ # collect data on installed packages
+ cl.collect_installed_packages()
-# diff installed and candidates
-# cl.collect_packages()
+ # diff installed and candidates
+ # cl.collect_packages()
-# report it
-cl.create_html_report("./pkg_versions.html")
+ # report it
+ cl.create_html_report("./pkg_versions.html")
-sys.exit(0)
+ sys.exit(0)
diff --git a/ci_checker/reclass_cmp.py b/cfg_checker/reclass_cmp.py
similarity index 99%
rename from ci_checker/reclass_cmp.py
rename to cfg_checker/reclass_cmp.py
index fd0dff3..d644679 100644
--- a/ci_checker/reclass_cmp.py
+++ b/cfg_checker/reclass_cmp.py
@@ -7,7 +7,7 @@
import yaml
import reporter
-from ci_checker.common import logger, logger_cli
+from cfg_checker.common import logger, logger_cli
global prefix_name
diff --git a/ci_checker/reporter.py b/cfg_checker/reporter.py
similarity index 98%
rename from ci_checker/reporter.py
rename to cfg_checker/reporter.py
index 591026c..3b21894 100644
--- a/ci_checker/reporter.py
+++ b/cfg_checker/reporter.py
@@ -3,7 +3,7 @@
import abc
import os
-from ci_checker.common import const
+from cfg_checker.common import const
pkg_dir = os.path.dirname(__file__)
pkg_dir = os.path.join(pkg_dir, os.pardir)
diff --git a/ci_checker/common/__init__.py b/ci_checker/common/__init__.py
deleted file mode 100644
index e1c9f55..0000000
--- a/ci_checker/common/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-import const
-import log
-
-from base_settings import PKG_DIR, base_config
-from other import Utils
-
-
-utils = Utils()
-const = const
-
-logger, logger_cli = log.setup_loggers(
- 'cee8_features',
- log_fname=os.path.join(PKG_DIR, base_config.logfile_name)
-)
diff --git a/ci_checker/common/base_settings.py b/ci_checker/common/base_settings.py
deleted file mode 100644
index f0a8f2b..0000000
--- a/ci_checker/common/base_settings.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""
-Base configuration module
-Gathers env values and supplies default ones
-
-Attributes:
- base_config: class with all of the values prepared to work with env
-"""
-
-import os
-
-from ci_checker.common.other import utils
-
-PKG_DIR = os.path.dirname(__file__)
-PKG_DIR = os.path.join(PKG_DIR, os.pardir, os.pardir)
-PKG_DIR = os.path.normpath(PKG_DIR)
-
-_default_work_folder = os.path.normpath(PKG_DIR)
-
-
-class TestsConfigurationBase(object):
- """
- Base configuration class. Only values that are common for all scripts
- """
-
- name = "CiTestsBaseConfig"
- logfile_name = 'ci_checker.log'
- working_folder = os.environ.get('CI_TESTS_WORK_DIR', _default_work_folder)
- salt_host = os.environ.get('SALT_URL', None)
- salt_port = os.environ.get('SALT_PORT', '6969')
- salt_user = os.environ.get('SALT_USER', 'salt')
- salt_pass = os.environ.get('SALT_PASSWORD', None)
-
- salt_timeout = os.environ.get('SALT_TIMEOUT', 30)
- salt_file_root = os.environ.get('SALT_FILE_ROOT', None)
- salt_scripts_folder = os.environ.get('SALT_SCRIPTS_FOLDER', 'test_scripts')
-
- all_nodes = utils.get_nodes_list(
- os.environ.get('CI_ALL_NODES', None),
- os.environ.get('SALT_NODE_LIST_FILE', None)
- )
- skip_nodes = utils.node_string_to_list(os.environ.get(
- 'CI_SKIP_NODES',
- None
- ))
-
-
-base_config = TestsConfigurationBase()
diff --git a/etc/example._env b/etc/example._env
index 477296c..44414a8 100644
--- a/etc/example._env
+++ b/etc/example._env
@@ -1,15 +1,12 @@
-# CI Checker
+# Cfg Checker
# Environment file example
# Either open a tunnel from your hosts using
# 'ssh -L 16969:<cfg-IP>:6969 <user>@<lab-IP>'
# Or run it from within a cloud
-# Not used so far, reserved
-# CI_TESTS_WORK_DIR=
-
# Main log file of the tests
-CEE8_LOGFILE = 'ci_checker.log'
+LOGFILE = 'cfg_checker.log'
# Salt master host to connect to
SALT_URL=127.0.0.1
diff --git a/requirements.txt b/requirements.txt
index eaae064..d68799f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
six
pyyaml
-jinja2
\ No newline at end of file
+jinja2
+requests