From b3dbde16375d6c82a0524b441ef8ff47ab64c955 Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Wed, 27 Apr 2022 17:47:27 +0300 Subject: [PATCH 01/14] Fix configurations Signed-off-by: roeiK-wix --- chaoslib/configuration.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/chaoslib/configuration.py b/chaoslib/configuration.py index d45f180e..e8ee76d8 100644 --- a/chaoslib/configuration.py +++ b/chaoslib/configuration.py @@ -66,6 +66,11 @@ def load_configuration( conf = {} for (key, value) in config_info.items(): + # ----------------FIX---------------- + if extra_vars.get(key): + value = extra_vars[key] + del extra_vars[key] + # ------------------------------------ if isinstance(value, dict) and "type" in value: if value["type"] == "env": env_key = value["key"] @@ -148,14 +153,13 @@ def load_dynamic_configuration( # from elsewhere from chaoslib.activity import run_activity - conf = {} secrets = secrets or {} had_errors = False logger.debug("Loading dynamic configuration...") for (key, value) in config.items(): if not (isinstance(value, dict) and value.get("type") == "probe"): - conf[key] = config.get(key, value) + config[key] = config.get(key, value) continue # we have a dynamic config @@ -163,14 +167,14 @@ def load_dynamic_configuration( provider_type = value["provider"]["type"] value["provider"]["secrets"] = deepcopy(secrets) try: - output = run_activity(value, conf, secrets) + output = run_activity(value, config, secrets) except Exception: had_errors = True logger.debug(f"Failed to load configuration '{name}'", exc_info=True) continue if provider_type == "python": - conf[key] = output + config[key] = output elif provider_type == "process": if output["status"] != 0: had_errors = True @@ -179,9 +183,9 @@ def load_dynamic_configuration( f"from probe '{name}': {output['stderr']}" ) else: - conf[key] = output.get("stdout", "").strip() + config[key] = output.get("stdout", "").strip() elif provider_type == "http": - conf[key] = output.get("body") + config[key] = output.get("body") if had_errors: logger.warning( @@ -189,4 +193,4 @@ def load_dynamic_configuration( "Please review the log file for understanding what happened." ) - return conf + return config From 8d25bee319823df190b117e143f16cd10ef0dd4b Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Wed, 27 Apr 2022 18:57:29 +0300 Subject: [PATCH 02/14] Fix test_configurations Signed-off-by: roeiK-wix --- chaoslib/configuration.py | 6 +++--- tests/test_configuration.py | 31 ++++++++++++++++++------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/chaoslib/configuration.py b/chaoslib/configuration.py index e8ee76d8..a78f2590 100644 --- a/chaoslib/configuration.py +++ b/chaoslib/configuration.py @@ -154,7 +154,7 @@ def load_dynamic_configuration( from chaoslib.activity import run_activity secrets = secrets or {} - + # output = None had_errors = False logger.debug("Loading dynamic configuration...") for (key, value) in config.items(): @@ -168,10 +168,10 @@ def load_dynamic_configuration( value["provider"]["secrets"] = deepcopy(secrets) try: output = run_activity(value, config, secrets) - except Exception: + except Exception as err: had_errors = True logger.debug(f"Failed to load configuration '{name}'", exc_info=True) - continue + raise err if provider_type == "python": config[key] = output diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 28772342..4cbf21f4 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -306,22 +306,23 @@ def test_that_environment_variables_are_typed_correctly(): def test_dynamic_configuration_exception_means_output_is_missing(): - config = load_dynamic_configuration( - { - "somekey": "hello world", - "token": { - "type": "probe", - "provider": { - "type": "python", - "module": "fixtures.configprobe", - "func": "raise_exception", + config = {"somekey": "hello world"} + with pytest.raises(Exception): + config = load_dynamic_configuration( + { + "somekey": "hello world", + "token": { + "type": "probe", + "provider": { + "type": "python", + "module": "fixtures.configprobe", + "func": "raise_exception", + }, }, - }, - } - ) + } + ) assert config["somekey"] == "hello world" - assert "token" not in config def test_dynamic_configuration_can_be_used_next_key(): @@ -350,3 +351,7 @@ def test_dynamic_configuration_can_be_used_next_key(): assert config["capped"] == "Hello World From Earth" assert config["shorten"] == "Hello [...]" + + +if __name__ == "__main__": + test_dynamic_configuration_exception_means_output_is_missing() From e5299091438be7078c777807be2da15f346d4360 Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Wed, 27 Apr 2022 19:01:15 +0300 Subject: [PATCH 03/14] Add CHANGELOG Signed-off-by: roeiK-wix --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fec5101..01832f68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ [1.27.3]: https://github.com/chaostoolkit/chaostoolkit-lib/compare/1.27.2...1.27.3 +### Fix + +- Fix bug in load_configurations + ### Changed - Ensure experiment level controls are only played once From a003b107d000354504c8a18b597c9587d29b623b Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Thu, 28 Apr 2022 15:58:16 +0300 Subject: [PATCH 04/14] Fix lint Signed-off-by: roeiK-wix --- chaoslib/provider/python.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/chaoslib/provider/python.py b/chaoslib/provider/python.py index 9836afd8..c74a2e41 100644 --- a/chaoslib/provider/python.py +++ b/chaoslib/provider/python.py @@ -88,10 +88,13 @@ def validate_python_activity(activity: Activity): # noqa: C901 try: mod = importlib.import_module(mod_name) - except ImportError: + except ImportError as err: raise InvalidActivity( - "could not find Python module '{mod}' " - "in activity '{name}'".format(mod=mod_name, name=activity_name) + "could not find Python module '{mod}'" + "in activity '{name}'" + "\nerror traceback:\n{error}".format( + mod=mod_name, name=activity_name, error=err + ) ) found_func = False From 2a4f3fca65a255c6a4abd25972e8f95e263f418d Mon Sep 17 00:00:00 2001 From: wix-chaos-hub <71383428+wix-chaos-hub@users.noreply.github.com> Date: Tue, 22 Aug 2023 18:52:37 +0300 Subject: [PATCH 05/14] Update requirements.txt --- requirements.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index ed4460f9..65eb2996 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,10 @@ +# logzero>=1.5.0 +# requests>=2.21 +# pyyaml~=5.4 +# importlib-metadata~=1.2; python_version < '3.8' +# importlib-metadata~=4.4; python_version > '3.9' +# contextvars;python_version<"3.7" logzero>=1.5.0 requests>=2.21 -pyyaml~=5.4 -importlib-metadata~=1.2; python_version < '3.8' -importlib-metadata~=4.4; python_version > '3.9' -contextvars;python_version<"3.7" \ No newline at end of file +pyyaml~=6.0 +importlib-metadata>=6.0 From 96199fd0ce255bbc8f208ddfe97b4c8c5713977f Mon Sep 17 00:00:00 2001 From: wix-chaos-hub <71383428+wix-chaos-hub@users.noreply.github.com> Date: Tue, 22 Aug 2023 18:55:09 +0300 Subject: [PATCH 06/14] Update __init__.py v1.27.3->v1.38.0 --- chaoslib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaoslib/__init__.py b/chaoslib/__init__.py index 457d4151..bd516d29 100644 --- a/chaoslib/__init__.py +++ b/chaoslib/__init__.py @@ -41,7 +41,7 @@ "convert_vars", "PayloadEncoder", ] -__version__ = "1.27.3" +__version__ = "1.38.0" def substitute( From 122dfb96d73eefc955c1b1969f2297e5eb69b277 Mon Sep 17 00:00:00 2001 From: wix-chaos-hub <71383428+wix-chaos-hub@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:00:55 +0300 Subject: [PATCH 07/14] Update setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 4c7fdcc2..7b583e31 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,7 +49,7 @@ setup_requires = install_requires = logzero~=1.5 requests~=2.21 - pyyaml~=5.4 + pyyaml~=6.0 contextvars;python_version<"3.7" importlib-metadata~=1.2; python_version < '3.8' importlib-metadata~=4.4; python_version > '3.9' From b602914648f298d893c04eacd43d6520a3236b8a Mon Sep 17 00:00:00 2001 From: wix-chaos-hub <71383428+wix-chaos-hub@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:03:11 +0300 Subject: [PATCH 08/14] Update requirements.txt to pyyaml~=6.0 --- requirements.txt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 65eb2996..3359c2e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,6 @@ -# logzero>=1.5.0 -# requests>=2.21 -# pyyaml~=5.4 -# importlib-metadata~=1.2; python_version < '3.8' -# importlib-metadata~=4.4; python_version > '3.9' -# contextvars;python_version<"3.7" logzero>=1.5.0 requests>=2.21 pyyaml~=6.0 -importlib-metadata>=6.0 +importlib-metadata~=1.2; python_version < '3.8' +importlib-metadata~=4.4; python_version > '3.9' +contextvars;python_version<"3.7" From 18de92823c7d08978c02fd86dbcf056eff3b9aa0 Mon Sep 17 00:00:00 2001 From: wix-chaos-hub <71383428+wix-chaos-hub@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:46:33 +0300 Subject: [PATCH 09/14] Update version 1.38.0->1.29.0 --- chaoslib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaoslib/__init__.py b/chaoslib/__init__.py index bd516d29..742667bc 100644 --- a/chaoslib/__init__.py +++ b/chaoslib/__init__.py @@ -41,7 +41,7 @@ "convert_vars", "PayloadEncoder", ] -__version__ = "1.38.0" +__version__ = "1.29.0" def substitute( From 5957801d61244173ded6e2a32faba2f703bb6cbc Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Mon, 4 Nov 2024 12:27:02 +0200 Subject: [PATCH 10/14] Add logs --- chaoslib/experiment.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/chaoslib/experiment.py b/chaoslib/experiment.py index 905687c2..4913bd00 100644 --- a/chaoslib/experiment.py +++ b/chaoslib/experiment.py @@ -71,12 +71,17 @@ def ensure_experiment_is_valid(experiment: Experiment): if list(filter(lambda t: t == "" or not isinstance(t, str), tags)): raise InvalidExperiment("experiment tags must be a non-empty string") + logger.info("Pass 1") validate_extensions(experiment) + logger.info("Pass 2") config = load_configuration(experiment.get("configuration", {})) + logger.info("Pass 3") load_secrets(experiment.get("secrets", {}), config) + logger.info("Pass 4") ensure_hypothesis_is_valid(experiment) + logger.info("Pass 5") method = experiment.get("method") if method is None: @@ -87,8 +92,10 @@ def ensure_experiment_is_valid(experiment: Experiment): "which can be empty for only checking steady state hypothesis " ) + logger.info("Pass 6") for activity in method: ensure_activity_is_valid(activity) + logger.info("Pass 7") # let's see if a ref is indeed found in the experiment ref = activity.get("ref") @@ -98,13 +105,18 @@ def ensure_experiment_is_valid(experiment: Experiment): "found in the experiment".format(r=ref) ) + logger.info("Pass 8") rollbacks = experiment.get("rollbacks", []) + logger.info("Pass 9") for activity in rollbacks: ensure_activity_is_valid(activity) + logger.info("Pass 10") warn_about_deprecated_features(experiment) + logger.info("Pass 11") validate_controls(experiment) + logger.info("Pass 12") logger.info("Experiment looks valid") From 5751d7d68625cfa8a461b7048a6ac6c3d0e79e01 Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Mon, 4 Nov 2024 12:33:34 +0200 Subject: [PATCH 11/14] Add more logs --- chaoslib/hypothesis.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/chaoslib/hypothesis.py b/chaoslib/hypothesis.py index adf2124b..01cc09d7 100644 --- a/chaoslib/hypothesis.py +++ b/chaoslib/hypothesis.py @@ -29,20 +29,27 @@ def ensure_hypothesis_is_valid(experiment: Experiment): or raises :exc:`InvalidExperiment` or :exc:`InvalidActivity`. """ hypo = experiment.get("steady-state-hypothesis") + logger.info("ensure_hypothesis_is_valid 1") if hypo is None: return + logger.info("ensure_hypothesis_is_valid 2") if not hypo.get("title"): raise InvalidExperiment("hypothesis requires a title") + logger.info("ensure_hypothesis_is_valid 3") probes = hypo.get("probes") + logger.info("ensure_hypothesis_is_valid 4") if probes: + logger.info("ensure_hypothesis_is_valid 5") for probe in probes: + logger.info(f"ensure_hypothesis_is_valid prob: {probe}") ensure_activity_is_valid(probe) if "tolerance" not in probe: raise InvalidActivity("hypothesis probe must have a tolerance entry") + logger.info("ensure_hypothesis_is_valid 6") ensure_hypothesis_tolerance_is_valid(probe["tolerance"]) From 3d829c342aac75e15fa7d1b5eec6d4a8dcf9215c Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Mon, 4 Nov 2024 12:45:13 +0200 Subject: [PATCH 12/14] Add more logs p2 --- chaoslib/activity.py | 15 +++++++++++++++ chaoslib/provider/python.py | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/chaoslib/activity.py b/chaoslib/activity.py index f09ea10b..c94b38bb 100644 --- a/chaoslib/activity.py +++ b/chaoslib/activity.py @@ -35,45 +35,57 @@ def ensure_activity_is_valid(activity: Activity): # noqa: C901 In all failing cases, raises :exc:`InvalidActivity`. """ + logger.info("ensuring activity is valid 1") if not activity: raise InvalidActivity("empty activity is no activity") + logger.info("ensuring activity is valid 2") # when the activity is just a ref, there is little to validate ref = activity.get("ref") + logger.info("ensuring activity is valid 3") if ref is not None: if not isinstance(ref, str) or ref == "": raise InvalidActivity("reference to activity must be non-empty strings") return + logger.info("ensuring activity is valid 4") activity_type = activity.get("type") if not activity_type: raise InvalidActivity("an activity must have a type") + logger.info("ensuring activity is valid 5") if activity_type not in ("probe", "action"): raise InvalidActivity(f"'{activity_type}' is not a supported activity type") + logger.info("ensuring activity is valid 6") if not activity.get("name"): raise InvalidActivity("an activity must have a name") + logger.info("ensuring activity is valid 7") provider = activity.get("provider") if not provider: raise InvalidActivity("an activity requires a provider") + logger.info("ensuring activity is valid 8") provider_type = provider.get("type") if not provider_type: raise InvalidActivity("a provider must have a type") + logger.info("ensuring activity is valid 9") if provider_type not in ("python", "process", "http"): raise InvalidActivity(f"unknown provider type '{provider_type}'") + logger.info("ensuring activity is valid 10") if not activity.get("name"): raise InvalidActivity("activity must have a name (cannot be empty)") + logger.info("ensuring activity is valid 11") timeout = activity.get("timeout") if timeout is not None: if not isinstance(timeout, numbers.Number): raise InvalidActivity("activity timeout must be a number") + logger.info("ensuring activity is valid 12") pauses = activity.get("pauses") if pauses is not None: before = pauses.get("before") @@ -83,16 +95,19 @@ def ensure_activity_is_valid(activity: Activity): # noqa: C901 if after is not None and not isinstance(after, numbers.Number): raise InvalidActivity("activity after pause must be a number") + logger.info("ensuring activity is valid 13") if "background" in activity: if not isinstance(activity["background"], bool): raise InvalidActivity("activity background must be a boolean") + logger.info("ensuring activity is valid 14") if provider_type == "python": validate_python_activity(activity) elif provider_type == "process": validate_process_activity(activity) elif provider_type == "http": validate_http_activity(activity) + logger.info("ensuring activity is valid 15") def run_activities( diff --git a/chaoslib/provider/python.py b/chaoslib/provider/python.py index c74a2e41..a1871b79 100644 --- a/chaoslib/provider/python.py +++ b/chaoslib/provider/python.py @@ -76,18 +76,24 @@ def validate_python_activity(activity: Activity): # noqa: C901 This should be considered as a private function. """ + logger.info("validate_python_activity 1") activity_name = activity["name"] provider = activity["provider"] mod_name = provider.get("module") + logger.info("validate_python_activity 2") if not mod_name: raise InvalidActivity("a Python activity must have a module path") + logger.info("validate_python_activity 3") func = provider.get("func") if not func: raise InvalidActivity("a Python activity must have a function name") + logger.info("validate_python_activity 4") try: + logger.info("validate_python_activity 5") mod = importlib.import_module(mod_name) + logger.info("validate_python_activity 6") except ImportError as err: raise InvalidActivity( "could not find Python module '{mod}'" @@ -97,11 +103,14 @@ def validate_python_activity(activity: Activity): # noqa: C901 ) ) + logger.info("validate_python_activity 7") found_func = False arguments = provider.get("arguments", {}) + logger.info("validate_python_activity 7") candidates = set(inspect.getmembers(mod, inspect.isfunction)).union( inspect.getmembers(mod, inspect.isbuiltin) ) + logger.info("validate_python_activity 8") for (name, cb) in candidates: if name == func: found_func = True @@ -147,6 +156,7 @@ def validate_python_activity(activity: Activity): # noqa: C901 raise break + logger.info("validate_python_activity 9") if not found_func: raise InvalidActivity( "The python module '{mod}' does not expose a function called " @@ -154,3 +164,4 @@ def validate_python_activity(activity: Activity): # noqa: C901 mod=mod_name, func=func, type=activity["type"], name=activity_name ) ) + logger.info("validate_python_activity 10") From 2e55dcaf98905648dbb1c3442e2b96270f3dfa63 Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Mon, 4 Nov 2024 13:18:26 +0200 Subject: [PATCH 13/14] Add mod name to log --- chaoslib/provider/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaoslib/provider/python.py b/chaoslib/provider/python.py index a1871b79..6af72761 100644 --- a/chaoslib/provider/python.py +++ b/chaoslib/provider/python.py @@ -91,7 +91,7 @@ def validate_python_activity(activity: Activity): # noqa: C901 logger.info("validate_python_activity 4") try: - logger.info("validate_python_activity 5") + logger.info(f"validate_python_activity 5 mod_name: {mod_name}") mod = importlib.import_module(mod_name) logger.info("validate_python_activity 6") except ImportError as err: From f56079aa4bfbc8abe6d26bf2099508aa5141e31a Mon Sep 17 00:00:00 2001 From: roeiK-wix Date: Mon, 4 Nov 2024 14:45:07 +0200 Subject: [PATCH 14/14] Add error log --- chaoslib/exceptions.py | 2 ++ chaoslib/provider/python.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/chaoslib/exceptions.py b/chaoslib/exceptions.py index 97e6bf20..1c993d9c 100644 --- a/chaoslib/exceptions.py +++ b/chaoslib/exceptions.py @@ -10,12 +10,14 @@ "InvalidControl", ] +from logzero import logger class ChaosException(Exception): pass class InvalidActivity(ChaosException): + logger.info("error in InvalidActivity") pass diff --git a/chaoslib/provider/python.py b/chaoslib/provider/python.py index 6af72761..6568fef8 100644 --- a/chaoslib/provider/python.py +++ b/chaoslib/provider/python.py @@ -95,6 +95,13 @@ def validate_python_activity(activity: Activity): # noqa: C901 mod = importlib.import_module(mod_name) logger.info("validate_python_activity 6") except ImportError as err: + logger.info( + "could not find Python module '{mod}'" + "in activity '{name}'" + "\nerror traceback:\n{error}".format( + mod=mod_name, name=activity_name, error=err + ) + ) raise InvalidActivity( "could not find Python module '{mod}'" "in activity '{name}'"