From 952d46a5cd3df0e63e0d465bb90cd17c66859a7e Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 09:58:16 +0200 Subject: [PATCH 01/14] add documentation for new mysql_info users_privs filter --- .../fragments/lie_mysql_info_users_privs.yml | 5 ++ plugins/modules/mysql_info.py | 49 ++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/lie_mysql_info_users_privs.yml diff --git a/changelogs/fragments/lie_mysql_info_users_privs.yml b/changelogs/fragments/lie_mysql_info_users_privs.yml new file mode 100644 index 000000000..ed17a7441 --- /dev/null +++ b/changelogs/fragments/lie_mysql_info_users_privs.yml @@ -0,0 +1,5 @@ +--- + +minor_changes: + + - mysql_info - add filter ``users_privs`` (https://github.com/ansible-collections/community.mysql/pull/572). diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index cb9f029bc..e5ef63a4b 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -19,7 +19,7 @@ description: - Limit the collected information by comma separated string or YAML list. - Allowable values are C(version), C(databases), C(settings), C(global_status), - C(users), C(engines), C(master_status), C(slave_status), C(slave_hosts). + C(users), C(users_privs), C(engines), C(master_status), C(slave_status), C(slave_hosts). - By default, collects all subsets. - You can use '!' before value (for example, C(!settings)) to exclude it from the information. - If you pass including and excluding values to the filter, for example, I(filter=!settings,version), @@ -74,6 +74,9 @@ # Display only databases and users info: # ansible mysql-hosts -m mysql_info -a 'filter=databases,users' +# Display all users privileges: +# ansible mysql-hosts -m mysql_info -a 'filter=users_privs' + # Display only slave status: # ansible standby -m mysql_info -a 'filter=slave_status' @@ -122,6 +125,35 @@ - databases exclude_fields: db_size return_empty_dbs: true + +- name: Clone users on another server - Step 1 + delegate_to: server_source + community.mysql.mysql_info: + filter: + - users_privs + register: result + +# Don't work with sha256_password and cache_sha2_password +- name: Clone users on another server - Step 2 + community.mysql.mysql_user: + name: "{{ item.name }}" + host: "{{ item.host }}" + plugin: "{{ item.plugin | default(omit) }}" + plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" + plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" + tls_require: "{{ item.tls_require | default(omit) }}" + priv: "{{ item.priv | default(omit) }}" + resource_limits: "{{ item.resource_limits | default(omit) }}" + column_case_sensitive: true + state: present + loop: "{{ result.users_privs }}" + loop_control: + label: "{{ item.name }}@{{ item.host }}" + when: + - item.name != 'root' # In case you don't want to import admin accounts + - item.name != 'mariadb.sys' + - item.name != 'mysql' + ''' RETURN = r''' @@ -186,6 +218,21 @@ type: dict sample: - { "localhost": { "root": { "Alter_priv": "Y", "Alter_routine_priv": "Y" } } } +users_privs: + description: + Information about users accounts. The output can be used as an input of the + mysql_user plugin. Useful when migrating accounts to a new server or to + create an inventory. Does not support proxy privileges. Cause issue with + authentications plugins C(sha256_password) and C(caching_sha2_password). + returned: if not excluded by filter + type: dict + sample: + - { "plugin_auth_string": '*1234567', + "name": "user1", + "host": "host.com", + "plugin": "mysql_native_password", + "priv": "db1.*:SELECT/db2.*:SELECT", + "resource_limits": { "MAX_USER_CONNECTIONS": 100 } } engines: description: Information about the server's storage engines. returned: if not excluded by filter From 1886753dfaa8b75395450f76d2fc8deaa81d5124 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 10:11:54 +0200 Subject: [PATCH 02/14] Add integration tests for mysql_info users_privs --- .../tasks/filter_users_privs.yml | 250 ++++++++++++++++++ .../targets/test_mysql_info/tasks/main.yml | 4 + 2 files changed, 254 insertions(+) create mode 100644 tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml b/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml new file mode 100644 index 000000000..08e419117 --- /dev/null +++ b/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml @@ -0,0 +1,250 @@ +--- + +- module_defaults: + community.mysql.mysql_db: &mysql_defaults + login_user: "{{ mysql_user }}" + login_password: "{{ mysql_password }}" + login_host: "{{ mysql_host }}" + login_port: "{{ mysql_primary_port }}" + community.mysql.mysql_query: *mysql_defaults + community.mysql.mysql_info: *mysql_defaults + community.mysql.mysql_user: *mysql_defaults + + block: + + # ================================ Prepare ============================== + - name: Mysql_info users_privs | Create databases + community.mysql.mysql_db: + name: + - users_privs_db + - users_privs_db2 + - users_privs_db3 + state: present + + - name: Mysql_info users_privs | Create tables + community.mysql.mysql_query: + query: + - >- + CREATE TABLE IF NOT EXISTS users_privs_db.t1 + (id int, name varchar(9)) + - >- + CREATE TABLE IF NOT EXISTS users_privs_db.T_UPPER + (id int, name1 varchar(9), NAME2 varchar(9), Name3 varchar(9)) + + # I failed to create a procedure using community.mysql.mysql_query. + # Maybe it's because we must changed the delimiter. + - name: Mysql_info users_privs | Create procedure SQL file + ansible.builtin.template: + src: files/users_privs_create_procedure.sql + dest: /root/create_procedure.sql + owner: root + group: root + mode: '0700' + + - name: Mysql_info users_privs | Create a procedure + community.mysql.mysql_db: + name: all + state: import + target: /root/create_procedure.sql + + # Use a query instead of mysql_user, because we want to caches differences + # at the end and a bug in mysql_user would be invisible to this tests + - name: Mysql_info users_privs | Prepare common tests users + community.mysql.mysql_query: + query: + - >- + CREATE USER users_privs_adm@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - > + GRANT ALL ON *.* to users_privs_adm@'users_privs.com' WITH GRANT + OPTION + + - >- + CREATE USER users_privs_schema@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT SELECT, INSERT, UPDATE, DELETE ON users_privs_db.* TO + users_privs_schema@'users_privs.com' + + - >- + CREATE USER users_privs_table@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT SELECT, INSERT, UPDATE ON users_privs_db.t1 TO + users_privs_table@'users_privs.com' + + - >- + CREATE USER users_privs_col@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + WITH MAX_USER_CONNECTIONS 100 + - >- + GRANT SELECT (id) ON users_privs_db.t1 TO + users_privs_col@'users_privs.com' + + - >- + CREATE USER users_privs_proc@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + WITH MAX_USER_CONNECTIONS 2 MAX_CONNECTIONS_PER_HOUR 60 + - >- + GRANT EXECUTE ON PROCEDURE users_privs_db.get_all_items TO + users_privs_proc@'users_privs.com' + + - >- + CREATE USER users_privs_multi@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT SELECT ON mysql.* TO + users_privs_multi@'users_privs.com' + - >- + GRANT ALL ON users_privs_db.* TO + users_privs_multi@'users_privs.com' + - >- + GRANT ALL ON users_privs_db2.* TO + users_privs_multi@'users_privs.com' + - >- + GRANT ALL ON users_privs_db3.* TO + users_privs_multi@'users_privs.com' + + - >- + CREATE USER users_privs_usage_only@'users_privs.com' IDENTIFIED WITH + mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT USAGE ON *.* TO + users_privs_usage_only@'users_privs.com' + + - >- + CREATE USER users_privs_columns_uppercase@'users_privs.com' + IDENTIFIED WITH mysql_native_password AS + '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT SELECT,UPDATE(name1,NAME2,Name3) ON users_privs_db.T_UPPER TO + users_privs_columns_uppercase@'users_privs.com' + + - name: Mysql_info users_privs | Prepare tests users for MariaDB + community.mysql.mysql_user: + name: "{{ item.name }}" + host: "users_privs.com" + plugin: "{{ item.plugin | default(omit) }}" + plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" + plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" + tls_require: "{{ item.tls_require | default(omit) }}" + priv: "{{ item.priv }}" + resource_limits: "{{ item.resource_limits | default(omit) }}" + column_case_sensitive: true + state: present + loop: + - name: users_privs_socket # Only for MariaDB + priv: + '*.*': 'ALL' + plugin: 'unix_socket' + when: + - db_engine == 'mariadb' + + - name: Mysql_info users_privs | Prepare tests users for MySQL + community.mysql.mysql_user: + name: "{{ item.name }}" + host: "users_privs.com" + plugin: "{{ item.plugin | default(omit) }}" + plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" + plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" + tls_require: "{{ item.tls_require | default(omit) }}" + priv: "{{ item.priv }}" + resource_limits: "{{ item.resource_limits | default(omit) }}" + column_case_sensitive: true + state: present + loop: + - name: users_privs_sha256 # Only for MySQL + priv: + '*.*': 'ALL' + plugin_auth_string: + '$5$/=') + + # ================================== Tests ============================== + + - name: Mysql_info users_privs | Collect users_privs + community.mysql.mysql_info: + filter: + - users_privs + register: result + + - name: Recreate users from mysql_info users_privs result + community.mysql.mysql_user: + name: "{{ item.name }}" + host: "{{ item.host }}" + plugin: "{{ item.plugin | default(omit) }}" + plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" + plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" + tls_require: "{{ item.tls_require | default(omit) }}" + priv: "{{ item.priv | default(omit) }}" + resource_limits: "{{ item.resource_limits | default(omit) }}" + column_case_sensitive: true + state: present + loop: "{{ result.users_privs }}" + loop_control: + label: "{{ item.name }}@{{ item.host }}" + register: recreate_users_result + failed_when: + - recreate_users_result is changed + when: + - item.name != 'root' + - item.name != 'mysql' + - item.name != 'mariadb.sys' + - item.name != 'mysql.sys' + - item.name != 'mysql.infoschema' + + + # ================================== Cleanup ============================ + + - name: Mysql_info users_privs | Cleanup users_privs + community.mysql.mysql_user: + name: "{{ item }}" + host: "users_privs.com" + column_case_sensitive: true + state: absent + loop: + - users_privs_adm + - users_privs_schema + - users_privs_table + - users_privs_col + - users_privs_proc + - users_privs_usage_only + - users_privs_columns_uppercase + + - name: Mysql_info users_privs | Cleanup databases + community.mysql.mysql_db: + name: + - users_privs_db + - users_privs_db2 + - users_privs_db3 + state: absent + + - name: Mysql_info users_privs | Cleanup sql file for the procedure + ansible.builtin.file: + path: /root/create_procedure.sql + state: absent diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index be367f068..10e1917ca 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -219,3 +219,7 @@ assert: that: - result.databases.allviews.size == 0 + + - name: Import tasks file to tests users_privs filter + ansible.builtin.import_tasks: + file: filter_users_privs.yml From 3efe61f50c936856d654a9d88f48969c9947ba0b Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 11:43:02 +0200 Subject: [PATCH 03/14] fix list parsing when cursor come from mysql_info Mysql_info use a DictCursor and mysql_user a normal cursor. --- plugins/module_utils/user.py | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index e1d80ab27..b3c13ce8b 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -115,7 +115,13 @@ def get_grants(cursor, user, host): def get_existing_authentication(cursor, user): # Return the plugin and auth_string if there is exactly one distinct existing plugin and auth_string. cursor.execute("SELECT VERSION()") - if 'mariadb' in cursor.fetchone()[0].lower(): + srv_type = cursor.fetchone() + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(srv_type, dict): + srv_type = list(srv_type.values()) + + if 'mariadb' in srv_type[0].lower(): # before MariaDB 10.2.19 and 10.3.11, "password" and "authentication_string" can differ # when using mysql_native_password cursor.execute("""select plugin, auth from ( @@ -127,8 +133,17 @@ def get_existing_authentication(cursor, user): cursor.execute("""select plugin, authentication_string as auth from mysql.user where user=%(user)s group by plugin, authentication_string limit 2""", {'user': user}) rows = cursor.fetchall() - if len(rows) == 1: - return {'plugin': rows[0][0], 'auth_string': rows[0][1]} + + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(rows, dict): + rows = list(rows.values()) + + if isinstance(rows[0], tuple): + return {'plugin': rows[0][0], 'plugin_auth_string': rows[0][1]} + + if isinstance(rows[0], dict): + return {'plugin': rows[0].get('plugin'), 'plugin_auth_string': rows[0].get('auth')} return None @@ -478,6 +493,12 @@ def pick(x): return x for grant in grants: + + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(grant, dict): + grant = list(grant.values()) + if not maria_role: res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0]) else: @@ -777,6 +798,11 @@ def get_resource_limits(cursor, user, host): cursor.execute(query, (user, host)) res = cursor.fetchone() + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(res, dict): + res = list(res.values()) + if not res: return None @@ -788,11 +814,22 @@ def get_resource_limits(cursor, user, host): } cursor.execute("SELECT VERSION()") - if 'mariadb' in cursor.fetchone()[0].lower(): + srv_type = cursor.fetchone() + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(srv_type, dict): + srv_type = list(srv_type.values()) + + if 'mariadb' in srv_type[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() + + # Mysql_info use a DictCursor so we must convert back to a list + # otherwise we get KeyError 0 + if isinstance(res_max_statement_time, dict): + res_max_statement_time = list(res_max_statement_time.values()) current_limits['MAX_STATEMENT_TIME'] = res_max_statement_time[0] return current_limits From e607ce19743a41b5627f39038fc90fd558d0150e Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 10:01:33 +0200 Subject: [PATCH 04/14] add method to get all users privileges --- plugins/modules/mysql_info.py | 90 +++++++++++++++++++ .../files/users_privs_create_procedure.sql | 7 ++ 2 files changed, 97 insertions(+) create mode 100644 tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index e5ef63a4b..16cd65b1f 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -285,6 +285,12 @@ get_connector_name, get_connector_version, ) + +from ansible_collections.community.mysql.plugins.module_utils.user import ( + privileges_get, + get_resource_limits, + get_existing_authentication, +) from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native @@ -321,6 +327,7 @@ def __init__(self, module, cursor): 'global_status': {}, 'engines': {}, 'users': {}, + 'users_privs': {}, 'master_status': {}, 'slave_hosts': {}, 'slave_status': {}, @@ -389,6 +396,9 @@ def __collect(self, exclude_fields, return_empty_dbs, wanted): if 'users' in wanted: self.__get_users() + if 'users_privs' in wanted: + self.__get_users_privs() + if 'master_status' in wanted: self.__get_master_status() @@ -527,6 +537,86 @@ def __get_users(self): if vname not in ('Host', 'User'): self.info['users'][host][user][vname] = self.__convert(val) + def __get_users_privs(self): + """Get user privileges. + + Query the server to get all the users and return a string + of privileges that can be used by the mysql_user plugin. + For instance: + + "users_privs": [ + { + "host": "users_privs.com", + "priv": "*.*: ALL,GRANT", + "name": "users_privs_adm" + }, + { + "host": "users_privs.com", + "priv": "`mysql`.*: SELECT/`users_privs_db`.*: SELECT", + "name": "users_privs_multi" + } + ] + """ + res = self.__exec_sql('SELECT * FROM mysql.user') + if not res: + return None + + output = list() + for line in res: + user = line['User'] + host = line['Host'] + + user_priv = privileges_get(self.cursor, user, host) + + if not user_priv: + self.module.warn("No privileges found for %s on host %s" % (user, host)) + continue + + priv_string = list() + for db_table, priv in user_priv.items(): + # Proxy privileges are hard to work with because of different quotes or + # backticks like ''@'', ''@'%' or even ``@``. In addition, MySQL will + # forbid you to grant a proxy privileges through TCP. + if set(priv) == {'PROXY', 'GRANT'} or set(priv) == {'PROXY'}: + continue + + unquote_db_table = db_table.replace('`', '').replace("'", '') + priv_string.append('%s:%s' % (unquote_db_table, ','.join(priv))) + + # Only keep *.* USAGE if it's the only user privilege given + if len(priv_string) > 1 and '*.*:USAGE' in priv_string: + priv_string.remove('*.*:USAGE') + + resource_limits = get_resource_limits(self.cursor, user, host) + + copy_ressource_limits = dict.copy(resource_limits) + output_dict = { + 'name': user, + 'host': host, + 'priv': '/'.join(priv_string), + 'resource_limits': copy_ressource_limits, + } + + # Prevent returning a resource limit if empty + if resource_limits: + for key, value in resource_limits.items(): + if value == 0: + del output_dict['resource_limits'][key] + if len(output_dict['resource_limits']) == 0: + del output_dict['resource_limits'] + + authentications = get_existing_authentication(self.cursor, user) + if authentications: + output_dict.update(authentications) + + # TODO password_option + # TODO lock_option + # but both are not supported by mysql_user atm. So no point yet. + + output.append(output_dict) + + self.info['users_privs'] = output + def __get_databases(self, exclude_fields, return_empty_dbs): """Get info about databases.""" if not exclude_fields: diff --git a/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql b/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql new file mode 100644 index 000000000..1f38020f0 --- /dev/null +++ b/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql @@ -0,0 +1,7 @@ +DELIMITER // +DROP PROCEDURE IF EXISTS users_privs_db.get_all_items; +CREATE PROCEDURE users_privs_db.get_all_items() +BEGIN +SELECT * from users_privs_db.t1; +END // +DELIMITER ; From 154d88084687db594f8ad71c571bb7ff05bae5e6 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 13:46:27 +0200 Subject: [PATCH 05/14] fix case when a account as same user but different host and password --- plugins/module_utils/user.py | 14 +++++----- plugins/modules/mysql_info.py | 2 +- .../tasks/filter_users_privs.yml | 27 +++++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index b3c13ce8b..a88b32e72 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -112,7 +112,7 @@ def get_grants(cursor, user, host): return grants.split(", ") -def get_existing_authentication(cursor, user): +def get_existing_authentication(cursor, user, host): # Return the plugin and auth_string if there is exactly one distinct existing plugin and auth_string. cursor.execute("SELECT VERSION()") srv_type = cursor.fetchone() @@ -126,12 +126,14 @@ def get_existing_authentication(cursor, user): # when using mysql_native_password cursor.execute("""select plugin, auth from ( select plugin, password as auth from mysql.user where user=%(user)s + and host=%(host)s union select plugin, authentication_string as auth from mysql.user where user=%(user)s - ) x group by plugin, auth limit 2 - """, {'user': user}) + and host=%(host)s) x group by plugin, auth limit 2 + """, {'user': user, 'host': host}) else: - cursor.execute("""select plugin, authentication_string as auth from mysql.user where user=%(user)s - group by plugin, authentication_string limit 2""", {'user': user}) + cursor.execute("""select plugin, authentication_string as auth + from mysql.user where user=%(user)s and host=%(host)s + group by plugin, authentication_string limit 2""", {'user': user, 'host': host}) rows = cursor.fetchall() # Mysql_info use a DictCursor so we must convert back to a list @@ -164,7 +166,7 @@ def user_add(cursor, user, host, host_all, password, encrypted, used_existing_password = False if reuse_existing_password: - existing_auth = get_existing_authentication(cursor, user) + existing_auth = get_existing_authentication(cursor, user, host) if existing_auth: plugin = existing_auth['plugin'] plugin_hash_string = existing_auth['auth_string'] diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 16cd65b1f..03e5ea6fc 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -605,7 +605,7 @@ def __get_users_privs(self): if len(output_dict['resource_limits']) == 0: del output_dict['resource_limits'] - authentications = get_existing_authentication(self.cursor, user) + authentications = get_existing_authentication(self.cursor, user, host) if authentications: output_dict.update(authentications) diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml b/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml index 08e419117..73a09d306 100644 --- a/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml +++ b/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml @@ -120,6 +120,33 @@ GRANT SELECT,UPDATE(name1,NAME2,Name3) ON users_privs_db.T_UPPER TO users_privs_columns_uppercase@'users_privs.com' + - >- + CREATE USER users_privs_multi_hosts@'%' + IDENTIFIED WITH mysql_native_password AS + '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'%' + + - >- + CREATE USER users_privs_multi_hosts@'localhost' + IDENTIFIED WITH mysql_native_password AS + '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - >- + GRANT SELECT ON users_privs_db.* TO + users_privs_multi_hosts@'localhost' + + - >- + CREATE USER users_privs_multi_hosts@'host1' + IDENTIFIED WITH mysql_native_password AS + '*6C387FC3893DBA1E3BA155E74754DA6682D04747' + - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'host1' + + # Different password than the others users_privs_multi_hosts + - >- + CREATE USER users_privs_multi_hosts@'host2' + IDENTIFIED WITH mysql_native_password AS + '*CB3326D5279DE7915FE5D743232165EE887883CA' + - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'host2' + - name: Mysql_info users_privs | Prepare tests users for MariaDB community.mysql.mysql_user: name: "{{ item.name }}" From 509099e21109cbbc071a4a87db929a9962a4c6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Thu, 12 Oct 2023 15:15:03 +0200 Subject: [PATCH 06/14] document example with tasks grouped in a block Co-authored-by: Andrew Klychkov --- plugins/modules/mysql_info.py | 59 ++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 03e5ea6fc..a566501ba 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -126,34 +126,37 @@ exclude_fields: db_size return_empty_dbs: true -- name: Clone users on another server - Step 1 - delegate_to: server_source - community.mysql.mysql_info: - filter: - - users_privs - register: result - -# Don't work with sha256_password and cache_sha2_password -- name: Clone users on another server - Step 2 - community.mysql.mysql_user: - name: "{{ item.name }}" - host: "{{ item.host }}" - plugin: "{{ item.plugin | default(omit) }}" - plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" - plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" - tls_require: "{{ item.tls_require | default(omit) }}" - priv: "{{ item.priv | default(omit) }}" - resource_limits: "{{ item.resource_limits | default(omit) }}" - column_case_sensitive: true - state: present - loop: "{{ result.users_privs }}" - loop_control: - label: "{{ item.name }}@{{ item.host }}" - when: - - item.name != 'root' # In case you don't want to import admin accounts - - item.name != 'mariadb.sys' - - item.name != 'mysql' - +- name: Clone users from one server to another + block: + # Step 1 + - name: Fetch information from a source server + delegate_to: server_source + community.mysql.mysql_info: + filter: + - users_privs + register: result + + # Step 2 + # Don't work with sha256_password and cache_sha2_password + - name: Clone users fetched in a previous task to a target server + community.mysql.mysql_user: + name: "{{ item.name }}" + host: "{{ item.host }}" + plugin: "{{ item.plugin | default(omit) }}" + plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" + plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" + tls_require: "{{ item.tls_require | default(omit) }}" + priv: "{{ item.priv | default(omit) }}" + resource_limits: "{{ item.resource_limits | default(omit) }}" + column_case_sensitive: true + state: present + loop: "{{ result.users_privs }}" + loop_control: + label: "{{ item.name }}@{{ item.host }}" + when: + - item.name != 'root' # In case you don't want to import admin accounts + - item.name != 'mariadb.sys' + - item.name != 'mysql' ''' RETURN = r''' From 71abdd7567c848d5ff4548d993377ab0d0887581 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 15:23:07 +0200 Subject: [PATCH 07/14] document why certain authentications plugins cause issues --- plugins/modules/mysql_info.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index a566501ba..0125a6a03 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -223,10 +223,14 @@ - { "localhost": { "root": { "Alter_priv": "Y", "Alter_routine_priv": "Y" } } } users_privs: description: - Information about users accounts. The output can be used as an input of the - mysql_user plugin. Useful when migrating accounts to a new server or to - create an inventory. Does not support proxy privileges. Cause issue with - authentications plugins C(sha256_password) and C(caching_sha2_password). + - Information about users accounts. + - The output can be used as an input of the M(community.mysql.mysql_user) plugin. + - Useful when migrating accounts to another server or to create an inventory. + - Does not support proxy privileges. If an account has proxy privileges, they won't appear in the output. + - Causes issues with authentications plugins C(sha256_password) and C(caching_sha2_password). + If the output is fed to M(community.mysql.mysql_user), the + ``plugin_auth_string`` will most likely be unreadable due to non-binary + characters. returned: if not excluded by filter type: dict sample: From db43c34f63239b3b03ff6a435c7d68919fc36496 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 16:44:14 +0200 Subject: [PATCH 08/14] change filter name to user_accounts --- .../fragments/lie_mysql_info_users_privs.yml | 2 +- plugins/modules/mysql_info.py | 34 ++-- .../files/users_privs_create_procedure.sql | 6 +- ...ers_privs.yml => filter_user_accounts.yml} | 150 +++++++++--------- .../targets/test_mysql_info/tasks/main.yml | 4 +- 5 files changed, 98 insertions(+), 98 deletions(-) rename tests/integration/targets/test_mysql_info/tasks/{filter_users_privs.yml => filter_user_accounts.yml} (61%) diff --git a/changelogs/fragments/lie_mysql_info_users_privs.yml b/changelogs/fragments/lie_mysql_info_users_privs.yml index ed17a7441..a6cbad4aa 100644 --- a/changelogs/fragments/lie_mysql_info_users_privs.yml +++ b/changelogs/fragments/lie_mysql_info_users_privs.yml @@ -2,4 +2,4 @@ minor_changes: - - mysql_info - add filter ``users_privs`` (https://github.com/ansible-collections/community.mysql/pull/572). + - mysql_info - add filter ``user_accounts`` (https://github.com/ansible-collections/community.mysql/pull/572). diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 0125a6a03..71f3c59c5 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -19,7 +19,7 @@ description: - Limit the collected information by comma separated string or YAML list. - Allowable values are C(version), C(databases), C(settings), C(global_status), - C(users), C(users_privs), C(engines), C(master_status), C(slave_status), C(slave_hosts). + C(users), C(user_accounts), C(engines), C(master_status), C(slave_status), C(slave_hosts). - By default, collects all subsets. - You can use '!' before value (for example, C(!settings)) to exclude it from the information. - If you pass including and excluding values to the filter, for example, I(filter=!settings,version), @@ -75,7 +75,7 @@ # ansible mysql-hosts -m mysql_info -a 'filter=databases,users' # Display all users privileges: -# ansible mysql-hosts -m mysql_info -a 'filter=users_privs' +# ansible mysql-hosts -m mysql_info -a 'filter=user_accounts' # Display only slave status: # ansible standby -m mysql_info -a 'filter=slave_status' @@ -133,7 +133,7 @@ delegate_to: server_source community.mysql.mysql_info: filter: - - users_privs + - user_accounts register: result # Step 2 @@ -150,7 +150,7 @@ resource_limits: "{{ item.resource_limits | default(omit) }}" column_case_sensitive: true state: present - loop: "{{ result.users_privs }}" + loop: "{{ result.user_accounts }}" loop_control: label: "{{ item.name }}@{{ item.host }}" when: @@ -221,7 +221,7 @@ type: dict sample: - { "localhost": { "root": { "Alter_priv": "Y", "Alter_routine_priv": "Y" } } } -users_privs: +user_accounts: description: - Information about users accounts. - The output can be used as an input of the M(community.mysql.mysql_user) plugin. @@ -334,7 +334,7 @@ def __init__(self, module, cursor): 'global_status': {}, 'engines': {}, 'users': {}, - 'users_privs': {}, + 'user_accounts': {}, 'master_status': {}, 'slave_hosts': {}, 'slave_status': {}, @@ -403,8 +403,8 @@ def __collect(self, exclude_fields, return_empty_dbs, wanted): if 'users' in wanted: self.__get_users() - if 'users_privs' in wanted: - self.__get_users_privs() + if 'user_accounts' in wanted: + self.__get_user_accounts() if 'master_status' in wanted: self.__get_master_status() @@ -544,23 +544,23 @@ def __get_users(self): if vname not in ('Host', 'User'): self.info['users'][host][user][vname] = self.__convert(val) - def __get_users_privs(self): - """Get user privileges. + def __get_user_accounts(self): + """Get user privileges, passwords, resources_limits, ... Query the server to get all the users and return a string of privileges that can be used by the mysql_user plugin. For instance: - "users_privs": [ + "user_accounts": [ { - "host": "users_privs.com", + "host": "user_accounts.com", "priv": "*.*: ALL,GRANT", - "name": "users_privs_adm" + "name": "user_accounts_adm" }, { - "host": "users_privs.com", - "priv": "`mysql`.*: SELECT/`users_privs_db`.*: SELECT", - "name": "users_privs_multi" + "host": "user_accounts.com", + "priv": "`mysql`.*: SELECT/`user_accounts_db`.*: SELECT", + "name": "user_accounts_multi" } ] """ @@ -622,7 +622,7 @@ def __get_users_privs(self): output.append(output_dict) - self.info['users_privs'] = output + self.info['user_accounts'] = output def __get_databases(self, exclude_fields, return_empty_dbs): """Get info about databases.""" diff --git a/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql b/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql index 1f38020f0..21fb3f482 100644 --- a/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql +++ b/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql @@ -1,7 +1,7 @@ DELIMITER // -DROP PROCEDURE IF EXISTS users_privs_db.get_all_items; -CREATE PROCEDURE users_privs_db.get_all_items() +DROP PROCEDURE IF EXISTS user_accounts_db.get_all_items; +CREATE PROCEDURE user_accounts_db.get_all_items() BEGIN -SELECT * from users_privs_db.t1; +SELECT * from user_accounts_db.t1; END // DELIMITER ; diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml b/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml similarity index 61% rename from tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml rename to tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml index 73a09d306..1464822be 100644 --- a/tests/integration/targets/test_mysql_info/tasks/filter_users_privs.yml +++ b/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml @@ -13,35 +13,35 @@ block: # ================================ Prepare ============================== - - name: Mysql_info users_privs | Create databases + - name: Mysql_info user_accounts | Create databases community.mysql.mysql_db: name: - - users_privs_db - - users_privs_db2 - - users_privs_db3 + - user_accounts_db + - user_accounts_db2 + - user_accounts_db3 state: present - - name: Mysql_info users_privs | Create tables + - name: Mysql_info user_accounts | Create tables community.mysql.mysql_query: query: - >- - CREATE TABLE IF NOT EXISTS users_privs_db.t1 + CREATE TABLE IF NOT EXISTS user_accounts_db.t1 (id int, name varchar(9)) - >- - CREATE TABLE IF NOT EXISTS users_privs_db.T_UPPER + CREATE TABLE IF NOT EXISTS user_accounts_db.T_UPPER (id int, name1 varchar(9), NAME2 varchar(9), Name3 varchar(9)) # I failed to create a procedure using community.mysql.mysql_query. # Maybe it's because we must changed the delimiter. - - name: Mysql_info users_privs | Create procedure SQL file + - name: Mysql_info user_accounts | Create procedure SQL file ansible.builtin.template: - src: files/users_privs_create_procedure.sql + src: files/user_accounts_create_procedure.sql dest: /root/create_procedure.sql owner: root group: root mode: '0700' - - name: Mysql_info users_privs | Create a procedure + - name: Mysql_info user_accounts | Create a procedure community.mysql.mysql_db: name: all state: import @@ -49,108 +49,108 @@ # Use a query instead of mysql_user, because we want to caches differences # at the end and a bug in mysql_user would be invisible to this tests - - name: Mysql_info users_privs | Prepare common tests users + - name: Mysql_info user_accounts | Prepare common tests users community.mysql.mysql_query: query: - >- - CREATE USER users_privs_adm@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_adm@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - > - GRANT ALL ON *.* to users_privs_adm@'users_privs.com' WITH GRANT + GRANT ALL ON *.* to user_accounts_adm@'user_accounts.com' WITH GRANT OPTION - >- - CREATE USER users_privs_schema@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_schema@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT, INSERT, UPDATE, DELETE ON users_privs_db.* TO - users_privs_schema@'users_privs.com' + GRANT SELECT, INSERT, UPDATE, DELETE ON user_accounts_db.* TO + user_accounts_schema@'user_accounts.com' - >- - CREATE USER users_privs_table@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_table@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT, INSERT, UPDATE ON users_privs_db.t1 TO - users_privs_table@'users_privs.com' + GRANT SELECT, INSERT, UPDATE ON user_accounts_db.t1 TO + user_accounts_table@'user_accounts.com' - >- - CREATE USER users_privs_col@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_col@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' WITH MAX_USER_CONNECTIONS 100 - >- - GRANT SELECT (id) ON users_privs_db.t1 TO - users_privs_col@'users_privs.com' + GRANT SELECT (id) ON user_accounts_db.t1 TO + user_accounts_col@'user_accounts.com' - >- - CREATE USER users_privs_proc@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_proc@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' WITH MAX_USER_CONNECTIONS 2 MAX_CONNECTIONS_PER_HOUR 60 - >- - GRANT EXECUTE ON PROCEDURE users_privs_db.get_all_items TO - users_privs_proc@'users_privs.com' + GRANT EXECUTE ON PROCEDURE user_accounts_db.get_all_items TO + user_accounts_proc@'user_accounts.com' - >- - CREATE USER users_privs_multi@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_multi@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- GRANT SELECT ON mysql.* TO - users_privs_multi@'users_privs.com' + user_accounts_multi@'user_accounts.com' - >- - GRANT ALL ON users_privs_db.* TO - users_privs_multi@'users_privs.com' + GRANT ALL ON user_accounts_db.* TO + user_accounts_multi@'user_accounts.com' - >- - GRANT ALL ON users_privs_db2.* TO - users_privs_multi@'users_privs.com' + GRANT ALL ON user_accounts_db2.* TO + user_accounts_multi@'user_accounts.com' - >- - GRANT ALL ON users_privs_db3.* TO - users_privs_multi@'users_privs.com' + GRANT ALL ON user_accounts_db3.* TO + user_accounts_multi@'user_accounts.com' - >- - CREATE USER users_privs_usage_only@'users_privs.com' IDENTIFIED WITH + CREATE USER user_accounts_usage_only@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- GRANT USAGE ON *.* TO - users_privs_usage_only@'users_privs.com' + user_accounts_usage_only@'user_accounts.com' - >- - CREATE USER users_privs_columns_uppercase@'users_privs.com' + CREATE USER user_accounts_columns_uppercase@'user_accounts.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT,UPDATE(name1,NAME2,Name3) ON users_privs_db.T_UPPER TO - users_privs_columns_uppercase@'users_privs.com' + GRANT SELECT,UPDATE(name1,NAME2,Name3) ON user_accounts_db.T_UPPER TO + user_accounts_columns_uppercase@'user_accounts.com' - >- - CREATE USER users_privs_multi_hosts@'%' + CREATE USER user_accounts_multi_hosts@'%' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'%' + - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'%' - >- - CREATE USER users_privs_multi_hosts@'localhost' + CREATE USER user_accounts_multi_hosts@'localhost' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT ON users_privs_db.* TO - users_privs_multi_hosts@'localhost' + GRANT SELECT ON user_accounts_db.* TO + user_accounts_multi_hosts@'localhost' - >- - CREATE USER users_privs_multi_hosts@'host1' + CREATE USER user_accounts_multi_hosts@'host1' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'host1' + - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'host1' - # Different password than the others users_privs_multi_hosts + # Different password than the others user_accounts_multi_hosts - >- - CREATE USER users_privs_multi_hosts@'host2' + CREATE USER user_accounts_multi_hosts@'host2' IDENTIFIED WITH mysql_native_password AS '*CB3326D5279DE7915FE5D743232165EE887883CA' - - GRANT SELECT ON users_privs_db.* TO users_privs_multi_hosts@'host2' + - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'host2' - - name: Mysql_info users_privs | Prepare tests users for MariaDB + - name: Mysql_info user_accounts | Prepare tests users for MariaDB community.mysql.mysql_user: name: "{{ item.name }}" - host: "users_privs.com" + host: "user_accounts.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -160,17 +160,17 @@ column_case_sensitive: true state: present loop: - - name: users_privs_socket # Only for MariaDB + - name: user_accounts_socket # Only for MariaDB priv: '*.*': 'ALL' plugin: 'unix_socket' when: - db_engine == 'mariadb' - - name: Mysql_info users_privs | Prepare tests users for MySQL + - name: Mysql_info user_accounts | Prepare tests users for MySQL community.mysql.mysql_user: name: "{{ item.name }}" - host: "users_privs.com" + host: "user_accounts.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -180,7 +180,7 @@ column_case_sensitive: true state: present loop: - - name: users_privs_sha256 # Only for MySQL + - name: user_accounts_sha256 # Only for MySQL priv: '*.*': 'ALL' plugin_auth_string: @@ -189,10 +189,10 @@ when: - db_engine == 'mysql' - - name: Mysql_info users_privs | Prepare tests users for MySQL 8+ + - name: Mysql_info user_accounts | Prepare tests users for MySQL 8+ community.mysql.mysql_user: name: "{{ item.name }}" - host: "users_privs.com" + host: "user_accounts.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -202,7 +202,7 @@ column_case_sensitive: true state: present loop: - - name: users_privs_caching_sha2 # Only for MySQL 8+ + - name: user_accounts_caching_sha2 # Only for MySQL 8+ priv: '*.*': 'ALL' plugin_auth_string: @@ -214,13 +214,13 @@ # ================================== Tests ============================== - - name: Mysql_info users_privs | Collect users_privs + - name: Mysql_info user_accounts | Collect user_accounts community.mysql.mysql_info: filter: - - users_privs + - user_accounts register: result - - name: Recreate users from mysql_info users_privs result + - name: Recreate users from mysql_info user_accounts result community.mysql.mysql_user: name: "{{ item.name }}" host: "{{ item.host }}" @@ -232,7 +232,7 @@ resource_limits: "{{ item.resource_limits | default(omit) }}" column_case_sensitive: true state: present - loop: "{{ result.users_privs }}" + loop: "{{ result.user_accounts }}" loop_control: label: "{{ item.name }}@{{ item.host }}" register: recreate_users_result @@ -248,30 +248,30 @@ # ================================== Cleanup ============================ - - name: Mysql_info users_privs | Cleanup users_privs + - name: Mysql_info user_accounts | Cleanup user_accounts community.mysql.mysql_user: name: "{{ item }}" - host: "users_privs.com" + host: "user_accounts.com" column_case_sensitive: true state: absent loop: - - users_privs_adm - - users_privs_schema - - users_privs_table - - users_privs_col - - users_privs_proc - - users_privs_usage_only - - users_privs_columns_uppercase + - user_accounts_adm + - user_accounts_schema + - user_accounts_table + - user_accounts_col + - user_accounts_proc + - user_accounts_usage_only + - user_accounts_columns_uppercase - - name: Mysql_info users_privs | Cleanup databases + - name: Mysql_info user_accounts | Cleanup databases community.mysql.mysql_db: name: - - users_privs_db - - users_privs_db2 - - users_privs_db3 + - user_accounts_db + - user_accounts_db2 + - user_accounts_db3 state: absent - - name: Mysql_info users_privs | Cleanup sql file for the procedure + - name: Mysql_info user_accounts | Cleanup sql file for the procedure ansible.builtin.file: path: /root/create_procedure.sql state: absent diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index 10e1917ca..38408fe6f 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -220,6 +220,6 @@ that: - result.databases.allviews.size == 0 - - name: Import tasks file to tests users_privs filter + - name: Import tasks file to tests user_accounts filter ansible.builtin.import_tasks: - file: filter_users_privs.yml + file: filter_user_accounts.yml From 5d305d3f81c6382e99f54333d52ebbb504dfd836 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Thu, 12 Oct 2023 17:02:22 +0200 Subject: [PATCH 09/14] fix filename --- ...vs_create_procedure.sql => user_accounts_create_procedure.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/integration/targets/test_mysql_info/files/{users_privs_create_procedure.sql => user_accounts_create_procedure.sql} (100%) diff --git a/tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql b/tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql similarity index 100% rename from tests/integration/targets/test_mysql_info/files/users_privs_create_procedure.sql rename to tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql From f1e7d960aa6bafdaeb2a2b657790da83519c229f Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Fri, 13 Oct 2023 08:54:49 +0200 Subject: [PATCH 10/14] add all tests accounts to the teardown task --- .../targets/test_mysql_info/tasks/filter_user_accounts.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml b/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml index 1464822be..ecf46b2dd 100644 --- a/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml +++ b/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml @@ -251,7 +251,7 @@ - name: Mysql_info user_accounts | Cleanup user_accounts community.mysql.mysql_user: name: "{{ item }}" - host: "user_accounts.com" + host_all: true column_case_sensitive: true state: absent loop: @@ -260,8 +260,11 @@ - user_accounts_table - user_accounts_col - user_accounts_proc + - user_accounts_multi + - user_accounts_db - user_accounts_usage_only - user_accounts_columns_uppercase + - user_accounts_multi_hosts - name: Mysql_info user_accounts | Cleanup databases community.mysql.mysql_db: From 070109e70d55d87eeeb3b3b30c94a969d88f21c5 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Fri, 13 Oct 2023 08:55:21 +0200 Subject: [PATCH 11/14] add version_added for user_accounts to the documentation --- plugins/modules/mysql_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 71f3c59c5..2619ce6de 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -240,6 +240,7 @@ "plugin": "mysql_native_password", "priv": "db1.*:SELECT/db2.*:SELECT", "resource_limits": { "MAX_USER_CONNECTIONS": 100 } } + version_added: '3.8.0' engines: description: Information about the server's storage engines. returned: if not excluded by filter From e61777cffbca5cc8313f5422c8e54455d7c8096c Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Fri, 13 Oct 2023 15:00:21 +0200 Subject: [PATCH 12/14] change filter name to users_info --- .../fragments/lie_mysql_info_users_info.yml | 5 + .../fragments/lie_mysql_info_users_privs.yml | 5 - plugins/modules/mysql_info.py | 32 ++-- .../files/user_accounts_create_procedure.sql | 7 - .../files/users_info_create_procedure.sql | 7 + ...ser_accounts.yml => filter_users_info.yml} | 154 +++++++++--------- .../targets/test_mysql_info/tasks/main.yml | 4 +- 7 files changed, 107 insertions(+), 107 deletions(-) create mode 100644 changelogs/fragments/lie_mysql_info_users_info.yml delete mode 100644 changelogs/fragments/lie_mysql_info_users_privs.yml delete mode 100644 tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql create mode 100644 tests/integration/targets/test_mysql_info/files/users_info_create_procedure.sql rename tests/integration/targets/test_mysql_info/tasks/{filter_user_accounts.yml => filter_users_info.yml} (60%) diff --git a/changelogs/fragments/lie_mysql_info_users_info.yml b/changelogs/fragments/lie_mysql_info_users_info.yml new file mode 100644 index 000000000..56c83b272 --- /dev/null +++ b/changelogs/fragments/lie_mysql_info_users_info.yml @@ -0,0 +1,5 @@ +--- + +minor_changes: + + - mysql_info - add filter ``users_info`` (https://github.com/ansible-collections/community.mysql/pull/572). diff --git a/changelogs/fragments/lie_mysql_info_users_privs.yml b/changelogs/fragments/lie_mysql_info_users_privs.yml deleted file mode 100644 index a6cbad4aa..000000000 --- a/changelogs/fragments/lie_mysql_info_users_privs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- - -minor_changes: - - - mysql_info - add filter ``user_accounts`` (https://github.com/ansible-collections/community.mysql/pull/572). diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 2619ce6de..da7dca0dc 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -19,7 +19,7 @@ description: - Limit the collected information by comma separated string or YAML list. - Allowable values are C(version), C(databases), C(settings), C(global_status), - C(users), C(user_accounts), C(engines), C(master_status), C(slave_status), C(slave_hosts). + C(users), C(users_info), C(engines), C(master_status), C(slave_status), C(slave_hosts). - By default, collects all subsets. - You can use '!' before value (for example, C(!settings)) to exclude it from the information. - If you pass including and excluding values to the filter, for example, I(filter=!settings,version), @@ -75,7 +75,7 @@ # ansible mysql-hosts -m mysql_info -a 'filter=databases,users' # Display all users privileges: -# ansible mysql-hosts -m mysql_info -a 'filter=user_accounts' +# ansible mysql-hosts -m mysql_info -a 'filter=users_info' # Display only slave status: # ansible standby -m mysql_info -a 'filter=slave_status' @@ -133,7 +133,7 @@ delegate_to: server_source community.mysql.mysql_info: filter: - - user_accounts + - users_info register: result # Step 2 @@ -150,7 +150,7 @@ resource_limits: "{{ item.resource_limits | default(omit) }}" column_case_sensitive: true state: present - loop: "{{ result.user_accounts }}" + loop: "{{ result.users_info }}" loop_control: label: "{{ item.name }}@{{ item.host }}" when: @@ -221,7 +221,7 @@ type: dict sample: - { "localhost": { "root": { "Alter_priv": "Y", "Alter_routine_priv": "Y" } } } -user_accounts: +users_info: description: - Information about users accounts. - The output can be used as an input of the M(community.mysql.mysql_user) plugin. @@ -335,7 +335,7 @@ def __init__(self, module, cursor): 'global_status': {}, 'engines': {}, 'users': {}, - 'user_accounts': {}, + 'users_info': {}, 'master_status': {}, 'slave_hosts': {}, 'slave_status': {}, @@ -404,8 +404,8 @@ def __collect(self, exclude_fields, return_empty_dbs, wanted): if 'users' in wanted: self.__get_users() - if 'user_accounts' in wanted: - self.__get_user_accounts() + if 'users_info' in wanted: + self.__get_users_info() if 'master_status' in wanted: self.__get_master_status() @@ -545,23 +545,23 @@ def __get_users(self): if vname not in ('Host', 'User'): self.info['users'][host][user][vname] = self.__convert(val) - def __get_user_accounts(self): + def __get_users_info(self): """Get user privileges, passwords, resources_limits, ... Query the server to get all the users and return a string of privileges that can be used by the mysql_user plugin. For instance: - "user_accounts": [ + "users_info": [ { - "host": "user_accounts.com", + "host": "users_info.com", "priv": "*.*: ALL,GRANT", - "name": "user_accounts_adm" + "name": "users_info_adm" }, { - "host": "user_accounts.com", - "priv": "`mysql`.*: SELECT/`user_accounts_db`.*: SELECT", - "name": "user_accounts_multi" + "host": "users_info.com", + "priv": "`mysql`.*: SELECT/`users_info_db`.*: SELECT", + "name": "users_info_multi" } ] """ @@ -623,7 +623,7 @@ def __get_user_accounts(self): output.append(output_dict) - self.info['user_accounts'] = output + self.info['users_info'] = output def __get_databases(self, exclude_fields, return_empty_dbs): """Get info about databases.""" diff --git a/tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql b/tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql deleted file mode 100644 index 21fb3f482..000000000 --- a/tests/integration/targets/test_mysql_info/files/user_accounts_create_procedure.sql +++ /dev/null @@ -1,7 +0,0 @@ -DELIMITER // -DROP PROCEDURE IF EXISTS user_accounts_db.get_all_items; -CREATE PROCEDURE user_accounts_db.get_all_items() -BEGIN -SELECT * from user_accounts_db.t1; -END // -DELIMITER ; diff --git a/tests/integration/targets/test_mysql_info/files/users_info_create_procedure.sql b/tests/integration/targets/test_mysql_info/files/users_info_create_procedure.sql new file mode 100644 index 000000000..5a358f0aa --- /dev/null +++ b/tests/integration/targets/test_mysql_info/files/users_info_create_procedure.sql @@ -0,0 +1,7 @@ +DELIMITER // +DROP PROCEDURE IF EXISTS users_info_db.get_all_items; +CREATE PROCEDURE users_info_db.get_all_items() +BEGIN +SELECT * from users_info_db.t1; +END // +DELIMITER ; diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml b/tests/integration/targets/test_mysql_info/tasks/filter_users_info.yml similarity index 60% rename from tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml rename to tests/integration/targets/test_mysql_info/tasks/filter_users_info.yml index ecf46b2dd..2c126c12f 100644 --- a/tests/integration/targets/test_mysql_info/tasks/filter_user_accounts.yml +++ b/tests/integration/targets/test_mysql_info/tasks/filter_users_info.yml @@ -13,35 +13,35 @@ block: # ================================ Prepare ============================== - - name: Mysql_info user_accounts | Create databases + - name: Mysql_info users_info | Create databases community.mysql.mysql_db: name: - - user_accounts_db - - user_accounts_db2 - - user_accounts_db3 + - users_info_db + - users_info_db2 + - users_info_db3 state: present - - name: Mysql_info user_accounts | Create tables + - name: Mysql_info users_info | Create tables community.mysql.mysql_query: query: - >- - CREATE TABLE IF NOT EXISTS user_accounts_db.t1 + CREATE TABLE IF NOT EXISTS users_info_db.t1 (id int, name varchar(9)) - >- - CREATE TABLE IF NOT EXISTS user_accounts_db.T_UPPER + CREATE TABLE IF NOT EXISTS users_info_db.T_UPPER (id int, name1 varchar(9), NAME2 varchar(9), Name3 varchar(9)) # I failed to create a procedure using community.mysql.mysql_query. # Maybe it's because we must changed the delimiter. - - name: Mysql_info user_accounts | Create procedure SQL file + - name: Mysql_info users_info | Create procedure SQL file ansible.builtin.template: - src: files/user_accounts_create_procedure.sql + src: files/users_info_create_procedure.sql dest: /root/create_procedure.sql owner: root group: root mode: '0700' - - name: Mysql_info user_accounts | Create a procedure + - name: Mysql_info users_info | Create a procedure community.mysql.mysql_db: name: all state: import @@ -49,108 +49,108 @@ # Use a query instead of mysql_user, because we want to caches differences # at the end and a bug in mysql_user would be invisible to this tests - - name: Mysql_info user_accounts | Prepare common tests users + - name: Mysql_info users_info | Prepare common tests users community.mysql.mysql_query: query: - >- - CREATE USER user_accounts_adm@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_adm@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - > - GRANT ALL ON *.* to user_accounts_adm@'user_accounts.com' WITH GRANT + GRANT ALL ON *.* to users_info_adm@'users_info.com' WITH GRANT OPTION - >- - CREATE USER user_accounts_schema@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_schema@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT, INSERT, UPDATE, DELETE ON user_accounts_db.* TO - user_accounts_schema@'user_accounts.com' + GRANT SELECT, INSERT, UPDATE, DELETE ON users_info_db.* TO + users_info_schema@'users_info.com' - >- - CREATE USER user_accounts_table@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_table@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT, INSERT, UPDATE ON user_accounts_db.t1 TO - user_accounts_table@'user_accounts.com' + GRANT SELECT, INSERT, UPDATE ON users_info_db.t1 TO + users_info_table@'users_info.com' - >- - CREATE USER user_accounts_col@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_col@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' WITH MAX_USER_CONNECTIONS 100 - >- - GRANT SELECT (id) ON user_accounts_db.t1 TO - user_accounts_col@'user_accounts.com' + GRANT SELECT (id) ON users_info_db.t1 TO + users_info_col@'users_info.com' - >- - CREATE USER user_accounts_proc@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_proc@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' WITH MAX_USER_CONNECTIONS 2 MAX_CONNECTIONS_PER_HOUR 60 - >- - GRANT EXECUTE ON PROCEDURE user_accounts_db.get_all_items TO - user_accounts_proc@'user_accounts.com' + GRANT EXECUTE ON PROCEDURE users_info_db.get_all_items TO + users_info_proc@'users_info.com' - >- - CREATE USER user_accounts_multi@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_multi@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- GRANT SELECT ON mysql.* TO - user_accounts_multi@'user_accounts.com' + users_info_multi@'users_info.com' - >- - GRANT ALL ON user_accounts_db.* TO - user_accounts_multi@'user_accounts.com' + GRANT ALL ON users_info_db.* TO + users_info_multi@'users_info.com' - >- - GRANT ALL ON user_accounts_db2.* TO - user_accounts_multi@'user_accounts.com' + GRANT ALL ON users_info_db2.* TO + users_info_multi@'users_info.com' - >- - GRANT ALL ON user_accounts_db3.* TO - user_accounts_multi@'user_accounts.com' + GRANT ALL ON users_info_db3.* TO + users_info_multi@'users_info.com' - >- - CREATE USER user_accounts_usage_only@'user_accounts.com' IDENTIFIED WITH + CREATE USER users_info_usage_only@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- GRANT USAGE ON *.* TO - user_accounts_usage_only@'user_accounts.com' + users_info_usage_only@'users_info.com' - >- - CREATE USER user_accounts_columns_uppercase@'user_accounts.com' + CREATE USER users_info_columns_uppercase@'users_info.com' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT,UPDATE(name1,NAME2,Name3) ON user_accounts_db.T_UPPER TO - user_accounts_columns_uppercase@'user_accounts.com' + GRANT SELECT,UPDATE(name1,NAME2,Name3) ON users_info_db.T_UPPER TO + users_info_columns_uppercase@'users_info.com' - >- - CREATE USER user_accounts_multi_hosts@'%' + CREATE USER users_info_multi_hosts@'%' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'%' + - GRANT SELECT ON users_info_db.* TO users_info_multi_hosts@'%' - >- - CREATE USER user_accounts_multi_hosts@'localhost' + CREATE USER users_info_multi_hosts@'localhost' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - >- - GRANT SELECT ON user_accounts_db.* TO - user_accounts_multi_hosts@'localhost' + GRANT SELECT ON users_info_db.* TO + users_info_multi_hosts@'localhost' - >- - CREATE USER user_accounts_multi_hosts@'host1' + CREATE USER users_info_multi_hosts@'host1' IDENTIFIED WITH mysql_native_password AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' - - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'host1' + - GRANT SELECT ON users_info_db.* TO users_info_multi_hosts@'host1' - # Different password than the others user_accounts_multi_hosts + # Different password than the others users_info_multi_hosts - >- - CREATE USER user_accounts_multi_hosts@'host2' + CREATE USER users_info_multi_hosts@'host2' IDENTIFIED WITH mysql_native_password AS '*CB3326D5279DE7915FE5D743232165EE887883CA' - - GRANT SELECT ON user_accounts_db.* TO user_accounts_multi_hosts@'host2' + - GRANT SELECT ON users_info_db.* TO users_info_multi_hosts@'host2' - - name: Mysql_info user_accounts | Prepare tests users for MariaDB + - name: Mysql_info users_info | Prepare tests users for MariaDB community.mysql.mysql_user: name: "{{ item.name }}" - host: "user_accounts.com" + host: "users_info.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -160,17 +160,17 @@ column_case_sensitive: true state: present loop: - - name: user_accounts_socket # Only for MariaDB + - name: users_info_socket # Only for MariaDB priv: '*.*': 'ALL' plugin: 'unix_socket' when: - db_engine == 'mariadb' - - name: Mysql_info user_accounts | Prepare tests users for MySQL + - name: Mysql_info users_info | Prepare tests users for MySQL community.mysql.mysql_user: name: "{{ item.name }}" - host: "user_accounts.com" + host: "users_info.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -180,7 +180,7 @@ column_case_sensitive: true state: present loop: - - name: user_accounts_sha256 # Only for MySQL + - name: users_info_sha256 # Only for MySQL priv: '*.*': 'ALL' plugin_auth_string: @@ -189,10 +189,10 @@ when: - db_engine == 'mysql' - - name: Mysql_info user_accounts | Prepare tests users for MySQL 8+ + - name: Mysql_info users_info | Prepare tests users for MySQL 8+ community.mysql.mysql_user: name: "{{ item.name }}" - host: "user_accounts.com" + host: "users_info.com" plugin: "{{ item.plugin | default(omit) }}" plugin_auth_string: "{{ item.plugin_auth_string | default(omit) }}" plugin_hash_string: "{{ item.plugin_hash_string | default(omit) }}" @@ -202,7 +202,7 @@ column_case_sensitive: true state: present loop: - - name: user_accounts_caching_sha2 # Only for MySQL 8+ + - name: users_info_caching_sha2 # Only for MySQL 8+ priv: '*.*': 'ALL' plugin_auth_string: @@ -214,13 +214,13 @@ # ================================== Tests ============================== - - name: Mysql_info user_accounts | Collect user_accounts + - name: Mysql_info users_info | Collect users_info community.mysql.mysql_info: filter: - - user_accounts + - users_info register: result - - name: Recreate users from mysql_info user_accounts result + - name: Recreate users from mysql_info users_info result community.mysql.mysql_user: name: "{{ item.name }}" host: "{{ item.host }}" @@ -232,7 +232,7 @@ resource_limits: "{{ item.resource_limits | default(omit) }}" column_case_sensitive: true state: present - loop: "{{ result.user_accounts }}" + loop: "{{ result.users_info }}" loop_control: label: "{{ item.name }}@{{ item.host }}" register: recreate_users_result @@ -248,33 +248,33 @@ # ================================== Cleanup ============================ - - name: Mysql_info user_accounts | Cleanup user_accounts + - name: Mysql_info users_info | Cleanup users_info community.mysql.mysql_user: name: "{{ item }}" host_all: true column_case_sensitive: true state: absent loop: - - user_accounts_adm - - user_accounts_schema - - user_accounts_table - - user_accounts_col - - user_accounts_proc - - user_accounts_multi - - user_accounts_db - - user_accounts_usage_only - - user_accounts_columns_uppercase - - user_accounts_multi_hosts + - users_info_adm + - users_info_schema + - users_info_table + - users_info_col + - users_info_proc + - users_info_multi + - users_info_db + - users_info_usage_only + - users_info_columns_uppercase + - users_info_multi_hosts - - name: Mysql_info user_accounts | Cleanup databases + - name: Mysql_info users_info | Cleanup databases community.mysql.mysql_db: name: - - user_accounts_db - - user_accounts_db2 - - user_accounts_db3 + - users_info_db + - users_info_db2 + - users_info_db3 state: absent - - name: Mysql_info user_accounts | Cleanup sql file for the procedure + - name: Mysql_info users_info | Cleanup sql file for the procedure ansible.builtin.file: path: /root/create_procedure.sql state: absent diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index 38408fe6f..5d34da9a0 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -220,6 +220,6 @@ that: - result.databases.allviews.size == 0 - - name: Import tasks file to tests user_accounts filter + - name: Import tasks file to tests users_info filter ansible.builtin.import_tasks: - file: filter_user_accounts.yml + file: filter_users_info.yml From 1bef84de96f27a529c9b7505af90157f6578bc87 Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Fri, 13 Oct 2023 15:00:44 +0200 Subject: [PATCH 13/14] fix link to the PR --- changelogs/fragments/lie_mysql_info_users_info.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/lie_mysql_info_users_info.yml b/changelogs/fragments/lie_mysql_info_users_info.yml index 56c83b272..5d7526fcc 100644 --- a/changelogs/fragments/lie_mysql_info_users_info.yml +++ b/changelogs/fragments/lie_mysql_info_users_info.yml @@ -2,4 +2,4 @@ minor_changes: - - mysql_info - add filter ``users_info`` (https://github.com/ansible-collections/community.mysql/pull/572). + - mysql_info - add filter ``users_info`` (https://github.com/ansible-collections/community.mysql/pull/580). From 77b0831f0964295b7fe68b60e19f37d6163a885b Mon Sep 17 00:00:00 2001 From: Laurent Indermuehle Date: Fri, 13 Oct 2023 15:02:43 +0200 Subject: [PATCH 14/14] Add 'users' description to differentiate it from 'users_info' --- plugins/modules/mysql_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index da7dca0dc..73e403a22 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -216,7 +216,7 @@ sample: - { "Innodb_buffer_pool_read_requests": 123, "Innodb_buffer_pool_reads": 32 } users: - description: Users information. + description: Return a dictionnary of users grouped by host and with global privileges only. returned: if not excluded by filter type: dict sample: