diff --git a/litellm/llms/sap/credentials.py b/litellm/llms/sap/credentials.py index be272ff11c4..474b3efeff9 100644 --- a/litellm/llms/sap/credentials.py +++ b/litellm/llms/sap/credentials.py @@ -37,15 +37,17 @@ def _get_nested(d: Union[Dict[str, Any], str], path: Sequence[str]) -> Any: cur = json.loads(cur) except json.JSONDecodeError: verbose_logger.warning( - "SAP service key is a string but not valid JSON." + "SAP service key or VCAP service is a string but not valid JSON." ) return None for k in path: - if not isinstance(cur, dict) or k not in cur: + if not isinstance(cur, dict): verbose_logger.warning( - f"SAP service key has unexpected type '{type(cur).__name__}' (expected dict or JSON string). " + f"SAP service key or VCAP service traversal hit non-dict type '{type(cur).__name__}' at key '{k}'." ) return None + if k not in cur: + return None cur = cur[k] return cur @@ -218,13 +220,15 @@ def fetch_credentials(service_key: Optional[Union[str, dict]] = None, profile: O Source("kwargs", lambda cv: _str_or_none(kwargs.get(cv.name))), Source("service key", - lambda cv: _get_nested(service_key, cv.vcap_key if cv.vcap_key else (cv.name,))), # type: ignore[arg-type] + lambda cv: _get_nested(service_key, cv.vcap_key if cv.vcap_key else (cv.name,)) + if service_key else None), # type: ignore[arg-type] Source("environment variables", lambda cv: _str_or_none(os.environ.get(f'AICORE_{cv.name.upper()}'))), Source("config file", lambda cv: _str_or_none(config.get(f'AICORE_{cv.name.upper()}') or config.get(cv.name))), Source("VCAP service", - lambda cv: _get_nested(vcap_service, ("credentials",) + cv.vcap_key if cv.vcap_key else (cv.name,))), # type: ignore[arg-type] + lambda cv: _get_nested(vcap_service, (("credentials",) + cv.vcap_key) if cv.vcap_key else (cv.name,)) + if vcap_service else None), # type: ignore[arg-type] ] credentials = resolve_credentials(sources) diff --git a/tests/test_litellm/llms/sap/test_sap_fetch_creds.py b/tests/test_litellm/llms/sap/test_sap_fetch_creds.py index 46e5656a523..c40ef5e8025 100644 --- a/tests/test_litellm/llms/sap/test_sap_fetch_creds.py +++ b/tests/test_litellm/llms/sap/test_sap_fetch_creds.py @@ -1,5 +1,6 @@ import json -from litellm.llms.sap.credentials import fetch_credentials +import litellm.llms.sap.credentials as sap_credentials + mock_sap_service_key_dict = { "serviceurls": { @@ -32,24 +33,28 @@ mock_sap_vcap_service_key_dict = { } def test_sap_fetch_creds_from_env_service_key(monkeypatch): + monkeypatch.setattr(sap_credentials, "sap_service_key", None) monkeypatch.setenv("AICORE_HOME", 'notexist') monkeypatch.setenv("AICORE_SERVICE_KEY", json.dumps(mock_sap_service_key_dict)) - creds = fetch_credentials() + creds = sap_credentials.fetch_credentials() assert creds == expected_creds def test_sap_fetch_creds_from_arg_service_key(monkeypatch): + monkeypatch.setattr(sap_credentials, "sap_service_key", None) monkeypatch.setenv("AICORE_HOME", 'notexist') - creds = fetch_credentials(service_key=json.dumps(mock_sap_service_key_dict)) + creds = sap_credentials.fetch_credentials(service_key=json.dumps(mock_sap_service_key_dict)) assert creds == expected_creds def test_fetch_creds_from_env_vcap_service(monkeypatch): + monkeypatch.setattr(sap_credentials, "sap_service_key", None) monkeypatch.setenv("AICORE_HOME", 'notexist') monkeypatch.setenv("VCAP_SERVICES", json.dumps(mock_sap_vcap_service_key_dict)) - creds = fetch_credentials() + creds = sap_credentials.fetch_credentials() assert creds['client_id'] == "vcap-clientid" assert creds['client_secret'] == "vcap-clientsecret" def test_fetch_creds_from_env(monkeypatch): + monkeypatch.setattr(sap_credentials, "sap_service_key", None) monkeypatch.setenv("AICORE_HOME", 'notexist') monkeypatch.setenv("AICORE_CLIENT_ID", "env-client-id") monkeypatch.setenv("AICORE_CLIENT_SECRET", "env-client-secret") @@ -57,7 +62,7 @@ def test_fetch_creds_from_env(monkeypatch): monkeypatch.setenv("AICORE_BASE_URL", "env-base-url") monkeypatch.setenv("AICORE_RESOURCE_GROUP", "env-resource-group") - creds = fetch_credentials() + creds = sap_credentials.fetch_credentials() assert creds['client_id'] == "env-client-id" assert creds['client_secret'] == "env-client-secret" @@ -66,12 +71,13 @@ def test_fetch_creds_from_env(monkeypatch): assert creds['resource_group'] == "env-resource-group" def test_creds_priority_order(monkeypatch): + monkeypatch.setattr(sap_credentials, "sap_service_key", None) monkeypatch.setenv("AICORE_HOME", 'notexist') monkeypatch.setenv("AICORE_CLIENT_ID", "env-client-id") monkeypatch.setenv("AICORE_CLIENT_SECRET", "env-client-secret") monkeypatch.setenv("AICORE_AUTH_URL", "env-auth-url") monkeypatch.setenv("AICORE_BASE_URL", "env-base-url") monkeypatch.setenv("AICORE_RESOURCE_GROUP", "env-resource-group") - creds = fetch_credentials(service_key=json.dumps(mock_sap_service_key_dict)) + creds = sap_credentials.fetch_credentials(service_key=json.dumps(mock_sap_service_key_dict)) assert creds['client_id'] == "mockclientid" assert creds['resource_group'] == "env-resource-group" \ No newline at end of file