B
    `A                  @   s   d dl mZmZmZ eZdZd dlZd dlZd dl	m
Z d dlmZ d dlmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZ yd dlmZmZ dZW n ek
r   dZY nX e ZG dd deZ dS )    )absolute_importdivisionprint_functiona  
    author: Unknown (!UNKNOWN)
    name: redis
    short_description: Use Redis DB for cache
    description:
        - This cache uses JSON formatted, per host records saved in Redis.
    requirements:
      - redis>=2.4.5 (python lib)
    options:
      _uri:
        description:
          - A colon separated string of connection information for Redis.
          - The format is C(host:port:db:password), for example C(localhost:6379:0:changeme).
          - To use encryption in transit, prefix the connection with C(tls://), as in C(tls://localhost:6379:0:changeme).
          - To use redis sentinel, use separator C(;), for example C(localhost:26379;localhost:26379;0:changeme). Requires redis>=2.9.0.
        required: True
        env:
          - name: ANSIBLE_CACHE_PLUGIN_CONNECTION
        ini:
          - key: fact_caching_connection
            section: defaults
      _prefix:
        description: User defined prefix to use when creating the DB entries
        default: ansible_facts
        env:
          - name: ANSIBLE_CACHE_PLUGIN_PREFIX
        ini:
          - key: fact_caching_prefix
            section: defaults
      _keyset_name:
        description: User defined name for cache keyset name.
        default: ansible_cache_keys
        env:
          - name: ANSIBLE_CACHE_REDIS_KEYSET_NAME
        ini:
          - key: fact_caching_redis_keyset_name
            section: defaults
        version_added: 1.3.0
      _sentinel_service_name:
        description: The redis sentinel service name (or referenced as cluster name).
        env:
          - name: ANSIBLE_CACHE_REDIS_SENTINEL
        ini:
          - key: fact_caching_redis_sentinel
            section: defaults
        version_added: 1.3.0
      _timeout:
        default: 86400
        description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
        env:
          - name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
        ini:
          - key: fact_caching_timeout
            section: defaults
        type: integer
N)	constants)AnsibleError)	to_native)AnsibleJSONEncoderAnsibleJSONDecoder)BaseCacheModule)__version__)Display)StrictRedisVERSIONTFc                   s   e Zd ZdZdZ fddZdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Z  ZS )CacheModulea  
    A caching module backed by redis.

    Keys are maintained in a zset with their score being the timestamp
    when they are inserted. This allows for the usage of 'zremrangebyscore'
    to expire keys. This mechanism is used or a pattern matched 'scan' for
    performance.
    Nc                s.  d}y^t t| j|| | dr,| d}t| d| _| d| _| d| _| d| _W nL t	k
r   t
dstdtjrtj}ttj| _tj| _d	| _Y nX tstd
i | _i }d}||rd|d< |t|d  }| jr| ||| _n|d}t||| _td| j  d S )N Z_uri_timeout_prefixZ_keyset_name_sentinel_service_namez2.9.zUDo not import CacheModules directly. Use ansible.plugins.loader.cache_loader instead.Zansible_cache_keyszlThe 'redis' python module (version 2.4.5 or newer) is required for the redis fact cache, 'pip install redis'ztls://Tssl:zRedis connection: %s)superr   __init__
get_optionfloatr   r   	_keys_setr   KeyErroransible_base_version
startswithr   CZCACHE_PLUGIN_CONNECTIONZCACHE_PLUGIN_TIMEOUTZCACHE_PLUGIN_PREFIX	HAS_REDIS_cachelen_get_sentinel_connection_dbsplitr   displayvv)selfargskwargsurikwZ	tlsprefix
connection)	__class__ h/home/dcms/DCMS/lib/python3.7/site-packages/ansible_collections/community/general/plugins/cache/redis.pyr   _   s<    




zCacheModule.__init__c       	   
   C   s  yddl m} W n tk
r,   tdY nX d|kr>td|d}|d}t|dkr|d}|d|d< y|d|d	< W n tk
r   Y nX d
d |D }t	d|  ||f|}y|j
| jddS  tk
r
 } ztdt| W dd}~X Y nX dS )z;
        get sentinel connection details from _uri
        r   )SentinelzUThe 'redis' python module (version 2.9.0 or newer) is required to use redis sentinel.;z#_uri does not have sentinel syntax.r   dbpasswordc             S   s   g | ]}t |d qS )r   )tupler$   ).0Zshostr.   r.   r/   
<listcomp>   s    z8CacheModule._get_sentinel_connection.<locals>.<listcomp>z
Using redis sentinels: %sg?)socket_timeoutz'Could not connect to redis sentinel: %sN)Zredis.sentinelr0   ImportErrorr   r$   popr!   
IndexErrorr%   r&   Z
master_forr   	Exceptionr   )	r'   r*   r+   r0   connectionsZconnection_argsZ	sentinelsZsconexcr.   r.   r/   r"      s,    


z$CacheModule._get_sentinel_connectionc             C   s
   | j | S )N)r   )r'   keyr.   r.   r/   	_make_key   s    zCacheModule._make_keyc             C   sR   || j krF| j| |}|d kr2| | ttj|td| j |< | j |S )N)cls)	r    r#   getr@   deleter   jsonloadsr	   )r'   r?   valuer.   r.   r/   rB      s    

zCacheModule.getc             C   s   t j|tddd}| jdkr:| j| |t| j| n| j| || t	d dkrr| j
| jt | n| j
| j|t i || j|< d S )NT   )rA   	sort_keysindentr      )rD   dumpsr   r   r#   setexr@   intsetr   Zzaddr   timer    )r'   r?   rF   Zvalue2r.   r.   r/   rN      s    
zCacheModule.setc             C   s.   | j dkr*t | j  }| j| jd| d S )Nr   )r   rO   r#   Zzremrangebyscorer   )r'   Z
expiry_ager.   r.   r/   _expire_keys   s    
zCacheModule._expire_keysc             C   s   |    | j| jddS )Nr   r2   )rP   r#   Zzranger   )r'   r.   r.   r/   keys   s    zCacheModule.keysc             C   s   |    | j| j|d k	S )N)rP   r#   Zzrankr   )r'   r?   r.   r.   r/   contains   s    zCacheModule.containsc             C   s8   || j kr| j |= | j| | | j| j| d S )N)r    r#   rC   r@   Zzremr   )r'   r?   r.   r.   r/   rC      s    
zCacheModule.deletec             C   s$   xt |  D ]}| | qW d S )N)listrQ   rC   )r'   r?   r.   r.   r/   flush   s    zCacheModule.flushc                s   t  fdd  D }|S )Nc                s   g | ]}|  |fqS r.   )rB   )r6   k)r'   r.   r/   r7      s    z$CacheModule.copy.<locals>.<listcomp>)dictrQ   )r'   retr.   )r'   r/   copy   s    zCacheModule.copyc             C   s   t  S )N)rV   )r'   r.   r.   r/   __getstate__   s    zCacheModule.__getstate__c             C   s   |    d S )N)r   )r'   datar.   r.   r/   __setstate__   s    zCacheModule.__setstate__)__name__
__module____qualname____doc__r   r   r"   r@   rB   rN   rP   rQ   rR   rC   rT   rX   rY   r[   __classcell__r.   r.   )r-   r/   r   T   s   +r   )!
__future__r   r   r   type__metaclass__ZDOCUMENTATIONrO   rD   Zansibler   r   Zansible.errorsr   Zansible.module_utils._textr   Zansible.parsing.ajsonr   r	   Zansible.plugins.cacher
   Zansible.releaser   r   Zansible.utils.displayr   Zredisr   r   r   r9   r%   r   r.   r.   r.   r/   <module>   s$   9
