HEX
Server: LiteSpeed
System: Linux s787.bom1.mysecurecloudhost.com 4.18.0-477.13.1.lve.el8.x86_64 #1 SMP Thu Jun 1 16:40:47 EDT 2023 x86_64
User: mobilech (5348)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/__pycache__/mysql.cpython-310.pyc
o

;j�r�@s$dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z
ddlZ
ddlZ
zddl
Z
ddlZ
ddlZ
ddl
mZddlmZmZmZWn;ey�z&ddlZe��ddl
Z
ddlZ
ddlZ
ddl
mZddlmZmZmZWney�dZ
YnwYnwzddlZdZWney�dZYnwe�e�Zgd�Zgd�Zed	d
gZgd�Z 	dd
�Z!dd�Z"dd�Z#dd�Z$dd�Z%dd�Z&dd�Z'dd�Z(dd�Z)dd�Z*d�d d!�Z+d�d"d#�Z,d$d%�Z-d&d'�Z.d(d)�Z/d*d+�Z0d,d-�Z1d.d/�Z2d0d1�Z3d2d3�Z4d�d4d5�Z5d6d7�Z6d8d9�Z7d:d;�Z8d�d<d=�Z9d>d?�Z:d@dA�Z;	B						Cd�dDdE�Z<	B						Cd�dFdG�Z=	B					d�dHdI�Z>d�dJdK�Z?	B						Cd�dLdM�Z@	B						Cd�dNdO�ZA	B						Cd�dPdQ�ZB	B						Cd�dRdS�ZC	B						Cd�dTdU�ZD	B					d�dVdW�ZEd�dXdY�ZFdZd[�ZGd�d\d]�ZHd�d^d_�ZId�d`da�ZJdbdc�ZKddde�ZLdfdg�ZM	B			d�dhdi�ZNd�djdk�ZOdldm�ZP	B		d�dndo�ZQ	B			d�dpdq�ZR	B		d�drds�ZSdtdu�ZTdvdw�ZUdxdy�ZVdzd{�ZWd|d}�ZXd~d�ZYd�d�d��ZZd�d��Z[d�d�d��Z\d�d��Z]d�d��Z^dS)�a�
Module to provide MySQL compatibility to salt.

:depends:   - Python module: MySQLdb, mysqlclient, or PyMYSQL

:configuration: In order to connect to MySQL, certain configuration is required
    in either the relevant minion config (/etc/salt/minion), or pillar.

    Some sample configs might look like::

        mysql.host: 'localhost'
        mysql.port: 3306
        mysql.user: 'root'
        mysql.pass: ''
        mysql.db: 'mysql'
        mysql.unix_socket: '/tmp/mysql.sock'
        mysql.charset: 'utf8'

    You can also use a defaults file::

        mysql.default_file: '/etc/mysql/debian.cnf'

.. versionchanged:: 2014.1.0
    'charset' connection argument added. This is a MySQL charset, not a python one.
.. versionchanged:: 0.16.2
    Connection arguments from the minion config file can be overridden on the
    CLI by using the arguments defined :mod:`here <salt.states.mysql_user>`.
    Additionally, it is now possible to setup a user with no password.
�N)�OperationalError)�CLIENT�
FIELD_TYPE�FLAGTF);�ALL PRIVILEGES�ALTER�
ALTER ROUTINE�BACKUP_ADMIN�BINLOG_ADMINzBINLOG ADMIN�BINLOG MONITORz
BINLOG REPLAY�CONNECTION_ADMINzCONNECTION ADMIN�CREATE�CREATE ROLE�CREATE ROUTINE�CREATE TABLESPACE�CREATE TEMPORARY TABLES�CREATE USER�CREATE VIEW�DELETEzDELETE HISTORY�DROP�	DROP ROLE�ENCRYPTION_KEY_ADMIN�EVENT�EXECUTEzFEDERATED ADMIN�FILE�GRANT OPTION�GROUP_REPLICATION_ADMIN�INDEX�INSERT�LOCK TABLES�PERSIST_RO_VARIABLES_ADMIN�PROCESSzREAD_ONLY ADMIN�
REFERENCES�RELOAD�REPLICA MONITOR�REPLICATION CLIENTzREPLICATION MASTER ADMIN�REPLICATION REPLICA�REPLICATION SLAVE�REPLICATION_SLAVE_ADMINzREPLICATION SLAVE ADMIN�RESOURCE_GROUP_ADMIN�RESOURCE_GROUP_USER�
ROLE_ADMIN�SELECTzSET USER�SET_USER_ID�SHOW DATABASES�	SHOW VIEW�SHUTDOWN�
SLAVE MONITOR�SUPER�SYSTEM_VARIABLES_ADMIN�TRIGGER�UPDATE�USAGE�XA_RECOVER_ADMIN)ZCIPHERZISSUERZSUBJECTZSSLZX509)+rrr	r
rr
rrrrrrrrrrrrrrrrrr r!r"r#r%r'r(r)r*r+r,r-r.r/r0r2r3r4r5r7cCstt�tdur
dfSdfS)z:
    Confirm that a python mysql client is installed.
    Nz!No python mysql client installed.�)�bool�MySQLdb�r;r;�F/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/mysql.py�__virtual__sr=cCs.t�|�����}dt�|�������}|S)N�*)�hashlib�sha1�encode�digest�	hexdigest�upper)�password�	_passwordr;r;r<�__mysql_hash_passwordsrGc	K�htdi|��}|dur
iS|�tjj�}t|�}t|�}d|�d|��}t||�|��}t�	|�|S)NzCHECK TABLE �.r;�
�_connect�cursorr:�cursors�
DictCursor�quote_identifier�_execute�fetchall�log�debug�	�name�table�connection_args�dbc�cur�s_nameZs_table�qry�resultsr;r;r<�
__check_table�

r]c	KrH)Nz
REPAIR TABLE rIr;rJrTr;r;r<�__repair_tabler^r_c	KrH)NzOPTIMIZE TABLE rIr;rJrTr;r;r<�__optimize_table,r^r`cKs|dtvrtdStd	i|��}|durdS|��}d}dddd�}t|||�t|j�dkr6dtd<tdSdtd<tdS)
Nzmysql.password_columnZPasswordz�SELECT column_name from information_schema.COLUMNS WHERE table_schema=%(schema)s and table_name=%(table)s and column_name=%(column)s�mysql�user)ZschemarV�columnrZauthentication_stringr;)�__context__rKrLrP�int�rowcount)rWrXrYr[�argsr;r;r<�__password_column;s��rhc

Ks�tdi|��}|dur
gS|�tjj�}zd}||d�}t|||�Wn#tjyF}zdj|j�}|t	d<t
�|�WYd}~dSd}~ww|��}	t
�
|	�|	rZ|	d�dd�SdS)	NzCSELECT plugin FROM mysql.user WHERE User=%(user)s and Host=%(host)s)rb�host�MySQL Error {}: {}�mysql.error�mysql_native_passwordrZpluginr;)rKrLr:rMrNrPr�formatrgrdrR�errorrQrS�get)
rbrirWrXrYr[rg�exc�errr\r;r;r<�__get_auth_pluginRs(

��
rrc	
st��d$��fdd�	}d�vrd}nd}d�d<i}tt�D]}|�d	�s.tt|�||��<q��d
g�D]}|�|�rG�d||O<q5t�d|�q5|dd
|�|dd|�|dd|�|dd|�|dd|�|dd|�|dd|�|dd|�|dd|�d�d<|dd�d t	_
t���D]	}�|s��|=q���dd�dur�t�
d!���d�z
t	jd%i���}WnFty�}zd"j|j�}|td#<t�|�WYd}~dSd}~wt	jj�y}zd"j|j�}|td#<t�|�WYd}~dSd}~ww|�d�|S)&z.
    wrap authentication credentials here
    NTcs�|dur|}|�vr�|�|<dS|rDd}|�|�r0z
|t|�d�}Wn
ty/YdSwtdd|��d�}|durF|�|<dSdSdS)a�
        Add key to connargs, only if name exists in our kwargs or,
        if get_opts is true, as mysql.<name> in __opts__ or __pillar__

        If get_opts is true, evaluate in said order - kwargs, opts
        then pillar. To avoid collision with other functions,
        kwargs-based connection arguments are prefixed with 'connection_'
        (i.e. 'connection_host', 'connection_user', etc.).
        NZconnection_z
config.optionzmysql.)�
startswith�len�
IndexError�__salt__)rU�key�get_opts�prefix�val�Zconnargs�kwargsr;r<�_connargos"

��z_connect.<locals>._connargZconnection_default_fileFrZclient_flag�__Zclient_flagsz)MySQL client flag %s not valid, ignoring.Zconnection_hostri�connection_userrb�connection_pass�passwdZconnection_port�port�
connection_db�db�connection_conv�convZconnection_unix_socket�unix_socketZread_default_fileZconnection_default_groupZread_default_groupZuse_unicodeZconnection_charset�charsetZpyformatz<MySQL password of None found. Attempting passwordless login.rjrk)NTr;)�dict�dirrrs�getattr�lowerrorRrnr:Z
paramstyle�copy�deepcopy�warning�pop�connectrrmrgrdrqZ
InternalErrorZ
autocommit)	r|r}rxZavailable_client_flags�flagrwrXrprqr;r{r<rKisf
�

�


�
��
rKc	Cs�t�d|�d}t|t�r,d}|�dd��dd�}|�di�}|�d	d�}|�d
d�}n|}d}t�|�}d|_d|_d|_	|j
d
7_
t|�}g}g}	d}
d}d}d}
d}||
d�D]�}|dkrl|dkrl|
d7}
q]|dkr{|dkr{|
d7}
d}
q]|dkr�|dkr�|
d7}
d}
q]|dkr�|dkr�d}|
d7}
q]|dkr�|dkr�d
}|
d7}
q]|dkr�|dkr�d	}|
d7}
q]|dkr�||
ddks�||
ddks�||
ddvr�|	r�|	�|�|�d�
|	��g}	ng|
s�|}n|�d|��}|�|�nU|	�|�nO|dk�r||7}z
||
ddk�rd}Wn8t�yYn3w|dk�r)||7}n#|d
k�rC|�r3n||7}||
ddk�rBd}n	|d	k�rL|}n|
d7}
q]z|�s_|�d�}|�d�}t�d||||�Wnt�yud}Ynwt||||d�S) a�

    This should correspond fairly closely to the YAML rendering of a
    mysql_grants state which comes out as follows:

     OrderedDict([
        ('whatever_identifier',
         OrderedDict([
            ('mysql_grants.present',
             [
              OrderedDict([('database', 'testdb.*')]),
              OrderedDict([('user', 'testuser')]),
              OrderedDict([('grant', 'ALTER, SELECT, LOCK TABLES')]),
              OrderedDict([('host', 'localhost')])
             ]
            )
         ])
        )
     ])

    :param grant: An un-parsed MySQL GRANT statement str, like
        "GRANT SELECT, ALTER, LOCK TABLES ON `mydb`.* TO 'testuser'@'localhost'"
        or a dictionary with 'qry' and 'args' keys for 'user' and 'host'.
    :return:
        A Python dict with the following keys/values:
            - user: MySQL User
            - host: MySQL host
            - grant: [grant1, grant2] (ala SELECT, USAGE, etc)
            - database: MySQL DB
    z_grant_to_tokens entry '%s'FTr[Z	undefined�%%�%rgrirbr8z'`�"��grantsN�,�(�)ZONr�ZTO�tables�@zpre-host)r�r�� rI�'z%grant to token '%s'::'%s'::'%s'::'%s'�rbri�grant�database)rRrS�
isinstancer�ro�replace�shlex�quotesZwhitespace_splitZ
commentersZ	wordchars�list�append�joinru�strip�UnboundLocalError)r�Z	dict_modeZ	grant_sqlZsql_argsrirbZlexZexploded_grant�grant_tokensZmultiword_statementZposition_trackerr��phrasercZ
current_grant�tokenr;r;r<�_grant_to_tokens�s�



��


�




��r�cCs�d|vr|Sd}d}d}g}|D]C}tjj�||�dkr&|dkr&|�d�qtjj�||�dkr:|dkr:|�d	�qtjj�||�dkrN|d
krN|�d�q|�|�q|S)a�

    There can be a situation where the database supports grants "A" and "B", where
    "B" is an alias for "A". In that case, when you want to grant "B" to a user,
    the database will actually report it added "A". We need to resolve those
    aliases to not report (wrong) errors.

    :param grants: the tokenized grants

    :param server_version: version string of the connected database

    �MariaDBz10.5.1z10.5.2z10.5.9rr&r'r%rr$r1)�salt�utils�versions�version_cmpr�)r��server_versionZ+mariadb_version_compare_replication_replicaZ&mariadb_version_compare_binlog_monitorZ%mariadb_version_compare_slave_monitorZresolved_tokensr�r;r;r<�_resolve_grant_aliasesvsB
��
��
��
r�cCsD|rd|�dd��dd��dd�dSd|�dd��dd�dS)a�
    Return an identifier name (column, table, database, etc) escaped for MySQL

    This means surrounded by "`" character and escaping this character inside.
    It also means doubling the '%' character for MySQLdb internal usage.

    :param identifier: the table, column or database identifier

    :param for_grants: is False by default, when using database names on grant
     queries you should set it to True to also escape "_" and "%" characters as
     requested by MySQL. Note that theses characters should only be escaped when
     requesting grants on the database level (`my\_\%db`.*) but not for table
     level grants (`my_%db`.`foo`)

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.quote_identifier 'foo`bar'
    �`z``�_z\_r�r�)r�)Z
identifier�
for_grantsr;r;r<rO�s���rOcCsP|dus|ikr|�dd�}t�d|�|�|�St�d|t|��|�||�S)a
    Internal wrapper around MySQLdb cursor.execute() function

    MySQLDb does not apply the same filters when arguments are used with the
    query. For example '%' characters on the query must be encoded as '%%' and
    will be restored as '%' when arguments are applied. But when there're no
    arguments the '%%' is not managed. We cannot apply Identifier quoting in a
    predictable way if the query are not always applying the same filters. So
    this wrapper ensure this escape is not made if no arguments are used.
    Nr�r�zDoing query: %szDoing query: %s args: %s )r�rRrS�execute�repr)rYr[rgr;r;r<rP�s
rPcCs ts	t�d�|Stj|dd�S)NzE_sanitize_comments unavailable, no python sqlparse library installed.T)Zstrip_comments)�HAS_SQLPARSErRrn�sqlparserm)�contentr;r;r<�_sanitize_comments�s�r�c
Kstjj}t|�}tt|tgt|���}ddi}|�tj	�
��rDtjtfg|t
j<tjtfg|t
j<tjtfg|t
j<tjtfg|t
j<|�||d��tdi|��}|durYiS|��}t��}	t�d||�zt||�}
Wn"ty�}zdj|j�}|td<t�|�WYd}~dSd}~ww|��}
t��|	}|d	kr�tt|d
d��d}n	tt|d
��d}i}|tt|d��d�|d<gd�}d}|D]}|�
�� ��!|�r�d}nq�|r�|
|d<d}|j"D]	}||df7}q�||d<|
|d<|S|
|d<|S)a
    Run an arbitrary SQL query and return the results or
    the number of affected rows.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.query mydb "UPDATE mytable set myfield=1 limit 1"

    Return data:

    .. code-block:: python

        {'query time': {'human': '39.0ms', 'raw': '0.03899'}, 'rows affected': 1L}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.query mydb "SELECT id,name,cash from users limit 3"

    Return data:

    .. code-block:: python

        {'columns': ('id', 'name', 'cash'),
            'query time': {'human': '1.0ms', 'raw': '0.001'},
            'results': ((1L, 'User 1', Decimal('110.000000')),
                        (2L, 'User 2', Decimal('215.636756')),
                        (3L, 'User 3', Decimal('0.040000'))),
            'rows returned': 3L}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.query mydb 'INSERT into users values (null,"user 4", 5)'

    Return data:

    .. code-block:: python

        {'query time': {'human': '25.6ms', 'raw': '0.02563'}, 'rows affected': 1L}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.query mydb 'DELETE from users where id = 4 limit 1'

    Return data:

    .. code-block:: python

        {'query time': {'human': '39.0ms', 'raw': '0.03899'}, 'rows affected': 1L}

    Jinja Example: Run a query on ``mydb`` and use row 0, column 0's data.

    .. code-block:: jinja

        {{ salt['mysql.query']('mydb', 'SELECT info from mytable limit 1')['results'][0][0] }}
    ZMYSQLDBT)r�r�NzUsing db: %s to run query %srjrkFg�������?i�r��ms��s�)�human�raw�
query time)r,ZSHOWZDESC�
rows returnedr;r�columnsr\�
rows affected)#r:Z
convertersZconversions�iterr��zip�strrtro�__package__rDrZBINARYrZBLOB�STRINGZ
VAR_STRINGZVARCHAR�updaterKrL�timerRrSrPrrmrgrdrnrQ�roundr�rs�description)r��queryrWZ	orig_convZ	conv_iterr�Zconv_mysqldbrXrY�startZaffectedrprqr\�elapsedZ	elapsed_h�retZselect_keywordsZselect_query�keywordr�rcr;r;r<r��sjF
�
�
�
�
���
r�c	s�ts	t�d�dSt�fdd�dD��rtd���tj���rBtj	j
��d��}tj	j�
|���}Wd�n1s<wYnt�d	��dSd
}dggdddid
�}t|�}|��D]m}t�d|�sk||}q^||}t||fi|��}d
}|dur�dSd|vr�|ddt|dd�7<d|vr�|d|d7<d|vr�|d�|d�d|vr�|d�|d�d|vr�|d|d7<q^ttt|dd�d��d|dd<tt|dd�d�|dd<dd�|��D�}|S)ar
    Run an arbitrary SQL query from the specified file and return the
    the number of affected rows.

    .. versionadded:: 2017.7.0

    database

        database to run script inside

    file_name

        File name of the script.  This can be on the minion, or a file that is reachable by the fileserver

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.file_query mydb file_name=/tmp/sqlfile.sql
        salt '*' mysql.file_query mydb file_name=salt://sqlfile.sql

    Return data:

    .. code-block:: python

        {'query time': {'human': '39.0ms', 'raw': '0.03899'}, 'rows affected': 1L}

    zCmysql.file_query unavailable, no python sqlparse library installed.Fc3s�|]}��|�VqdS�N)rs)�.0�proto��	file_namer;r<�	<genexpr>�s
��
�zfile_query.<locals>.<genexpr>)zsalt://zhttp://zhttps://zswift://zs3://z
cp.cache_file�rNzFile "%s" does not existr8rr�)r�r�r\r�r�z[^-;]+;r�r�r�r\r�r�r�r�r�cSsi|]	\}}|r||�qSr;r;)r��k�vr;r;r<�
<dictcomp>�szfile_query.<locals>.<dictcomp>)r�rRrn�anyrv�os�path�existsr�r��filesZfopenZstringutilsZ
to_unicode�readr��
splitlines�re�searchr��floatr�r�r��items)	r�r�rWZifile�contentsZquery_stringr��lineZquery_resultr;r�r<�
file_queryvs\
����
� �&r�c	
Ks�tdi|��}|dur
iS|��}d}zt||�Wn#ty=}zdj|j�}|td<t�|�iWYd}~Sd}~wwi}t	|j
�D]}|��}|d||d<qE|S)z�
    Return the status of a MySQL server using the output from the ``SHOW
    STATUS`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.status
    NzSHOW STATUSrjrkr�rr;)rKrLrPrrmrgrdrRrn�rangerf�fetchone)	rWrXrYr[rprqr�r��rowr;r;r<�status�s&
��r�c
Ks�dtvrtdStdi|��}|durdS|��}d}zt||�Wn#tjyE}zdj|j�}|td<t�	|�WYd}~dSd}~wwzt
jj�
|��d�td<tdWStybYdSw)	z�
    Return the version of a MySQL server using the output from the ``SELECT
    VERSION()`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.version
    z
mysql.versionNr8zSELECT VERSION()rjrkrr;)rdrKrLrPr:rrmrgrRrnr�r��data�decoder�ru)rWrXrYr[rprqr;r;r<�version�s,
��
�r�c
Ks�tdi|��}|dur
dS|�tjj�}d}zt||�Wn#tjy@}zdj|j�}|t	d<t
�|�WYd}~dSd}~ww|��}|j
dkrLdS|dd	krV|d
SdS)
a�
    Return the number of seconds that a slave SQL server is lagging behind the
    master, if the host is not a slave it will return -1.  If the server is
    configured to be a slave for replication but slave IO is not running then
    -2 will be returned. If there was an error connecting to the database or
    checking the slave status, -3 will be returned.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.slave_lag
    N����show slave statusrjrkr���ZSlave_IO_RunningZYesZSeconds_Behind_Master���r;)rKrLr:rMrNrPrrmrgrdrRrnr�rf�rWrXrYr[rprqr\r;r;r<�	slave_lags(
��
r�cKs�tdi|��}|dur
dS|�tjj�}|�d�|��}d|di}ztdi|��}|dur2WdS|��}|�d�|��Wn
tjyJYnw|�d�|�d�|�d	�|�d�|��}|durid
SdS)
z�
    Frees a slave from its master.  This is a WIP, do not use.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.free_slave
    Nr8r�riZMaster_Hostz
flush logsz
stop slavezreset masterzchange master to MASTER_HOST=ZpromotedZfailedr;)	rKrLr:rMrNr�r��closer)rWZslave_dbZ	slave_curZslave_statusZmasterZ	master_dbZ
master_curr\r;r;r<�
free_slave<s2


�



r�c	
Ks�tdi|��}|dur
gS|��}d}zt||�Wn$tjy>}zdj|j�}|td<t�	|�gWYd}~Sd}~wwg}|�
�}|D]	}|�|d�qGt�|�|S)z�
    Return a list of databases of a MySQL server using the output
    from the ``SHOW DATABASES`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_list
    Nr.rjrkrr;�
rKrLrPr:rrmrgrdrRrnrQr�rS�	rWrXrYr[rprqr�r\Zdbsr;r;r<�db_listjs(
��
rc
Ks�td
i|��}|dur
gS|��}t|fi|��}d�||p"|�d�|p(|�d��}i}zt|||�r<t�d|�WdSWd	Stj	ya}	zdj|	j
�}
|
td<t�|
�WYd}	~	d	Sd}	~	ww)z�
    Modify database using ``ALTER DATABASE %(dbname)s CHARACTER SET %(charset)s
    COLLATE %(collation)s;`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.alter_db testdb charset='latin1'
    Nz0ALTER DATABASE `{}` CHARACTER SET {} COLLATE {};�
character_set�collatezDB '%s' alteredTrjrkFr;)
rKrL�db_getrmrorPrR�infor:rrgrdrn)rUrrrWrXrY�existingr[rgrprqr;r;r<�alter_db�s0�����rc	
Ks�td	i|��}|dur
gS|��}d}d|i}zt|||�Wn$tjyC}zdj|j�}|td<t�	|�gWYd}~Sd}~ww|j
rX|��}|dd|ddd�SiS)
a*
    Return a list of databases of a MySQL server using the output
    from the ``SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM
    INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='dbname';`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_get test
    NzxSELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME=%(dbname)s;�dbnamerjrkrr�)rrr;)rKrLrPr:rrmrgrdrRrnrfrQ)	rUrWrXrYr[rgrprqZrowsr;r;r<r�s(�
��rc
Ks�t|fi|��st�d|�dStdi|��}|durgS|��}t|�}d|��}zt||�Wn$tjyU}zdj	|j
�}|td<t�|�gWYd}~Sd}~wwg}|�
�}	|	D]	}
|�|
d�q^t�|�|S)	z�
    Shows the tables in the given MySQL database (if exists)

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_tables 'database'
    zDatabase '%s' does not existFNzSHOW TABLES IN rjrkrr;)�	db_existsrRrrKrLrOrPr:rrmrgrdrnrQr�rS)rUrWrXrYrZr[rprqr�r\rVr;r;r<�	db_tables�s0


��
r	c
Ks�tdi|��}|dur
dS|��}d|i}d}zt|||�Wn#tjyB}zdj|j�}|td<t�	|�WYd}~dSd}~ww|�
�|jdkS)	z�
    Checks if a database exists on the MySQL server.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_exists 'dbname'
    NFrzSHOW DATABASES LIKE %(dbname)s;rjrkr�r;)rKrLrPr:rrmrgrdrRrnrQrf)rUrWrXrYrgr[rprqr;r;r<r�s"

��
rc
Ks�t|fi|��rt�d|�dStdi|��}|durdS|��}t|�}d|��}i}|dur8|d7}||d<|durD|d7}||d<|d	7}zt|||�rXt�d
|�WdSWdStjy}}	zdj	|	j
�}
|
td
<t�|
�WYd}	~	dSd}	~	ww)a�
    Adds a databases to the MySQL server.

    name
        The name of the database to manage

    character_set
        The character set, if left empty the MySQL default will be used

    collate
        The collation, if left empty the MySQL default will be used

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_create 'dbname'
        salt '*' mysql.db_create 'dbname' 'utf8' 'utf8_general_ci'
    zDB '%s' already existsFNzCREATE DATABASE IF NOT EXISTS z  CHARACTER SET %(character_set)srz COLLATE %(collate)sr�;zDB '%s' createdTrjrkr;�
rrRrrKrLrOrPr:rrmrgrdrn)rUrrrWrXrYrZr[rgrprqr;r;r<�	db_creates<
����rc
Ks�t|fi|��st�d|�dS|dvrt�d|�dStd
i|��}|dur)dS|��}t|�}d|�d�}zt||�Wn#tjya}zdj	|j
�}|td	<t�|�WYd}~dSd}~wwt|fi|��srt�d
|�dSt�d|�dS)z�
    Removes a databases from the MySQL server.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_remove 'dbname'
    zDB '%s' does not existF)raZinformation_schemezDB '%s' may not be removedNzDROP DATABASE r
rjrkzDatabase '%s' has been removedTz"Database '%s' has not been removedr;r)rUrWrXrYrZr[rprqr;r;r<�	db_removeHs4
��r
c
Ks�tdi|��}|dur
gS|�tjj�}z	d}t||�Wn$tjyA}zdj|j�}|t	d<t
�|�gWYd}~Sd}~ww|��}t
�
|�|S)z�
    Return a list of users on a MySQL server

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.user_list
    Nz SELECT User,Host FROM mysql.userrjrkr;)rKrLr:rMrNrPrrmrgrdrRrnrQrSr�r;r;r<�	user_listts"

��
r�	localhostrlcKs6tjj�tdi|���}	d}
d}i}||d<||d<tjj�|�r@tjj�|�r4|d7}d|d<||fS|d|d	7}||fS|r�tjj�|	|
�d
krw|dkrhtt	|��}
|d|d7}t	|
�|d
<||fSd}t
�|�|td<||fS|d|d7}t	|�|d
<||fS|r�|d|d7}||d
<||fS)N�8.0.11�JSELECT User,Host FROM mysql.user WHERE User = %(user)s AND Host = %(host)srbri� AND plugin=%(unix_socket)s�auth_socketr�� AND � = ''rrl� = %(password)srEzUnable to verify password.rk� = PASSWORD(%(password)s)r;)
r�r�r�r�r��is_truer�r�rGr�rRrnrd)rbrirE�
password_hash�passwordlessr��password_column�auth_pluginrWr��compare_versionr[rgrFrqr;r;r<�_mysql_user_exists�s>���
��rcKs�d}	i}
||
d<||
d<tjj�|�r2tjj�|�r&|	d7}	d|
d<|	|
fS|	d|d7}	|	|
fS|rF|	d|d7}	t|�|
d	<|	|
fS|rT|	d|d
7}	||
d	<|	|
fS)Nrrbrirr�rrrrEr)r�r�r�rr�)rbrirErrr�rrrWr[rgr;r;r<�_mariadb_user_exists�s&
���rc
Ks�d}tjj�tdi|���}	|	s8|r8dtd<||d<tjj�tdi|���}	|	s8td}
d�|
�}t�|�dSt	di|��}|dur_td�
d|�d��r_|r_dtd<||d<t	di|��}|duredS|sntdi|��}t||fi|��}
|�
�}d|	vr�t||||||f||
d	�|��\}}nt||||||f||
d	�|��\}}zt|||�Wn#tjy�}zd
j|j�}|td<t�|�WYd}~dSd}~ww|jdkS)
ar
    Checks if a user exists on the MySQL server. A login can be checked to see
    if passwordless login is permitted by omitting ``password`` and
    ``password_hash``, and using ``passwordless=True``.

    .. versionadded:: 0.16.2
        The ``passwordless`` option was added.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.user_exists 'username' 'hostname' 'password'
        salt '*' mysql.user_exists 'username' 'hostname' password_hash='hash'
        salt '*' mysql.user_exists 'username' passwordless=True
        salt '*' mysql.user_exists 'username' password_column='authentication_string'
    FNrkr��IMySQL Error: Unable to fetch current server version. Last error was: "{}"z*MySQL Error 1045: Access denied for user 'z'@r��rrrjr�r;)r�r�r�r�r�rdrmrRrnrKrsrhrrrLrrrPr:rrgrf)rbrirErrr�rrWZ
run_verifyr��last_errrqrXrrYr[rgrpr;r;r<�user_exists�s��

�����	���	
�
��
r#c

Ks�tdi|��}|dur
dS|�tjj�}d}i}||d<||d<zt|||�Wn#tjyK}zdj|j�}|t	d<t
�|�WYd}~dSd}~ww|��}	t
�
|	�|	S)	z�
    Get full info on a MySQL user

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.user_info root localhost
    NFzBSELECT * FROM mysql.user WHERE User = %(user)s AND Host = %(host)srbrirjrkr;)rKrLr:rMrNrPrrmrgrdrRrnr�rS)
rbrirWrXrYr[rgrprq�resultr;r;r<�	user_infoGs(

��
r%cKsRtjj�tdi|���}	d}
d}i}||d<||d<|rOtdi|��s4d}
t�|
�|
td<d}||fS|d	kr@|d
7}||fSt�d�|
td<d}||fStjj�	|�s�|dur{tjj
�|	|
�dkrm||d
<|d7}n|d7}t|�|d<||fS|dur�tjj
�|	|
�dkr�||d
<|d7}n|d7}||d<||fSt�d�d}||fS)Nr�CREATE USER %(user)s@%(host)srbrir�&The auth_socket plugin is not enabled.rkFrz IDENTIFIED WITH auth_socket�7Auth via unix_socket can be set only for host=localhostrrz0 IDENTIFIED WITH %(auth_plugin)s BY %(password)s� IDENTIFIED BY %(password)srEz0 IDENTIFIED WITH %(auth_plugin)s AS %(password)s�$ IDENTIFIED BY PASSWORD %(password)s�Kpassword or password_hash must be specified, unless allow_passwordless=Truer;�r)
r�r�r�r�r��
plugin_statusrRrnrdrr�r�r�)rbrirEr�allow_passwordlessr�rrrWr�rr[rgrqr;r;r<�_mysql_user_creategsX
$�!
���
��
��r/cKs�d}	i}
||
d<||
d<|rAtdi|��s&d}t�|�|td<d}	|	|
fS|dkr2|	d	7}	|	|
fSt�d
�|td<d}	|	|
fStjj�|�sq|durZ|	d7}	t|�|
d<|	|
fS|durj|	d
7}	||
d<|	|
fSt�d�d}	|	|
fS)Nr&rbrir��&The unix_socket plugin is not enabled.rkFrz IDENTIFIED VIA unix_socketr(r)rEr*r+�r�)	r-rRrnrdr�r�r�rr�)rbrirErr.r�rrrWr[rgrqr;r;r<�_mariadb_user_create�s@
�
��
���r2c
Ks�tjj�tdi|���}	|	s6|r6dtd<||d<tjj�tdi|���}	|	s6td}
d�|
�}t�|�dSt	||fi|��rHt�
d||�dStdi|��}|durUdS|s^tdi|��}|�
�}
d|	vryt||||||f||d�|��\}}nt||||||f||d�|��\}}t|t�r�|Szt|
||�Wn#tjy�}zd	j|j�}|td<t�|�WYd}~dSd}~wwt	||||fd
|i|��r�d|�d|�d
�}t||f�s�|d7}t�
|�dSt�
d||�dS)aq
    Creates a MySQL user

    host
        Host for which this user/password combo applies

    password
        The password to use for the new user. Will take precedence over the
        ``password_hash`` option if both are specified.

    password_hash
        The password in hashed form. Be sure to quote the password because YAML
        doesn't like the ``*``. A password hash can be obtained from the mysql
        command-line client like so::

            mysql> SELECT PASSWORD('mypass');
            +-------------------------------------------+
            | PASSWORD('mypass')                        |
            +-------------------------------------------+
            | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
            +-------------------------------------------+
            1 row in set (0.00 sec)

    allow_passwordless
        If ``True``, then ``password`` and ``password_hash`` can be omitted (or
        set to ``None``) to permit a passwordless login.

    unix_socket
        If ``True`` and allow_passwordless is ``True`` then will be used unix_socket auth plugin.

    password_column
        The password column to use in the user table.

    auth_plugin
        The authentication plugin to use, default is to use the mysql_native_password plugin.

    .. versionadded:: 0.16.2
        The ``allow_passwordless`` option was added.

    CLI Examples:

    .. code-block:: bash

        salt '*' mysql.user_create 'username' 'hostname' 'password'
        salt '*' mysql.user_create 'username' 'hostname' password_hash='hash'
        salt '*' mysql.user_create 'username' 'hostname' allow_passwordless=True
    Nrkr�r FzUser '%s'@'%s' already existsr�r!rjrzUser 'z'@'z' has been createdz with passwordless loginTzUser '%s'@'%s' was not createdr;)r�r�r�r�r�rdrmrRrnr#rrKrhrLr2r/r�r9rPr:rrgr�)rbrirErr.r�rrrWr�r"rqrXrYr[rgrp�msgr;r;r<�user_create�s�:�
��	���	
�

�����
r4cKs�tjj�tdi|���}	d}
i}|dur(tjj�|	|
�dkr!d}nd}||d<n|dur3d}||d<ntjj�|�sAt�	d�dSd}||d	<||d
<tjj�|	|
�dkrm||d<d}
|durd|
d
7}
n|durl|
d7}
n
d|d|d}
tjj�|�r�tjj�|�r�|dkr�t
di|��s�d}t�	|�|td<d}
|
|fSd|d<tjj�|	|
�dkr�d}
|
|fSd|d|dd}
|
|fSt�	d�|
|fS)Nrr�%(password)s�PASSWORD(%(password)s)rEr+F�''rbrirz=ALTER USER %(user)s@%(host)s IDENTIFIED WITH %(auth_plugin)s zBY %(password)s;zAS %(password)s;�UPDATE mysql.user SET �=�) WHERE User=%(user)s AND Host = %(host)s;rrr'rkr�zIALTER USER %(user)s@%(host)s IDENTIFIED WITH %(unix_socket)s AS %(user)s;�, plugin=%(unix_socket)sr(r;r,)r�r�r�r�r�r�r�rrRrnr-rd�rbrirErr.r�rrrWr�rrgZpassword_sqlr[rqr;r;r<�_mysql_user_chpasscs�

�
�������
����������
�r=cKsHtjj�tdi|���}	d}
i}|durd}||d<n|dur&d}||d<ntjj�|�s4t�d�dSd}||d<||d	<tjj�	|	|
�d
krS||d<d}
|
|7}
n
d
|d|d}
tjj�|�r�tjj�|�r�|dkr�t
di|��s�d}t�|�|td<d}
|
|fSd|d<d
|d|dd}
|
|fSt�d�|
|fS)Nz10.4r6rEr5r+Fr7rbrirrzBALTER USER %(user)s@%(host)s IDENTIFIED VIA %(auth_plugin)s USING r8r9r:rr�r0rkr;r(r;r1)r�r�r�r�r�rrRrnr�r�r-rdr<r;r;r<�_mariadb_user_chpass�sr

�
������
�������
�r>c
Ks$tjj�tdi|���}|s6|r6dtd<||d<tjj�tdi|���}|s6td}	d�|	�}
t�|
�dSt	||fi|��sHt�
d||�dStdi|��}|durUdS|s^tdi|��}t
||fi|��}|��}
d|vr�t||||||f||d�|��\}}nt||||||f||d�|��\}}zt|
||�}Wn#tjy�}zd	j|j�}
|
td<t�|
�WYd}~dSd}~wwd|vr�d
nd}d}tjj�||�dkr�t|
d
�d}n	|r�t|
d
�d}|r�t�
d||t||f�r�d�dSd�dSt�
d||t||f��r
d�dSd�dS)a?
    Change password for a MySQL user

    host
        Host for which this user/password combo applies

    password
        The password to set for the new user. Will take precedence over the
        ``password_hash`` option if both are specified.

    password_hash
        The password in hashed form. Be sure to quote the password because YAML
        doesn't like the ``*``. A password hash can be obtained from the mysql
        command-line client like so::

            mysql> SELECT PASSWORD('mypass');
            +-------------------------------------------+
            | PASSWORD('mypass')                        |
            +-------------------------------------------+
            | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
            +-------------------------------------------+
            1 row in set (0.00 sec)

    allow_passwordless
        If ``True``, then ``password`` and ``password_hash`` can be omitted (or
        set to ``None``) to permit a passwordless login.

    .. versionadded:: 0.16.2
        The ``allow_passwordless`` option was added.

    CLI Examples:

    .. code-block:: bash

        salt '*' mysql.user_chpass frank localhost newpassword
        salt '*' mysql.user_chpass frank localhost password_hash='hash'
        salt '*' mysql.user_chpass frank localhost allow_passwordless=True
    Nrkr�r F�User '%s'@'%s' does not existsr�r!rjz10.4.0rrzFLUSH PRIVILEGES;Tz'Password for user '%s'@'%s' has been %s�changedZclearedz&Password for user '%s'@'%s' was not %sr;)r�r�r�r�r�rdrmrRrnr#rrKrhrrrLr>r=rPr:rrgr�r�r�)rbrirErr.r�rrWr�r"rqrXrrYr[rgr$rpr�resr;r;r<�user_chpasss�0�
��	���	
�
��

������rBc	
Ks�t||fi|��sd||f}|td<t�|�dStdi|��}|dur&dS|��}d}i}||d<||d<zt|||�Wn#tjya}zdj	|j
�}|td<t�|�WYd}~dSd}~wwt||fi|��stt�d	||�d
St�d||�dS)
z{
    Delete MySQL user

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.user_remove frank localhost
    r?rkFNzDROP USER %(user)s@%(host)srbrirjzUser '%s'@'%s' has been removedTz#User '%s'@'%s' has NOT been removedr;)r#rdrRrrKrLrPr:rrmrgrn)	rbrirWrqrXrYr[rgrpr;r;r<�user_remove�s6



��rCcCst|�S)z�
    External wrapper function
    :param grant:
    :return: dict

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.tokenize_grant             "GRANT SELECT, INSERT ON testdb.* TO 'testuser'@'localhost'"
    )r�)r�r;r;r<�tokenize_grant�s
rDcK�tg}|dur(t|fi|��}|D]}t�d||�|�t||fi|���q|St�d||�t||fi|��}|S)z�
    Repairs the full database or just a given table

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_check dbname
        salt '*' mysql.db_check dbname dbtable
    Nz Checking table '%s' in db '%s'..)r	rRrr�r]�rUrVrWr�r�r;r;r<�db_check�s�rGcKrE)z�
    Repairs the full database or just a given table

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_repair dbname
    Nz!Repairing table '%s' in db '%s'..)r	rRrr�r_rFr;r;r<�	db_repair��
�rHcKrE)z�
    Optimizes the full database or just a given table

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.db_optimize dbname
    Nz"Optimizing table '%s' in db '%s'..)r	rRrr�r`rFr;r;r<�db_optimize�rIrJcCsN|����dkr
d}t|�}|D]\}}|����tvr$td|�d���q|S)N�ALLrzInvalid grant : 'r�)r�rD�
__grant_split�
__grants__�	Exception)r�Zexploded_grantsZchkgrantr�r;r;r<�__grant_normalize	s�rOcCst�d�}|�|�S)Nz([\w\s]+)(\([^)(]*\))?\s*,?)r��compile�findall)r��patternr;r;r<rL!	s

rLc
Cs�g}|D]9}tt|����}|����}|tvr td|�d���|tvr4|�d�	|||�
dd���q||r=|�|�qdd�|�S)NzInvalid SSL option : 'r�z{} '{}'r8z	 REQUIRE r)�nextr��keysr�rD�__ssl_options__rN�__ssl_options_parameterized__r�rmr�r�)�
ssl_optionZnew_ssl_option�optrwZ
normal_keyr;r;r<�__ssl_option_sanitize&	s�
�rYcCs�t�dd|���}t|�}|�d�}|d}|d}	|r0|dkr(t||	dkd�}|	dkr0t|	�}	d|�d	|�d|	�d
�}
i}||d<||d<|rSt|t�rS|
t|�7}
t	j
j�|�r^|
d
7}
t
�d|
t|��|
|d�S)z�
    Validate grants and build the query that could set the given grants

    Note that this query contains arguments for user and host but not for
    grants or database.
    z\s*,\s*z, rIrr�r>�r�zGRANT � ON z TO %(user)s@%(host)srbri� WITH GRANT OPTIONz!Grant Query generated: %s args %s)r[rg)r��subrDrO�
rpartitionrOr�r�rYr�r�r�rrRrSr�)r�r�rbri�grant_option�escaperW�db_partrXrVr[rgr;r;r<�__grant_generate?	s(

rbc

Kst||fi|��st�d||�dStd
i|��}|durdS|��}d}i}||d<||d<zt|||�Wn#tjyZ}zdj|j	�}|t
d<t�|�WYd}~dSd}~wwg}	tj
j�|���}
|
D]}|d	�d
�d	}d|d	vr�d|vr�|�d�}|	�|�qht�|	�|	S)z�
    Shows the grants for the given MySQL user (if it exists)

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.user_grants 'frank' 'localhost'
    zUser '%s'@'%s' does not existFNz!SHOW GRANTS FOR %(user)s@%(host)srbrirjrkrz IDENTIFIED BYzWITH GRANT OPTIONr\r;)r#rRrrKrLrPr:rrmrgrdrnr�r�r�r�rQ�splitr�rS)
rbrirWrXrYr[rgrprqr�r\r��tmpr;r;r<�user_grantsl	s:

��

rec	
Ks�z	tdi|��}Wn
tyYdSw|durdS|��}zt|d�Wn!tyF}zd|��}|td<t�|�WYd}~dSd}~wwhd�}g}tjj	�
|���D]}|s[qV|d���
�}||vrhqV|�|�qV|pqdS)ao
    Return the list of privileges the connected MySQL server reports via
    ``SHOW PRIVILEGES`` (excluding ``USAGE``, ``GRANT OPTION``, and ``PROXY``,
    which are not granted by ``GRANT ALL PRIVILEGES``).

    Returns ``None`` if the query fails (no connection, no permission, etc.)
    so callers can fall back to the hard-coded ``__all_privileges__`` list.
    NzSHOW PRIVILEGESz
MySQL Error: rk>r6ZPROXYrrr;)rKrNrLrPrdrRrnr�r�r�r�rQr�rDr�)	rWrXrYrprqZexcludedZ
privilegesr�rUr;r;r<�_server_all_privileges�	s6	�

��rfcstjj�tdi|���}|std}d�|�}	t�|	�dSd}
d|�	�vrFtjj
�|d�dkrFd|vrF|d	krFtdi|��}t
|pCt�}
nd|�	�vrNd
}|
dur�zt||||||�}Wntyz}
zt�d�t�|
�WYd}
~
dSd}
~
wwt|�}n	d}|||
|d�}t||fi|��}|dur�t�d
�dSi}|D]6}t|�}t|d|�|d<|d|vr�|d|d|d|dd�||d<q�||dd�|d�q�t|d|�|d<|��D]�\}�zei}i}�fdd�|dD�}dD]&}�|�dd��dd��dd�||<||�dd��dd��dd�||<q�|d|dk�rF|d|dk�rF|d|dk�rFt|��rFWdSt�d�|�Wq�t�y�}
z't�|
�|du�rx|du�rx||v�rxt�d�WYd}
~
dSWYd}
~
q�d}
~
wwt�d�dS)z�
    Checks to see if a grant exists in the database

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.grant_exists              'SELECT,INSERT,UPDATE,...' 'database.*' 'frank' 'localhost'
    rkr FNrKz8.0rr�z*.*rzError during grant generation.r�z�Grant does not exist or may not be ordered properly. In some cases, this could also indicate a connection error. Check your configuration.r�r�rbri)rbr�rir�cs g|]}|�dvrdnd�qS)r�TFr;)r��i�r�r;r<�
<listcomp>
s��z grant_exists.<locals>.<listcomp>)rbr�rir�r8�\r�Tzgrants mismatch '%s'<>'%s'z
Grant exists.z9Grant does not exist, or is perhaps not ordered properly?r;)r�r�r�r�r�rdrmrRrnrDr�r�rfr��__all_privileges__rbrNr�rer��extendr�r��allrS�	exception)r�r�rbrir_r`rWr�r"rqZtarget_privsZserver_privs�targetrpZ
target_tokensr�Z_grantsZgrant_tokenZ
_grant_tokensZ_target_tokensZ_grant_matches�itemr;rhr<�grant_exists�	s��


��
�����
����

��
rqc

Ks
tdi|��}|dur
dS|��}	|��}zt|||||||�}
Wnty0t�d�YdSwzt|	|
d|
d�Wn&tj	tj
fyc}zdj|j�}|t
d<t�|�WYd}~dSd}~wwt||||||fi|��r{t�d|||�d	St�d
|||�dS)a
    Adds a grant to the MySQL server.

    For database, make sure you specify database.table or database.*

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.grant_add             'SELECT,INSERT,UPDATE,...' 'database.*' 'frank' 'localhost'
    NFzError during grant generationr[rgrjrkz/Grant '%s' on '%s' for user '%s' has been addedTz3Grant '%s' on '%s' for user '%s' has NOT been addedr;)rKrLr�rbrNrRrnrPr:rZProgrammingErrorrmrgrdrqr)
r�r�rbrir_r`rWrWrXrYr[rprqr;r;r<�	grant_addE
sF�
�
������rrc
KsTtdi|��}|dur
dS|��}t|�}tjj�|�r |d7}|�d�}	|	d}|	d}
|dkr9t||
dkd�}|dkr?|}|
dkrGt|
�}
d	|�d
|�d|
�d�}i}
||
d<||
d
<zt	|||
�Wn#t
jy�}zdj|j
�}|td<t�|�WYd}~dSd}~wwt||||||fi|��s�t�d|||�dSt�d|||�dS)z�
    Removes a grant from the MySQL server.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.grant_revoke             'SELECT,INSERT,UPDATE' 'database.*' 'frank' 'localhost'
    NFz, GRANT OPTIONrIrr�r>rZzREVOKE r[z FROM %(user)s@%(host)s;rbrirjrkz1Grant '%s' on '%s' for user '%s' has been revokedTz5Grant '%s' on '%s' for user '%s' has NOT been revokedr;)rKrLrOr�r�r�rr^rOrPr:rrmrgrdrRrnrqr)r�r�rbrir_r`rWrXrYrarVZ
s_databaser[rgrprqr;r;r<�grant_revoke~
s`

������rsc
Ks�g}tdi|��}|durgS|��}t|d�dd�|jD�}t|j�D]}|��}i}t|�D]\}}	|||||<q1|�|�q%|�	�|S)a(
    Retrieves the processlist from the MySQL server via
    "SHOW FULL PROCESSLIST".

    Returns: a list of dicts, with each dict representing a process:

    .. code-block:: python

        {'Command': 'Query',
        'Host': 'localhost',
        'Id': 39,
        'Info': 'SHOW FULL PROCESSLIST',
        'Rows_examined': 0,
        'Rows_read': 1,
        'Rows_sent': 0,
        'State': None,
        'Time': 0,
        'User': 'root',
        'db': 'mysql'}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.processlist

    NzSHOW FULL PROCESSLISTcSsg|]}|d�qS)rr;)r��cr;r;r<ri�
szprocesslist.<locals>.<listcomp>r;)
rKrLrPr�r�rfr��	enumerater�r�)
rWr�rXrY�hdrr�r�Zidx_rZidx_jZvalue_jr;r;r<�processlist�
s
rwcCst��jj}t�d||�g}d}z|��}Wntjy6t�	d||�|r,|�
�t�d|�|YSwzt||�Wntjy[t�	d||�|�
�t�d|�|YSw|��}|D]}d}i}|j
D]}	|	d}
||||
<|d7}qk|�|�qb|�
�t�d|�|S)zd
    Perform the query that is passed to it (sql_str).

    Returns:
       results in a dict.

    z	%s<--(%s)Nz %s: Can't get cursor for SQL->%sz%s-->z%s: try to execute : SQL->%srr�)�sys�	_getframe�f_code�co_namerRrSrLr:Z
MySQLErrorrnr�rPrQr�r�)�connZsql_str�modZrtn_resultsrLZqrsZrow_dataZcol_cntr�Zcol_dataZcol_namer;r;r<�__do_query_into_hash�
sB��

r~cK�pt��jj}t�d|�tdi|��}|durgSt|d�}|��|s)|�	g�t�d|t
|d��|dS)a_
    Retrieves the master status from the minion.

    Returns::

        {'host.domain.com': {'Binlog_Do_DB': '',
                         'Binlog_Ignore_DB': '',
                         'File': 'mysql-bin.000021',
                         'Position': 107}}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.get_master_status

    �%s<--NzSHOW MASTER STATUS�%s-->%srr;�rxryrzr{rRrSrKr~r�r�rt�rWr}r|Zrtnvr;r;r<�get_master_status)s

r�cKr)a�
    Retrieves the slave status from the minion.

    Returns::

        {'host.domain.com': {'Connect_Retry': 60,
                       'Exec_Master_Log_Pos': 107,
                       'Last_Errno': 0,
                       'Last_Error': '',
                       'Last_IO_Errno': 0,
                       'Last_IO_Error': '',
                       'Last_SQL_Errno': 0,
                       'Last_SQL_Error': '',
                       'Master_Host': 'comet.scion-eng.com',
                       'Master_Log_File': 'mysql-bin.000021',
                       'Master_Port': 3306,
                       'Master_SSL_Allowed': 'No',
                       'Master_SSL_CA_File': '',
                       'Master_SSL_CA_Path': '',
                       'Master_SSL_Cert': '',
                       'Master_SSL_Cipher': '',
                       'Master_SSL_Key': '',
                       'Master_SSL_Verify_Server_Cert': 'No',
                       'Master_Server_Id': 1,
                       'Master_User': 'replu',
                       'Read_Master_Log_Pos': 107,
                       'Relay_Log_File': 'klo-relay-bin.000071',
                       'Relay_Log_Pos': 253,
                       'Relay_Log_Space': 553,
                       'Relay_Master_Log_File': 'mysql-bin.000021',
                       'Replicate_Do_DB': '',
                       'Replicate_Do_Table': '',
                       'Replicate_Ignore_DB': '',
                       'Replicate_Ignore_Server_Ids': '',
                       'Replicate_Ignore_Table': '',
                       'Replicate_Wild_Do_Table': '',
                       'Replicate_Wild_Ignore_Table': '',
                       'Seconds_Behind_Master': 0,
                       'Skip_Counter': 0,
                       'Slave_IO_Running': 'Yes',
                       'Slave_IO_State': 'Waiting for master to send event',
                       'Slave_SQL_Running': 'Yes',
                       'Until_Condition': 'None',
                       'Until_Log_File': '',
                       'Until_Log_Pos': 0}}

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.get_slave_status

    r�NzSHOW SLAVE STATUSr�rr;r�r�r;r;r<�get_slave_statusKs6

r�cK�lt��jj}t�d|�tdi|��}|durgSt|d�}|��|s)|�	g�t�d|t
|d��|S)z�
    Retrieves the show variables from the minion.

    Returns::
        show variables full dict

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.showvariables

    r�NzSHOW VARIABLESr�rr;r�r�r;r;r<�
showvariables��

r�cKr�)z�
    Retrieves the show global variables from the minion.

    Returns::
        show global variables full dict

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.showglobal

    r�NzSHOW GLOBAL VARIABLESr�rr;r�r�r;r;r<�
showglobal�r�r�cKs<||d<||d<tdi|��}|durdtvrtd=dSdS)z�
    Attempt to login using the provided credentials.
    If successful, return true.  Otherwise, return False.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.verify_login root password
    rr�NrkFTr;)rKrd)rbrErWrXr;r;r<�verify_login�sr�c	
Ks�tdi|��}|dur
gS|��}d}zt||�Wn$tjy>}zdj|j�}|td<t�	|�gWYd}~Sd}~wwg}|�
�}|D]}|�|d|dd��qGt�|�|S)	z�
    Return a list of plugins and their status
    from the ``SHOW PLUGINS`` query.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.plugins_list
    NzSHOW PLUGINSrjrkrr�)rUr�r;r�r�r;r;r<�plugins_list�s(
��
r�c
Ks�|s	t�d�dSt|fi|��rt�d|�dStdi|��}|dur&dS|��}d|��}|r:|d|�d�7}n|d|�d	�7}zt||�WdStjym}zd
j|j	�}|t
d<t�|�WYd}~dSd}~ww)
zs
    Add a plugina.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.plugin_add auth_socket
    �Plugin name is required.FzPlugin %s is already installed.TNzINSTALL PLUGIN z	 SONAME "r�z.so"rjrkr;�rRrnr-rKrLrPr:rrmrgrd)rUZsonamerWrXrYr[rprqr;r;r<�
plugin_adds0


�
��r�c
Ks�|s	t�d�dSt|fi|��st�d|�dStd
i|��}|dur&dS|��}d|��}i}||d<zt||�WdStjy`}zdj|j	�}|t
d	<t�|�WYd}~dSd}~ww)zx
    Remove a plugin.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.plugin_remove auth_socket
    r�FzPlugin %s is not installed.TNzUNINSTALL PLUGIN rUrjrkr;r�)rUrWrXrYr[rgrprqr;r;r<�
plugin_remove+s.


�
��r�c	
Ks�|s	t�d�dStd
i|��}|durdS|��}d}i}||d<zt|||�Wn#tjyM}zdj|j�}|t	d<t�|�WYd}~dSd}~wwz|�
�}|durZWdS|d	WStyhYdSw)z�
    Return the status of a plugin.

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.plugin_status auth_socket
    r�FNr8zQSELECT PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = %(name)srUrjrkrr;)rRrnrKrLrPr:rrmrgrdr�ru)	rUrWrXrYr[rgrprqr�r;r;r<r-Ps8

�
��
�r-)Fr�)NN)rNNFFNrl)rNNFFN)r)rNNFNNrl)rNNFNN)rFTF)rFT)_�__doc__r�r?�loggingr�r�r�rxr�Zsalt.utils.datar�Zsalt.utils.filesZsalt.utils.stringutilsr:ZMySQLdb.convertersZMySQLdb.cursorsrZMySQLdb.constantsrrr�ImportErrorZpymysqlZinstall_as_MySQLdbr�r��	getLogger�__name__rRrMrVrUrkr=rGr]r_r`rhrrrKr�r�rOrPr�r�r�r�r�r�r�rrrr	rrr
rrrr#r%r/r2r4r=r>rBrCrDrGrHrJrOrLrYrbrerfrqrrrsrwr~r�r�r�r�r�r�r�r�r-r;r;r;r<�<module>st����
>.Hb,
=
["*.
!"#%
5,
�/
�#
�
j"
�A
�0
�
�X
�J
�
)



�
-)(
�
�=
�M.0"F

!(%