diff --git a/.env_integration_tests.example b/.env_integration_tests.example index f90d019..1089a5e 100644 --- a/.env_integration_tests.example +++ b/.env_integration_tests.example @@ -17,5 +17,5 @@ CLOUD_SDK_CFG_DESTINATION_DEFAULT_IDENTITYZONE=your-identity-zone-here CLOUD_SDK_CFG_SDM_DEFAULT_URI=https://your-sdm-api-uri-here CLOUD_SDK_CFG_SDM_DEFAULT_UAA='{"url":"https://your-auth-url","clientid":"your-client-id","clientsecret":"your-client-secret","identityzone":"your-identity-zone"}' -CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL=https://your-agent-memory-api-url-here +CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL=https://your-agent-memory-api-url-here CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA='{"url":"https://your-auth-url","clientid":"your-client-id","clientsecret":"your-client-secret"}' diff --git a/docs/INTEGRATION_TESTS.md b/docs/INTEGRATION_TESTS.md index 5a33ff5..a056627 100644 --- a/docs/INTEGRATION_TESTS.md +++ b/docs/INTEGRATION_TESTS.md @@ -70,7 +70,7 @@ For Agent Memory integration tests, configure the following variables in `.env_i ```bash # Agent Memory Configuration -CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL=https://your-agent-memory-api-url +CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL=https://your-agent-memory-api-url CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA='{"url":"https://your-auth-url","clientid":"your-client-id","clientsecret":"your-client-secret"}' ``` diff --git a/src/sap_cloud_sdk/agent_memory/config.py b/src/sap_cloud_sdk/agent_memory/config.py index ab41f86..e2cbdfa 100644 --- a/src/sap_cloud_sdk/agent_memory/config.py +++ b/src/sap_cloud_sdk/agent_memory/config.py @@ -5,16 +5,16 @@ Mount path convention:: - /etc/secrets/appfnd/hana-agent-memory/default/url + /etc/secrets/appfnd/hana-agent-memory/default/application_url /etc/secrets/appfnd/hana-agent-memory/default/uaa -``url`` is the Agent Memory service base URL (plain string). +``application_url`` is the Agent Memory service base URL (plain string). ``uaa`` is a JSON string with OAuth2 credentials containing at minimum: ``clientid``, ``clientsecret``, and ``url`` (UAA base URL). Env fallback convention:: - CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL + CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA """ @@ -81,14 +81,14 @@ class BindingData: All fields must be plain ``str`` to satisfy the resolver contract. """ - url: str = "" + application_url: str = "" uaa: str = "" def validate(self) -> None: """Raise ``AgentMemoryConfigError`` if any required field is empty.""" - if not self.url: + if not self.application_url: raise AgentMemoryConfigError( - "Agent Memory binding is missing required field: url" + "Agent Memory binding is missing required field: application_url" ) if not self.uaa: raise AgentMemoryConfigError( @@ -104,7 +104,7 @@ def extract_config(self) -> AgentMemoryConfig: try: return AgentMemoryConfig( - base_url=self.url, + base_url=self.application_url, token_url=uaa_data["url"].rstrip("/") + "/oauth/token", client_id=uaa_data["clientid"], client_secret=uaa_data["clientsecret"], diff --git a/src/sap_cloud_sdk/agent_memory/user-guide.md b/src/sap_cloud_sdk/agent_memory/user-guide.md index 16e9644..caf98fc 100644 --- a/src/sap_cloud_sdk/agent_memory/user-guide.md +++ b/src/sap_cloud_sdk/agent_memory/user-guide.md @@ -775,7 +775,7 @@ environment variables or service binding. ### Service Binding - **Mount path**: `$SERVICE_BINDING_ROOT/hana-agent-memory/default/` (defaults to `/etc/secrets/appfnd/hana-agent-memory/default/`) -- **Required keys**: `url` (Agent Memory service URL), `uaa` (JSON string with XSUAA credentials) +- **Required keys**: `application_url` (Agent Memory service URL), `uaa` (JSON string with XSUAA credentials) - **Env var fallback**: `CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_{FIELD}` (uppercased) > **Note:** `SERVICE_BINDING_ROOT` defaults to `/etc/secrets/appfnd` when not set. See the [Secret Resolver guide](../core/secret_resolver/user-guide.md) for details. @@ -784,14 +784,14 @@ environment variables or service binding. ``` $SERVICE_BINDING_ROOT/hana-agent-memory/default/ -├── url +├── application_url └── uaa ``` #### Environment Variables ```bash -export CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL="https://agent-memory.example.com" +export CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL="https://agent-memory.example.com" export CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA='{"clientid":"...","clientsecret":"...","url":"https://..."}' ``` diff --git a/tests/agent_memory/unit/test_client.py b/tests/agent_memory/unit/test_client.py index c7a94ec..b3dbbdd 100644 --- a/tests/agent_memory/unit/test_client.py +++ b/tests/agent_memory/unit/test_client.py @@ -46,7 +46,7 @@ def test_uses_provided_config(self): def test_reads_env_when_no_config_provided(self, monkeypatch): """Factory falls back to environment variables when no config given.""" import json - monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL", "http://memory.example.com") + monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL", "http://memory.example.com") monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA", json.dumps({ "url": "http://auth.example.com", "clientid": "client-id", diff --git a/tests/agent_memory/unit/test_config.py b/tests/agent_memory/unit/test_config.py index 8dae51c..d3e895a 100644 --- a/tests/agent_memory/unit/test_config.py +++ b/tests/agent_memory/unit/test_config.py @@ -64,43 +64,43 @@ def test_valid_config_with_all_fields_does_not_raise(self): class TestBindingData: - def test_validate_raises_when_url_missing(self): - with pytest.raises(AgentMemoryConfigError, match="url"): - BindingData(url="", uaa=_VALID_UAA).validate() + def test_validate_raises_when_application_url_missing(self): + with pytest.raises(AgentMemoryConfigError, match="application_url"): + BindingData(application_url="", uaa=_VALID_UAA).validate() def test_validate_raises_when_uaa_missing(self): with pytest.raises(AgentMemoryConfigError, match="uaa"): - BindingData(url="https://memory.example.com", uaa="").validate() + BindingData(application_url="https://memory.example.com", uaa="").validate() def test_validate_passes_when_all_fields_set(self): - BindingData(url="https://memory.example.com", uaa=_VALID_UAA).validate() + BindingData(application_url="https://memory.example.com", uaa=_VALID_UAA).validate() def test_extract_config_maps_url(self): - config = BindingData(url="https://memory.example.com", uaa=_VALID_UAA).extract_config() + config = BindingData(application_url="https://memory.example.com", uaa=_VALID_UAA).extract_config() assert config.base_url == "https://memory.example.com" def test_extract_config_derives_token_url(self): - config = BindingData(url="https://memory.example.com", uaa=_VALID_UAA).extract_config() + config = BindingData(application_url="https://memory.example.com", uaa=_VALID_UAA).extract_config() assert config.token_url == "https://auth.example.com/oauth/token" def test_extract_config_strips_trailing_slash_from_uaa_url(self): uaa = json.dumps({"url": "https://auth.example.com/", "clientid": "c", "clientsecret": "s"}) - config = BindingData(url="https://memory.example.com", uaa=uaa).extract_config() + config = BindingData(application_url="https://memory.example.com", uaa=uaa).extract_config() assert config.token_url == "https://auth.example.com/oauth/token" def test_extract_config_maps_client_credentials(self): - config = BindingData(url="https://memory.example.com", uaa=_VALID_UAA).extract_config() + config = BindingData(application_url="https://memory.example.com", uaa=_VALID_UAA).extract_config() assert config.client_id == "my-client" assert config.client_secret == "my-secret" def test_extract_config_raises_on_invalid_json(self): with pytest.raises(AgentMemoryConfigError, match="Failed to parse uaa JSON"): - BindingData(url="https://memory.example.com", uaa="not-json").extract_config() + BindingData(application_url="https://memory.example.com", uaa="not-json").extract_config() def test_extract_config_raises_on_missing_json_key(self): uaa = json.dumps({"url": "https://auth.example.com"}) # missing clientid/clientsecret with pytest.raises(AgentMemoryConfigError, match="Missing required field in uaa JSON"): - BindingData(url="https://memory.example.com", uaa=uaa).extract_config() + BindingData(application_url="https://memory.example.com", uaa=uaa).extract_config() def test_extract_config_ignores_extra_uaa_fields(self): uaa = json.dumps({ @@ -114,7 +114,7 @@ def test_extract_config_ignores_extra_uaa_fields(self): "xsappname": "my-app", "zoneid": "1acb547d-6df6-40a6-abb6-e41dd7d079d1", }) - config = BindingData(url="https://memory.example.com", uaa=uaa).extract_config() + config = BindingData(application_url="https://memory.example.com", uaa=uaa).extract_config() assert config.base_url == "https://memory.example.com" assert config.token_url == "https://auth.example.com/oauth/token" assert config.client_id == "my-client" @@ -122,7 +122,7 @@ def test_extract_config_ignores_extra_uaa_fields(self): def test_extract_config_raises_on_empty_uaa_object(self): with pytest.raises(AgentMemoryConfigError, match="Missing required field in uaa JSON"): - BindingData(url="https://memory.example.com", uaa="{}").extract_config() + BindingData(application_url="https://memory.example.com", uaa="{}").extract_config() # ── _load_config_from_env ───────────────────────────────────────────────────── @@ -130,7 +130,7 @@ def test_extract_config_raises_on_empty_uaa_object(self): def _fill_binding(**kwargs) -> None: target = kwargs["target"] - target.url = "https://memory.example.com" + target.application_url = "https://memory.example.com" target.uaa = _VALID_UAA @@ -156,7 +156,7 @@ def test_calls_resolver_with_correct_arguments(self): assert kwargs["instance"] == "default" def test_falls_back_to_env_vars(self, monkeypatch): - monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL", "https://memory.example.com") + monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL", "https://memory.example.com") monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA", _VALID_UAA) # Let the real resolver run — mount will fail, env vars will succeed @@ -173,7 +173,7 @@ def test_raises_config_error_when_resolver_fails(self): def test_raises_config_error_when_binding_incomplete(self): def partial_fill(**kwargs): - kwargs["target"].url = "https://memory.example.com" + kwargs["target"].application_url = "https://memory.example.com" # uaa remains empty → validate() raises with patch(_RESOLVER, side_effect=partial_fill): @@ -181,7 +181,7 @@ def partial_fill(**kwargs): _load_config_from_env() def test_raises_config_error_when_uaa_json_invalid(self, monkeypatch): - monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_URL", "https://memory.example.com") + monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_APPLICATION_URL", "https://memory.example.com") monkeypatch.setenv("CLOUD_SDK_CFG_HANA_AGENT_MEMORY_DEFAULT_UAA", "not-valid-json") with patch("os.stat", side_effect=FileNotFoundError("no mount")):