From ec1ffcf12bd34313cdcfda06f2ce8c858eb1a0fc Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Sat, 28 Feb 2026 16:04:38 -0800 Subject: [PATCH] Simplify config override endpoints: extract helpers, fix env var ordering --- .../config_override_endpoints.py | 34 ++++++++++++------- litellm/proxy/proxy_server.py | 19 +++-------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/litellm/proxy/management_endpoints/config_override_endpoints.py b/litellm/proxy/management_endpoints/config_override_endpoints.py index cdd43d0c33c..838559435bd 100644 --- a/litellm/proxy/management_endpoints/config_override_endpoints.py +++ b/litellm/proxy/management_endpoints/config_override_endpoints.py @@ -3,6 +3,7 @@ import os from typing import Any, Dict, Set from fastapi import APIRouter, Depends, HTTPException +from pydantic import TypeAdapter from litellm._logging import verbose_proxy_logger from litellm.proxy._types import CommonProxyErrors, LitellmUserRoles, UserAPIKeyAuth @@ -87,8 +88,6 @@ def _get_current_env_values(env_var_mapping: Dict[str, str]) -> Dict[str, Any]: def _build_field_schema(model_class: type) -> Dict[str, Any]: """Build field_schema dict from a Pydantic model for UI rendering.""" - from pydantic import TypeAdapter - schema = TypeAdapter(model_class).json_schema(by_alias=True) properties = {} for field_name, field_info in schema.get("properties", {}).items(): @@ -102,6 +101,21 @@ def _build_field_schema(model_class: type) -> Dict[str, Any]: } +def _parse_config_value(raw: Any) -> Dict[str, Any]: + """Parse a config_value from DB (may be JSON string or dict).""" + if isinstance(raw, str): + return json.loads(raw) + return dict(raw) + + +def _set_env_vars(config_data: Dict[str, Any]) -> None: + """Set HCP_VAULT_* env vars from config data.""" + for field_name, value in config_data.items(): + env_var_name = HASHICORP_ENV_VAR_MAPPING.get(field_name) + if env_var_name and value is not None: + os.environ[env_var_name] = str(value) + + # --- Hashicorp Vault endpoints --- @@ -157,16 +171,10 @@ async def update_hashicorp_vault_config( }, ) - # Set environment variables - for field_name, value in config_data.items(): - env_var_name = HASHICORP_ENV_VAR_MAPPING.get(field_name) - if env_var_name and value is not None: - os.environ[env_var_name] = str(value) - # Encrypt sensitive fields before storing in DB encrypted_data = _encrypt_sensitive_fields(config_data, HASHICORP_SENSITIVE_FIELDS) - # Upsert to DB + # Upsert to DB first — only mutate env vars after DB write succeeds await prisma_client.db.litellm_configoverrides.upsert( where={"config_type": "hashicorp_vault"}, data={ @@ -180,6 +188,9 @@ async def update_hashicorp_vault_config( }, ) + # Set environment variables after DB write succeeds + _set_env_vars(config_data) + # Reinitialize the secret manager on this pod try: proxy_config.initialize_secret_manager( @@ -237,10 +248,7 @@ async def get_hashicorp_vault_config( ) if db_record is not None and db_record.config_value is not None: - if isinstance(db_record.config_value, str): - config_data = json.loads(db_record.config_value) - else: - config_data = dict(db_record.config_value) + config_data = _parse_config_value(db_record.config_value) # Decrypt sensitive fields decrypted_data = _decrypt_sensitive_fields( diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 3397d36aae5..c9aa73bd4dd 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -4560,9 +4560,10 @@ class ProxyConfig: Only runs once at startup (guarded by _hashicorp_config_override_initialized flag). """ from litellm.proxy.management_endpoints.config_override_endpoints import ( - HASHICORP_ENV_VAR_MAPPING, HASHICORP_SENSITIVE_FIELDS, _decrypt_sensitive_fields, + _parse_config_value, + _set_env_vars, ) try: @@ -4573,23 +4574,13 @@ class ProxyConfig: if db_record is None or db_record.config_value is None: return - import json + config_data = _parse_config_value(db_record.config_value) - if isinstance(db_record.config_value, str): - config_data = json.loads(db_record.config_value) - else: - config_data = dict(db_record.config_value) - - # Decrypt sensitive fields + # Decrypt sensitive fields and set env vars decrypted_data = _decrypt_sensitive_fields( config_data, HASHICORP_SENSITIVE_FIELDS ) - - # Set env vars - for field_name, value in decrypted_data.items(): - env_var_name = HASHICORP_ENV_VAR_MAPPING.get(field_name) - if env_var_name and value is not None: - os.environ[env_var_name] = str(value) + _set_env_vars(decrypted_data) # Reinitialize the secret manager self.initialize_secret_manager(