Updates to kube env interaction
- local KUBECONFIG var detection
- proper handling of env vars
- fixes for KUBECONFIG loading when env file is given/not given
- main IP extraction
- wording fixes
Related-PROD: PROD-35903
Change-Id: I68f1fd18a72a99502460d3b6158a43cd60d7cf1b
diff --git a/cfg_checker/common/kube_utils.py b/cfg_checker/common/kube_utils.py
index f6f499d..315f5ee 100644
--- a/cfg_checker/common/kube_utils.py
+++ b/cfg_checker/common/kube_utils.py
@@ -23,18 +23,18 @@
# Init kube library locally
_path = "local:{}".format(config.kube_config_path)
try:
- kconfig.load_kube_config()
+ kconfig.load_kube_config(config_file=config.kube_config_path)
if config.insecure:
kconfig.assert_hostname = False
kconfig.client_side_validation = False
logger_cli.debug(
- "...found Kube env: core, {}". format(
+ "... found Kube env: core, {}". format(
",".join(
kclient.CoreApi().get_api_versions().versions
)
)
)
- return kconfig, kclient.ApiClient()
+ return kconfig, kclient.ApiClient(), _path
except Exception as e:
logger.warn("Failed to init local Kube client: {}".format(
str(e)
@@ -63,14 +63,15 @@
"""
import yaml
_path = ''
- if not config.env_name == ENV_LOCAL:
+ # Try to load remote config only if it was not detected already
+ if not config.kube_config_detected and not config.env_name == ENV_LOCAL:
_path = "{}@{}:{}".format(
config.ssh_user,
config.ssh_host,
config.kube_config_path
)
_c_data = ssh_shell_p(
- "sudo cat " + config.kube_config_path,
+ "cat " + config.kube_config_path,
config.ssh_host,
username=config.ssh_user,
keypath=config.ssh_key,
@@ -116,7 +117,7 @@
)
else:
logger_cli.debug(
- "...'context' host extracted: '{}' via SSH@{}".format(
+ "... 'context' host extracted: '{}' via SSH@{}".format(
_host,
config.ssh_host
)
@@ -128,7 +129,7 @@
_tmp[0] + "://" + config.mcp_host + ":" + _tmp[2]
config.kube_port = _tmp[2]
logger_cli.debug(
- "...kube remote host updated to {}".format(
+ "... kube remote host updated to {}".format(
_kube_conf.host
)
)
@@ -169,9 +170,11 @@
self.config
)
self.is_local = True
- # Load local config data
- if os.path.exists(self.config.kube_config_path):
- _c_data = shell("sudo cat " + self.config.kube_config_path)
+ # Try to load local config data
+ if self.config.kube_config_path and \
+ os.path.exists(self.config.kube_config_path):
+ _cmd = "cat " + self.config.kube_config_path
+ _c_data = shell(_cmd)
_conf = yaml.load(_c_data, Loader=yaml.SafeLoader)
self.user_keypath = create_temp_file_with_content(
base64.standard_b64decode(
@@ -277,7 +280,7 @@
**kwargs
):
logger_cli.debug(
- "...searching for pods with the name '{}'".format(pod_name)
+ "... searching for pods with the name '{}'".format(pod_name)
)
_pods = {}
_pods = self._coreV1.list_namespaced_pod(namespace)
@@ -288,8 +291,8 @@
_pnames = [n for n in _names if n.startswith(pod_name)]
if len(_pnames) > 1:
logger_cli.debug(
- "...more than one pod found for '{}': {}\n"
- "...using first one".format(
+ "... more than one pod found for '{}': {}\n"
+ "... using first one".format(
pod_name,
", ".join(_pnames)
)
@@ -300,7 +303,7 @@
else:
_pname = pod_name
logger_cli.debug(
- "...cmd: [CoreV1] exec {} -n {} -- {}".format(
+ "... cmd: [CoreV1] exec {} -n {} -- {}".format(
_pname,
namespace,
cmd
diff --git a/cfg_checker/common/other.py b/cfg_checker/common/other.py
index e3a3271..3d0cc13 100644
--- a/cfg_checker/common/other.py
+++ b/cfg_checker/common/other.py
@@ -16,7 +16,7 @@
# 'Dirty' and simple way to execute piped cmds
def piped_shell(command):
- logger_cli.debug("...cmd:'{}'".format(command))
+ logger_cli.debug("... cmd:'{}'".format(command))
_code, _out = subprocess.getstatusoutput(command)
if _code:
logger_cli.error("Non-zero return code: {}, '{}'".format(_code, _out))
@@ -25,7 +25,7 @@
# 'Proper way to execute shell
def shell(command):
- logger_cli.debug("...cmd:'{}'".format(command))
+ logger_cli.debug("... cmd:'{}'".format(command))
_ps = subprocess.Popen(
command.split(),
stdout=subprocess.PIPE,
diff --git a/cfg_checker/common/settings.py b/cfg_checker/common/settings.py
index c654970..dac917e 100644
--- a/cfg_checker/common/settings.py
+++ b/cfg_checker/common/settings.py
@@ -2,6 +2,7 @@
import json
import pwd
import sys
+import yaml
from cfg_checker.common.const import ENV_TYPE_GLOB, ENV_TYPE_SALT
from cfg_checker.common.const import ENV_TYPE_KUBE, ENV_TYPE_LINUX, ENV_LOCAL
@@ -26,14 +27,14 @@
def _extract_salt_return(_raw):
if not isinstance(_raw, str):
_json = _raw
- logger_cli.debug("...ambigious return detected")
+ logger_cli.debug("... ambigious return detected")
else:
try:
_json = json.loads(_raw)
except ValueError:
_json = _raw
logger_cli.debug(
- "...return value is not a json: '{}'".format(_raw)
+ "... return value is not a json: '{}'".format(_raw)
)
return _json
@@ -53,7 +54,7 @@
return None
def _detect(self, _type):
- logger_cli.debug("...detecting '{}'".format(_type))
+ logger_cli.debug("... detecting '{}'".format(_type))
if _type is None:
raise ConfigException("# Unexpected supported env type")
elif _type == ENV_TYPE_SALT:
@@ -64,7 +65,7 @@
)
# Try to call salt API on target host
_r = None
- logger_cli.debug("...trying to detect env type '{}'".format(_type))
+ logger_cli.debug("... detecting env type '{}'".format(_type))
if self.env_name == ENV_LOCAL:
_r = shell(" ".join(_detect_cmd))
else:
@@ -90,7 +91,7 @@
_kube = get_kube_remote(self)
if not _kube.initialized:
logger_cli.debug(
- "... failed to load config from '{}'".format(
+ "... failed to init kube using '{}'".format(
_kube.kConfigPath
)
)
@@ -107,12 +108,11 @@
if hasattr(_v, "platform") and \
hasattr(_v, "major") and \
hasattr(_v, "minor"):
- _host = "localhost" if _kube.is_local else _kube.kConf.host
logger_cli.info(
"# Kube server found: {}:{} on '{}'".format(
_v.major,
_v.minor,
- _host
+ _kube.kConfigPath
)
)
return True
@@ -130,7 +130,7 @@
from platform import system, release
_s = system()
_r = release()
- logger_cli.debug("...running on {} {}".format(_s, _r))
+ logger_cli.debug("... running on {} {}".format(_s, _r))
if _s in ['Linux', 'Darwin']:
return True
else:
@@ -163,6 +163,10 @@
self.salt_vars = []
self.kube_vars = []
for _key, _value in self.vars:
+ if _key in os.environ:
+ logger_cli.info(
+ "-> Using env var '{}={}'".format(_key, os.environ[_key])
+ )
if _key.startswith(ENV_TYPE_GLOB):
os.environ[_key] = _value
elif _key.startswith(ENV_TYPE_SALT):
@@ -213,23 +217,28 @@
def _init_env_values(self):
if ENV_TYPE_SALT in self.detected_envs:
for _key, _value in self.salt_vars:
- os.environ[_key] = _value
+ if _key not in os.environ:
+ os.environ[_key] = _value
self.salt_user = os.environ.get('SALT_USER', 'salt')
self.salt_timeout = os.environ.get('SALT_TIMEOUT', 30)
- self.salt_file_root = os.environ.get('SALT_FILE_ROOT', None)
+ self.salt_file_root = os.environ.get(
+ 'SALT_FILE_ROOT',
+ "/usr/share/salt-formulas/env/"
+ )
self.salt_scripts_folder = os.environ.get(
'SALT_SCRIPTS_FOLDER',
'cfg_checker_scripts'
)
elif ENV_TYPE_KUBE in self.detected_envs:
for _key, _value in self.kube_vars:
- os.environ[_key] = _value
+ if _key not in os.environ:
+ os.environ[_key] = _value
- self.kube_config_root = os.environ.get('KUBE_CONFIG_ROOT', None)
+ self.kube_config_root = os.environ.get('KUBE_CONFIG_ROOT', "/root")
self.kube_scripts_folder = os.environ.get(
'KUBE_SCRIPTS_FOLDER',
- None
+ "cfg-checker-scripts"
)
self.kube_node_user = os.environ.get(
'KUBE_NODE_USER',
@@ -286,6 +295,57 @@
ConfigException -- on IO error when loading env file
ConfigException -- on env file failed validation
"""
+ # detect kubeconfig placement
+ _env_kubeconf_path = os.environ.get('KUBECONFIG', None)
+ if not os.path.exists(self.kube_config_path):
+ logger_cli.debug(
+ "... kubeconfig not detected at '{}'".format(
+ self.kube_config_path
+ )
+ )
+ # not exists, get KUBECONFIG var
+ if _env_kubeconf_path:
+ # get the env var path
+ self.kube_config_path = _env_kubeconf_path
+ logger_cli.debug(
+ "... KUBECONFIG var points to '{}'".format(
+ self.kube_config_path
+ )
+ )
+ self.kube_config_detected = True
+ else:
+ logger_cli.debug("... KUBECONFIG env var not found")
+ self.kube_config_path = None
+ self.kube_config_detected = False
+ else:
+ logger_cli.debug(
+ "... kubeconfig detected at '{}'".format(
+ self.kube_config_path
+ )
+ )
+ self.kube_config_detected = True
+
+ # try to load values from KUBECONF
+ _kube_conf = None
+ if self.kube_config_path:
+ with open(self.kube_config_path) as kF:
+ _kube_conf = yaml.load(kF, Loader=yaml.SafeLoader)
+ # extract host ip
+ try:
+ _server = _kube_conf["clusters"][0]["cluster"]["server"]
+ except KeyError as e:
+ logger_cli.debug(
+ "... failed to extract server ip: "
+ "no '{}' key in 'clusters/[0]/cluster/server".format(e)
+ )
+ except IndexError:
+ logger_cli.debug(
+ "... failed to extract server ip: empty cluster list"
+ )
+ _ip = _server.split(':')
+ self.remote_ip = _ip[1].replace('/', '')
+ logger_cli.debug("... detected ip: '{}'".format(self.remote_ip))
+
# load env file as init os.environment with its values
if os.path.isfile(config_path):
with open(config_path) as _f:
@@ -326,7 +386,7 @@
)
else:
logger_cli.debug(
- "-> ...loaded total of '{}' vars".format(
+ "... loaded total of '{}' vars".format(
len(_list)
)
)
diff --git a/cfg_checker/common/ssh_utils.py b/cfg_checker/common/ssh_utils.py
index fdf4c91..bdfe6b5 100644
--- a/cfg_checker/common/ssh_utils.py
+++ b/cfg_checker/common/ssh_utils.py
@@ -27,6 +27,7 @@
# Build SSH cmd
if keypath:
_ssh_cmd.append("-i " + keypath)
+ _ssh_cmd.append("-o " + "IdentitiesOnly=yes")
if port:
_ssh_cmd.append("-p " + str(port))
if username:
@@ -106,7 +107,8 @@
self._options += ["-p", str(self.port)]
self._extra_options = [
"-o", "UserKnownHostsFile=/dev/null",
- "-o", "StrictHostKeyChecking=no"
+ "-o", "StrictHostKeyChecking=no",
+ "-o", "IdentitiesOnly=yes"
]
self._host_uri = ""
@@ -120,7 +122,7 @@
raise CheckerException(
"Invalid SSH banner type: '{}'".format(type(banner))
)
- logger.debug("...connecting")
+ logger.debug("... connecting")
while True:
try:
line = self.outq.get(block=False)
@@ -136,11 +138,11 @@
"...timed out after {} sec".format(str(self.timeout))
)
return False
- logger.debug("...connected")
+ logger.debug("... connected")
return True
def _wait_for_string(self, string):
- logger.debug("...waiting for '{}'".format(string))
+ logger.debug("... waiting for '{}'".format(string))
while True:
try:
line = self.outq.get(block=False)
@@ -156,10 +158,10 @@
self.timeout -= 1
if not self.timeout:
logger.debug(
- "...timed out after {} sec".format(str(self.timeout))
+ "... timed out after {} sec".format(str(self.timeout))
)
return False
- logger.debug("...found")
+ logger.debug("... found")
return True
def _init_connection(self, cmd):
@@ -203,7 +205,7 @@
def do(self, cmd, timeout=30, sudo=False, strip_cmd=True):
cmd = cmd if isinstance(cmd, bytes) else bytes(cmd.encode('utf-8'))
- logger.debug("...ssh: '{}'".format(cmd))
+ logger.debug("... ssh: '{}'".format(cmd))
if sudo:
_cmd = b"sudo " + cmd
else:
@@ -376,7 +378,7 @@
self._cmd += [self._host_uri]
logger.debug(
- "...port forwarding: '{}'".format(" ".join(self._cmd))
+ "... port forwarding: '{}'".format(" ".join(self._cmd))
)
self._init_connection(self._cmd)
return self
diff --git a/cfg_checker/modules/network/checker.py b/cfg_checker/modules/network/checker.py
index b65e14d..c2de426 100644
--- a/cfg_checker/modules/network/checker.py
+++ b/cfg_checker/modules/network/checker.py
@@ -75,7 +75,7 @@
skip_list=None,
skip_list_file=None
):
- super(SaltNetworkChecker, self).__init__()
+ super(KubeNetworkChecker, self).__init__()
self.mapper = KubeNetworkMapper(
config,
errors_class=self.errors,
diff --git a/cfg_checker/modules/reclass/comparer.py b/cfg_checker/modules/reclass/comparer.py
index 3c308e0..c9cac60 100644
--- a/cfg_checker/modules/reclass/comparer.py
+++ b/cfg_checker/modules/reclass/comparer.py
@@ -66,7 +66,7 @@
# logger.warning("WARN: empty file '{}'".format(fname))
_yaml = {}
else:
- logger.debug("...loaded YAML '{}' ({}b)".format(fname, _size))
+ logger.debug("... loaded YAML '{}' ({}b)".format(fname, _size))
return _yaml
except yaml.YAMLError as exc:
logger_cli.error(exc)
diff --git a/cfg_checker/nodes.py b/cfg_checker/nodes.py
index fde217f..f0b7b38 100644
--- a/cfg_checker/nodes.py
+++ b/cfg_checker/nodes.py
@@ -813,7 +813,7 @@
self.not_responded = []
_results = {}
logger_cli.debug(
- "...running '{}' on active nodes, {} worker threads".format(
+ "... running '{}' on active nodes, {} worker threads".format(
script_filename,
self.env_config.threads
)
@@ -887,7 +887,7 @@
if not _folder_exists:
_sh.do("mkdir " + _folder)
logger_cli.debug(
- "...create data on node '{}':'{}'".format(node, _target_path)
+ "... create data on node '{}':'{}'".format(node, _target_path)
)
_code, _r, _e = _sh.scp(
_source_path,