mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-04-23 02:41:29 -07:00
Add MAX_STATEMENT_TIME resource limit (#523)
* Add MAX_STATEMENT_TIME to resource_limits * Move version check for resource_limits to implementations
This commit is contained in:
parent
21e42b5777
commit
526e674e6f
6 changed files with 177 additions and 29 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- mysql_user - add ``MAX_STATEMENT_TIME`` support for mariadb to the ``resource_limits`` argument (https://github.com/ansible-collections/community.mysql/issues/211).
|
|
@ -17,3 +17,9 @@ def use_old_user_mgmt(cursor):
|
||||||
|
|
||||||
def supports_identified_by_password(cursor):
|
def supports_identified_by_password(cursor):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def server_supports_alter_user(cursor):
|
||||||
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
|
return LooseVersion(version) >= LooseVersion("10.2")
|
||||||
|
|
|
@ -18,3 +18,9 @@ def use_old_user_mgmt(cursor):
|
||||||
def supports_identified_by_password(cursor):
|
def supports_identified_by_password(cursor):
|
||||||
version = get_server_version(cursor)
|
version = get_server_version(cursor)
|
||||||
return LooseVersion(version) < LooseVersion("8")
|
return LooseVersion(version) < LooseVersion("8")
|
||||||
|
|
||||||
|
|
||||||
|
def server_supports_alter_user(cursor):
|
||||||
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
|
return LooseVersion(version) >= LooseVersion("5.6")
|
||||||
|
|
|
@ -753,33 +753,6 @@ def convert_priv_dict_to_str(priv):
|
||||||
return '/'.join(priv_list)
|
return '/'.join(priv_list)
|
||||||
|
|
||||||
|
|
||||||
# Alter user is supported since MySQL 5.6 and MariaDB 10.2.0
|
|
||||||
def server_supports_alter_user(cursor):
|
|
||||||
"""Check if the server supports ALTER USER statement or doesn't.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
cursor (cursor): DB driver cursor object.
|
|
||||||
|
|
||||||
Returns: True if supports, False otherwise.
|
|
||||||
"""
|
|
||||||
cursor.execute("SELECT VERSION()")
|
|
||||||
version_str = cursor.fetchone()[0]
|
|
||||||
version = version_str.split('.')
|
|
||||||
|
|
||||||
if 'mariadb' in version_str.lower():
|
|
||||||
# MariaDB 10.2 and later
|
|
||||||
if int(version[0]) * 1000 + int(version[1]) >= 10002:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
# MySQL 5.6 and later
|
|
||||||
if int(version[0]) * 1000 + int(version[1]) >= 5006:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_resource_limits(cursor, user, host):
|
def get_resource_limits(cursor, user, host):
|
||||||
"""Get user resource limits.
|
"""Get user resource limits.
|
||||||
|
|
||||||
|
@ -808,6 +781,15 @@ def get_resource_limits(cursor, user, host):
|
||||||
'MAX_CONNECTIONS_PER_HOUR': res[2],
|
'MAX_CONNECTIONS_PER_HOUR': res[2],
|
||||||
'MAX_USER_CONNECTIONS': res[3],
|
'MAX_USER_CONNECTIONS': res[3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cursor.execute("SELECT VERSION()")
|
||||||
|
if 'mariadb' in cursor.fetchone()[0].lower():
|
||||||
|
query = ('SELECT max_statement_time AS MAX_STATEMENT_TIME '
|
||||||
|
'FROM mysql.user WHERE User = %s AND Host = %s')
|
||||||
|
cursor.execute(query, (user, host))
|
||||||
|
res_max_statement_time = cursor.fetchone()
|
||||||
|
current_limits['MAX_STATEMENT_TIME'] = res_max_statement_time[0]
|
||||||
|
|
||||||
return current_limits
|
return current_limits
|
||||||
|
|
||||||
|
|
||||||
|
@ -860,10 +842,15 @@ def limit_resources(module, cursor, user, host, resource_limits, check_mode):
|
||||||
|
|
||||||
Returns: True, if changed, False otherwise.
|
Returns: True, if changed, False otherwise.
|
||||||
"""
|
"""
|
||||||
if not server_supports_alter_user(cursor):
|
if not impl.server_supports_alter_user(cursor):
|
||||||
module.fail_json(msg="The server version does not match the requirements "
|
module.fail_json(msg="The server version does not match the requirements "
|
||||||
"for resource_limits parameter. See module's documentation.")
|
"for resource_limits parameter. See module's documentation.")
|
||||||
|
|
||||||
|
cursor.execute("SELECT VERSION()")
|
||||||
|
if 'mariadb' not in cursor.fetchone()[0].lower():
|
||||||
|
if 'MAX_STATEMENT_TIME' in resource_limits:
|
||||||
|
module.fail_json(msg="MAX_STATEMENT_TIME resource limit is only supported by MariaDB.")
|
||||||
|
|
||||||
current_limits = get_resource_limits(cursor, user, host)
|
current_limits = get_resource_limits(cursor, user, host)
|
||||||
|
|
||||||
needs_to_change = match_resource_limits(module, current_limits, resource_limits)
|
needs_to_change = match_resource_limits(module, current_limits, resource_limits)
|
||||||
|
|
|
@ -145,7 +145,7 @@ options:
|
||||||
description:
|
description:
|
||||||
- Limit the user for certain server resources. Provided since MySQL 5.6 / MariaDB 10.2.
|
- Limit the user for certain server resources. Provided since MySQL 5.6 / MariaDB 10.2.
|
||||||
- "Available options are C(MAX_QUERIES_PER_HOUR: num), C(MAX_UPDATES_PER_HOUR: num),
|
- "Available options are C(MAX_QUERIES_PER_HOUR: num), C(MAX_UPDATES_PER_HOUR: num),
|
||||||
C(MAX_CONNECTIONS_PER_HOUR: num), C(MAX_USER_CONNECTIONS: num)."
|
C(MAX_CONNECTIONS_PER_HOUR: num), C(MAX_USER_CONNECTIONS: num), C(MAX_STATEMENT_TIME: num) (supported only for MariaDB since collection version 3.7.0)."
|
||||||
- Used when I(state=present), ignored otherwise.
|
- Used when I(state=present), ignored otherwise.
|
||||||
type: dict
|
type: dict
|
||||||
version_added: '0.1.0'
|
version_added: '0.1.0'
|
||||||
|
|
|
@ -129,4 +129,151 @@
|
||||||
that:
|
that:
|
||||||
- result.rowcount[0] == 1
|
- result.rowcount[0] == 1
|
||||||
|
|
||||||
|
- name: Resource limits | Drop mysql user {{ user_name_1 }} if exists
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
host_all: true
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Resource limits | Create mysql user {{ user_name_1 }} with MAX_STATEMENT_TIME in check_mode
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
password: '{{ user_password_1 }}'
|
||||||
|
state: present
|
||||||
|
resource_limits:
|
||||||
|
MAX_QUERIES_PER_HOUR: 10
|
||||||
|
MAX_STATEMENT_TIME: 1
|
||||||
|
check_mode: true
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that create user with MAX_STATEMENT_TIME is changed for mariadb
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that create user with MAX_STATEMENT_TIME is failed for mysql
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
when: db_engine == 'mysql'
|
||||||
|
|
||||||
|
- name: Resource limits | Create mysql user {{ user_name_1 }} with MAX_STATEMENT_TIME in actual mode
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
password: '{{ user_password_1 }}'
|
||||||
|
state: present
|
||||||
|
resource_limits:
|
||||||
|
MAX_QUERIES_PER_HOUR: 10
|
||||||
|
MAX_STATEMENT_TIME: 1
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that create user with MAX_STATEMENT_TIME is changed for MariaDB
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that create user with MAX_STATEMENT_TIME is failed for MySQL
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
when: db_engine == 'mysql'
|
||||||
|
|
||||||
|
- name: Resource limits | Retrieve user with MAX_STATEMENT_TIME
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query: >
|
||||||
|
SELECT User FROM mysql.user
|
||||||
|
WHERE User = '{{ user_name_1 }}'
|
||||||
|
AND Host = 'localhost'
|
||||||
|
AND max_questions = 10
|
||||||
|
AND max_statement_time = 1
|
||||||
|
register: result
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that rowcount is 1 with MAX_STATEMENT_TIME
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result.rowcount[0] == 1
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Try to set the same limits with MAX_STATEMENT_TIME again in check mode
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
password: '{{ user_password_1 }}'
|
||||||
|
state: present
|
||||||
|
resource_limits:
|
||||||
|
MAX_QUERIES_PER_HOUR: 10
|
||||||
|
MAX_STATEMENT_TIME: 1
|
||||||
|
check_mode: true
|
||||||
|
register: result
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that set same limits with MAX_STATEMENT_TIME again is not changed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Try to set the same limits with MAX_STATEMENT_TIME again in actual mode
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
password: '{{ user_password_1 }}'
|
||||||
|
state: present
|
||||||
|
resource_limits:
|
||||||
|
MAX_QUERIES_PER_HOUR: 10
|
||||||
|
MAX_STATEMENT_TIME: 1
|
||||||
|
register: result
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert that set same limits with MAX_STATEMENT_TIME again in actual mode is not changed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Change limits with MAX_STATEMENT_TIME
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_1 }}'
|
||||||
|
password: '{{ user_password_1 }}'
|
||||||
|
state: present
|
||||||
|
resource_limits:
|
||||||
|
MAX_QUERIES_PER_HOUR: 5
|
||||||
|
MAX_STATEMENT_TIME: 2
|
||||||
|
register: result
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert limits with MAX_STATEMENT_TIME changed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Get user limits with MAX_STATEMENT_TIME
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query: >
|
||||||
|
SELECT User FROM mysql.user
|
||||||
|
WHERE User = '{{ user_name_1 }}'
|
||||||
|
AND Host = 'localhost'
|
||||||
|
AND max_questions = 5
|
||||||
|
AND max_statement_time = 2
|
||||||
|
register: result
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
- name: Resource limits | Assert limit with MAX_STATEMENT_TIME row count
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result.rowcount[0] == 1
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
when: (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version >= '18') or (ansible_distribution == 'CentOS' and ansible_distribution_major_version >= '8')
|
when: (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version >= '18') or (ansible_distribution == 'CentOS' and ansible_distribution_major_version >= '8')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue