Skip to content

Commit 3f905ed

Browse files
committed
add support for MariaDB
Signed-off-by: Frederic Descamps <lefred.descamps@gmail.com>
1 parent 0dc82a5 commit 3f905ed

File tree

4 files changed

+432
-232
lines changed

4 files changed

+432
-232
lines changed

mysqlsh_plugins_common.py

+5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ def are_instruments_enabled(instrument_name, session, shell):
5959

6060
return ok
6161

62+
def get_distro(session):
63+
result = session.run_sql("SELECT @@version_comment")
64+
col = result.fetch_one()
65+
return col[0]
66+
6267
def get_version(session):
6368
result = session.run_sql("SELECT @@version")
6469
col = result.fetch_one()

user/clone.py

+129-78
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
from mysqlsh.plugin_manager import plugin, plugin_function
22
from mysqlsh_plugins_common import get_major_version
3+
from mysqlsh_plugins_common import get_distro
34
from user import mds
45

56
import re
67

78

89
def _get_server_info(session):
9-
return session.run_sql("""SELECT CONCAT(@@hostname," (",@@version,")")""").fetch_one()[0]
10+
return session.run_sql(
11+
"""SELECT CONCAT(@@hostname," (",@@version,")")"""
12+
).fetch_one()[0]
1013

1114

1215
@plugin_function("user.clone")
13-
def copy_users_grants(userfrom=None, userto=None, dryrun=False, ocimds=False, force=False, session=None):
16+
def copy_users_grants(
17+
userfrom=None, userto=None, dryrun=False, ocimds=False, force=False, session=None
18+
):
1419
"""
1520
Clone a user to the same server
1621
@@ -26,17 +31,22 @@ def copy_users_grants(userfrom=None, userto=None, dryrun=False, ocimds=False, fo
2631
"""
2732
# Get hold of the global shell object
2833
import mysqlsh
34+
2935
shell = mysqlsh.globals.shell
3036
old_format = None
3137

3238
if session is None:
3339
session = shell.get_session()
3440
if session is None:
35-
print("No session specified. Either pass a session object to this "
36-
"function or connect the shell to a database")
41+
print(
42+
"No session specified. Either pass a session object to this "
43+
"function or connect the shell to a database"
44+
)
3745
return
3846
if not userfrom:
39-
search_string = shell.prompt("Enter the user to search (you can use wildcards '%', leave blank for all): ")
47+
search_string = shell.prompt(
48+
"Enter the user to search (you can use wildcards '%', leave blank for all): "
49+
)
4050
if len(search_string.strip()) > 0:
4151
search_string = 'AND user LIKE "{}"'.format(search_string)
4252
else:
@@ -46,15 +56,21 @@ def copy_users_grants(userfrom=None, userto=None, dryrun=False, ocimds=False, fo
4656
print("Info: locked users and users having expired password are not listed.")
4757

4858
mysql_version = get_major_version(session)
49-
mysql_major_int = int(mysql_version.split('.')[0])
59+
mysql_major_int = int(mysql_version.split(".")[0])
60+
mysql_distro = get_distro(session)
61+
if mysql_distro.lower().startswith("maria"):
62+
print("-- MariaDB Detected and not supported")
63+
return
5064
if mysql_major_int >= 8 or mysql_version == "5.7":
5165
# Get the list of users
5266
stmt = """SELECT DISTINCT User, Host,
5367
IF(authentication_string = "","NO", "YES") HAS_PWD
5468
FROM mysql.user
5569
WHERE NOT( `account_locked`="Y" AND `password_expired`="Y" AND `authentication_string`="" ) {}
5670
ORDER BY User, Host;
57-
""".format(search_string)
71+
""".format(
72+
search_string
73+
)
5874
else:
5975
stmt = """SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
6076
WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user' AND COLUMN_NAME='password';"""
@@ -65,86 +81,115 @@ def copy_users_grants(userfrom=None, userto=None, dryrun=False, ocimds=False, fo
6581
FROM mysql.user
6682
WHERE NOT(`password_expired`="Y" AND `authentication_string`="" ) {}
6783
ORDER BY User, Host;
68-
""".format(search_string)
84+
""".format(
85+
search_string
86+
)
6987
else:
7088
stmt = """SELECT DISTINCT User, Host,
7189
IF(authentication_string = "","NO", "YES") HAS_PWD
7290
FROM mysql.user
7391
WHERE NOT(`password_expired`="Y" AND `authentication_string`="" ) {}
7492
ORDER BY User, Host;
75-
""".format(search_string)
76-
users = session.run_sql(stmt).fetch_all()
93+
""".format(
94+
search_string
95+
)
96+
users = session.run_sql(stmt).fetch_all()
7797
final_s = ""
78-
if len(users)>1:
98+
if len(users) > 1:
7999
final_s = "s"
80100
print("{} user{} found!".format(len(users), final_s))
81101
for user in users:
82102
if ocimds and user[2] == "NO":
83-
print("[`{}`@`{}`] is not compatible with OCI MDS as it has not password, ignoring it...".format(user[0], user[1]))
103+
print(
104+
"[`{}`@`{}`] is not compatible with OCI MDS as it has not password, ignoring it...".format(
105+
user[0], user[1]
106+
)
107+
)
84108
continue
85109
if not force:
86-
answer = shell.prompt("Do you want to clone [`{}`@`{}`] ? (y/N) ".format(user[0], user[1]), {'defaultValue': 'n'})
110+
answer = shell.prompt(
111+
"Do you want to clone [`{}`@`{}`] ? (y/N) ".format(user[0], user[1]),
112+
{"defaultValue": "n"},
113+
)
87114
else:
88115
answer = "y"
89-
if answer.lower() == 'y':
116+
if answer.lower() == "y":
90117
if mysql_major_int >= 8:
91118
stmt = """SELECT from_user, from_host FROM mysql.role_edges WHERE to_user = ? and to_host = ?"""
92119
roles = session.run_sql(stmt, [user[0], user[1]]).fetch_all()
93-
if len(roles)>0:
120+
if len(roles) > 0:
94121
for role in roles:
95-
stmt = """SHOW GRANTS FOR `{}`@`{}`""".format(role[0], role[1])
96-
grants = session.run_sql(stmt).fetch_all()
97-
for grant in grants:
98-
if ocimds:
99-
grant_stmt = grant[0]
100-
on_stmt=re.sub(r"^.*( ON .*\..* TO .*$)",r"\1", grant_stmt)
101-
grant_stmt_tmp = re.sub('^GRANT ','', grant_stmt)
102-
grant_stmt_tmp = re.sub(' ON .*\..* TO .*$','', grant_stmt_tmp)
103-
tab_grants = grant_stmt_tmp.split(', ')
104-
tab_list = []
105-
for priv in tab_grants:
106-
for allowed_priv in mds.mds_allowed_privileges:
107-
if allowed_priv == priv:
108-
tab_list.append(allowed_priv)
109-
break
110-
if len(tab_list)>0:
111-
grant_stmt="GRANT " + ', '.join(tab_list) + on_stmt
112-
else:
113-
grant_stmt=None
114-
122+
stmt = """SHOW GRANTS FOR `{}`@`{}`""".format(role[0], role[1])
123+
grants = session.run_sql(stmt).fetch_all()
124+
for grant in grants:
125+
if ocimds:
126+
grant_stmt = grant[0]
127+
on_stmt = re.sub(
128+
r"^.*( ON .*\..* TO .*$)", r"\1", grant_stmt
129+
)
130+
grant_stmt_tmp = re.sub("^GRANT ", "", grant_stmt)
131+
grant_stmt_tmp = re.sub(
132+
" ON .*\..* TO .*$", "", grant_stmt_tmp
133+
)
134+
tab_grants = grant_stmt_tmp.split(", ")
135+
tab_list = []
136+
for priv in tab_grants:
137+
for allowed_priv in mds.mds_allowed_privileges:
138+
if allowed_priv == priv:
139+
tab_list.append(allowed_priv)
140+
break
141+
if len(tab_list) > 0:
142+
grant_stmt = (
143+
"GRANT " + ", ".join(tab_list) + on_stmt
144+
)
115145
else:
116-
grant_stmt = grant[0]
117-
if grant_stmt:
118-
grant_stmt = grant_stmt.replace("TO `{}`@`{}`".format(user[0], user[1]), "TO {}".format(userto))
119-
if dryrun:
120-
print("{};".format(grant_stmt))
121-
else:
122-
try:
123-
session.run_sql(grant_stmt)
124-
except mysqlsh.DBError as err:
125-
print("Aborting: {}".format(err))
126-
return
146+
grant_stmt = None
127147

148+
else:
149+
grant_stmt = grant[0]
150+
if grant_stmt:
151+
grant_stmt = grant_stmt.replace(
152+
"TO `{}`@`{}`".format(user[0], user[1]),
153+
"TO {}".format(userto),
154+
)
155+
if dryrun:
156+
print("{};".format(grant_stmt))
157+
else:
158+
try:
159+
session.run_sql(grant_stmt)
160+
except mysqlsh.DBError as err:
161+
print("Aborting: {}".format(err))
162+
return
128163

129164
if mysql_major_int < 8 and mysql_version != "5.7":
130-
stmt = """SHOW GRANTS FOR `{}`@`{}`""".format(user[0], user[1])
131-
create_user = session.run_sql(stmt).fetch_one()[0] + ";"
132-
create_user=create_user.replace(" TO '{}'@'{}'".format(user[0], user[1]),"CREATE USER {}".format(userto))
133-
create_user = re.sub(r".*CREATE USER ","CREATE USER ", create_user)
165+
stmt = """SHOW GRANTS FOR `{}`@`{}`""".format(user[0], user[1])
166+
create_user = session.run_sql(stmt).fetch_one()[0] + ";"
167+
create_user = create_user.replace(
168+
" TO '{}'@'{}'".format(user[0], user[1]),
169+
"CREATE USER {}".format(userto),
170+
)
171+
create_user = re.sub(r".*CREATE USER ", "CREATE USER ", create_user)
134172
else:
135-
stmt = """SHOW CREATE USER `{}`@`{}`""".format(user[0], user[1])
136-
create_user = session.run_sql(stmt).fetch_one()[0] + ";"
137-
#print("-- DEBUG: {}".format(create_user))
138-
create_user=create_user.replace("CREATE USER `{}`@`{}`".format(user[0], user[1]),"CREATE USER IF NOT EXISTS {}".format(userto))
139-
#print("-- DEBUG: {}".format(create_user))
140-
# we need to find the password in binary format
141-
stmt = """SELECT authentication_string, convert(authentication_string using binary) authbin
142-
FROM mysql.user where user='{}' and host='{}'""".format(user[0], user[1])
143-
auth_user = session.run_sql(stmt).fetch_one()
144-
auth_string = auth_user[0]
145-
auth_string_bin = auth_user[1]
146-
hex_string = auth_string_bin.hex()
147-
create_user = re.sub(r" AS '(.*)' ", r" AS 0x{} ".format(hex_string), create_user)
173+
stmt = """SHOW CREATE USER `{}`@`{}`""".format(user[0], user[1])
174+
create_user = session.run_sql(stmt).fetch_one()[0] + ";"
175+
# print("-- DEBUG: {}".format(create_user))
176+
create_user = create_user.replace(
177+
"CREATE USER `{}`@`{}`".format(user[0], user[1]),
178+
"CREATE USER IF NOT EXISTS {}".format(userto),
179+
)
180+
# print("-- DEBUG: {}".format(create_user))
181+
# we need to find the password in binary format
182+
stmt = """SELECT authentication_string, convert(authentication_string using binary) authbin
183+
FROM mysql.user where user='{}' and host='{}'""".format(
184+
user[0], user[1]
185+
)
186+
auth_user = session.run_sql(stmt).fetch_one()
187+
auth_string = auth_user[0]
188+
auth_string_bin = auth_user[1]
189+
hex_string = auth_string_bin.hex()
190+
create_user = re.sub(
191+
r" AS '(.*)' ", r" AS 0x{} ".format(hex_string), create_user
192+
)
148193
if dryrun:
149194
print("-- User `{}`@`{}`".format(user[0], user[1]))
150195
print(create_user)
@@ -159,42 +204,48 @@ def copy_users_grants(userfrom=None, userto=None, dryrun=False, ocimds=False, fo
159204

160205
stmt = """SHOW GRANTS FOR `{}`@`{}`""".format(user[0], user[1])
161206
grants = session.run_sql(stmt).fetch_all()
162-
if not dryrun and len(grants)>0:
163-
print("Copying GRANTS.", end='')
207+
if not dryrun and len(grants) > 0:
208+
print("Copying GRANTS.", end="")
164209
for grant in grants:
165210
if "IDENTIFIED BY PASSWORD" in grant[0]:
166-
grant_stmt = re.sub(r" IDENTIFIED BY PASSWORD.*$","", grant[0])
211+
grant_stmt = re.sub(r" IDENTIFIED BY PASSWORD.*$", "", grant[0])
167212
else:
168213
grant_stmt = grant[0]
169214
if ocimds:
170-
on_stmt=re.sub(r"^.*( ON .*\..* TO .*$)",r"\1", grant_stmt)
171-
grant_stmt_tmp = re.sub('^GRANT ','', grant_stmt)
172-
grant_stmt_tmp = re.sub(' ON .*\..* TO .*$','', grant_stmt_tmp)
173-
tab_grants = grant_stmt_tmp.split(', ')
215+
on_stmt = re.sub(r"^.*( ON .*\..* TO .*$)", r"\1", grant_stmt)
216+
grant_stmt_tmp = re.sub("^GRANT ", "", grant_stmt)
217+
grant_stmt_tmp = re.sub(" ON .*\..* TO .*$", "", grant_stmt_tmp)
218+
tab_grants = grant_stmt_tmp.split(", ")
174219
tab_list = []
175220
for priv in tab_grants:
176221
for allowed_priv in mds.mds_allowed_privileges:
177222
if allowed_priv == priv:
178223
tab_list.append(allowed_priv)
179224
break
180-
if len(tab_list)>0:
181-
grant_stmt="GRANT " + ', '.join(tab_list) + on_stmt
225+
if len(tab_list) > 0:
226+
grant_stmt = "GRANT " + ", ".join(tab_list) + on_stmt
182227
else:
183-
grant_stmt=None
228+
grant_stmt = None
184229
if grant_stmt:
185-
grant_stmt = grant_stmt.replace("TO `{}`@`{}`".format(user[0], user[1]), "TO {}".format(userto))
186-
grant_stmt = grant_stmt.replace("TO '{}'@'{}'".format(user[0], user[1]), "TO {}".format(userto))
230+
grant_stmt = grant_stmt.replace(
231+
"TO `{}`@`{}`".format(user[0], user[1]), "TO {}".format(userto)
232+
)
233+
grant_stmt = grant_stmt.replace(
234+
"TO '{}'@'{}'".format(user[0], user[1]), "TO {}".format(userto)
235+
)
187236
if dryrun:
188237
print("{};".format(grant_stmt))
189238
else:
190239
try:
191240
session.run_sql(grant_stmt)
192-
print(".", end='')
241+
print(".", end="")
193242
except mysqlsh.DBError as err:
194243
print("\nAborting: {}".format(err))
195-
print("You may need to install mysql-client to save the password.")
244+
print(
245+
"You may need to install mysql-client to save the password."
246+
)
196247
return
197-
if not dryrun and len(grants)>0:
248+
if not dryrun and len(grants) > 0:
198249
print("\nUser(s) copied successfully!")
199250

200251
return

0 commit comments

Comments
 (0)