Multi env support and Kube client integration
Kube friendly Beta
Package versions supports Kube env
Added:
- Env type detection
- New option: --use-env, for selecting env
when function supports multiple detected envs
- Updated config loading
- Each module and command type has supported env check
and stops execution if it is on unsupported env
- Functions can support multiple envs
- Kubernetes dependency
- Kubenernetes API detection: local and remote
- Package checking class hierachy for using Salt or Kube
- Remote pod execution routine
- Flexible SSH/SSH Forwarder classes: with, ssh,do(), etc
- Multithreaded SSH script execution
- Number of workers parameter, default 5
Fixed:
- Config dependency
- Command loading with supported envs list
- Unittests structure and execution flow updated
- Unittests fixes
- Fixed debug mode handling
- Unified command type/support routine
- Nested attrs getter/setter
Change-Id: I3ade693ac21536e2b5dcee4b24d511749dc72759
Related-PROD: PROD-35811
diff --git a/cfg_checker/common/salt_utils.py b/cfg_checker/common/salt_utils.py
index b3f5cae..f7ea50b 100644
--- a/cfg_checker/common/salt_utils.py
+++ b/cfg_checker/common/salt_utils.py
@@ -7,12 +7,13 @@
import requests
-from cfg_checker.common import config, logger, logger_cli
+from cfg_checker.common import logger, logger_cli
from cfg_checker.common.exception import InvalidReturnException, SaltException
from cfg_checker.common.other import shell
+from cfg_checker.common.ssh_utils import ssh_shell_p
-def _extract_password(_raw):
+def _extract_salt_password(_raw):
if not isinstance(_raw, str):
raise InvalidReturnException(_raw)
else:
@@ -26,45 +27,40 @@
return _json["local"]
-def get_remote_env_password():
+def get_remote_salt_env_password(config):
"""Uses ssh call with configured options to get password from salt master
:return: password string
"""
_salt_cmd = "salt-call --out=json pillar.get _param:salt_api_password"
- _ssh_cmd = ["ssh"]
- # Build SSH cmd
- if config.ssh_key:
- _ssh_cmd.append("-i " + config.ssh_key)
- if config.ssh_user:
- _ssh_cmd.append(config.ssh_user+'@'+config.ssh_host)
- else:
- _ssh_cmd.append(config.ssh_host)
- if config.ssh_uses_sudo:
- _ssh_cmd.append("sudo")
-
- _ssh_cmd.append(_salt_cmd)
- _ssh_cmd = " ".join(_ssh_cmd)
- logger_cli.debug("... calling salt: '{}'".format(_ssh_cmd))
+ logger_cli.debug("... calling salt using ssh: '{}'".format(_salt_cmd))
try:
- _result = shell(_ssh_cmd)
+ _result = ssh_shell_p(
+ _salt_cmd,
+ config.ssh_host,
+ username=config.ssh_user,
+ keypath=config.ssh_key,
+ piped=False,
+ use_sudo=config.ssh_uses_sudo,
+ silent=True
+ )
if len(_result) < 1:
raise InvalidReturnException(
"# Empty value returned for '{}".format(
- _ssh_cmd
+ _salt_cmd
)
)
else:
- return _extract_password(_result)
+ return _extract_salt_password(_result)
except OSError as e:
raise SaltException(
"Salt error calling '{}': '{}'\n"
- "\nConsider checking 'SALT_ENV' "
- "and '<pkg>/etc/<env>.env' files".format(_ssh_cmd, e.strerror)
+ "\nConsider checking 'MCP_ENV' "
+ "and '<pkg>/etc/<env>.env' files".format(_salt_cmd, e.strerror)
)
-def get_local_password():
+def get_salt_local_password(config):
"""Calls salt locally to get password from the pillar
:return: password string
@@ -80,10 +76,10 @@
except OSError as e:
raise SaltException(
"Salt error calling '{}': '{}'\n"
- "\nConsider checking 'SALT_ENV' "
+ "\nConsider checking 'MCP_ENV' "
"and '<pkg>/etc/<env>.env' files".format(_cmd, e.strerror)
)
- return _extract_password(_result)
+ return _extract_salt_password(_result)
def list_to_target_string(node_list, separator):
@@ -94,9 +90,6 @@
class SaltRest(object):
- _host = config.salt_host
- _port = config.salt_port
- uri = "http://" + config.salt_host + ":" + config.salt_port
_auth = {}
default_headers = {
@@ -105,7 +98,13 @@
'X-Auth-Token': None
}
- def __init__(self):
+ def __init__(self, config):
+ self.config = config
+
+ self._host = config.mcp_host
+ self._port = config.salt_port
+ self.uri = "http://" + config.mcp_host + ":" + config.salt_port
+
self._token = self._login()
self.last_response = None
@@ -154,12 +153,12 @@
def _login(self):
# if there is no password - try to get local, if this available
- if config.salt_env == "local":
- _pass = get_local_password()
+ if self.config.env_name == "local":
+ _pass = get_salt_local_password(self.config)
else:
- _pass = get_remote_env_password()
+ _pass = get_remote_salt_env_password(self.config)
login_payload = {
- 'username': config.salt_user,
+ 'username': self.config.salt_user,
'password': _pass,
'eauth': 'pam'
}
@@ -212,8 +211,8 @@
class SaltRemote(SaltRest):
master_node = ""
- def __init__(self):
- super(SaltRemote, self).__init__()
+ def __init__(self, config):
+ super(SaltRemote, self).__init__(config)
def cmd(
self,
@@ -226,7 +225,7 @@
tgt_type=None,
timeout=None
):
- _timeout = timeout if timeout is not None else config.salt_timeout
+ _timeout = timeout if timeout is not None else self.config.salt_timeout
_payload = {
'fun': fun,
'tgt': tgt,
@@ -256,7 +255,7 @@
_payload = {
'client': 'runner',
'fun': fun,
- 'timeout': config.salt_timeout
+ 'timeout': self.config.salt_timeout
}
if kwarg:
@@ -275,7 +274,7 @@
_payload = {
'client': 'wheel',
'fun': fun,
- 'timeout': config.salt_timeout
+ 'timeout': self.config.salt_timeout
}
if arg:
@@ -358,11 +357,13 @@
:return: json result from salt test.ping
"""
- if config.skip_nodes:
- logger.info("# Nodes to be skipped: {0}".format(config.skip_nodes))
+ if self.config.skip_nodes:
+ logger.info(
+ "# Nodes to be skipped: {0}".format(self.config.skip_nodes)
+ )
_r = self.cmd(
'* and not ' + list_to_target_string(
- config.skip_nodes,
+ self.config.skip_nodes,
'and not'
),
'test.ping',