diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b70e5d..b8f55b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ ### Changed +- Log the path of the Kubernetes config file used, if found +- Client have logging at debug level with `KUBERNETES_DEBUG` - Allow to not verify Kubernetes certificates even when using the default config or the one from a pod. This is useful when Kubernetes is deployed with a self-signed certificate. diff --git a/chaosk8s/__init__.py b/chaosk8s/__init__.py index 0e8946e..5616b66 100644 --- a/chaosk8s/__init__.py +++ b/chaosk8s/__init__.py @@ -14,9 +14,12 @@ __version__ = '0.25.1' -def has_local_config_file(): - config_path = os.path.expanduser( - os.environ.get('KUBECONFIG', '~/.kube/config')) +def get_config_path() -> str: + return os.path.expanduser(os.environ.get('KUBECONFIG', '~/.kube/config')) + + +def has_local_config_file(config_file: str = None): + config_path = config_file or get_config_path() return os.path.exists(config_path) @@ -61,25 +64,29 @@ def lookup(k: str, d: str = None) -> str: return secrets.get(k, env.get(k, d)) verify_ssl = lookup("KUBERNETES_VERIFY_SSL", False) is not False + debug = lookup("KUBERNETES_DEBUG", False) is not False + config_file = get_config_path() - if has_local_config_file(): + if has_local_config_file(config_file): context = lookup("KUBERNETES_CONTEXT") - logger.debug("Using Kubernetes context: {}".format( - context or "default")) + logger.debug( + "Using Kubernetes context '{}' from config '{}'".format( + context or "default", config_file)) config.load_kube_config(context=context) client.Configuration.verify_ssl = verify_ssl + client.Configuration.debug = debug proxy_url = os.getenv('HTTP_PROXY', None) if proxy_url: client.Configuration._default.proxy = proxy_url - return client.ApiClient() elif env.get("CHAOSTOOLKIT_IN_POD") == "true": config.load_incluster_config() client.Configuration.verify_ssl = verify_ssl + client.Configuration.debug = debug proxy_url = os.getenv('HTTP_PROXY', None) if proxy_url: @@ -89,7 +96,7 @@ def lookup(k: str, d: str = None) -> str: else: configuration = client.Configuration() - configuration.debug = True + configuration.debug = debug configuration.host = lookup("KUBERNETES_HOST", "http://localhost") configuration.verify_ssl = lookup( "KUBERNETES_VERIFY_SSL", False) is not False diff --git a/chaosk8s/pod/actions.py b/chaosk8s/pod/actions.py index 922325c..0acf8bb 100644 --- a/chaosk8s/pod/actions.py +++ b/chaosk8s/pod/actions.py @@ -17,6 +17,8 @@ from chaosk8s import create_k8s_api_client +import shlex + __all__ = ["terminate_pods", "exec_in_pods", "delete_pods"] @@ -112,7 +114,7 @@ def exec_in_pods(cmd: str, pods = _select_pods(v1, label_selector, name_pattern, all, rand, mode, qty, ns, order) - exec_command = cmd.strip().split() + exec_command = shlex.split(cmd) results = [] for po in pods: @@ -138,7 +140,16 @@ def exec_in_pods(cmd: str, resp.run_forever(timeout=request_timeout) - err = json.loads(resp.read_channel(ERROR_CHANNEL)) + # When timeout_request is triggered, resp.read_channel(ERROR_CHANNEL) + # could return a None object + try: + err = json.loads(resp.read_channel(ERROR_CHANNEL)) + except Exception: + err = json.loads('{"status": "Timedout", \ + "message": "Action has been timed out",\ + "details": {"causes": \ + [{"message": "Action stopped by timeout"}]}}') + out = resp.read_channel(STDOUT_CHANNEL) if err['status'] != "Success":