diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c75bc48..026cbf50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,15 @@ ## [Unreleased][] -[Unreleased]: https://github.com/chaostoolkit-incubator/chaostoolkit-aws/compare/0.26.0...HEAD +[Unreleased]: https://github.com/chaostoolkit-incubator/chaostoolkit-aws/compare/0.27.0...HEAD + +## [0.27.0][] - 2023-11-29 + +[0.27.0]: https://github.com/chaostoolkit-incubator/chaostoolkit-aws/compare/0.26.0...0.27.0 + +### Added + +- Action to stop FIS experiments by tags ## [0.26.0][] - 2023-11-20 diff --git a/chaosaws/__init__.py b/chaosaws/__init__.py index b97ed949..c7dbbce0 100644 --- a/chaosaws/__init__.py +++ b/chaosaws/__init__.py @@ -16,7 +16,7 @@ from chaoslib.types import Configuration, DiscoveredActivities, Discovery, Secrets from logzero import logger -__version__ = "0.26.0" +__version__ = "0.27.0" __all__ = ["__version__", "discover", "aws_client", "signed_api_call"] diff --git a/chaosaws/fis/actions.py b/chaosaws/fis/actions.py index 2ccc2a52..cc46b87f 100644 --- a/chaosaws/fis/actions.py +++ b/chaosaws/fis/actions.py @@ -1,4 +1,4 @@ -from typing import Dict +from typing import Dict, List from chaoslib.exceptions import FailedActivity from chaoslib.types import Configuration, Secrets @@ -6,7 +6,7 @@ from chaosaws import aws_client from chaosaws.types import AWSResponse -__all__ = ["start_experiment", "stop_experiment"] +__all__ = ["start_experiment", "stop_experiment", "stop_experiments_by_tags"] def start_experiment( @@ -107,3 +107,48 @@ def stop_experiment( return fis_client.stop_experiment(id=experiment_id) except Exception as ex: raise FailedActivity(f"Stop Experiment failed, reason was: {ex}") + + +def stop_experiments_by_tags( + tags: Dict[str, str], + configuration: Configuration = None, + secrets: Secrets = None, +) -> List[AWSResponse]: + """ + Stops the experiments matching the given tags. + + Useful in rollbacks when experiment id isn't known. + + :param tags: Dict[str, str] representing tags to lookup experiments + :param configuration: Configuration object representing the CTK Configuration + :param secrets: Secret object representing the CTK Secrets + :returns: AWSResponse representing the response from FIS upon stopping the + experiment + + Examples + -------- + >>> stop_experiments_by_tags(tags={"mytarget": "123"}) + [{'ResponseMetadata': {'RequestId': 'e5e9f9a9-f4d0-4d72-8704-1f26cc8b6ad6', + 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Fri, 13 Aug 2021 09:12:17 GMT', + ...'experiment': {'id': 'EXPTUCK2dxepXgkR38', + 'experimentTemplateId': 'EXT6oWVA1WrLNy4XS', ... }] + """ + fis_client = aws_client( + resource_name="fis", configuration=configuration, secrets=secrets + ) + + try: + experiments = fis_client.list_experiments(maxResults=100) + except Exception as ex: + raise FailedActivity(f"Listing Experiments failed, reason was: {ex}") + + stopped = [] + for x in experiments["experiments"]: + try: + if x["tags"] == tags: + result = fis_client.stop_experiment(id=x["id"]) + stopped.append(result) + except Exception as ex: + raise FailedActivity(f"Stop Experiment failed, reason was: {ex}") + + return stopped diff --git a/tests/fis/test_fis_actions.py b/tests/fis/test_fis_actions.py index 3c34f5ff..cc18e9d2 100644 --- a/tests/fis/test_fis_actions.py +++ b/tests/fis/test_fis_actions.py @@ -3,7 +3,11 @@ import pytest from chaoslib.exceptions import FailedActivity -from chaosaws.fis.actions import start_experiment, stop_experiment +from chaosaws.fis.actions import ( + start_experiment, + stop_experiment, + stop_experiments_by_tags, +) def test_that_fis_action_modules___all___attribute_exposed_correctly(): @@ -127,3 +131,15 @@ def test_that_stop_experiment_returns_client_response(aws_client): actual_resp = stop_experiment(experiment_id="an-id") assert actual_resp == resp + + +@patch("chaosaws.fis.actions.aws_client", autospec=True) +def test_that_stop_experiment_by_tags(aws_client): + client = MagicMock() + aws_client.return_value = client + + resp = {"experiments": [{"id": "an-id", "tags": {"test-tag": "a-value"}}]} + client.list_experiments.return_value = resp + + stop_experiments_by_tags(tags={"test-tag": "a-value"}) + client.stop_experiment.assert_called_once_with(id="an-id")