From 68fab2bf5d160e670e03be36b26b42ca2b83af8d Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Thu, 10 Oct 2024 19:11:36 +0530 Subject: [PATCH 1/3] add sentinel_password support --- litellm/_redis.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/litellm/_redis.py b/litellm/_redis.py index 289a7d4aed33..1adcabcd2784 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -12,7 +12,7 @@ # s/o [@Frank Colson](https://www.linkedin.com/in/frank-colson-422b9b183/) for this redis implementation import os -from typing import List, Optional, Union +from typing import Dict, List, Optional, Union import redis # type: ignore import redis.asyncio as async_redis # type: ignore @@ -215,8 +215,13 @@ def _init_redis_sentinel(redis_kwargs) -> redis.Redis: def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: sentinel_nodes = redis_kwargs.get("sentinel_nodes") + sentinel_password = redis_kwargs.get("sentinel_password") service_name = redis_kwargs.get("service_name") + sentinel_kwargs: Optional[Dict] = None + if sentinel_password: + sentinel_kwargs = {"password": sentinel_password} + if not sentinel_nodes or not service_name: raise ValueError( "Both 'sentinel_nodes' and 'service_name' are required for Redis Sentinel." @@ -225,7 +230,9 @@ def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: verbose_logger.debug("init_redis_sentinel: sentinel nodes are being initialized.") # Set up the Sentinel client - sentinel = async_redis.Sentinel(sentinel_nodes, socket_timeout=0.1) + sentinel = async_redis.Sentinel( + sentinel_nodes, socket_timeout=0.1, sentinel_kwargs=sentinel_kwargs + ) # Return the master instance for the given service From 671ac7c043de85e69db2e245dd5b2679a585e2be Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Thu, 10 Oct 2024 19:15:52 +0530 Subject: [PATCH 2/3] add doc for setting redis sentinel password --- docs/my-website/docs/proxy/caching.md | 2 ++ litellm/_redis.py | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/my-website/docs/proxy/caching.md b/docs/my-website/docs/proxy/caching.md index 4d44a4da0273..56acbc4dbfdb 100644 --- a/docs/my-website/docs/proxy/caching.md +++ b/docs/my-website/docs/proxy/caching.md @@ -130,6 +130,7 @@ litellm_settings: type: "redis" service_name: "mymaster" sentinel_nodes: [["localhost", 26379]] + sentinel_password: "password" # [OPTIONAL] ``` @@ -143,6 +144,7 @@ You can configure redis sentinel in your .env by setting `REDIS_SENTINEL_NODES` ```env REDIS_SENTINEL_NODES='[["localhost", 26379]]' REDIS_SERVICE_NAME = "mymaster" +REDIS_SENTINEL_PASSWORD = "password" ``` :::note diff --git a/litellm/_redis.py b/litellm/_redis.py index 1adcabcd2784..4a750a314e17 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -18,7 +18,7 @@ import redis.asyncio as async_redis # type: ignore import litellm -from litellm import get_secret +from litellm import get_secret, get_secret_str from ._logging import verbose_logger @@ -139,6 +139,13 @@ def _get_redis_client_logic(**env_overrides): if _sentinel_nodes is not None and isinstance(_sentinel_nodes, str): redis_kwargs["sentinel_nodes"] = json.loads(_sentinel_nodes) + _sentinel_password: Optional[str] = redis_kwargs.get( + "sentinel_password", None + ) or get_secret_str("REDIS_SENTINEL_PASSWORD") + + if _sentinel_password is not None: + redis_kwargs["sentinel_password"] = _sentinel_password + _service_name: Optional[str] = redis_kwargs.get("service_name", None) or get_secret( # type: ignore "REDIS_SERVICE_NAME" ) From 4506fa952b9311dc77b18a244905308e71528eb6 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Fri, 11 Oct 2024 23:55:14 +0530 Subject: [PATCH 3/3] fix redis sentinel - use sentinel password --- litellm/_redis.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/litellm/_redis.py b/litellm/_redis.py index 4a750a314e17..e58d14ebc958 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -225,10 +225,6 @@ def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: sentinel_password = redis_kwargs.get("sentinel_password") service_name = redis_kwargs.get("service_name") - sentinel_kwargs: Optional[Dict] = None - if sentinel_password: - sentinel_kwargs = {"password": sentinel_password} - if not sentinel_nodes or not service_name: raise ValueError( "Both 'sentinel_nodes' and 'service_name' are required for Redis Sentinel." @@ -238,7 +234,9 @@ def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: # Set up the Sentinel client sentinel = async_redis.Sentinel( - sentinel_nodes, socket_timeout=0.1, sentinel_kwargs=sentinel_kwargs + sentinel_nodes, + socket_timeout=0.1, + password=sentinel_password, ) # Return the master instance for the given service