From 20227b2a10398431c932bf34242775d8b6309520 Mon Sep 17 00:00:00 2001 From: "T.J Ariyawansa" Date: Wed, 15 Apr 2026 14:53:02 -0400 Subject: [PATCH] fix: validate region parameter to prevent SSRF request redirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The region parameter was interpolated directly into endpoint URL f-strings without validation, allowing crafted values like "x@attacker.com:443/#" to redirect SDK API calls — including SigV4-signed requests with credentials — to non-AWS hosts. Same vulnerability class as CVE-2026-22611. Defense-in-depth fix: 1. validate_region() in endpoints.py checks against regex \A[a-z]{2}(-[a-z]+)+-\d+\Z using \Z anchor to prevent newline bypass. Applied in get_data_plane_endpoint(), build_runtime_url(), AgentCoreRuntimeClient, and BrowserClient. 2. _validate_endpoint_url() verifies constructed URL hostname ends with .amazonaws.com. Also validates env var endpoint overrides. 3. Boto3-based clients (CodeInterpreter, IdentityClient, ResourcePolicyClient, MemoryControlPlaneClient) no longer pass redundant endpoint_url — boto3 resolves identical endpoints natively and includes its own region validation. Ref: V2177374595 --- src/bedrock_agentcore/_utils/endpoints.py | 69 ++++- src/bedrock_agentcore/memory/controlplane.py | 11 +- src/bedrock_agentcore/runtime/a2a.py | 3 + .../runtime/agent_core_runtime_client.py | 3 + src/bedrock_agentcore/services/identity.py | 16 +- .../services/resource_policy.py | 11 +- src/bedrock_agentcore/tools/browser_client.py | 31 +- .../tools/code_interpreter_client.py | 29 +- .../services/test_identity.py | 1 - .../services/test_resource_policy.py | 1 - .../test_region_validation.py | 268 ++++++++++++++++++ .../tools/test_browser_client.py | 213 +++----------- .../tools/test_code_interpreter_client.py | 248 ++++------------ 13 files changed, 492 insertions(+), 412 deletions(-) create mode 100644 tests/bedrock_agentcore/test_region_validation.py diff --git a/src/bedrock_agentcore/_utils/endpoints.py b/src/bedrock_agentcore/_utils/endpoints.py index 9b1233ff..a8e8f528 100644 --- a/src/bedrock_agentcore/_utils/endpoints.py +++ b/src/bedrock_agentcore/_utils/endpoints.py @@ -1,16 +1,81 @@ """Endpoint utilities for BedrockAgentCore services.""" import os +import re +from urllib.parse import urlparse # Environment-configurable constants with fallback defaults DP_ENDPOINT_OVERRIDE = os.getenv("BEDROCK_AGENTCORE_DP_ENDPOINT") CP_ENDPOINT_OVERRIDE = os.getenv("BEDROCK_AGENTCORE_CP_ENDPOINT") DEFAULT_REGION = os.getenv("AWS_REGION", "us-west-2") +# Regex for valid AWS region names (e.g., us-east-1, eu-west-2, cn-north-1, us-gov-west-1). +# Uses \A and \Z anchors to prevent newline injection bypass that $ allows. +_VALID_REGION_PATTERN = re.compile(r"\A[a-z]{2}(-[a-z]+)+-\d+\Z") + + +class InvalidRegionError(ValueError): + """Raised when an invalid AWS region string is provided. + + This prevents SSRF attacks where a crafted region value + (e.g., ``x@attacker.com:443/#``) could redirect SDK API calls + to non-AWS hosts. + """ + + +def validate_region(region: str) -> str: + """Validate that a region string is a well-formed AWS region name. + + Args: + region: The region string to validate. + + Returns: + The validated region string (unchanged). + + Raises: + InvalidRegionError: If the region does not match the expected pattern. + """ + if not isinstance(region, str) or not _VALID_REGION_PATTERN.match(region): + raise InvalidRegionError( + f"Invalid AWS region: {region!r}. Region must match pattern like 'us-east-1', 'eu-west-2', 'cn-north-1'." + ) + return region + + +def _validate_endpoint_url(url: str) -> str: + """Validate that a constructed endpoint URL resolves to an AWS host. + + This is a defense-in-depth check that catches URL manipulation even if + the region regex is somehow bypassed. + + Args: + url: The constructed endpoint URL. + + Returns: + The validated URL (unchanged). + + Raises: + InvalidRegionError: If the URL hostname does not end with an AWS domain. + """ + parsed = urlparse(url) + hostname = parsed.hostname or "" + _AWS_DOMAINS = (".amazonaws.com", ".amazonaws.com.cn", ".api.aws") + if not any(hostname.endswith(d) for d in _AWS_DOMAINS): + raise InvalidRegionError(f"Constructed endpoint resolves to non-AWS host: {hostname!r}") + return url + def get_data_plane_endpoint(region: str = DEFAULT_REGION) -> str: - return DP_ENDPOINT_OVERRIDE or f"https://bedrock-agentcore.{region}.amazonaws.com" + if DP_ENDPOINT_OVERRIDE: + return _validate_endpoint_url(DP_ENDPOINT_OVERRIDE) + validate_region(region) + url = f"https://bedrock-agentcore.{region}.amazonaws.com" + return _validate_endpoint_url(url) def get_control_plane_endpoint(region: str = DEFAULT_REGION) -> str: - return CP_ENDPOINT_OVERRIDE or f"https://bedrock-agentcore-control.{region}.amazonaws.com" + if CP_ENDPOINT_OVERRIDE: + return _validate_endpoint_url(CP_ENDPOINT_OVERRIDE) + validate_region(region) + url = f"https://bedrock-agentcore-control.{region}.amazonaws.com" + return _validate_endpoint_url(url) diff --git a/src/bedrock_agentcore/memory/controlplane.py b/src/bedrock_agentcore/memory/controlplane.py index 64fb77ee..2b6a64de 100644 --- a/src/bedrock_agentcore/memory/controlplane.py +++ b/src/bedrock_agentcore/memory/controlplane.py @@ -33,12 +33,13 @@ def __init__(self, region_name: str = "us-west-2", environment: str = "prod"): self.region_name = region_name self.environment = environment - self.endpoint = os.getenv( - "BEDROCK_AGENTCORE_CONTROL_ENDPOINT", f"https://bedrock-agentcore-control.{region_name}.amazonaws.com" - ) - service_name = os.getenv("BEDROCK_AGENTCORE_CONTROL_SERVICE", "bedrock-agentcore-control") - self.client = boto3.client(service_name, region_name=self.region_name, endpoint_url=self.endpoint) + cp_kwargs: dict = {"region_name": self.region_name} + control_endpoint = os.getenv("BEDROCK_AGENTCORE_CONTROL_ENDPOINT") + if control_endpoint: + cp_kwargs["endpoint_url"] = control_endpoint + self.client = boto3.client(service_name, **cp_kwargs) + self.endpoint = self.client.meta.endpoint_url logger.info("Initialized MemoryControlPlaneClient for %s in %s", environment, region_name) diff --git a/src/bedrock_agentcore/runtime/a2a.py b/src/bedrock_agentcore/runtime/a2a.py index 0cbfe60f..efbe9002 100644 --- a/src/bedrock_agentcore/runtime/a2a.py +++ b/src/bedrock_agentcore/runtime/a2a.py @@ -75,6 +75,8 @@ def build_runtime_url(agent_arn: str, region: Optional[str] = None) -> str: """ from urllib.parse import quote + from .._utils.endpoints import validate_region + if region is None: # ARN format: arn:aws:bedrock-agentcore:::runtime/ parts = agent_arn.split(":") @@ -83,6 +85,7 @@ def build_runtime_url(agent_arn: str, region: Optional[str] = None) -> str: else: raise ValueError(f"Cannot extract region from ARN: {agent_arn}") + validate_region(region) encoded_arn = quote(agent_arn, safe="") return f"https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{encoded_arn}/invocations" diff --git a/src/bedrock_agentcore/runtime/agent_core_runtime_client.py b/src/bedrock_agentcore/runtime/agent_core_runtime_client.py index e905119f..ab91de5a 100644 --- a/src/bedrock_agentcore/runtime/agent_core_runtime_client.py +++ b/src/bedrock_agentcore/runtime/agent_core_runtime_client.py @@ -43,6 +43,9 @@ def __init__(self, region: str, session: Optional[boto3.Session] = None) -> None session (Optional[boto3.Session]): Optional boto3 session. If not provided, a new session will be created using default credentials. """ + from .._utils.endpoints import validate_region + + validate_region(region) self.region = region self.logger = logging.getLogger(__name__) diff --git a/src/bedrock_agentcore/services/identity.py b/src/bedrock_agentcore/services/identity.py index 5ffc8692..88d5e605 100644 --- a/src/bedrock_agentcore/services/identity.py +++ b/src/bedrock_agentcore/services/identity.py @@ -10,7 +10,7 @@ import boto3 from pydantic import BaseModel -from bedrock_agentcore._utils.endpoints import get_control_plane_endpoint, get_data_plane_endpoint +from bedrock_agentcore._utils.endpoints import CP_ENDPOINT_OVERRIDE, DP_ENDPOINT_OVERRIDE class TokenPoller(ABC): @@ -75,12 +75,14 @@ class IdentityClient: def __init__(self, region: str): """Initialize the identity client with the specified region.""" self.region = region - self.cp_client = boto3.client( - "bedrock-agentcore-control", region_name=region, endpoint_url=get_control_plane_endpoint(region) - ) - self.dp_client = boto3.client( - "bedrock-agentcore", region_name=region, endpoint_url=get_data_plane_endpoint(region) - ) + cp_kwargs: dict = {"region_name": region} + if CP_ENDPOINT_OVERRIDE: + cp_kwargs["endpoint_url"] = CP_ENDPOINT_OVERRIDE + self.cp_client = boto3.client("bedrock-agentcore-control", **cp_kwargs) + dp_kwargs: dict = {"region_name": region} + if DP_ENDPOINT_OVERRIDE: + dp_kwargs["endpoint_url"] = DP_ENDPOINT_OVERRIDE + self.dp_client = boto3.client("bedrock-agentcore", **dp_kwargs) self.logger = logging.getLogger("bedrock_agentcore.identity_client") def create_oauth2_credential_provider(self, req): diff --git a/src/bedrock_agentcore/services/resource_policy.py b/src/bedrock_agentcore/services/resource_policy.py index 9840f7dd..1bd767fb 100644 --- a/src/bedrock_agentcore/services/resource_policy.py +++ b/src/bedrock_agentcore/services/resource_policy.py @@ -6,7 +6,7 @@ import boto3 -from bedrock_agentcore._utils.endpoints import get_control_plane_endpoint +from bedrock_agentcore._utils.endpoints import CP_ENDPOINT_OVERRIDE class ResourcePolicyClient: @@ -19,11 +19,10 @@ class ResourcePolicyClient: def __init__(self, region: str): """Initialize the client for the specified region.""" self.region = region - self.client = boto3.client( - "bedrock-agentcore-control", - region_name=region, - endpoint_url=get_control_plane_endpoint(region), - ) + cp_kwargs: dict = {"region_name": region} + if CP_ENDPOINT_OVERRIDE: + cp_kwargs["endpoint_url"] = CP_ENDPOINT_OVERRIDE + self.client = boto3.client("bedrock-agentcore-control", **cp_kwargs) self.logger = logging.getLogger("bedrock_agentcore.resource_policy_client") def put_resource_policy(self, resource_arn: str, policy: Union[str, dict]) -> dict: diff --git a/src/bedrock_agentcore/tools/browser_client.py b/src/bedrock_agentcore/tools/browser_client.py index d583060b..9371297c 100644 --- a/src/bedrock_agentcore/tools/browser_client.py +++ b/src/bedrock_agentcore/tools/browser_client.py @@ -21,7 +21,7 @@ from bedrock_agentcore._utils.user_agent import build_user_agent_suffix -from .._utils.endpoints import get_control_plane_endpoint, get_data_plane_endpoint +from .._utils.endpoints import get_data_plane_endpoint from .config import ( BrowserExtension, Certificate, @@ -68,6 +68,9 @@ def __init__(self, region: str, integration_source: Optional[str] = None) -> Non for telemetry (e.g., 'langchain', 'crewai'). Used to track customer acquisition from different integrations. """ + from bedrock_agentcore._utils.endpoints import CP_ENDPOINT_OVERRIDE, DP_ENDPOINT_OVERRIDE, validate_region + + validate_region(region) self.region = region self.logger = logging.getLogger(__name__) self.integration_source = integration_source @@ -76,21 +79,17 @@ def __init__(self, region: str, integration_source: Optional[str] = None) -> Non user_agent_extra = build_user_agent_suffix(integration_source) client_config = Config(user_agent_extra=user_agent_extra) - # Control plane client for browser management - self.control_plane_client = boto3.client( - "bedrock-agentcore-control", - region_name=region, - endpoint_url=get_control_plane_endpoint(region), - config=client_config, - ) - - # Data plane client for session operations - self.data_plane_client = boto3.client( - "bedrock-agentcore", - region_name=region, - endpoint_url=get_data_plane_endpoint(region), - config=client_config, - ) + # Control plane client — let boto3 resolve endpoint natively. + cp_kwargs: dict = {"region_name": region, "config": client_config} + if CP_ENDPOINT_OVERRIDE: + cp_kwargs["endpoint_url"] = CP_ENDPOINT_OVERRIDE + self.control_plane_client = boto3.client("bedrock-agentcore-control", **cp_kwargs) + + # Data plane client — same pattern. + dp_kwargs: dict = {"region_name": region, "config": client_config} + if DP_ENDPOINT_OVERRIDE: + dp_kwargs["endpoint_url"] = DP_ENDPOINT_OVERRIDE + self.data_plane_client = boto3.client("bedrock-agentcore", **dp_kwargs) self._identifier = None self._session_id = None diff --git a/src/bedrock_agentcore/tools/code_interpreter_client.py b/src/bedrock_agentcore/tools/code_interpreter_client.py index e8c05639..359e5d0b 100644 --- a/src/bedrock_agentcore/tools/code_interpreter_client.py +++ b/src/bedrock_agentcore/tools/code_interpreter_client.py @@ -14,7 +14,7 @@ import boto3 from botocore.config import Config -from bedrock_agentcore._utils.endpoints import get_control_plane_endpoint, get_data_plane_endpoint +from bedrock_agentcore._utils.endpoints import CP_ENDPOINT_OVERRIDE, DP_ENDPOINT_OVERRIDE from bedrock_agentcore._utils.user_agent import build_user_agent_suffix from .config import Certificate @@ -102,21 +102,18 @@ def __init__( # Data plane config (preserve existing read_timeout) data_config = Config(read_timeout=300, user_agent_extra=user_agent_extra) - # Control plane client for interpreter management - self.control_plane_client = session.client( - "bedrock-agentcore-control", - region_name=region, - endpoint_url=get_control_plane_endpoint(region), - config=control_config, - ) - - # Data plane client for session operations - self.data_plane_client = session.client( - "bedrock-agentcore", - region_name=region, - endpoint_url=get_data_plane_endpoint(region), - config=data_config, - ) + # Control plane client — let boto3 resolve endpoint natively (includes region validation). + # Only pass endpoint_url when an environment override is set. + cp_kwargs: dict = {"region_name": region, "config": control_config} + if CP_ENDPOINT_OVERRIDE: + cp_kwargs["endpoint_url"] = CP_ENDPOINT_OVERRIDE + self.control_plane_client = session.client("bedrock-agentcore-control", **cp_kwargs) + + # Data plane client — same pattern. + dp_kwargs: dict = {"region_name": region, "config": data_config} + if DP_ENDPOINT_OVERRIDE: + dp_kwargs["endpoint_url"] = DP_ENDPOINT_OVERRIDE + self.data_plane_client = session.client("bedrock-agentcore", **dp_kwargs) self._identifier = None self._session_id = None diff --git a/tests/bedrock_agentcore/services/test_identity.py b/tests/bedrock_agentcore/services/test_identity.py index 918c61da..1c03f8a8 100644 --- a/tests/bedrock_agentcore/services/test_identity.py +++ b/tests/bedrock_agentcore/services/test_identity.py @@ -29,7 +29,6 @@ def test_initialization(self): mock_boto_client.assert_called_with( "bedrock-agentcore", region_name=region, - endpoint_url="https://bedrock-agentcore.us-east-1.amazonaws.com", ) def test_create_oauth2_credential_provider(self): diff --git a/tests/bedrock_agentcore/services/test_resource_policy.py b/tests/bedrock_agentcore/services/test_resource_policy.py index 6ce1cdb0..64360256 100644 --- a/tests/bedrock_agentcore/services/test_resource_policy.py +++ b/tests/bedrock_agentcore/services/test_resource_policy.py @@ -17,7 +17,6 @@ def test_initialization(self): mock_boto.assert_called_once_with( "bedrock-agentcore-control", region_name=TEST_REGION, - endpoint_url=f"https://bedrock-agentcore-control.{TEST_REGION}.amazonaws.com", ) def test_put_serializes_dict_to_json(self): diff --git a/tests/bedrock_agentcore/test_region_validation.py b/tests/bedrock_agentcore/test_region_validation.py new file mode 100644 index 00000000..cee328f7 --- /dev/null +++ b/tests/bedrock_agentcore/test_region_validation.py @@ -0,0 +1,268 @@ +"""Tests for region validation and SSRF prevention. + +Covers the fix for V2177374595 — unvalidated region parameter in endpoint +construction allows request redirection to non-AWS hosts. +""" + +import pytest + +from bedrock_agentcore._utils.endpoints import ( + InvalidRegionError, + _validate_endpoint_url, + get_control_plane_endpoint, + get_data_plane_endpoint, + validate_region, +) + +# --------------------------------------------------------------------------- +# Layer 1: validate_region() — regex input validation +# --------------------------------------------------------------------------- + + +class TestValidateRegion: + """Tests for the validate_region() function.""" + + @pytest.mark.parametrize( + "region", + [ + "us-east-1", + "us-west-2", + "eu-west-1", + "eu-central-1", + "ap-southeast-1", + "ap-northeast-1", + "sa-east-1", + "ca-central-1", + "me-south-1", + "af-south-1", + # GovCloud + "us-gov-west-1", + "us-gov-east-1", + ], + ) + def test_valid_regions_accepted(self, region): + assert validate_region(region) == region + + @pytest.mark.parametrize( + "region", + [ + # SSRF payloads (CVE-2026-22611 class) + "x@attacker.com:443/#", + "evil.com/#", + "us-east-1.attacker.com", + "attacker.com:443", + # URL control characters + "us-east-1/../../", + "us-east-1?foo=bar", + "us-east-1#fragment", + # Newline injection (the \Z vs $ distinction) + "us-east-1\n", + "us-east-1\r\n", + # Whitespace + " us-east-1", + "us-east-1 ", + # Uppercase + "US-EAST-1", + "Us-East-1", + # Empty / None-like + "", + # Very long string + "a" * 200, + # Unicode homoglyphs + "us-e\u0430st-1", # Cyrillic 'a' + # Command injection attempts + "us-east-1$(whoami)", + "us-east-1`id`", + # Null byte + "us-east-1\x00", + ], + ) + def test_malicious_regions_rejected(self, region): + with pytest.raises(InvalidRegionError): + validate_region(region) + + def test_non_string_rejected(self): + with pytest.raises(InvalidRegionError): + validate_region(123) # type: ignore[arg-type] + + def test_none_rejected(self): + with pytest.raises(InvalidRegionError): + validate_region(None) # type: ignore[arg-type] + + def test_error_is_valueerror_subclass(self): + """Ensure existing `except ValueError` handlers still catch it.""" + with pytest.raises(ValueError): + validate_region("evil.com") + + +# --------------------------------------------------------------------------- +# Layer 2: _validate_endpoint_url() — output hostname validation +# --------------------------------------------------------------------------- + + +class TestValidateEndpointUrl: + """Tests for defense-in-depth URL hostname check.""" + + def test_valid_aws_url(self): + url = "https://bedrock-agentcore.us-east-1.amazonaws.com" + assert _validate_endpoint_url(url) == url + + def test_valid_china_url(self): + url = "https://bedrock-agentcore.cn-north-1.amazonaws.com.cn" + assert _validate_endpoint_url(url) == url + + def test_valid_api_aws_url(self): + url = "https://bedrock-agentcore.us-east-1.api.aws" + assert _validate_endpoint_url(url) == url + + def test_attacker_url_rejected(self): + url = "https://bedrock-agentcore.x@attacker.com:443/#.amazonaws.com" + with pytest.raises(InvalidRegionError, match="non-AWS host"): + _validate_endpoint_url(url) + + def test_non_aws_host_rejected(self): + url = "https://not-amazonaws.com/something" + with pytest.raises(InvalidRegionError, match="non-AWS host"): + _validate_endpoint_url(url) + + +# --------------------------------------------------------------------------- +# Endpoint functions (both layers combined) +# --------------------------------------------------------------------------- + + +class TestEndpointFunctions: + """Tests for get_data_plane_endpoint / get_control_plane_endpoint.""" + + def test_valid_data_plane_endpoint(self): + url = get_data_plane_endpoint("us-west-2") + assert url == "https://bedrock-agentcore.us-west-2.amazonaws.com" + + def test_valid_control_plane_endpoint(self): + url = get_control_plane_endpoint("eu-west-1") + assert url == "https://bedrock-agentcore-control.eu-west-1.amazonaws.com" + + def test_malicious_region_rejected_dp(self): + with pytest.raises(InvalidRegionError): + get_data_plane_endpoint("x@attacker.com:443/#") + + def test_malicious_region_rejected_cp(self): + with pytest.raises(InvalidRegionError): + get_control_plane_endpoint("evil.com/#") + + def test_env_override_skips_region_validation(self): + """Environment overrides skip region validation but are still URL-validated.""" + import bedrock_agentcore._utils.endpoints as ep + + original_override = ep.DP_ENDPOINT_OVERRIDE + try: + # Valid AWS override works + ep.DP_ENDPOINT_OVERRIDE = "https://bedrock-agentcore.us-east-1.amazonaws.com" + result = ep.get_data_plane_endpoint("not-a-region") + assert result == "https://bedrock-agentcore.us-east-1.amazonaws.com" + + # Malicious override is rejected + ep.DP_ENDPOINT_OVERRIDE = "https://attacker.com" + with pytest.raises(InvalidRegionError, match="non-AWS host"): + ep.get_data_plane_endpoint("not-a-region") + finally: + ep.DP_ENDPOINT_OVERRIDE = original_override + + def test_govcloud_regions(self): + url = get_data_plane_endpoint("us-gov-west-1") + assert "us-gov-west-1" in url + + +# --------------------------------------------------------------------------- +# build_runtime_url (ARN extraction path) +# --------------------------------------------------------------------------- + + +class TestBuildRuntimeUrlValidation: + """Tests for SSRF prevention in build_runtime_url.""" + + def test_valid_arn_builds_url(self): + from bedrock_agentcore.runtime.a2a import build_runtime_url + + arn = "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my-agent" + url = build_runtime_url(arn) + assert "bedrock-agentcore.us-east-1.amazonaws.com" in url + + def test_malicious_arn_region_rejected(self): + from bedrock_agentcore.runtime.a2a import build_runtime_url + + malicious_arn = "arn:aws:bedrock-agentcore:evil.com/#:123456789012:runtime/agent1" + with pytest.raises(InvalidRegionError): + build_runtime_url(malicious_arn) + + def test_explicit_malicious_region_override_rejected(self): + from bedrock_agentcore.runtime.a2a import build_runtime_url + + arn = "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my-agent" + with pytest.raises(InvalidRegionError): + build_runtime_url(arn, region="x@attacker.com:443/#") + + def test_valid_region_override(self): + from bedrock_agentcore.runtime.a2a import build_runtime_url + + arn = "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my-agent" + url = build_runtime_url(arn, region="eu-west-1") + assert "bedrock-agentcore.eu-west-1.amazonaws.com" in url + + +# --------------------------------------------------------------------------- +# Client constructor fail-fast validation +# --------------------------------------------------------------------------- + + +class TestClientConstructorValidation: + """Tests that all client constructors reject malicious regions early.""" + + def test_agent_core_runtime_client_rejects_bad_region(self): + with pytest.raises(InvalidRegionError): + from bedrock_agentcore.runtime.agent_core_runtime_client import AgentCoreRuntimeClient + + AgentCoreRuntimeClient("x@attacker.com:443/#") + + def test_browser_client_rejects_bad_region(self): + """BrowserClient still uses validate_region() for WebSocket URL construction.""" + with pytest.raises(InvalidRegionError): + from bedrock_agentcore.tools.browser_client import BrowserClient + + BrowserClient("evil.com/#") + + def test_code_interpreter_rejects_bad_region(self): + """CodeInterpreter delegates to boto3 which has its own region validation.""" + from botocore.exceptions import InvalidRegionError as BotocoreInvalidRegionError + + with pytest.raises(BotocoreInvalidRegionError): + from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter + + CodeInterpreter("evil.com/#") + + def test_identity_client_rejects_bad_region(self): + """IdentityClient delegates to boto3 which has its own region validation.""" + from botocore.exceptions import InvalidRegionError as BotocoreInvalidRegionError + + with pytest.raises(BotocoreInvalidRegionError): + from bedrock_agentcore.services.identity import IdentityClient + + IdentityClient("x@attacker.com:443/#") + + def test_resource_policy_client_rejects_bad_region(self): + """ResourcePolicyClient delegates to boto3 which has its own region validation.""" + from botocore.exceptions import InvalidRegionError as BotocoreInvalidRegionError + + with pytest.raises(BotocoreInvalidRegionError): + from bedrock_agentcore.services.resource_policy import ResourcePolicyClient + + ResourcePolicyClient("evil.com/#") + + def test_memory_controlplane_rejects_bad_region(self): + """MemoryControlPlaneClient delegates to boto3 which has its own region validation.""" + from botocore.exceptions import InvalidRegionError as BotocoreInvalidRegionError + + with pytest.raises(BotocoreInvalidRegionError): + from bedrock_agentcore.memory.controlplane import MemoryControlPlaneClient + + MemoryControlPlaneClient(region_name="x@attacker.com:443/#") diff --git a/tests/bedrock_agentcore/tools/test_browser_client.py b/tests/bedrock_agentcore/tools/test_browser_client.py index 47b7f0d6..63605709 100644 --- a/tests/bedrock_agentcore/tools/test_browser_client.py +++ b/tests/bedrock_agentcore/tools/test_browser_client.py @@ -26,16 +26,12 @@ class TestBrowserClient: - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_init(self, mock_boto3): # Arrange mock_control_client = MagicMock() mock_data_client = MagicMock() mock_boto3.client.side_effect = [mock_control_client, mock_data_client] - mock_get_control_endpoint.return_value = "https://mock-control-endpoint.com" - mock_get_data_endpoint.return_value = "https://mock-data-endpoint.com" region = "us-west-2" # Act @@ -46,13 +42,11 @@ def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoin mock_boto3.client.assert_any_call( "bedrock-agentcore-control", region_name=region, - endpoint_url="https://mock-control-endpoint.com", config=ANY, ) mock_boto3.client.assert_any_call( "bedrock-agentcore", region_name=region, - endpoint_url="https://mock-data-endpoint.com", config=ANY, ) assert client.control_plane_client == mock_control_client @@ -61,16 +55,12 @@ def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoin assert client.identifier is None assert client.session_id is None - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_init_with_integration_source(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_init_with_integration_source(self, mock_boto3): # Arrange mock_control_client = MagicMock() mock_data_client = MagicMock() mock_boto3.client.side_effect = [mock_control_client, mock_data_client] - mock_get_control_endpoint.return_value = "https://mock-control-endpoint.com" - mock_get_data_endpoint.return_value = "https://mock-data-endpoint.com" region = "us-west-2" integration_source = "langchain" @@ -81,10 +71,8 @@ def test_init_with_integration_source(self, mock_boto3, mock_get_data_endpoint, assert client.integration_source == integration_source assert mock_boto3.client.call_count == 2 - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_property_getters_setters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_property_getters_setters(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -99,10 +87,8 @@ def test_property_getters_setters(self, mock_boto3, mock_get_data_endpoint, mock client.session_id = test_session_id assert client.session_id == test_session_id - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_create_browser_minimal(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_create_browser_minimal(self, mock_boto3): # Arrange mock_control_client = MagicMock() mock_data_client = MagicMock() @@ -131,10 +117,8 @@ def test_create_browser_minimal(self, mock_boto3, mock_get_data_endpoint, mock_g ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_create_browser_with_all_options(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_create_browser_with_all_options(self, mock_boto3): # Arrange mock_control_client = MagicMock() mock_data_client = MagicMock() @@ -182,10 +166,8 @@ def test_create_browser_with_all_options(self, mock_boto3, mock_get_data_endpoin ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_delete_browser(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_delete_browser(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -204,10 +186,8 @@ def test_delete_browser(self, mock_boto3, mock_get_data_endpoint, mock_get_contr client.control_plane_client.delete_browser.assert_called_once_with(browserId="test-browser-123") assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_delete_browser_with_client_token(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_delete_browser_with_client_token(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -228,10 +208,8 @@ def test_delete_browser_with_client_token(self, mock_boto3, mock_get_data_endpoi ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_get_browser(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_browser(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -252,10 +230,8 @@ def test_get_browser(self, mock_boto3, mock_get_data_endpoint, mock_get_control_ client.control_plane_client.get_browser.assert_called_once_with(browserId="test-browser-123") assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_list_browsers_default(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_browsers_default(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -275,10 +251,8 @@ def test_list_browsers_default(self, mock_boto3, mock_get_data_endpoint, mock_ge client.control_plane_client.list_browsers.assert_called_once_with(maxResults=10) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_list_browsers_with_filters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_browsers_with_filters(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -298,11 +272,9 @@ def test_list_browsers_with_filters(self, mock_boto3, mock_get_data_endpoint, mo ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_defaults(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_defaults(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -324,11 +296,9 @@ def test_start_with_defaults(self, mock_uuid4, mock_boto3, mock_get_data_endpoin assert client.identifier == "aws.browser.v1" assert client.session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_custom_params(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_custom_params(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -350,10 +320,8 @@ def test_start_with_custom_params(self, mock_uuid4, mock_boto3, mock_get_data_en assert client.identifier == "custom.browser" assert client.session_id == "custom-session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_stop_when_session_exists(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_stop_when_session_exists(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -370,10 +338,8 @@ def test_stop_when_session_exists(self, mock_boto3, mock_get_data_endpoint, mock assert client.identifier is None assert client.session_id is None - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_stop_when_no_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_stop_when_no_session(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -387,10 +353,8 @@ def test_stop_when_no_session(self, mock_boto3, mock_get_data_endpoint, mock_get client.data_plane_client.stop_browser_session.assert_not_called() assert result is True - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_get_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -413,10 +377,8 @@ def test_get_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_ ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_get_session_with_params(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session_with_params(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -437,10 +399,8 @@ def test_get_session_with_params(self, mock_boto3, mock_get_data_endpoint, mock_ ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_get_session_missing_ids(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session_missing_ids(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -449,10 +409,8 @@ def test_get_session_missing_ids(self, mock_boto3, mock_get_data_endpoint, mock_ with pytest.raises(ValueError, match="Browser ID and Session ID must be provided"): client.get_session() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_list_sessions(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -475,10 +433,8 @@ def test_list_sessions(self, mock_boto3, mock_get_data_endpoint, mock_get_contro ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_list_sessions_with_filters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions_with_filters(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -506,10 +462,8 @@ def test_list_sessions_with_filters(self, mock_boto3, mock_get_data_endpoint, mo ) assert result == mock_response - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_list_sessions_missing_browser_id(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions_missing_browser_id(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -518,10 +472,8 @@ def test_list_sessions_missing_browser_id(self, mock_boto3, mock_get_data_endpoi with pytest.raises(ValueError, match="Browser ID must be provided"): client.list_sessions() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_update_stream(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_update_stream(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -538,10 +490,8 @@ def test_update_stream(self, mock_boto3, mock_get_data_endpoint, mock_get_contro streamUpdate={"automationStreamUpdate": {"streamStatus": "DISABLED"}}, ) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_update_stream_with_params(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_update_stream_with_params(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -556,10 +506,8 @@ def test_update_stream_with_params(self, mock_boto3, mock_get_data_endpoint, moc streamUpdate={"automationStreamUpdate": {"streamStatus": "ENABLED"}}, ) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_update_stream_missing_ids(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_update_stream_missing_ids(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -568,7 +516,6 @@ def test_update_stream_missing_ids(self, mock_boto3, mock_get_data_endpoint, moc with pytest.raises(ValueError, match="Browser ID and Session ID must be provided"): client.update_stream("DISABLED") - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.datetime") @@ -581,7 +528,6 @@ def test_get_ws_headers( mock_datetime, mock_boto3, mock_get_data_endpoint, - mock_get_control_endpoint, ): # Arrange mock_boto_session = MagicMock() @@ -664,10 +610,9 @@ def test_browser_session_context_manager_with_identifier(self, mock_client_class mock_client.start.assert_called_once_with(identifier="custom-browser-123") # ✅ CORRECT mock_client.stop.assert_called_once() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_get_ws_headers_no_credentials(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_ws_headers_no_credentials(self, mock_boto3, mock_get_data_endpoint): # Arrange mock_boto_session = MagicMock() mock_boto_session.get_credentials.return_value = None # No credentials @@ -680,10 +625,9 @@ def test_get_ws_headers_no_credentials(self, mock_boto3, mock_get_data_endpoint, with pytest.raises(RuntimeError, match="No AWS credentials found"): client.generate_ws_headers() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_generate_live_view_url(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_generate_live_view_url(self, mock_boto3, mock_get_data_endpoint): # Arrange mock_boto_session = MagicMock() mock_credentials = MagicMock() @@ -728,12 +672,9 @@ def test_generate_live_view_url(self, mock_boto3, mock_get_data_endpoint, mock_g expires=MAX_LIVE_VIEW_PRESIGNED_URL_TIMEOUT, ) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_generate_live_view_url_expires_validation_valid( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_generate_live_view_url_expires_validation_valid(self, mock_boto3, mock_get_data_endpoint): # Arrange client = BrowserClient("us-west-2") client.identifier = "test-browser-id" @@ -767,12 +708,8 @@ def test_generate_live_view_url_expires_validation_valid( # Assert assert result == "https://api.example.com/signed-url" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_generate_live_view_url_expires_validation_invalid( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_generate_live_view_url_expires_validation_invalid(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -787,10 +724,8 @@ def test_generate_live_view_url_expires_validation_invalid( with pytest.raises(ValueError, match=expected_msg): client.generate_live_view_url(expires=invalid_expires) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_take_control(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_take_control(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -807,10 +742,8 @@ def test_take_control(self, mock_boto3, mock_get_data_endpoint, mock_get_control streamUpdate={"automationStreamUpdate": {"streamStatus": "DISABLED"}}, ) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_release_control(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_release_control(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() client = BrowserClient("us-west-2") @@ -827,11 +760,9 @@ def test_release_control(self, mock_boto3, mock_get_data_endpoint, mock_get_cont streamUpdate={"automationStreamUpdate": {"streamStatus": "ENABLED"}}, ) - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_viewport(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_viewport(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -887,13 +818,9 @@ def test_browser_session_context_manager_with_all_params(self, mock_client_class mock_client.start.assert_called_once_with(viewport=viewport, identifier="custom-browser") mock_client.stop.assert_called_once() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_proxy_configuration( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_proxy_configuration(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -934,13 +861,9 @@ def test_start_with_proxy_configuration( assert client.identifier == "aws.browser.v1" assert client.session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_proxy_configuration_and_viewport( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_proxy_configuration_and_viewport(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -974,13 +897,9 @@ def test_start_with_proxy_configuration_and_viewport( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_proxy_configuration_multiple_proxies( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_proxy_configuration_multiple_proxies(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1026,13 +945,9 @@ def test_start_with_proxy_configuration_multiple_proxies( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_without_proxy_configuration_unchanged( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_without_proxy_configuration_unchanged(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1114,11 +1029,9 @@ def test_browser_session_context_manager_with_all_params_including_proxy(self, m ) mock_client.stop.assert_called_once() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_extensions(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_extensions(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1141,13 +1054,9 @@ def test_start_with_extensions(self, mock_uuid4, mock_boto3, mock_get_data_endpo ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_profile_configuration( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_profile_configuration(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1170,13 +1079,9 @@ def test_start_with_profile_configuration( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_all_session_params( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_all_session_params(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1246,13 +1151,9 @@ def test_browser_session_context_manager_with_profile_configuration(self, mock_c mock_client.start.assert_called_once_with(profile_configuration=profile_config) mock_client.stop.assert_called_once() - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_proxy_configuration_dataclass( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_proxy_configuration_dataclass(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1306,13 +1207,9 @@ def test_start_with_proxy_configuration_dataclass( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_extensions_dataclass( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_extensions_dataclass(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1449,13 +1346,9 @@ def test_session_configuration_with_name_and_viewport(self): "viewport": {"width": 1920, "height": 1080}, } - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_enterprise_policies( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_enterprise_policies(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1478,11 +1371,9 @@ def test_start_with_enterprise_policies( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_certificates(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_certificates(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1505,13 +1396,9 @@ def test_start_with_certificates(self, mock_uuid4, mock_boto3, mock_get_data_end ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_enterprise_policies_dataclass( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_enterprise_policies_dataclass(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1541,13 +1428,9 @@ def test_start_with_enterprise_policies_dataclass( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") @patch("bedrock_agentcore.tools.browser_client.uuid.uuid4") - def test_start_with_certificates_dataclass( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_start_with_certificates_dataclass(self, mock_uuid4, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() mock_uuid4.return_value.hex = "12345678abcdef" @@ -1572,12 +1455,8 @@ def test_start_with_certificates_dataclass( ) assert session_id == "session-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_create_browser_with_enterprise_policies( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_create_browser_with_enterprise_policies(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() @@ -1603,10 +1482,8 @@ def test_create_browser_with_enterprise_policies( ) assert response["browserId"] == "browser-123" - @patch("bedrock_agentcore.tools.browser_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.browser_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.browser_client.boto3") - def test_create_browser_with_certificates(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_create_browser_with_certificates(self, mock_boto3): # Arrange mock_boto3.client.return_value = MagicMock() diff --git a/tests/bedrock_agentcore/tools/test_code_interpreter_client.py b/tests/bedrock_agentcore/tools/test_code_interpreter_client.py index e856c3fc..12796609 100644 --- a/tests/bedrock_agentcore/tools/test_code_interpreter_client.py +++ b/tests/bedrock_agentcore/tools/test_code_interpreter_client.py @@ -8,18 +8,14 @@ class TestCodeInterpreterClient: - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_init(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() mock_data_client = MagicMock() mock_session.client.side_effect = [mock_control_client, mock_data_client] mock_boto3.Session.return_value = mock_session - mock_get_control_endpoint.return_value = "https://mock-control-endpoint.com" - mock_get_data_endpoint.return_value = "https://mock-data-endpoint.com" region = "us-west-2" # Act @@ -29,13 +25,11 @@ def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoin mock_session.client.assert_any_call( "bedrock-agentcore-control", region_name=region, - endpoint_url="https://mock-control-endpoint.com", config=ANY, ) mock_session.client.assert_any_call( "bedrock-agentcore", region_name=region, - endpoint_url="https://mock-data-endpoint.com", config=ANY, ) assert client.control_plane_client == mock_control_client @@ -43,18 +37,14 @@ def test_init(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoin assert client.identifier is None assert client.session_id is None - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_init_with_integration_source(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_init_with_integration_source(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() mock_data_client = MagicMock() mock_session.client.side_effect = [mock_control_client, mock_data_client] mock_boto3.Session.return_value = mock_session - mock_get_control_endpoint.return_value = "https://mock-control-endpoint.com" - mock_get_data_endpoint.return_value = "https://mock-data-endpoint.com" region = "us-west-2" integration_source = "strands" @@ -65,16 +55,12 @@ def test_init_with_integration_source(self, mock_boto3, mock_get_data_endpoint, assert client.integration_source == integration_source assert mock_session.client.call_count == 2 - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") - def test_init_with_custom_session(self, mock_get_data_endpoint, mock_get_control_endpoint): + def test_init_with_custom_session(self): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() mock_data_client = MagicMock() mock_session.client.side_effect = [mock_control_client, mock_data_client] - mock_get_control_endpoint.return_value = "https://mock-control-endpoint.com" - mock_get_data_endpoint.return_value = "https://mock-data-endpoint.com" region = "us-west-2" # Act @@ -87,10 +73,8 @@ def test_init_with_custom_session(self, mock_get_data_endpoint, mock_get_control assert client.identifier is None assert client.session_id is None - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_property_getters_setters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_property_getters_setters(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -108,10 +92,8 @@ def test_property_getters_setters(self, mock_boto3, mock_get_data_endpoint, mock client.session_id = test_session_id assert client.session_id == test_session_id - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_create_code_interpreter_minimal(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_create_code_interpreter_minimal(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() @@ -142,12 +124,8 @@ def test_create_code_interpreter_minimal(self, mock_boto3, mock_get_data_endpoin ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_create_code_interpreter_with_all_options( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_create_code_interpreter_with_all_options(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() @@ -191,10 +169,8 @@ def test_create_code_interpreter_with_all_options( ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_delete_code_interpreter(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_delete_code_interpreter(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -215,12 +191,8 @@ def test_delete_code_interpreter(self, mock_boto3, mock_get_data_endpoint, mock_ client.control_plane_client.delete_code_interpreter.assert_called_once_with(codeInterpreterId="test-interp-123") assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_delete_code_interpreter_with_client_token( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_delete_code_interpreter_with_client_token(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -243,10 +215,8 @@ def test_delete_code_interpreter_with_client_token( ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_get_code_interpreter(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_code_interpreter(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -268,10 +238,8 @@ def test_get_code_interpreter(self, mock_boto3, mock_get_data_endpoint, mock_get client.control_plane_client.get_code_interpreter.assert_called_once_with(codeInterpreterId="test-interp-123") assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_list_code_interpreters_default(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_code_interpreters_default(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -293,10 +261,8 @@ def test_list_code_interpreters_default(self, mock_boto3, mock_get_data_endpoint client.control_plane_client.list_code_interpreters.assert_called_once_with(maxResults=10) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_list_code_interpreters_with_filters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_code_interpreters_with_filters(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -318,11 +284,9 @@ def test_list_code_interpreters_with_filters(self, mock_boto3, mock_get_data_end ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") @patch("bedrock_agentcore.tools.code_interpreter_client.uuid.uuid4") - def test_start_with_defaults(self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_defaults(self, mock_uuid4, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -347,10 +311,8 @@ def test_start_with_defaults(self, mock_uuid4, mock_boto3, mock_get_data_endpoin assert client.identifier == "aws.codeinterpreter.v1" assert client.session_id == "session-123" - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_start_with_custom_params(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_start_with_custom_params(self, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -378,10 +340,8 @@ def test_start_with_custom_params(self, mock_boto3, mock_get_data_endpoint, mock assert client.identifier == "custom.interpreter" assert client.session_id == "custom-session-123" - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_stop_when_session_exists(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_stop_when_session_exists(self, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -402,10 +362,8 @@ def test_stop_when_session_exists(self, mock_boto3, mock_get_data_endpoint, mock assert client.identifier is None assert client.session_id is None - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_stop_when_no_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_stop_when_no_session(self, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -423,10 +381,8 @@ def test_stop_when_no_session(self, mock_boto3, mock_get_data_endpoint, mock_get client.data_plane_client.stop_code_interpreter_session.assert_not_called() assert result is True - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_get_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -451,10 +407,8 @@ def test_get_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_ ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_get_session_with_params(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session_with_params(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -477,10 +431,8 @@ def test_get_session_with_params(self, mock_boto3, mock_get_data_endpoint, mock_ ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_get_session_missing_ids(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_get_session_missing_ids(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -491,10 +443,8 @@ def test_get_session_missing_ids(self, mock_boto3, mock_get_data_endpoint, mock_ with pytest.raises(ValueError, match="Interpreter ID and Session ID must be provided"): client.get_session() - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_list_sessions(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -519,10 +469,8 @@ def test_list_sessions(self, mock_boto3, mock_get_data_endpoint, mock_get_contro ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_list_sessions_with_filters(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions_with_filters(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -552,10 +500,8 @@ def test_list_sessions_with_filters(self, mock_boto3, mock_get_data_endpoint, mo ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_list_sessions_missing_interpreter_id(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_list_sessions_missing_interpreter_id(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -566,13 +512,9 @@ def test_list_sessions_missing_interpreter_id(self, mock_boto3, mock_get_data_en with pytest.raises(ValueError, match="Interpreter ID must be provided"): client.list_sessions() - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") @patch("bedrock_agentcore.tools.code_interpreter_client.uuid.uuid4") - def test_invoke_with_existing_session( - self, mock_uuid4, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_invoke_with_existing_session(self, mock_uuid4, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -599,10 +541,8 @@ def test_invoke_with_existing_session( ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_invoke_with_no_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_invoke_with_no_session(self, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -678,10 +618,8 @@ def test_code_session_context_manager_with_identifier(self, mock_client_class): mock_client.start.assert_called_once_with(identifier="custom-interpreter-123") mock_client.stop.assert_called_once() - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_file_text_content(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_file_text_content(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -705,10 +643,8 @@ def test_upload_file_text_content(self, mock_boto3, mock_get_data_endpoint, mock ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_file_binary_content(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_file_binary_content(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -735,10 +671,8 @@ def test_upload_file_binary_content(self, mock_boto3, mock_get_data_endpoint, mo ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_file_nested_path(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_file_nested_path(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -761,10 +695,8 @@ def test_upload_file_nested_path(self, mock_boto3, mock_get_data_endpoint, mock_ arguments={"content": [{"path": "scripts/analysis.py", "text": "print('hello')"}]}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_file_absolute_path_error(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_file_absolute_path_error(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -777,10 +709,8 @@ def test_upload_file_absolute_path_error(self, mock_boto3, mock_get_data_endpoin with pytest.raises(ValueError, match="Path must be relative, not absolute"): client.upload_file(path="/absolute/path/file.txt", content="test") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_files_multiple(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_files_multiple(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -814,10 +744,8 @@ def test_upload_files_multiple(self, mock_boto3, mock_get_data_endpoint, mock_ge ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_files_mixed_content(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_files_mixed_content(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -853,10 +781,8 @@ def test_upload_files_mixed_content(self, mock_boto3, mock_get_data_endpoint, mo }, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_upload_files_absolute_path_error(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_upload_files_absolute_path_error(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -874,10 +800,8 @@ def test_upload_files_absolute_path_error(self, mock_boto3, mock_get_data_endpoi with pytest.raises(ValueError, match="Path must be relative, not absolute"): client.upload_files(files) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_install_packages_basic(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_install_packages_basic(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -901,10 +825,8 @@ def test_install_packages_basic(self, mock_boto3, mock_get_data_endpoint, mock_g ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_install_packages_with_versions(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_install_packages_with_versions(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -927,10 +849,8 @@ def test_install_packages_with_versions(self, mock_boto3, mock_get_data_endpoint arguments={"command": "pip install pandas>=2.0 numpy<2.0 scikit-learn==1.3.0"}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_install_packages_with_upgrade(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_install_packages_with_upgrade(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -953,10 +873,8 @@ def test_install_packages_with_upgrade(self, mock_boto3, mock_get_data_endpoint, arguments={"command": "pip install --upgrade pandas"}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_install_packages_empty_list_error(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_install_packages_empty_list_error(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -969,12 +887,8 @@ def test_install_packages_empty_list_error(self, mock_boto3, mock_get_data_endpo with pytest.raises(ValueError, match="At least one package name must be provided"): client.install_packages([]) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_install_packages_invalid_characters_error( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_install_packages_invalid_characters_error(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1003,10 +917,8 @@ def test_install_packages_invalid_characters_error( with pytest.raises(ValueError, match="Invalid package name"): client.install_packages(["pandas$HOME"]) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_file_text(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_file_text(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1040,10 +952,8 @@ def test_download_file_text(self, mock_boto3, mock_get_data_endpoint, mock_get_c ) assert result == "col1,col2\n1,2\n3,4" - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_file_binary(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_file_binary(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1075,10 +985,8 @@ def test_download_file_binary(self, mock_boto3, mock_get_data_endpoint, mock_get assert result == binary_content assert isinstance(result, bytes) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_file_blob_utf8_returns_str(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_file_blob_utf8_returns_str(self, mock_boto3): """Blob content that is valid UTF-8 should be decoded and returned as str.""" # Arrange mock_session = MagicMock() @@ -1111,10 +1019,8 @@ def test_download_file_blob_utf8_returns_str(self, mock_boto3, mock_get_data_end assert result == text_content assert isinstance(result, str) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_file_not_found(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_file_not_found(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1130,10 +1036,8 @@ def test_download_file_not_found(self, mock_boto3, mock_get_data_endpoint, mock_ with pytest.raises(FileNotFoundError, match="Could not read file"): client.download_file("nonexistent.txt") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_files_multiple(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_files_multiple(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1168,10 +1072,8 @@ def test_download_files_multiple(self, mock_boto3, mock_get_data_endpoint, mock_ ) assert result == {"data.csv": "col1,col2\n1,2", "config.json": '{"key": "value"}'} - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_files_empty_result(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_files_empty_result(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1189,10 +1091,8 @@ def test_download_files_empty_result(self, mock_boto3, mock_get_data_endpoint, m # Assert assert result == {} - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_files_binary(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_files_binary(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1238,10 +1138,8 @@ def test_download_files_binary(self, mock_boto3, mock_get_data_endpoint, mock_ge assert result["/opt/amazon/genesis1p-tools/var/chart.png"] == binary_content assert isinstance(result["/opt/amazon/genesis1p-tools/var/chart.png"], bytes) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_download_files_blob_utf8_returns_str(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_download_files_blob_utf8_returns_str(self, mock_boto3): """Blob content that is valid UTF-8 should be decoded and returned as str in multi-file download.""" # Arrange mock_session = MagicMock() @@ -1291,10 +1189,8 @@ def test_download_files_blob_utf8_returns_str(self, mock_boto3, mock_get_data_en assert result["/opt/amazon/genesis1p-tools/var/chart.png"] == binary_content assert isinstance(result["/opt/amazon/genesis1p-tools/var/chart.png"], bytes) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_python_default(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_python_default(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1320,10 +1216,8 @@ def test_execute_code_python_default(self, mock_boto3, mock_get_data_endpoint, m ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_javascript(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_javascript(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1348,10 +1242,8 @@ def test_execute_code_javascript(self, mock_boto3, mock_get_data_endpoint, mock_ arguments={"code": code, "language": "javascript", "clearContext": False}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_typescript(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_typescript(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1376,10 +1268,8 @@ def test_execute_code_typescript(self, mock_boto3, mock_get_data_endpoint, mock_ arguments={"code": code, "language": "typescript", "clearContext": False}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_with_clear_context(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_with_clear_context(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1404,10 +1294,8 @@ def test_execute_code_with_clear_context(self, mock_boto3, mock_get_data_endpoin arguments={"code": code, "language": "python", "clearContext": True}, ) - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_invalid_language_error(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_invalid_language_error(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1420,10 +1308,8 @@ def test_execute_code_invalid_language_error(self, mock_boto3, mock_get_data_end with pytest.raises(ValueError, match="Language must be one of"): client.execute_code("code", language="ruby") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_shell_basic(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_shell_basic(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1447,10 +1333,8 @@ def test_execute_shell_basic(self, mock_boto3, mock_get_data_endpoint, mock_get_ ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_shell_python_version(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_shell_python_version(self, mock_boto3): # Arrange mock_session = MagicMock() mock_session.client.return_value = MagicMock() @@ -1474,10 +1358,8 @@ def test_execute_shell_python_version(self, mock_boto3, mock_get_data_endpoint, ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_execute_code_auto_starts_session(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint): + def test_execute_code_auto_starts_session(self, mock_boto3): # Arrange mock_session = MagicMock() mock_data_client = MagicMock() @@ -1501,12 +1383,8 @@ def test_execute_code_auto_starts_session(self, mock_boto3, mock_get_data_endpoi client.data_plane_client.start_code_interpreter_session.assert_called_once() client.data_plane_client.invoke_code_interpreter.assert_called_once() - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_create_code_interpreter_with_certificates( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_create_code_interpreter_with_certificates(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() @@ -1549,12 +1427,8 @@ def test_create_code_interpreter_with_certificates( ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_create_code_interpreter_with_certificate_dataclass( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_create_code_interpreter_with_certificate_dataclass(self, mock_boto3): # Arrange mock_session = MagicMock() mock_control_client = MagicMock() @@ -1594,12 +1468,8 @@ def test_create_code_interpreter_with_certificate_dataclass( ) assert result == mock_response - @patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") - @patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") - def test_create_code_interpreter_without_certificates( - self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint - ): + def test_create_code_interpreter_without_certificates(self, mock_boto3): """Verify that omitting certificates does not include it in the API call (backward compatibility).""" # Arrange mock_session = MagicMock() @@ -1626,8 +1496,6 @@ def test_create_code_interpreter_without_certificates( assert "certificates" not in call_kwargs -@patch("bedrock_agentcore.tools.code_interpreter_client.get_control_plane_endpoint") -@patch("bedrock_agentcore.tools.code_interpreter_client.get_data_plane_endpoint") @patch("bedrock_agentcore.tools.code_interpreter_client.boto3") class TestInstallPackagesAllowlist: """Verify install_packages() rejects all flag-injection and shell-injection @@ -1673,7 +1541,7 @@ def _client(self, mock_boto3): "-r /proc/self/environ", ], ) - def test_pip_flags_blocked(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint, pkg): + def test_pip_flags_blocked(self, mock_boto3, pkg): client = self._client(mock_boto3) with pytest.raises(ValueError, match="Invalid package name"): client.install_packages([pkg]) @@ -1699,7 +1567,7 @@ def test_pip_flags_blocked(self, mock_boto3, mock_get_data_endpoint, mock_get_co "pandas\nrm -rf /", ], ) - def test_shell_and_path_injection_blocked(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint, pkg): + def test_shell_and_path_injection_blocked(self, mock_boto3, pkg): client = self._client(mock_boto3) with pytest.raises(ValueError, match="Invalid package name"): client.install_packages([pkg]) @@ -1717,7 +1585,7 @@ def test_shell_and_path_injection_blocked(self, mock_boto3, mock_get_data_endpoi "requests[| whoami]", ], ) - def test_extras_injection_blocked(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint, pkg): + def test_extras_injection_blocked(self, mock_boto3, pkg): client = self._client(mock_boto3) with pytest.raises(ValueError, match="Invalid package name"): client.install_packages([pkg]) @@ -1747,7 +1615,7 @@ def test_extras_injection_blocked(self, mock_boto3, mock_get_data_endpoint, mock "pandas[excel]>=1.5", ], ) - def test_valid_packages_accepted(self, mock_boto3, mock_get_data_endpoint, mock_get_control_endpoint, pkg): + def test_valid_packages_accepted(self, mock_boto3, pkg): client = self._client(mock_boto3) client.data_plane_client.invoke_code_interpreter.return_value = {"stream": []} # Should not raise