| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 1 | import os | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 2 | import json | 
|  | 3 | import pwd | 
| Alex | e9908f7 | 2020-05-19 16:04:53 -0500 | [diff] [blame] | 4 | import sys | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 5 |  | 
| Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 6 | from cfg_checker.common.exception import ConfigException | 
| Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 7 | from cfg_checker.common.log import logger_cli | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 8 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 9 | from cfg_checker.common.other import utils, shell | 
|  | 10 | from cfg_checker.common.ssh_utils import ssh_shell_p | 
|  | 11 |  | 
|  | 12 | from cfg_checker.clients import get_kube_remote | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 13 |  | 
|  | 14 | pkg_dir = os.path.dirname(__file__) | 
|  | 15 | pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir) | 
|  | 16 | pkg_dir = os.path.normpath(pkg_dir) | 
|  | 17 | pkg_dir = os.path.abspath(pkg_dir) | 
|  | 18 |  | 
|  | 19 | _default_work_folder = os.path.normpath(pkg_dir) | 
|  | 20 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 21 | ENV_TYPE_GLOB = "MCP" | 
|  | 22 | ENV_TYPE_SALT = "SALT" | 
|  | 23 | ENV_TYPE_KUBE = "KUBE" | 
|  | 24 | ENV_TYPE_LINUX = "LINUX" | 
|  | 25 |  | 
|  | 26 | ENV_LOCAL = "local" | 
|  | 27 |  | 
|  | 28 | supported_envs = [ENV_TYPE_LINUX, ENV_TYPE_SALT, ENV_TYPE_KUBE] | 
|  | 29 |  | 
|  | 30 |  | 
|  | 31 | def _extract_salt_return(_raw): | 
|  | 32 | if not isinstance(_raw, str): | 
|  | 33 | _json = _raw | 
|  | 34 | logger_cli.debug("...ambigious return detected") | 
|  | 35 | else: | 
|  | 36 | try: | 
|  | 37 | _json = json.loads(_raw) | 
|  | 38 | except ValueError: | 
|  | 39 | _json = _raw | 
|  | 40 | logger_cli.debug( | 
|  | 41 | "...return value is not a json: '{}'".format(_raw) | 
|  | 42 | ) | 
|  | 43 |  | 
|  | 44 | return _json | 
|  | 45 |  | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 46 |  | 
|  | 47 | class CheckerConfiguration(object): | 
| Alex | e9908f7 | 2020-05-19 16:04:53 -0500 | [diff] [blame] | 48 | @staticmethod | 
| Alex Savatieiev | 9df93a9 | 2019-02-27 17:40:16 -0600 | [diff] [blame] | 49 | def load_nodes_list(): | 
| Alex | e9908f7 | 2020-05-19 16:04:53 -0500 | [diff] [blame] | 50 | _file = os.environ.get('SALT_NODE_LIST_FILE', None) | 
|  | 51 | if _file: | 
|  | 52 | _v, _ = utils.get_nodes_list( | 
|  | 53 | os.path.join(pkg_dir, _file), | 
|  | 54 | env_sting=os.environ.get('CFG_ALL_NODES', None) | 
|  | 55 | ) | 
|  | 56 | return _v | 
|  | 57 | else: | 
|  | 58 | return None | 
| Alex Savatieiev | 9df93a9 | 2019-02-27 17:40:16 -0600 | [diff] [blame] | 59 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 60 | def _detect(self, _type): | 
|  | 61 | logger_cli.debug("...detecting '{}'".format(_type)) | 
|  | 62 | if _type is None: | 
|  | 63 | raise ConfigException("# Unexpected supported env type") | 
|  | 64 | elif _type == ENV_TYPE_SALT: | 
|  | 65 | # Detect salt env | 
|  | 66 | _detect_cmd = ["curl", "-s"] | 
|  | 67 | _detect_cmd.append( | 
|  | 68 | "http://" + self.mcp_host + ':' + self.salt_port | 
|  | 69 | ) | 
|  | 70 | # Try to call salt API on target host | 
|  | 71 | _r = None | 
|  | 72 | logger_cli.debug("...trying to detect env type '{}'".format(_type)) | 
|  | 73 | if self.env_name == ENV_LOCAL: | 
|  | 74 | _r = shell(" ".join(_detect_cmd)) | 
|  | 75 | else: | 
|  | 76 | _r = ssh_shell_p( | 
|  | 77 | " ".join(_detect_cmd), | 
|  | 78 | self.ssh_host, | 
|  | 79 | username=self.ssh_user, | 
|  | 80 | keypath=self.ssh_key, | 
|  | 81 | piped=False, | 
|  | 82 | use_sudo=self.ssh_uses_sudo, | 
|  | 83 | silent=True | 
|  | 84 | ) | 
|  | 85 | # Parse return | 
|  | 86 | _r = _extract_salt_return(_r) | 
|  | 87 |  | 
|  | 88 | if len(_r) < 1: | 
|  | 89 | return False | 
|  | 90 | elif _r["return"] == "Welcome": | 
|  | 91 | return True | 
|  | 92 | else: | 
|  | 93 | return False | 
|  | 94 | elif _type == ENV_TYPE_KUBE: | 
|  | 95 | _kube = get_kube_remote(self) | 
|  | 96 | try: | 
|  | 97 | _vApi = _kube.get_versions_api() | 
|  | 98 | _v = _vApi.get_code() | 
|  | 99 | if hasattr(_v, "platform") and \ | 
|  | 100 | hasattr(_v, "major") and \ | 
|  | 101 | hasattr(_v, "minor"): | 
|  | 102 | _host = "localhost" if _kube.is_local else _kube.kConf.host | 
|  | 103 | logger_cli.info( | 
|  | 104 | "# Kube server found: {}:{} on '{}'".format( | 
|  | 105 | _v.major, | 
|  | 106 | _v.minor, | 
|  | 107 | _host | 
|  | 108 | ) | 
|  | 109 | ) | 
|  | 110 | return True | 
|  | 111 | else: | 
|  | 112 | return False | 
|  | 113 | except Exception as e: | 
|  | 114 | logger_cli.warn( | 
|  | 115 | "# Unexpected error finding Kube env: '{}' ".format( | 
|  | 116 | str(e) | 
|  | 117 | ) | 
|  | 118 | ) | 
|  | 119 | return False | 
|  | 120 | elif _type == ENV_TYPE_LINUX: | 
|  | 121 | # Detect Linux env | 
|  | 122 | from platform import system, release | 
|  | 123 | _s = system() | 
|  | 124 | _r = release() | 
|  | 125 | logger_cli.debug("...running on {} {}".format(_s, _r)) | 
|  | 126 | if _s in ['Linux', 'Darwin']: | 
|  | 127 | return True | 
|  | 128 | else: | 
|  | 129 | return False | 
|  | 130 | else: | 
|  | 131 | raise ConfigException( | 
|  | 132 | "# Env type of '{}' is not supported".format( | 
|  | 133 | _type | 
|  | 134 | ) | 
|  | 135 | ) | 
|  | 136 |  | 
|  | 137 | def _detect_types(self): | 
|  | 138 | """Try to detect env type based on the name | 
|  | 139 | """ | 
|  | 140 | self.detected_envs = [] | 
|  | 141 | logger_cli.info('# Detecting env types') | 
|  | 142 | for _env in supported_envs: | 
|  | 143 | if self._detect(_env): | 
|  | 144 | logger_cli.info("# '{}' found".format(_env)) | 
|  | 145 | self.detected_envs.append(_env) | 
|  | 146 | else: | 
|  | 147 | logger_cli.info("# '{}' not found".format(_env)) | 
|  | 148 |  | 
|  | 149 | return | 
|  | 150 |  | 
|  | 151 | def _init_mcp_values(self): | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 152 | """Load values from environment variables or put default ones | 
|  | 153 | """ | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 154 | # filter vars and preload if needed | 
|  | 155 | self.salt_vars = [] | 
|  | 156 | self.kube_vars = [] | 
|  | 157 | for _key, _value in self.vars: | 
|  | 158 | if _key.startswith(ENV_TYPE_GLOB): | 
|  | 159 | os.environ[_key] = _value | 
|  | 160 | elif _key.startswith(ENV_TYPE_SALT): | 
|  | 161 | self.salt_vars.append([_key, _value]) | 
|  | 162 | elif _key.startswith(ENV_TYPE_KUBE): | 
|  | 163 | self.kube_vars.append([_key, _value]) | 
|  | 164 | else: | 
|  | 165 | logger_cli.warn( | 
|  | 166 | "Unsupported config variable: '{}={}'".format( | 
|  | 167 | _key, | 
|  | 168 | _value | 
|  | 169 | ) | 
|  | 170 | ) | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 171 | self.name = "CheckerConfig" | 
|  | 172 | self.working_folder = os.environ.get( | 
|  | 173 | 'CFG_TESTS_WORK_DIR', | 
|  | 174 | _default_work_folder | 
|  | 175 | ) | 
|  | 176 | self.date_format = "%Y-%m-%d %H:%M:%S.%f%z" | 
|  | 177 | self.default_tz = "UTC" | 
|  | 178 |  | 
| Alex | 4148552 | 2019-04-12 17:26:18 -0500 | [diff] [blame] | 179 | self.pkg_versions_map = 'versions_map.csv' | 
|  | 180 |  | 
| Alex Savatieiev | 6357683 | 2019-02-27 15:46:26 -0600 | [diff] [blame] | 181 | self.ssh_uses_sudo = False | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 182 | self.ssh_key = os.environ.get('MCP_SSH_KEY', None) | 
|  | 183 | self.ssh_user = os.environ.get('MCP_SSH_USER', None) | 
|  | 184 | self.ssh_host = os.environ.get('MCP_SSH_HOST', None) | 
| Alex Savatieiev | 6357683 | 2019-02-27 15:46:26 -0600 | [diff] [blame] | 185 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 186 | self.mcp_host = os.environ.get('MCP_ENV_HOST', None) | 
|  | 187 | self.salt_port = os.environ.get('MCP_SALT_PORT', '6969') | 
|  | 188 | self.threads = int(os.environ.get('MCP_THREADS', "5")) | 
| Alex Savatieiev | 9df93a9 | 2019-02-27 17:40:16 -0600 | [diff] [blame] | 189 |  | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 190 | self.skip_nodes = utils.node_string_to_list(os.environ.get( | 
|  | 191 | 'CFG_SKIP_NODES', | 
|  | 192 | None | 
|  | 193 | )) | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 194 | # prebuild user data and folder path | 
|  | 195 | self.pw_user = pwd.getpwuid(os.getuid()) | 
|  | 196 | if self.env_name == "local": | 
|  | 197 | pass | 
|  | 198 | else: | 
|  | 199 | if not self.ssh_key and not self.force_no_key: | 
|  | 200 | raise ConfigException( | 
|  | 201 | "Please, supply a key for the cluster's master node. " | 
|  | 202 | "Use MCP_SSH_KEY, see 'etc/example.env'" | 
|  | 203 | ) | 
|  | 204 |  | 
|  | 205 | def _init_env_values(self): | 
|  | 206 | if ENV_TYPE_SALT in self.detected_envs: | 
|  | 207 | for _key, _value in self.salt_vars: | 
|  | 208 | os.environ[_key] = _value | 
|  | 209 |  | 
|  | 210 | self.salt_user = os.environ.get('SALT_USER', 'salt') | 
|  | 211 | self.salt_timeout = os.environ.get('SALT_TIMEOUT', 30) | 
|  | 212 | self.salt_file_root = os.environ.get('SALT_FILE_ROOT', None) | 
|  | 213 | self.salt_scripts_folder = os.environ.get( | 
|  | 214 | 'SALT_SCRIPTS_FOLDER', | 
|  | 215 | 'cfg_checker_scripts' | 
|  | 216 | ) | 
|  | 217 | elif ENV_TYPE_KUBE in self.detected_envs: | 
|  | 218 | for _key, _value in self.kube_vars: | 
|  | 219 | os.environ[_key] = _value | 
|  | 220 |  | 
|  | 221 | self.kube_config_root = os.environ.get('KUBE_CONFIG_ROOT', None) | 
|  | 222 | self.kube_scripts_folder = os.environ.get( | 
|  | 223 | 'KUBE_SCRIPTS_FOLDER', | 
|  | 224 | None | 
|  | 225 | ) | 
|  | 226 | self.kube_node_user = os.environ.get( | 
|  | 227 | 'KUBE_NODE_USER', | 
|  | 228 | 'ubuntu' | 
|  | 229 | ) | 
|  | 230 | self.kube_node_keypath = os.environ.get( | 
|  | 231 | 'KUBE_NODE_KEYPATH', | 
|  | 232 | None | 
|  | 233 | ) | 
|  | 234 | # Warn user only if Kube env is detected locally | 
|  | 235 | if self.env_name == "local": | 
|  | 236 | if not os.path.exists(self.kube_config_path): | 
|  | 237 | logger_cli.warn( | 
|  | 238 | "Kube config path not found on local env: '{}'".format( | 
|  | 239 | self.kube_config_path | 
|  | 240 | ) | 
|  | 241 | ) | 
|  | 242 | # On local envs, KUBE_NODE_KEYPATH is mandatory and is | 
|  | 243 | # provided to give cfg-checker access to kube nodes | 
|  | 244 | if not self.kube_node_keypath and not self.force_no_key: | 
|  | 245 | raise ConfigException( | 
|  | 246 | "Please, supply a key for the cluster nodes. " | 
|  | 247 | "Use KUBE_NODE_KEYPATH, see 'etc/example.env'. " | 
|  | 248 | "Consider checking KUBE_NODE_USER as well" | 
|  | 249 | ) | 
|  | 250 | else: | 
|  | 251 | # Init keys for nodes in case of remote env | 
|  | 252 | # KUBE_NODE_KEYPATH is provided in case of nodes key would be | 
|  | 253 | # different to master nodes key, which is supplied | 
|  | 254 | # using MCP_SSH_KEY (mandatory) and, for the most cases, | 
|  | 255 | # should be the same for remote envs | 
|  | 256 | if not self.kube_node_keypath and not self.force_no_key: | 
|  | 257 | logger_cli.debug( | 
|  | 258 | "... using MCP_SSH_KEY as node keys. " | 
|  | 259 | "Supply KUBE_NODE_KEYPATH to update." | 
|  | 260 | ) | 
|  | 261 | self.kube_node_keypath = self.ssh_key | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 262 |  | 
| Alex Savatieiev | 6357683 | 2019-02-27 15:46:26 -0600 | [diff] [blame] | 263 | def _init_env(self, env_name=None): | 
|  | 264 | """Inits the environment vars from the env file | 
|  | 265 | Uses simple validation for the values and names | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 266 |  | 
|  | 267 | Keyword Arguments: | 
|  | 268 | env_name {str} -- environment name to search configuration | 
|  | 269 | files in etc/<env_name>.env (default: {None}) | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 270 | env_type {str} -- environment type to use: salt/kube | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 271 |  | 
|  | 272 | Raises: | 
|  | 273 | ConfigException -- on IO error when loading env file | 
|  | 274 | ConfigException -- on env file failed validation | 
|  | 275 | """ | 
|  | 276 | # load env file as init os.environment with its values | 
|  | 277 | if env_name is None: | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 278 | _env_name = ENV_LOCAL | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 279 | else: | 
|  | 280 | _env_name = env_name | 
|  | 281 | _config_path = os.path.join(pkg_dir, 'etc', _env_name + '.env') | 
|  | 282 | if os.path.isfile(_config_path): | 
|  | 283 | with open(_config_path) as _f: | 
|  | 284 | _list = _f.read().splitlines() | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 285 | logger_cli.info( | 
|  | 286 | "# Loading env vars from '{}'".format( | 
|  | 287 | _config_path | 
|  | 288 | ) | 
|  | 289 | ) | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 290 | else: | 
|  | 291 | raise ConfigException( | 
| Alex Savatieiev | f808cd2 | 2019-03-01 13:17:59 -0600 | [diff] [blame] | 292 | "# Failed to load enviroment vars from '{}'".format( | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 293 | _config_path | 
|  | 294 | ) | 
|  | 295 | ) | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 296 | self.vars = [] | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 297 | for index in range(len(_list)): | 
|  | 298 | _line = _list[index] | 
|  | 299 | # skip comments | 
|  | 300 | if _line.strip().startswith('#'): | 
|  | 301 | continue | 
|  | 302 | # validate | 
|  | 303 | _errors = [] | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 304 | if len(_line) < 1: | 
|  | 305 | _errors.append("Line {}: empty".format(index)) | 
|  | 306 | elif _line.find('=') < 0 or _line.count('=') > 1: | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 307 | _errors.append("Line {}: {}".format(index, _line)) | 
|  | 308 | else: | 
|  | 309 | # save values | 
|  | 310 | _t = _line.split('=') | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 311 | self.vars.append([_t[0], _t[1]]) | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 312 | # if there was errors, report them | 
|  | 313 | if _errors: | 
|  | 314 | raise ConfigException( | 
| Alex Savatieiev | f808cd2 | 2019-03-01 13:17:59 -0600 | [diff] [blame] | 315 | "# Environment file failed validation in lines: {}".format( | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 316 | "\n".join(_errors) | 
|  | 317 | ) | 
|  | 318 | ) | 
|  | 319 | else: | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 320 | logger_cli.debug( | 
|  | 321 | "-> ...loaded total of '{}' vars".format( | 
|  | 322 | len(_list) | 
|  | 323 | ) | 
|  | 324 | ) | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 325 | self.env_name = _env_name | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 326 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 327 | def __init__(self, args): | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 328 | """Base configuration class. Only values that are common for all scripts | 
|  | 329 | """ | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 330 | self.ssh_uses_sudo = args.sudo | 
|  | 331 | self.kube_config_path = args.kube_config_path | 
|  | 332 | self.debug = args.debug | 
|  | 333 | self.force_no_key = args.force_no_key | 
| Alex | e9908f7 | 2020-05-19 16:04:53 -0500 | [diff] [blame] | 334 | # Make sure we running on Python 3 | 
|  | 335 | if sys.version_info[0] < 3 and sys.version_info[1] < 5: | 
|  | 336 | logger_cli.error("# ERROR: Python 3.5+ is required") | 
|  | 337 | sys.exit(1) | 
|  | 338 | else: | 
|  | 339 | logger_cli.debug("### Python version is {}.{}".format( | 
|  | 340 | sys.version_info[0], | 
|  | 341 | sys.version_info[1] | 
|  | 342 | )) | 
|  | 343 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 344 | _env = os.getenv('MCP_ENV', None) | 
|  | 345 |  | 
|  | 346 | # Init environment variables from file, validate | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 347 | self._init_env(_env) | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 348 | # Load Common vars for any type of the env | 
|  | 349 | self._init_mcp_values() | 
|  | 350 | # Detect env types present | 
|  | 351 | self._detect_types() | 
|  | 352 | # handle forced env type var | 
|  | 353 | _forced_type = os.getenv('MCP_TYPE_FORCE', None) | 
|  | 354 | if _forced_type in supported_envs: | 
|  | 355 | self.detected_envs.append(_forced_type) | 
|  | 356 | elif _forced_type is not None: | 
|  | 357 | logger_cli.warn( | 
|  | 358 | "Unsupported forced type of '{}'".format( | 
|  | 359 | _forced_type | 
|  | 360 | ) | 
|  | 361 | ) | 
|  | 362 | # Check if any of the envs detected | 
|  | 363 | if len(self.detected_envs) < 1: | 
|  | 364 | if _env is None: | 
|  | 365 | raise ConfigException("No environment types detected locally") | 
|  | 366 | else: | 
|  | 367 | raise ConfigException( | 
|  | 368 | "No environment types detected at '{}'".format( | 
|  | 369 | self.mcp_host | 
|  | 370 | ) | 
|  | 371 | ) | 
|  | 372 | # Init vars that is specific to detected envs only | 
|  | 373 | self._init_env_values() | 
| Alex Savatieiev | 5118de0 | 2019-02-20 15:50:42 -0600 | [diff] [blame] | 374 |  | 
| Alex | 9a4ad21 | 2020-10-01 18:04:25 -0500 | [diff] [blame^] | 375 | # initialize path to folders | 
|  | 376 | if self.env_name == "local": | 
|  | 377 | # names and folders | 
|  | 378 | self.user = self.pw_user.pw_name | 
|  | 379 | self.homepath = self.pw_user.pw_dir | 
|  | 380 | self.node_homepath = os.path.join('/home', self.kube_node_user) | 
|  | 381 | else: | 
|  | 382 | # names and folders in case of remote env | 
|  | 383 | self.user = self.ssh_user | 
|  | 384 | self.homepath = os.path.join('/home', self.ssh_user) | 
|  | 385 | self.node_homepath = self.homepath |