mysql_variables: add mode parameter (#63547)
* mysql_variables: add mode parameter * mysql_variables: add mode parameter, add changelog fragment * mysql_variables: add mode parameter, fix * mysql_variables: add mode parameter, fix * mysql_variables: add mode parameter, fix * mysql_variables: add mode parameter, fix sanity * mysql_variables: add mode parameter, remove warns * mysql_variables: add mode parameter, refactoring * mysql_variables: add mode parameter, fix logic
This commit is contained in:
parent
42b290b781
commit
73526b9d65
3 changed files with 179 additions and 19 deletions
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- mysql_variables - add ``mode`` parameter (https://github.com/ansible/ansible/issues/60119).
|
|
@ -19,7 +19,7 @@ module: mysql_variables
|
|||
short_description: Manage MySQL global variables
|
||||
description:
|
||||
- Query / Set MySQL variables.
|
||||
version_added: 1.3
|
||||
version_added: '1.3'
|
||||
author:
|
||||
- Balazs Pocze (@banyek)
|
||||
options:
|
||||
|
@ -32,6 +32,22 @@ options:
|
|||
description:
|
||||
- If set, then sets variable value to this
|
||||
type: str
|
||||
mode:
|
||||
description:
|
||||
- C(global) assigns C(value) to a global system variable which will be changed at runtime
|
||||
but won't persist across server restarts.
|
||||
- C(persist) assigns C(value) to a global system variable and persists it to
|
||||
the mysqld-auto.cnf option file in the data directory
|
||||
(the variable will survive service restarts).
|
||||
- C(persist_only) persists C(value) to the mysqld-auto.cnf option file in the data directory
|
||||
but without setting the global variable runtime value
|
||||
(the value will be changed after the next service restart).
|
||||
- Supported by MySQL 8.0 or later.
|
||||
- For more information see U(https://dev.mysql.com/doc/refman/8.0/en/set-variable.html).
|
||||
type: str
|
||||
choices: ['global', 'persist', 'persist_only']
|
||||
default: global
|
||||
version_added: '2.10'
|
||||
|
||||
seealso:
|
||||
- module: mysql_info
|
||||
|
@ -48,10 +64,11 @@ EXAMPLES = r'''
|
|||
mysql_variables:
|
||||
variable: sync_binlog
|
||||
|
||||
- name: Set read_only variable to 1
|
||||
- name: Set read_only variable to 1 persistently
|
||||
mysql_variables:
|
||||
variable: read_only
|
||||
value: 1
|
||||
mode: persist
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
|
@ -75,6 +92,24 @@ from ansible.module_utils._text import to_native
|
|||
executed_queries = []
|
||||
|
||||
|
||||
def check_mysqld_auto(module, cursor, mysqlvar):
|
||||
"""Check variable's value in mysqld-auto.cnf."""
|
||||
query = ("SELECT VARIABLE_VALUE "
|
||||
"FROM performance_schema.persisted_variables "
|
||||
"WHERE VARIABLE_NAME = %s")
|
||||
try:
|
||||
cursor.execute(query, (mysqlvar,))
|
||||
res = cursor.fetchone()
|
||||
except Exception as e:
|
||||
if "Table 'performance_schema.persisted_variables' doesn't exist" in str(e):
|
||||
module.fail_json(msg='Server version must be 8.0 or greater.')
|
||||
|
||||
if res:
|
||||
return res[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def typedvalue(value):
|
||||
"""
|
||||
Convert value to number whenever possible, return same value
|
||||
|
@ -110,7 +145,7 @@ def getvariable(cursor, mysqlvar):
|
|||
return None
|
||||
|
||||
|
||||
def setvariable(cursor, mysqlvar, value):
|
||||
def setvariable(cursor, mysqlvar, value, mode='global'):
|
||||
""" Set a global mysql variable to a given value
|
||||
|
||||
The DB driver will handle quoting of the given value based on its
|
||||
|
@ -118,7 +153,13 @@ def setvariable(cursor, mysqlvar, value):
|
|||
should be passed as numeric literals.
|
||||
|
||||
"""
|
||||
if mode == 'persist':
|
||||
query = "SET PERSIST %s = " % mysql_quote_identifier(mysqlvar, 'vars')
|
||||
elif mode == 'global':
|
||||
query = "SET GLOBAL %s = " % mysql_quote_identifier(mysqlvar, 'vars')
|
||||
elif mode == 'persist_only':
|
||||
query = "SET PERSIST_ONLY %s = " % mysql_quote_identifier(mysqlvar, 'vars')
|
||||
|
||||
try:
|
||||
cursor.execute(query + "%s", (value,))
|
||||
executed_queries.append(query + "%s" % value)
|
||||
|
@ -126,6 +167,7 @@ def setvariable(cursor, mysqlvar, value):
|
|||
result = True
|
||||
except Exception as e:
|
||||
result = to_native(e)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
@ -144,6 +186,7 @@ def main():
|
|||
ca_cert=dict(type='path', aliases=['ssl_ca']),
|
||||
connect_timeout=dict(type='int', default=30),
|
||||
config_file=dict(type='path', default='~/.my.cnf'),
|
||||
mode=dict(type='str', choices=['global', 'persist', 'persist_only'], default='global'),
|
||||
),
|
||||
)
|
||||
user = module.params["login_user"]
|
||||
|
@ -157,6 +200,8 @@ def main():
|
|||
|
||||
mysqlvar = module.params["variable"]
|
||||
value = module.params["value"]
|
||||
mode = module.params["mode"]
|
||||
|
||||
if mysqlvar is None:
|
||||
module.fail_json(msg="Cannot run without variable to operate with")
|
||||
if match('^[0-9a-z_]+$', mysqlvar) is None:
|
||||
|
@ -177,19 +222,46 @@ def main():
|
|||
else:
|
||||
module.fail_json(msg="unable to find %s. Exception message: %s" % (config_file, to_native(e)))
|
||||
|
||||
mysqlvar_val = None
|
||||
var_in_mysqld_auto_cnf = None
|
||||
|
||||
mysqlvar_val = getvariable(cursor, mysqlvar)
|
||||
if mysqlvar_val is None:
|
||||
module.fail_json(msg="Variable not available \"%s\"" % mysqlvar, changed=False)
|
||||
|
||||
if value is None:
|
||||
module.exit_json(msg=mysqlvar_val)
|
||||
|
||||
if mode in ('persist', 'persist_only'):
|
||||
var_in_mysqld_auto_cnf = check_mysqld_auto(module, cursor, mysqlvar)
|
||||
|
||||
if mode == 'persist_only':
|
||||
if var_in_mysqld_auto_cnf is None:
|
||||
mysqlvar_val = False
|
||||
else:
|
||||
mysqlvar_val = var_in_mysqld_auto_cnf
|
||||
|
||||
# Type values before using them
|
||||
value_wanted = typedvalue(value)
|
||||
value_actual = typedvalue(mysqlvar_val)
|
||||
if value_wanted == value_actual:
|
||||
module.exit_json(msg="Variable already set to requested value", changed=False)
|
||||
value_in_auto_cnf = None
|
||||
if var_in_mysqld_auto_cnf is not None:
|
||||
value_in_auto_cnf = typedvalue(var_in_mysqld_auto_cnf)
|
||||
|
||||
if value_wanted == value_actual and mode in ('global', 'persist'):
|
||||
if mode == 'persist' and value_wanted == value_in_auto_cnf:
|
||||
module.exit_json(msg="Variable is already set to requested value globally"
|
||||
"and stored into mysqld-auto.cnf file.", changed=False)
|
||||
|
||||
elif mode == 'global':
|
||||
module.exit_json(msg="Variable is already set to requested value.", changed=False)
|
||||
|
||||
if mode == 'persist_only' and value_wanted == value_in_auto_cnf:
|
||||
module.exit_json(msg="Variable is already stored into mysqld-auto.cnf "
|
||||
"with requested value.", changed=False)
|
||||
|
||||
try:
|
||||
result = setvariable(cursor, mysqlvar, value_wanted)
|
||||
result = setvariable(cursor, mysqlvar, value_wanted, mode)
|
||||
except SQLParseError as e:
|
||||
result = to_native(e)
|
||||
|
||||
|
|
|
@ -308,3 +308,89 @@
|
|||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
|
||||
#=========================================
|
||||
# Check mode 'persist' and 'persist_only':
|
||||
#
|
||||
- name: update mysql variable value (expect changed=true) in persist mode
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '{{ set_value }}'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.queries == ["SET PERSIST `{{ set_name }}` = {{ set_value }}"]
|
||||
|
||||
- include: assert_var.yml changed=true output={{result}} var_name={{set_name}} var_value='{{set_value}}'
|
||||
|
||||
- name: try to update mysql variable value (expect changed=false) in persist mode again
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '{{ set_value }}'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist
|
||||
register: result
|
||||
|
||||
- include: assert_var.yml changed=false output={{result}} var_name={{set_name}} var_value='{{set_value}}'
|
||||
|
||||
- name: set mysql variable to a temp value
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '200'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist
|
||||
|
||||
- name: update mysql variable value (expect changed=true) in persist_only mode
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '{{ set_value }}'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist_only
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.queries == ["SET PERSIST_ONLY `{{ set_name }}` = {{ set_value }}"]
|
||||
|
||||
- name: try to update mysql variable value (expect changed=false) in persist_only mode again
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '{{ set_value }}'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist_only
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- set_fact:
|
||||
set_name: max_connections
|
||||
set_value: 105
|
||||
def_val: 151
|
||||
|
||||
- name: update mysql variable value (expect changed=true) in persist_only mode
|
||||
mysql_variables:
|
||||
variable: '{{ set_name }}'
|
||||
value: '{{ set_value }}'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
login_user: root
|
||||
login_password: '{{ root_pass }}'
|
||||
mode: persist_only
|
||||
register: result
|
||||
|
||||
- include: assert_var.yml changed=true output={{result}} var_name={{set_name}} var_value='{{def_val}}'
|
||||
|
|
Loading…
Reference in a new issue