HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.109.1.lve.el8.x86_64 #1 SMP Thu Mar 5 20:23:46 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.30
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/__pycache__/etcd_util.cpython-310.pyc
o

�N�g߄�@s dZddlZddlZddlZddlmZzddlZddlm	Z	m
Z
dZWney/dZYnwzddl
Z
dZWneyCdZYnwe�e�ZGdd�de�ZGd	d
�d
e�ZGdd�de�ZGd
d�de�ZGdd�d�ZGdd�de�ZGdd�de�Zddd�Zddd�Zdd�ZdS)a�

Utilities for working with etcd

.. versionadded:: 2014.7.0

:depends:  - python-etcd or etcd3-py

This library sets up a client object for etcd, using the configuration passed
into the get_conn() function. Normally, this is __opts__. Optionally, a profile
may be passed in. The following configurations are both valid:

.. code-block:: yaml

    # No profile name
    etcd.host: 127.0.0.1
    etcd.port: 2379
    etcd.username: larry  # Optional; requires etcd.password to be set
    etcd.password: 123pass  # Optional; requires etcd.username to be set
    etcd.ca: /path/to/your/ca_cert/ca.pem # Optional
    etcd.client_key: /path/to/your/client_key/client-key.pem # Optional; requires etcd.ca and etcd.client_cert to be set
    etcd.client_cert: /path/to/your/client_cert/client.pem # Optional; requires etcd.ca and etcd.client_key to be set
    etcd.require_v2: True # Optional; defaults to True
    etcd.encode_keys: False # Optional (v3 ONLY); defaults to False
    etcd.encode_values: True # Optional (v3 ONLY); defaults to True
    etcd.raw_keys: False # Optional (v3 ONLY); defaults to False
    etcd.raw_values: False # Optional (v3 ONLY); defaults to False
    etcd.unicode_errors: "surrogateescape" # Optional (v3 ONLY); defaults to "surrogateescape"

    # One or more profiles defined
    my_etcd_config:
      etcd.host: 127.0.0.1
      etcd.port: 2379
      etcd.username: larry  # Optional; requires etcd.password to be set
      etcd.password: 123pass  # Optional; requires etcd.username to be set
      etcd.ca: /path/to/your/ca_cert/ca.pem # Optional
      etcd.client_key: /path/to/your/client_key/client-key.pem # Optional; requires etcd.ca and etcd.client_cert to be set
      etcd.client_cert: /path/to/your/client_cert/client.pem # Optional; requires etcd.ca and etcd.client_key to be set
      etcd.require_v2: True # Optional; defaults to True
      etcd.encode_keys: False # Optional (v3 ONLY); defaults to False
      etcd.encode_values: True # Optional (v3 ONLY); defaults to True
      etcd.raw_keys: False # Optional (v3 ONLY); defaults to False
      etcd.raw_values: False # Optional (v3 ONLY); defaults to False
      etcd.unicode_errors: "surrogateescape" # Optional (v3 ONLY); defaults to "surrogateescape"

Encoding keys for etcd v3 allows a differentiation within etcd between byte and string keys.
It is worth noting that if you chose to encode keys, due to the way encoding pre-etcd with msgpack works,
all recursive functionality will not work as intended. This includes tree and ls along
with all methods that have recurse kwargs.  Thus, enabling this option is not recommended.

Once configured, the client() function is passed a set of opts, and optionally,
the name of a profile to be used.

.. code-block:: python

    import salt.utils.etcd_utils
    client = salt.utils.etcd_utils.get_conn(__opts__, profile='my_etcd_config')

You may also use the newer syntax and bypass the generator function.

V2 API
.. code-block:: python

    import salt.utils.etcd_utils
    client = salt.utils.etcd_utils.EtcdClient(__opts__, profile='my_etcd_config')

V3 API
.. versionadded:: 3005

.. code-block:: python

    import salt.utils.etcd_utils
    client = salt.utils.etcd_utils.EtcdClientV3(__opts__, profile='my_etcd_config')

It should be noted that some usages of etcd require a profile to be specified,
rather than top-level configurations. This being the case, it is better to
always use a named configuration profile, as shown above.
�N)�
SaltException)�
MaxRetryError�ReadTimeoutErrorTFc@�eZdZdZdS)�EtcdLibraryNotInstalled�2
    We didn't find the required etcd library
    N��__name__�
__module__�__qualname__�__doc__�r
r
�H/opt/saltstack/salt/lib/python3.10/site-packages/salt/utils/etcd_util.pyrh�rc@r)�IncompatibleEtcdRequirementszX
    A user is explicitly creating a client class, but requires a different version
    Nrr
r
r
rrnrrc@r)�Etcd3DirectoryExceptionrNrr
r
r
rrtrrc@r)�EtcdUtilWatchTimeoutz6
    A watch timed out without returning a result
    Nrr
r
r
rrzrrc@s�eZdZdZ								d"dd�Zd#dd�Zd$d	d
�Z				d%dd�Zd&dd�Zd&dd�Z	d'dd�Z
d'dd�Zd(dd�Zd(dd�Z
dd�Zd$dd�Zd$dd�Zd d!�ZdS))�EtcdBasez�
    Base class for the different versions of etcd clients.

    This also serves as a documentation hub for all superclasses.
    Nc
Ks2|
�dd�st||�}n|}||_|p|j�dd�|_|p#|j�dd�|_|jdkr4|jdkr4t�d�|p;|j�d�}|pC|j�d	�}|pK|j�d
�}|pS|j�d�}
|	p[|j�d�}i}|rk|rkt|�t|�d
�}i}|rz|sz|
szt|�dd�}|r�|r�|
r�||
f}t|�|dd�}|��|_	|j	�
|�dS)N�
has_etcd_optsFz	etcd.hostz	127.0.0.1z	etcd.portiK	z:Using default etcd host and port, use a profile if needed.z
etcd.usernamez
etcd.passwordzetcd.cazetcd.client_keyzetcd.client_cert)�username�password�https)�ca_cert�protocol)r�certr)�get�_get_etcd_opts�conf�host�port�log�warning�str�copy�xargs�update)�self�opts�profilerrrr�caZ
client_keyZclient_cert�kwargsZ	etcd_optsrZcli_keyZcli_certZauth�certsrr
r
r�__init__�s:

��
zEtcdBase.__init__FrcK�t���N��NotImplementedError)r&�key�recurse�timeout�start_revisionr*r
r
r�watch�szEtcdBase.watchcCr-)zi
        Get the value of a specific key.  If recurse is true, defer to EtcdBase.tree() instead.
        r/�r&r1r2r
r
rr��zEtcdBase.getcKr-)z�
        Read a value of a key.

        This method also provides the ability to wait for changes after a given index and/or
        within a certain timeout.
        r/)r&r1r2�waitr3r4r*r
r
r�read�sz
EtcdBase.read�cCs�|s|iiS|�d�}i}|��D].\}}|�d�}|r%d|�d|��}nd|��}t|t�r;|�||�}|�|�q|||<q|S)a%
        Take a data dictionary and flatten it to a dictionary with values that are all strings.

        If path is given, prepend it to all keys.

        For example, given path="/salt" it will convert...

        {
            "key1": "value1",
            "key2": {
                "subkey1": "subvalue1",
                "subkey2": "subvalue2",
            }
        }

        to...

        {
            "/salt/key1": "value1",
            "/salt/key2/subkey1": "subvalue1",
            "/salt/key2/subkey2": "subvalue2",
        }
        �/)�strip�items�
isinstance�dict�_flattenr%)r&�data�pathZflat�k�v�p�retr
r
rr@�s




zEtcdBase._flattencCr-)a�
        Update etcd according to the layout of fields.

        Given etcd with this layout...
        {
            ...
            "/salt/key1": "OLDvalue1",
            "/salt/key2/subkey1": "OLDsubvalue1",
            "/salt/key2/subkey2": "OLDsubvalue2",
            ...
        }

        fields = {
            "key1": "value1",
            "key2": {
                "subkey1": "subvalue1",
                "subkey2": "subvalue2",
            }
        }

        will update etcd to look like the following...
        {
            ...
            "/salt/key1": "value1",
            "/salt/key2/subkey1": "subvalue1",
            "/salt/key2/subkey2": "subvalue2",
            ...
        }

        r/)r&�fieldsrBr
r
rr%�szEtcdBase.updatecCs|j||||d�S)zH
        Write a file or directory, a higher interface to write
        )�ttl�	directory)�write�r&r1�valuerHrIr
r
r�set szEtcdBase.setcCs |r	|�|||�S|�|||�S)�G
        Write a file or directory depending on directory flag
        )�write_directory�
write_filerKr
r
rrJ&szEtcdBase.writecCr-)z8
        Write a file (key: value pair) to etcd
        r/�r&r1rLrHr
r
rrP.r7zEtcdBase.write_filecCr-)z5
        Write a directory (key: {}) to etcd
        r/rQr
r
rrO4r7zEtcdBase.write_directorycCr-)z�
        Get all the top level keys and their values at the given path.

        If the key is a directory, its value is an empty dictionary.
        r/�r&rBr
r
r�ls:�zEtcdBase.lscCs|�||�S)z%
        An alias for delete
        )�deleter6r
r
r�rmBszEtcdBase.rmcKr-)z@
        Delete keys or (recursively) whole directories
        r/)r&r1r2r*r
r
rrUHr7zEtcdBase.deletecCr-)z`
        .. versionadded:: 2014.7.0

        Recurse through etcd and return all values
        r/rRr
r
r�treeNrTz
EtcdBase.tree)NNNNNNNN�FrN�F�FFNN�r:�NFr.)r	r
rrr,r5rr9r@r%rMrJrPrOrSrVrUrWr
r
r
rr�s8	
�
5
	
�

)
!




rcs�eZdZ�fdd�Zddd�Zddd	�Z				dd
d�Zdd
d�Zddd�Zd dd�Z	d dd�Z
dd�Zddd�Zdd�Z
�ZS)!�
EtcdClientcsbtstd��t�d�t�j|fi|��|j�dd�s td��t	j
d|j|jd�|j
��|_dS)Nz+Don't have python-etcd, need to install it.z.etcd_util has the libraries needed for etcd v2�etcd.require_v2Tz%Can't create v2 with a v3 requirement�rrr
)�HAS_ETCD_V2rr �debug�superr,rrr�etcd�Clientrrr$�client)r&r'r*��	__class__r
rr,Xs
"zEtcdClient.__init__FrNc
Ks�|�dd�}|durtjj�dd�|}|rt�d|�|ddddd�}z|j||d||d	�}Wn~ty{z|�|�}Wnt	j
yQt�d
�|YYSty]iYYSw|rit
|d�rid|d<t
|d�|d<t
|d
�|d<|YSty�t�d|�iYSt	jy�}	z
t�d|	�WYd}	~	dSd}	~	wty�iYSw|dur�iS|r�t
|dd�|d<t
|dd�|d<t
|dd�|d<d|d<t
|d
�|d<|S)N�index�Argon�qThe index kwarg has been deprecated, and will be removed in the Argon release. Please use start_revision instead.�-Invalid kwargs passed in will not be used: %sFr�r1rL�changed�mIndex�dirT�r2r8r3r4z(etcd: key was not created while watchingrorLZ
modifiedIndexrnzKetcd: failed to perform 'watch' operation on key %s due to connection error�etcd: %sr1rm)�pop�salt�utils�versions�
warn_untilr r!r9rrc�EtcdKeyNotFoundra�
ValueError�getattrr�error�EtcdConnectionFailed)
r&r1r2r3r4r*rhrF�result�errr
r
rr5dsl�
�
����zEtcdClient.watchcCsr|s4z|�|�}Wn$tjyYdStjy$t�d|�YdSty-YdSwt|dd�S|�|�S)NzIetcd: failed to perform 'get' operation on key %s due to connection errorrL)	r9rcrwr{r rzrxryrW�r&r1r2r|r
r
rr�s ��
zEtcdClient.getc
Ks�|�dd�}|�dd�}|durtjj�dd�|}|dur(tjj�dd�|}|r0t�d|�z|rA|jj|||||d�}	W|	S|jj||||d�}	W|	St	j
t	jfyd}
zt�d	|
��d}
~
wt
y�|ryt�d
�td|�d���t�d
�t	�
d��ty�}
z
t�d�t	�
d��d}
~
wt	jy�}
zt�d	|
��d}
~
wty�t�d��ty�}
zt�d|
��d}
~
ww)N�	recursive�	waitIndexri�nThe recursive kwarg has been deprecated, and will be removed in the Argon release. Please use recurse instead.�uThe waitIndex kwarg has been deprecated, and will be removed in the Argon release. Please use start_revision instead.rk)rr8r3r�)rr8r3rqz&etcd: Timed out while executing a waitz	Watch on z
 timed outzetcd: Timed outzConnection failedzetcd: Could not connectz Could not connect to etcd serverzZetcd: error. python-etcd does not fully support python 2.6, no error information available�etcd: uncaught exception %s)rrrsrtrurvr r!rer9rcr{rwrzrrarrZ
EtcdExceptionrx�	Exception)r&r1r2r8r3r4r*r�
wait_indexr|r}r
r
rr9�st	���/��'��




�����zEtcdClient.readr:cCsvt|t�st�d�dS|�||�}i}|��D] \}}d}t|t�r%d}|j|||d�||<||dur8dSq|S)N�$etcd.update: fields is not type dictFT)rI)r>r?r rzr@r=rJ)r&rGrB�keysrCrD�is_dirr
r
rr%s


�zEtcdClient.updatec
CsZz|r|�|||�WS|�|||�WStjy,}z
t�d|�WYd}~dSd}~ww)rNrqN)rOrPrcr{r rz)r&r1rLrHrIr}r
r
rrJs��zEtcdClient.writec
Cs�z|jj|||dd�}WnHtjtjtfy*}z
t�d|�WYd}~dSd}~wtyB}z
t�d|�WYd}~dSd}~wt	yT}zt�d|��d}~wwt
|d�S)NF�rHrorq�*etcd: Could not connect to etcd server: %sr�rL)rerJrc�EtcdNotFile�EtcdRootReadOnlyrxr rzrr�ry�r&r1rLrHr|r}r
r
rrPs ����
zEtcdClient.write_filec
Cs�|dur
t�d|�z|jj|d|dd�}WnXtjy't�d|�YdStjtjtfyD}z
t�	d|�WYd}~dSd}~wt
y\}z
t�	d|�WYd}~dSd}~wtyn}zt�	d|��d}~wwt|d�S)	Nz.etcd: non-empty value passed for directory: %sTr�z"etcd: directory already exists: %srqr�r�ro)
r �inforerJrcr�Z
EtcdNotDirr�rxrzrr�ryr�r
r
rrO0s*����
zEtcdClient.write_directoryc	Cs�i}z|�|�}WntjtfyiYStjy't�d|�YdSw|jD]}|jdurC|j	|kr8q+|j	�d�}i||<q+|j
||j	<q+||iS)NzIetcd: failed to perform 'ls' operation on path %s due to connection errorTr;)r9rcrwrxr{r rz�childrenror1rL)r&rBrFr=�itemZdir_namer
r
rrSIs(��
	


z
EtcdClient.lsc
Ks�|�dd�}|durtjj�dd�|}|rt�d|�z|jj||d�r(WdSWdSt	j
t	jt	jt	j
t	jtfyN}z
t�d|�WYd}~dSd}~wtyf}z
t�d	|�WYd}~dSd}~wtyx}zt�d
|��d}~ww)Nrrir�rk)rTFrqr�r�)rrrsrtrurvr r!rerUrcr�r�ZEtcdDirNotEmptyrwr{rxrzrr�)r&r1r2r*rr}r
r
rrUbsB������zEtcdClient.deletec
Cs�i}z|�|�}Wn&tjtfyYdStjy/}z
t�d|�WYd}~dSd}~ww|jD]'}t|j	��
d�}|jdurS|j	|krHq3|�|j	�||d<q3|j
||d<q3|S)Nrqr;T���)r9rcrwrxr{r rzr�r"r1�splitrorWrL)r&rBrFr=r}r��compsr
r
rrW�s$��


zEtcdClient.treerXrYrZr[r\r.)r	r
rr,r5rr9r%rJrPrOrSrUrW�
__classcell__r
r
rfrr]Ws 

;
�
O



"r]cs�eZdZdZ					d(�fdd�	Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	d)dd�Z
d*dd�Z				d+dd�Zd,dd�Z
d-dd�Zd-dd�Zdd�Zd*d d!�Zd"d#�Zd$d%�Zd&d'�Z�ZS).�EtcdClientV3z�
    .. versionadded:: 3005

    Since etcd3 has no concept of directories, this class leaves write_directory unimplemented.
    NFcs�tstd��t�d�t�j|fi|��|j�dd�r td��|p(|j�dd�|_	|p2|j�dd�|_
|p<|j�d	d�|_|pF|j�d
d�|_|pP|j�dd�|_
|j�d
d�|jd<tjd|j|jd�|j��|_dS)Nz(Don't have etcd3-py, need to install it.z.etcd_util has the libraries needed for etcd v3r^Tz%Can't create v3 with a v2 requirementzetcd.encode_keysFzetcd.encode_valuesz
etcd.raw_keyszetcd.raw_valueszetcd.unicode_errors�surrogateescaperZverifyr_r
)�HAS_ETCD_V3rr rarbr,rrr�encode_keys�
encode_values�raw_keys�
raw_values�unicode_errorsr$rr�etcd3rdrrre)r&r'r�r�r�r�r�r*rfr
rr,�s


�"zEtcdClientV3.__init__cK�X|�d|j�|jrtjjj|fd|ji|��}|S|js*t|t	�r*|j
d|jd�}|S�Nr��raw�UTF-8)�encoding�errors)�
setdefaultr�r�rsrt�msgpack�loadsr�r>�bytes�decode�r&r1�extra_kwargsr
r
r�_maybe_decode_key���zEtcdClientV3._maybe_decode_keycK�.|�d|j�|jrtjjj|fi|��}|S�Nr�)r�r�r�rsrtr��dumpsr�r
r
r�_maybe_encode_key��zEtcdClientV3._maybe_encode_keycKr�r�)r�r�r�rsrtr�r�r�r>r�r��r&rLr�r
r
r�_maybe_decode_value�r�z EtcdClientV3._maybe_decode_valuecKr�r�)r�r�r�rsrtr�r�r�r
r
r�_maybe_encode_value�r�z EtcdClientV3._maybe_encode_valuec
CsVz|�|j�|_|�|j�|_W|Sty*}z
t�d|�WYd}~|Sd}~ww)Nzetcd3 decoding error: %s)r�r1r�rL�AttributeErrorr rz)r&�kvr}r
r
r�
_decode_kv�s���zEtcdClientV3._decode_kvrc	Ks�|�dd�}|durtjj�dd�|}|rt�d|�|ddddd�}|j||d||d	�}|durJ|j|d
<|j	|d<t
|dd�|d
<d|d<|SdS)NrhrirjrkFrrlTrpr1rLZmod_revisionrnrm)rrrsrtrurvr r!r9r1rLry)	r&r1r2r3r4r*rhrFr|r
r
rr5�s0��

�zEtcdClientV3.watchcCs0|s|�|�}t|t�r|��jSdS|�|�Sr.)r9r>�listrrrLrWr~r
r
rrs



zEtcdClientV3.getc
KsR|�dd�}|�dd�}|durtjj�dd�|}|dur(tjj�dd�|}|r0t�d|�|swz+|jj|�	|�|d�}	t
|	dd�}
|
durQt�d	|�|
WS|
D]}|�|�}qS|
WSt
yv}z
t�d
|�WYd}~dSd}~wwz|jj|�	|�||d�}
|
j|d�}|�|�WSt
y�}z
t�d
|�WYd}~dSd}~ww)Nrr�rir�r�rk��prefix�kvsz&etcd3 read: No values found for key %szetcd3 read: %s)r1r�r4)r3zetcd3 watch: %s)rrrsrtrurvr r!re�ranger�ryrzr�r�ZWatcherZ
watch_once)r&r1r2r8r3r4r*rr�r|r�r�r}ZwatcherZwatch_eventr
r
rr9sX	��������zEtcdClientV3.readr:cCsft|t�st�d�dS|�||�}i}|��D]\}}t|t�r(t�d|�q|�||�||<q|S)Nr�z4etcd3 has no concept of directories, skipping key %s)r>r?r rzr@r=r!rJ)r&rGrBr�rCrDr
r
rr%>s


zEtcdClientV3.updatecCs`|r|jj|d�}|��|jj|�|�|�|�|jd�n
|j�|�|�|�|��|�|�S)N)rH)�lease)reZLeaseZgrant�putr�r��IDr)r&r1rLrHr�r
r
rrPLs��
zEtcdClientV3.write_filecCstd��)Nzetcd3 does not have directories)rrQr
r
rrO[szEtcdClientV3.write_directorycCs�i}|�|�}|dur
iS|jsdnd}|jrt|t�r|n|jd|jd�}|��D]$\}}|�|�s:|||}n||}t|t�rJi|||<q*|||<q*||iS)Nr;�/r�)r�)	rWr�r>r��encoder�r=�endswithr?)r&rBrFrW�sepr1rLZret_keyr
r
rrS^s&
���


zEtcdClientV3.lscKsj|�dd�}|durtjj�dd�|}|rt�d|�|jj|�	|�|d�}t
|d�r3|jr1dSdSdS)	Nrrir�rkr��deletedTF)rrrsrtrurvr r!reZdelete_ranger��hasattrr�)r&r1r2r*rr|r
r
rrUys�
zEtcdClientV3.deletecCs^|jsdnd}|�|��|d�^}}|r)||vri||<|�|d|||�dS|||<dS)z$
        Helper for _expand
        r;r��rN)r��lstripr��_expand_recurse)r&r1rL�destr�Zouter�innerr
r
rr��szEtcdClientV3._expand_recursecCs(i}|��D]\}}|�|||�q|S)a�
        This does the opposite of EtcdBase._flatten

        For example, it will convert...

        {
            "/key1": "value1",
            "/key2/subkey1": "subvalue1",
            "/key2/subkey2": "subvalue2",
        }

        to...

        {
            "key1": "value1",
            "key2": {
                "subkey1": "subvalue1",
                "subkey2": "subvalue2",
            }
        }
        )r=r�)r&r�r�r1rLr
r
r�_expand�szEtcdClientV3._expandcs||j�dd�}|dur
dS|jsdnd}t|�dkr0|dj�kr0|��}|j�|�d|jiS�fdd	�|D�}|�|�S)
NT)r2r;r�r�rr�cs"i|]
}|jt��d�|j�qSr.)r1�lenrL)�.0r��rBr
r�
<dictcomp>�s"z%EtcdClientV3.tree.<locals>.<dictcomp>)r9r�r�r1rrr�rLr�)r&rBr=r�r�r�r
r�rrW�s
zEtcdClientV3.tree)NNFFNrXrYrZr[r.)r	r
rrr,r�r�r�r�r�r5rr9r%rPrOrSrUr�r�rWr�r
r
rfrr��s8	�


�
6



r�cCsN|�di�}|�di�}i}|�|�|�|�|�|�|r%|�|i�S|S)NZpillarZmaster)rr%rr)r'r(Zopts_pillarZopts_masterZopts_mergedr
r
rr�s


rcKspt||d�}|�dd�}|r'tjj�dd�t|fddi|��}t�d�|St	|fddi|��}t�d�|S)	zk
    Client creation at the module level.

    This is the way users are meant to instantiate a client
    )r(r^TZ	Potassiumzsetcd API v2 has been deprecated.  It will be removed in the Potassium release, and etcd API v3 will be the default.rz<etcd_util will be attempting to use etcd API v2: python-etcdz9etcd_util will be attempting to use etcd API v3: etcd3-py)
rrrsrtrurvr]r rar�)r'r(r*rZuse_v2rer
r
r�get_conn�s�
�
r�cCs
|�|�S)z3
    Module level find tree at the given path.
    )rW)rerBr
r
rrW�s
rWr.)r�loggingZsalt.utils.msgpackrsZsalt.utils.versionsZsalt.exceptionsrrcZurllib3.exceptionsrrr`�ImportErrorr�r��	getLoggerr	r rrrr�rrr]r�rr�rWr
r
r
r�<module>sDN��
XD
'