From 05e003a9fb490b3e431ed83121c4b54c35862a33 Mon Sep 17 00:00:00 2001 From: Joel Scheuner Date: Wed, 22 Jan 2025 10:12:56 +0100 Subject: [PATCH 1/2] Remove deprecated Java-based event ruler --- docs/development-environment-setup/README.md | 5 -- localstack-core/localstack/deprecations.py | 3 +- .../localstack/services/events/event_ruler.py | 71 ------------------- .../localstack/services/events/packages.py | 38 ---------- .../localstack/services/events/plugins.py | 8 --- .../localstack/utils/event_matcher.py | 12 ---- .../events/test_archive_and_replay.py | 6 +- 7 files changed, 3 insertions(+), 140 deletions(-) delete mode 100644 localstack-core/localstack/services/events/event_ruler.py delete mode 100644 localstack-core/localstack/services/events/packages.py delete mode 100644 localstack-core/localstack/services/events/plugins.py diff --git a/docs/development-environment-setup/README.md b/docs/development-environment-setup/README.md index 9520424356a0b..7f23a4f5a946a 100644 --- a/docs/development-environment-setup/README.md +++ b/docs/development-environment-setup/README.md @@ -85,11 +85,6 @@ LocalStack runs its own [DNS server](https://docs.localstack.cloud/user-guide/to * macOS users need to configure `LAMBDA_DEV_PORT_EXPOSE=1` such that the host can reach Lambda containers via IPv4 in bridge mode (see [#7367](https://github.com/localstack/localstack/pull/7367)). -#### EVENT_RULE_ENGINE=java - -* Requires Java to execute to invoke the AWS [event-ruler](https://github.com/aws/event-ruler) using [JPype](https://github.com/jpype-project/jpype), a Python to Java bridge. -* Set `JAVA_HOME` to a JDK installation. For example: `JAVA_HOME=/opt/homebrew/Cellar/openjdk/21.0.2` - ### Changing our fork of moto 1. Fork our moto repository on GitHub [https://github.com/localstack/moto](https://github.com/localstack/moto) diff --git a/localstack-core/localstack/deprecations.py b/localstack-core/localstack/deprecations.py index 3bcbe735124ec..1ece1f5ccfec3 100644 --- a/localstack-core/localstack/deprecations.py +++ b/localstack-core/localstack/deprecations.py @@ -306,7 +306,8 @@ def is_affected(self) -> bool: EnvVarDeprecation( "EVENT_RULE_ENGINE", "4.0.3", - "The Java-based event ruler is deprecated because our latest Python-native implementation introduced in 4.0.3" + "This option is ignored because the Java-based event ruler has been removed since 4.1.0." + " Our latest Python-native implementation introduced in 4.0.3" " is faster, achieves great AWS parity, and fixes compatibility issues with the StepFunctions JSONata feature." " Please remove EVENT_RULE_ENGINE.", ), diff --git a/localstack-core/localstack/services/events/event_ruler.py b/localstack-core/localstack/services/events/event_ruler.py deleted file mode 100644 index fd1a825f5b60a..0000000000000 --- a/localstack-core/localstack/services/events/event_ruler.py +++ /dev/null @@ -1,71 +0,0 @@ -import logging -import os -from functools import cache -from pathlib import Path -from typing import Tuple - -from localstack.aws.api.events import InvalidEventPatternException -from localstack.services.events.packages import event_ruler_package -from localstack.utils.objects import singleton_factory - -THIS_FOLDER = os.path.dirname(os.path.realpath(__file__)) - -LOG = logging.getLogger(__name__) - - -@singleton_factory -def start_jvm() -> None: - import jpype - from jpype import config as jpype_config - - # Workaround to unblock LocalStack shutdown. By default, JPype waits until all daemon threads are terminated, - # which blocks the LocalStack shutdown during testing because pytest runs LocalStack in a separate thread and - # `jpype.shutdownJVM()` only works from the main Python thread. - # Shutting down the JVM: https://jpype.readthedocs.io/en/latest/userguide.html#shutting-down-the-jvm - # JPype shutdown discussion: https://github.com/MPh-py/MPh/issues/15#issuecomment-778486669 - jpype_config.destroy_jvm = False - - if not jpype.isJVMStarted(): - jvm_lib, event_ruler_libs_path = get_jpype_lib_paths() - event_ruler_libs_pattern = Path(event_ruler_libs_path).joinpath("*") - - jpype.startJVM(jvm_lib, classpath=[event_ruler_libs_pattern], interrupt=False) - - -@cache -def get_jpype_lib_paths() -> Tuple[str, str]: - """ - Downloads Event Ruler, its dependencies and returns a tuple of: - - Path to libjvm.so/libjli.dylib to be used by JPype as jvmpath. JPype requires this to start the JVM. - See https://jpype.readthedocs.io/en/latest/userguide.html#path-to-the-jvm - - Path to Event Ruler libraries to be used by JPype as classpath - """ - installer = event_ruler_package.get_installer() - installer.install() - - return installer.get_java_lib_path(), installer.get_installed_dir() - - -def matches_rule(event: str, rule: str) -> bool: - """Invokes the AWS Event Ruler Java library: https://github.com/aws/event-ruler - There is a single static boolean method Ruler.matchesRule(event, rule) - - both arguments are provided as JSON strings. - """ - - start_jvm() - import jpype.imports # noqa F401: required for importing Java modules - from jpype import java - - # Import of the Java class "Ruler" needs to happen after the JVM start - from software.amazon.event.ruler import Ruler - - try: - # "Static rule matching" is the easiest implementation to get started. - # "Matching with a machine" using a compiled machine is faster and enables rule validation before matching. - # https://github.com/aws/event-ruler?tab=readme-ov-file#matching-with-a-machine - return Ruler.matchesRule(event, rule) - except java.lang.Exception as e: - reason = e.args[0] - raise InvalidEventPatternException( - message=f"Event pattern is not valid. Reason: {reason}" - ) from e diff --git a/localstack-core/localstack/services/events/packages.py b/localstack-core/localstack/services/events/packages.py deleted file mode 100644 index 7e5d8237ecb5d..0000000000000 --- a/localstack-core/localstack/services/events/packages.py +++ /dev/null @@ -1,38 +0,0 @@ -from localstack.packages import Package, PackageInstaller -from localstack.packages.core import MavenPackageInstaller -from localstack.packages.java import JavaInstallerMixin - -# Map of Event Ruler version to Jackson version -# https://central.sonatype.com/artifact/software.amazon.event.ruler/event-ruler -# The dependent jackson.version is defined in the Maven POM File of event-ruler -EVENT_RULER_VERSIONS = { - "1.7.3": "2.16.2", -} - -EVENT_RULER_DEFAULT_VERSION = "1.7.3" - - -class EventRulerPackage(Package): - def __init__(self): - super().__init__("EventRulerLibs", EVENT_RULER_DEFAULT_VERSION) - - def get_versions(self) -> list[str]: - return list(EVENT_RULER_VERSIONS.keys()) - - def _get_installer(self, version: str) -> PackageInstaller: - return EventRulerPackageInstaller(version) - - -class EventRulerPackageInstaller(JavaInstallerMixin, MavenPackageInstaller): - def __init__(self, version: str): - jackson_version = EVENT_RULER_VERSIONS[version] - - super().__init__( - f"pkg:maven/software.amazon.event.ruler/event-ruler@{version}", - f"pkg:maven/com.fasterxml.jackson.core/jackson-annotations@{jackson_version}", - f"pkg:maven/com.fasterxml.jackson.core/jackson-core@{jackson_version}", - f"pkg:maven/com.fasterxml.jackson.core/jackson-databind@{jackson_version}", - ) - - -event_ruler_package = EventRulerPackage() diff --git a/localstack-core/localstack/services/events/plugins.py b/localstack-core/localstack/services/events/plugins.py deleted file mode 100644 index 82570e48cb20b..0000000000000 --- a/localstack-core/localstack/services/events/plugins.py +++ /dev/null @@ -1,8 +0,0 @@ -from localstack.packages import Package, package - - -@package(name="event-ruler") -def event_ruler_package() -> Package: - from localstack.services.events.packages import event_ruler_package - - return event_ruler_package diff --git a/localstack-core/localstack/utils/event_matcher.py b/localstack-core/localstack/utils/event_matcher.py index 051c6a09fa3b3..f804a61e33bf8 100644 --- a/localstack-core/localstack/utils/event_matcher.py +++ b/localstack-core/localstack/utils/event_matcher.py @@ -1,13 +1,10 @@ -import json from typing import Any -from localstack import config from localstack.services.events.event_rule_engine import ( EventPatternCompiler, EventRuleEngine, InvalidEventPatternException, ) -from localstack.services.events.event_ruler import matches_rule _event_pattern_compiler = EventPatternCompiler() _event_rule_engine = EventRuleEngine() @@ -45,15 +42,6 @@ def matches_event(event_pattern: dict[str, Any] | str | None, event: dict[str, A if not event_pattern: return True - if config.EVENT_RULE_ENGINE == "java": - # If inputs are already strings (EventBridge), use directly - if isinstance(event, str) and isinstance(event_pattern, str): - return matches_rule(event, event_pattern) - # Convert dicts (ESM/Pipes) to strings for Java engine - event_str = event if isinstance(event, str) else json.dumps(event) - pattern_str = event_pattern if isinstance(event_pattern, str) else json.dumps(event_pattern) - return matches_rule(event_str, pattern_str) - # Python implementation (default) compiled_event_pattern = _event_pattern_compiler.compile_event_pattern( event_pattern=event_pattern diff --git a/tests/aws/services/events/test_archive_and_replay.py b/tests/aws/services/events/test_archive_and_replay.py index 9fb0ce8a7535d..994f4f326e474 100644 --- a/tests/aws/services/events/test_archive_and_replay.py +++ b/tests/aws/services/events/test_archive_and_replay.py @@ -3,7 +3,6 @@ import pytest -from localstack import config from localstack.testing.pytest import markers from localstack.utils.strings import short_uid from localstack.utils.sync import retry @@ -363,10 +362,7 @@ def test_delete_archive_error_unknown_archive(self, aws_client, snapshot): class TestReplay: @markers.aws.validated @pytest.mark.skipif(is_old_provider(), reason="not supported by the old provider") - @pytest.mark.skipif( - condition=config.EVENT_RULE_ENGINE == "python", - reason="Not supported with Python-based rule engine", - ) + @pytest.mark.skip(reason="Not supported with Python-based rule engine") @pytest.mark.parametrize("event_bus_type", ["default", "custom"]) @pytest.mark.skip_snapshot_verify(paths=["$..State"]) def test_start_list_describe_canceled_replay( From c6f3cc8cb04c1ac13f55e2e9dfe6b9ba5bbca52b Mon Sep 17 00:00:00 2001 From: Joel Scheuner Date: Wed, 22 Jan 2025 16:27:04 +0100 Subject: [PATCH 2/2] Clarify reason for test failure --- tests/aws/services/events/test_archive_and_replay.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/aws/services/events/test_archive_and_replay.py b/tests/aws/services/events/test_archive_and_replay.py index 994f4f326e474..084cec055abbe 100644 --- a/tests/aws/services/events/test_archive_and_replay.py +++ b/tests/aws/services/events/test_archive_and_replay.py @@ -362,7 +362,8 @@ def test_delete_archive_error_unknown_archive(self, aws_client, snapshot): class TestReplay: @markers.aws.validated @pytest.mark.skipif(is_old_provider(), reason="not supported by the old provider") - @pytest.mark.skip(reason="Not supported with Python-based rule engine") + # TODO: Investigate and fix type error + @pytest.mark.skip(reason="Fails with `TypeError: str.replace() takes no keyword arguments`") @pytest.mark.parametrize("event_bus_type", ["default", "custom"]) @pytest.mark.skip_snapshot_verify(paths=["$..State"]) def test_start_list_describe_canceled_replay(