mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-10 08:28:25 +00:00
fix(proxy): let /config/field/delete remove ignored stored general_settings keys
This commit is contained in:
parent
02367d7449
commit
8fd9c71c46
3 changed files with 67 additions and 15 deletions
|
|
@ -8501,7 +8501,7 @@ class ProxyConfig:
|
|||
for key in sorted(unmanaged - self._warned_unmanaged_keys):
|
||||
verbose_proxy_logger.warning(
|
||||
"general_settings.%s is stored in the database, but no settings API manages it, so the stored value "
|
||||
"is ignored. Set it in the config file to use it.",
|
||||
"is ignored. Set it in the config file to use it, or remove it with POST /config/field/delete.",
|
||||
key,
|
||||
)
|
||||
self._warned_unmanaged_keys = unmanaged
|
||||
|
|
@ -20646,7 +20646,16 @@ async def delete_config_general_settings(
|
|||
if data.field_name in _GENERAL_SETTINGS_UI_LITELLM_FIELDS:
|
||||
return await _reset_general_settings_ui_litellm_field(data.field_name, user_api_key_dict)
|
||||
|
||||
if data.field_name not in ConfigGeneralSettings.model_fields:
|
||||
db_general_settings: Final[_ConfigParamRow | None] = await _config_param_table(prisma_client).find_first(
|
||||
where={"param_name": "general_settings"}
|
||||
)
|
||||
stored_keys: Final[frozenset[str]] = (
|
||||
frozenset(dict(db_general_settings.param_value))
|
||||
if db_general_settings is not None and db_general_settings.param_value is not None
|
||||
else frozenset()
|
||||
)
|
||||
|
||||
if data.field_name not in ConfigGeneralSettings.model_fields and data.field_name not in stored_keys:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail={"error": f"Invalid field={data.field_name} passed in."},
|
||||
|
|
@ -20654,12 +20663,6 @@ async def delete_config_general_settings(
|
|||
|
||||
proxy_config.reject_config_owned_deletes(section_name="general_settings", keys=(data.field_name,))
|
||||
|
||||
## get general settings from db
|
||||
db_general_settings: Final[_ConfigParamRow | None] = await _config_param_table(prisma_client).find_first(
|
||||
where={"param_name": "general_settings"}
|
||||
)
|
||||
### pop the value
|
||||
|
||||
if db_general_settings is None or db_general_settings.param_value is None:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
|
|
|
|||
|
|
@ -4355,14 +4355,13 @@ async def test_ProxyConfig__update_general_settings_updates_health_check_retenti
|
|||
reschedule.assert_awaited_once()
|
||||
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ProxyConfig__update_general_settings_ignores_a_stored_key_no_settings_api_manages_and_warns_once(
|
||||
monkeypatch, caplog
|
||||
):
|
||||
monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
monkeypatch.setattr("litellm.proxy.proxy_server.general_settings", {})
|
||||
pc = ProxyConfig()
|
||||
stored_row = {"enforce_user_param": True, "store_prompts_in_spend_logs": True}
|
||||
pc: Final = ProxyConfig()
|
||||
stored_row: Final = {"enforce_user_param": True, "store_prompts_in_spend_logs": True}
|
||||
|
||||
with caplog.at_level(logging.WARNING, logger="LiteLLM Proxy"):
|
||||
await pc._update_general_settings(stored_row)
|
||||
|
|
@ -4371,10 +4370,10 @@ async def test_ProxyConfig__update_general_settings_ignores_a_stored_key_no_sett
|
|||
|
||||
assert proxy_server.general_settings["store_prompts_in_spend_logs"] is True
|
||||
assert "enforce_user_param" not in proxy_server.general_settings
|
||||
warnings = [record.getMessage() for record in caplog.records if "enforce_user_param" in record.getMessage()]
|
||||
warnings: Final = [record.getMessage() for record in caplog.records if "enforce_user_param" in record.getMessage()]
|
||||
assert warnings == [
|
||||
"general_settings.enforce_user_param is stored in the database, but no settings API manages it, so the "
|
||||
"stored value is ignored. Set it in the config file to use it."
|
||||
"stored value is ignored. Set it in the config file to use it, or remove it with POST /config/field/delete."
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15417,6 +15417,56 @@ async def test_delete_config_general_settings_still_removes_a_key_the_database_o
|
|||
assert "max_request_size_mb" not in pc.settings
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_config_general_settings_removes_a_stored_key_no_settings_api_manages(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
from litellm.proxy._types import ConfigFieldDelete
|
||||
from litellm.proxy.proxy_server import ProxyConfig, delete_config_general_settings
|
||||
|
||||
pc: Final = ProxyConfig()
|
||||
pc._load_yaml_settings_stores({"general_settings": {}})
|
||||
stored_row: Final = {"enforce_user_param": True, "store_prompts_in_spend_logs": True}
|
||||
pc.settings.apply_db_row("general_settings", stored_row)
|
||||
fake_prisma: Final = _fake_prisma_with_config(stored_row)
|
||||
monkeypatch.setattr(proxy_server_module, "proxy_config", pc)
|
||||
monkeypatch.setattr(proxy_server_module, "prisma_client", fake_prisma)
|
||||
|
||||
admin: Final = UserAPIKeyAuth(api_key="hashed-admin", user_id="admin-1", user_role=LitellmUserRoles.PROXY_ADMIN)
|
||||
await delete_config_general_settings(
|
||||
data=ConfigFieldDelete(field_name="enforce_user_param", config_type="general_settings"),
|
||||
user_api_key_dict=admin,
|
||||
)
|
||||
|
||||
written: Final = json.loads(fake_prisma.db.litellm_config.upsert.await_args.kwargs["data"]["update"]["param_value"])
|
||||
assert written == {"store_prompts_in_spend_logs": True}
|
||||
assert pc.settings.unmanaged_db_keys() == ()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_config_general_settings_refuses_a_key_neither_managed_nor_stored(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
from litellm.proxy._types import ConfigFieldDelete
|
||||
from litellm.proxy.proxy_server import ProxyConfig, delete_config_general_settings
|
||||
|
||||
pc: Final = ProxyConfig()
|
||||
pc._load_yaml_settings_stores({"general_settings": {}})
|
||||
fake_prisma: Final = _fake_prisma_with_config({"store_prompts_in_spend_logs": True})
|
||||
monkeypatch.setattr(proxy_server_module, "proxy_config", pc)
|
||||
monkeypatch.setattr(proxy_server_module, "prisma_client", fake_prisma)
|
||||
|
||||
admin: Final = UserAPIKeyAuth(api_key="hashed-admin", user_id="admin-1", user_role=LitellmUserRoles.PROXY_ADMIN)
|
||||
with pytest.raises(HTTPException) as refused:
|
||||
await delete_config_general_settings(
|
||||
data=ConfigFieldDelete(field_name="enforce_user_param", config_type="general_settings"),
|
||||
user_api_key_dict=admin,
|
||||
)
|
||||
|
||||
assert refused.value.status_code == 400
|
||||
fake_prisma.db.litellm_config.upsert.assert_not_awaited()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_config_field_info_reports_the_declared_value_of_a_config_owned_secret(monkeypatch):
|
||||
from litellm.proxy.proxy_server import ProxyConfig, get_config_general_settings
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue