Handle divergences between MySQL and MariaDB (#103)

* Initial attempt

* First functional approach

* Remove unused imports

* Add dychotomy handling for mysql_replication

* Fix cursor lookup

* Fix sanity tests

* Cleanup implementation conditional import

* Fix unit tests

* Fix conditional import to satisfy both sanity and integration tests

* Add changelog fragment
This commit is contained in:
Jorge Rodriguez (A.K.A. Tiriel) 2021-03-16 10:15:19 +02:00 committed by GitHub
parent a5ee4b3d1a
commit 11958ec46a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 162 additions and 92 deletions

View file

@ -298,12 +298,11 @@ RETURN = '''#'''
import re
import string
from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.mysql.plugins.module_utils.database import SQLParseError
from ansible_collections.community.mysql.plugins.module_utils.mysql import (
mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec, get_server_version
mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec
)
from ansible.module_utils.six import iteritems
from ansible.module_utils._text import to_native
@ -353,40 +352,6 @@ class InvalidPrivsError(Exception):
#
# User Authentication Management changed in MySQL 5.7 and MariaDB 10.2.0
def use_old_user_mgmt(cursor):
cursor.execute("SELECT VERSION()")
result = cursor.fetchone()
version_str = result[0]
version = version_str.split('.')
if 'mariadb' in version_str.lower():
# Prior to MariaDB 10.2
if int(version[0]) * 1000 + int(version[1]) < 10002:
return True
else:
return False
else:
# Prior to MySQL 5.7
if int(version[0]) * 1000 + int(version[1]) < 5007:
return True
else:
return False
def supports_identified_by_password(cursor):
"""
Determines whether the 'CREATE USER %s@%s IDENTIFIED BY PASSWORD %s' syntax is supported. This was dropped in
MySQL 8.0.
"""
version_str = get_server_version(cursor)
if 'mariadb' in version_str.lower():
return True
else:
return LooseVersion(version_str) < LooseVersion('8')
def get_mode(cursor):
cursor.execute('SELECT @@GLOBAL.sql_mode')
result = cursor.fetchone()
@ -445,7 +410,7 @@ def do_not_mogrify_requires(query, params, tls_requires):
def get_tls_requires(cursor, user, host):
if user:
if not use_old_user_mgmt(cursor):
if not impl.use_old_user_mgmt(cursor):
query = "SHOW CREATE USER '%s'@'%s'" % (user, host)
else:
query = "SHOW GRANTS for '%s'@'%s'" % (user, host)
@ -487,12 +452,12 @@ def user_add(cursor, user, host, host_all, password, encrypted,
return True
# Determine what user management method server uses
old_user_mgmt = use_old_user_mgmt(cursor)
old_user_mgmt = impl.use_old_user_mgmt(cursor)
mogrify = do_not_mogrify_requires if old_user_mgmt else mogrify_requires
if password and encrypted:
if supports_identified_by_password(cursor):
if impl.supports_identified_by_password(cursor):
query_with_args = "CREATE USER %s@%s IDENTIFIED BY PASSWORD %s", (user, host, password)
else:
query_with_args = "CREATE USER %s@%s IDENTIFIED WITH mysql_native_password AS %s", (user, host, password)
@ -539,7 +504,7 @@ def user_mod(cursor, user, host, host_all, password, encrypted,
grant_option = False
# Determine what user management method server uses
old_user_mgmt = use_old_user_mgmt(cursor)
old_user_mgmt = impl.use_old_user_mgmt(cursor)
if host_all:
hostnames = user_get_hostnames(cursor, user)
@ -985,7 +950,7 @@ def privileges_grant(cursor, user, host, db_table, priv, tls_requires):
query = ["GRANT %s ON %s" % (priv_string, db_table)]
query.append("TO %s@%s")
params = (user, host)
if tls_requires and use_old_user_mgmt(cursor):
if tls_requires and impl.use_old_user_mgmt(cursor):
query, params = mogrify_requires(" ".join(query), params, tls_requires)
query = [query]
if 'REQUIRESSL' in priv and not tls_requires:
@ -1224,6 +1189,15 @@ def main():
if not sql_log_bin:
cursor.execute("SET SQL_LOG_BIN=0;")
global impl
cursor.execute("SELECT VERSION()")
if 'mariadb' in cursor.fetchone()[0].lower():
from ansible_collections.community.mysql.plugins.module_utils.implementations.mariadb import user as mysqluser
impl = mysqluser
else:
from ansible_collections.community.mysql.plugins.module_utils.implementations.mysql import user as mariauser
impl = mariauser
if priv is not None:
try:
mode = get_mode(cursor)