o
    ưiT                     @   sf  d dl Z d dlZd dlZd dlmZmZmZmZ d dlZd dl	m
Z d dlmZmZ d dlmZmZ d dlmZ ddlmZ dd	 Zd-d
dZd-ddZdd Zdd ZdedefddZ	d-dedee defddZdd Zdd Zdej fddZ!dej"fdd Z#dej"fd!d"Z$d#d$ Z%	d-d%eej& deej"ej f fd&d'Z'd(d) Z(d*e)ddfd+d,Z*dS ).    N)CallableListOptionalUnion)
get_secretget_secret_str)REDIS_CONNECTION_POOL_TIMEOUTREDIS_SOCKET_TIMEOUT)SensitiveDataMasker   )verbose_loggerc                     s8   t tj} h d g d} fdd| jD | }|S )N>   retryconnection_poolself)urlredis_connect_funcgcp_service_accountgcp_ssl_ca_certsc                       g | ]}| vr|qS  r   .0xZexclude_argsr   E/home/app/Keep/.python/lib/python3.10/site-packages/litellm/_redis.py
<listcomp>'       z%_get_redis_kwargs.<locals>.<listcomp>)inspectgetfullargspecredisRedisargs)arg_specinclude_argsavailable_argsr   r   r   _get_redis_kwargs   s
   r%   c                    sH   | d u rt jj} tt jj}h d dg} fdd|jD | }|S )N>   r   r   r   r   c                    r   r   r   r   r   r   r   r   :   r   z)_get_redis_url_kwargs.<locals>.<listcomp>)r   r    from_urlr   r   r!   )clientr"   r#   r$   r   r   r   _get_redis_url_kwargs,   s   r(   c                    s   | d u rt jj} tt j}h d  fdd|jD }|d |d |d |d |d |d	 |d
 |d |d |d |S )N>   hostr   r   r   startup_nodesportc                    r   r   r   r   r   r   r   r   G   r   z-_get_redis_cluster_kwargs.<locals>.<listcomp>passwordusernamesslZssl_cert_reqsZssl_check_hostnamessl_ca_certsr   r   r   max_connections)r   r    r&   r   r   RedisClusterr!   append)r'   r"   r$   r   r   r   _get_redis_cluster_kwargs?   s    









r3   c                      s   d  fddt  D S )NZREDIS_c                    s   i | ]}  |   |qS r   )upperr   ZPREFIXr   r   
<dictcomp>Y   s    z0_get_redis_env_kwarg_mapping.<locals>.<dictcomp>)r%   r   r   r5   r   _get_redis_env_kwarg_mappingV   s   r7   c                  C   s<   t  } i }|  D ]\}}t|d d}|d ur|||< q	|S )N)default_value)r7   itemsr   )mappingZreturn_dictkvvaluer   r   r   _redis_kwargs_from_environment\   s   r>   service_accountreturnc                 C   sV   zddl m} W n ty   tdw | }|j| dgd}|j|d}t|jS )a  
    Generate GCP IAM access token for Redis authentication.
    
    Args:
        service_account: GCP service account in format 'projects/-/serviceAccounts/name@project.iam.gserviceaccount.com'
    
    Returns:
        Access token string for GCP IAM authentication
    r   )iam_credentials_v1zlgoogle-cloud-iam is required for GCP IAM Redis authentication. Install it with: pip install google-cloud-iamz.https://www.googleapis.com/auth/cloud-platform)namescope)request)Zgoogle.cloudrA   ImportErrorZIAMCredentialsClientZGenerateAccessTokenRequestZgenerate_access_tokenstraccess_token)r?   rA   r'   rD   responser   r   r   _generate_gcp_iam_access_tokeng   s   

rI   r/   c                    s    fdd}|S )ay  
    Creates a custom Redis connection function for GCP IAM authentication.
    
    Args:
        service_account: GCP service account in format 'projects/-/serviceAccounts/name@project.iam.gserviceaccount.com'
        ssl_ca_certs: Path to SSL CA certificate file for secure connections
    
    Returns:
        A connection function that can be used with Redis clients
    c                    s   ddl m}m} ddlm} | j|  t f}| jdg|R ddi z| 	 }W n  |yK   t
| drH| jrH| jd| jdd | 	 }n Y nw ||d	krV|d
dS )z8Initialize the connection and authenticate using GCP IAMr   )AuthenticationError$AuthenticationWrongNumberOfArgsError)str_if_bytesZAUTHcheck_healthFr,   )rM   OKzGCP IAM authentication failedN)redis.exceptionsrJ   rK   Zredis.utilsrL   _parserZ
on_connectrI   Zsend_commandZread_responsehasattrr,   )r   rJ   rK   rL   Z	auth_argsZauth_responser?   r   r   iam_connect   s"   

z6create_gcp_iam_redis_connect_func.<locals>.iam_connectr   )r?   r/   rS   r   rR   r   !create_gcp_iam_redis_connect_func   s   rT   c                  C   s   dt jv r
t jd S dt jvsdt jvrtddt jv r)t jd  dkr)d} nd} d	}d
t jv rFdt jv rFt jd
  dt jd  d}ndt jv rSt jd  d}|  d| t jd  dt jd  S )NZ	REDIS_URLZ
REDIS_HOSTZ
REDIS_PORTzUEither 'REDIS_URL' or both 'REDIS_HOST' and 'REDIS_PORT' must be specified for Redis.Z	REDIS_SSLtrueZredissr    ZREDIS_USERNAMEZREDIS_PASSWORD:@z://)osenviron
ValueErrorlower)Zredis_protocolZ	auth_partr   r   r   get_redis_url_from_environment   s    


"r]   c                  K   s   |   D ]\}}t|tr |dr |dd}t|}|| |< qi t | }|ddp1td}|durBt|trBt	||d< |ddpKtd}|dur\t|tr\t	||d< |ddpet
d	}|durn||d< |d
dpwtd}|dur||d
< |dpt
d}	|dpt
d}
|	durtd t|	|
d|d< |	|d _|dd |dd |
r|ddr|
|d< d|v r|d dur|dd |dd |dd |dd |S d|v r|d dur	 |S d|v r|d dur	 |S d|vs
|d du rtd|S )zO
    Common functionality across sync + async redis client implementations
    zos.environ/rV   r*   NREDIS_CLUSTER_NODESsentinel_nodesZREDIS_SENTINEL_NODESsentinel_passwordZREDIS_SENTINEL_PASSWORDservice_nameZREDIS_SERVICE_NAMEr   REDIS_GCP_SERVICE_ACCOUNTr   ZREDIS_GCP_SSL_CA_CERTSzASetting up GCP IAM authentication for Redis with service account.)r?   r/   r   r.   Fr/   r   r)   r+   dbr,   z3Either 'host' or 'url' must be specified for redis.)r9   
isinstancerF   
startswithreplacer   r>   getjsonloadsr   r   debugrT   _gcp_service_accountpopr[   )env_overridesr;   r<   r=   redis_kwargsZ_startup_nodesZ_sentinel_nodesZ_sentinel_passwordZ_service_namerk   Z_gcp_ssl_ca_certsr   r   r   _get_redis_client_logic   sz   


	ro   c                 C   s   t d}|d urz	t|| d< W n tjy   tdw td ddlm} t	 }i }| D ]}||v r<| | ||< q0g }| d D ]}|
|di | qC|dd  tjdd|i|S )Nr^   r*   zbREDIS_CLUSTER_NODES environment variable is not valid JSON. Please ensure it's properly formatted.z8init_redis_cluster: startup nodes are being initialized.r   ClusterNoder   )r   rh   ri   JSONDecodeErrorr[   r   rj   redis.clusterrq   r3   r2   rl   r   r1   )rn   Z_redis_cluster_nodes_in_envrq   r!   cluster_kwargsargnew_startup_nodesitemr   r   r   init_redis_cluster  s,   
rx   c                 C   R   |  d}|  d}|  d}|r|stdtd tj|t|d}||S Nr_   r`   ra   zIBoth 'sentinel_nodes' and 'service_name' are required for Redis Sentinel.z:init_redis_sentinel: sentinel nodes are being initialized.)socket_timeoutr,   )rg   r[   r   rj   r   Sentinelr	   
master_forrn   r_   r`   ra   sentinelr   r   r   _init_redis_sentinel6     




r   c                 C   ry   rz   )rg   r[   r   rj   async_redisr|   r	   r}   r~   r   r   r   _init_async_redis_sentinelN  r   r   c                  K   s   t di | }d|v r.|d d ur.t }i }|D ]}||v r$|| ||< qtjjdi |S d|v s8tdd ur<t|S d|v rHd|v rHt|S tjdi |S )Nr   r*   r^   r_   ra   r   )ro   r(   r   r    r&   r   rx   r   )rm   rn   r!   
url_kwargsru   r   r   r   get_redis_clientf  s   r   r   c              
   K   sF  t di |}d|v rE|d d urE| d urtj| dS ttjjd}i }|D ]}||v r3|| ||< q&td| q&tjjdi |S d|v rddlm	} t
 }i }|D ]}||v rb|| ||< qV|dd }dd	lm}	 d }
|r|t|d
r||j}
n	|dp|	d}
td|d u d|
d u  |r|
rtd zt|
}||d< td W n- ty } ztd|  ddlm} |dd }~ww td|d u d|
d u  g }|d D ]}||di | q|dd  tjdd|i|}|S d|v rd|v rt|S t|d | d ur| |d< tjdi |S )Nr   )r   )r'   zLREDIS: ignoring argument: {}. Not an allowed async_redis.Redis.from_url arg.r*   r   rp   r   )r   rk   r   rb   z0DEBUG: Redis cluster kwargs: redis_connect_func=z, gcp_service_account_provided=zWDEBUG: Generating IAM token for service account (value not logged for security reasons)r,   zJDEBUG: Successfully generated GCP IAM access token for async Redis clusterz)Failed to generate GCP IAM access token: )rJ   z'Failed to generate GCP IAM access tokenz3DEBUG: Not using GCP IAM auth - redis_connect_func=r_   ra   )rn   r   r   )ro   r   r    r(   r&   r   rj   formatrs   rq   r3   rl   litellmr   rQ   rk   rg   rI   	ExceptionerrorrO   rJ   r2   r1   r   _pretty_print_redis_config)r   rm   rn   r!   r   ru   rq   rt   r   r   r   rG   erJ   rv   rw   Zcluster_clientr   r   r   get_redis_async_client{  sz   


r   c               	   K   s   t d
i | }td| d|v rI|d d urIt|d d}d|v r@z
t|d |d< W n ttfy?   td|d  Y nw tj	j
d
i |S tj}d|v r]tj}|dd  ||d< |dd  tj	d
d	ti|S )Nz'get_redis_connection_pool: redis_kwargsr   )timeoutr   r0   z1REDIS: invalid max_connections value %r, ignoringr.   connection_classr*   r   r   )ro   r   rj   r   int	TypeErrorr[   warningr   BlockingConnectionPoolr&   
ConnectionZSSLConnectionrl   )rm   rn   pool_kwargsr   r   r   r   get_redis_connection_pool  s2   r   rn   c              
   C   s0  zddl }ddlm} ddlm} ddlm} ddlm} t	
|js&W dS | }t }|| }|ddd	}	|d
dddd}
|
jdddd |
jddd	 | D ]:\}}|durt|tr|dkrn|rndt| d}n|dkr}|r}dt| d}n	t|}nt|}|
|| qRd}|drd}n|drd}n|drd}|ddddd}|jd ddd |jddd	 |d!| |d" |||	d#d$ || ||
 |d" W dS  ty   t }|| }t	d%|  Y dS  ty } zt	d&|  W Y d}~dS d}~ww )'zKPretty print the Redis configuration using rich with sensitive data maskingr   N)Console)Panel)Table)TextzRedis Configurationz	bold blue)styleu    🔧 Redis Connection ParametersTzbold magentaleft)titleshow_headerheader_styletitle_justify	Parametercyan)r   no_wrapValueyellowr*   [z cluster nodes]r_   z sentinel nodes]zStandard RediszRedis ClusterzRedis Sentinelr   zRedis (URL-based)u   📊 Connection Infoz
bold greenPropertyzConnection Type
blue)border_stylezRedis configuration: z+Error pretty printing Redis configuration: )loggingZrich.consoler   Z
rich.panelr   Z
rich.tabler   Z	rich.textr   r   isEnabledForDEBUGr
   Z	mask_dict
add_columnr9   rd   listlenrF   add_rowrg   printrE   infor   r   )rn   r   r   r   r   r   consoleZmaskerZmasked_redis_kwargsr   Zconfig_tablekeyr=   Z	value_strZconnection_typeZ
info_tabler   r   r   r   r     sx   









r   )N)+r   rh   rY   typingr   r   r   r   r   Zredis.asyncioasyncior   r   r   r   Zlitellm.constantsr   r	   Z0litellm.litellm_core_utils.sensitive_data_maskerr
   Z_loggingr   r%   r(   r3   r7   r>   rF   rI   rT   r]   ro   r1   rx   r    r   r   r   r   r   r   dictr   r   r   r   r   <module>   sL   	


+S
S