From 5fb85e9dda3c7c929f4affcab9caaf9dcdd91da5 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Mon, 5 Sep 2022 18:25:30 +0200 Subject: [PATCH 01/11] Compare privileges from before and after manipulation --- plugins/module_utils/user.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index bc874e17..3e56992c 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -385,7 +385,12 @@ def user_mod(cursor, user, host, host_all, password, encrypted, privileges_revoke(cursor, user, host, db_table, revoke_privs, grant_option, maria_role) if len(grant_privs) > 0: privileges_grant(cursor, user, host, db_table, grant_privs, tls_requires, maria_role) - changed = True + + # after privilege manipulation, compare privileges from before and now + changed = changed or not privileges_equal( + curr_priv, + privileges_get(cursor, user, host, maria_role) + ) if role: continue @@ -880,3 +885,15 @@ def get_impl(cursor): else: from ansible_collections.community.mysql.plugins.module_utils.implementations.mysql import user as mysqluser impl = mysqluser + + +def privileges_equal(before_privs, after_privs): + """Compare 2 priv dicts + + Args: + before_privs (dict): contains privileges, built with privileges_get() + after_privs (dict): contains privileges, built with privileges_get() + + Returns: True, if equal, False otherwise. + """ + return before_privs == after_privs From eaf5cbfefd4392b5a4b198a49041e1ff60593f4d Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Mon, 5 Sep 2022 18:26:31 +0200 Subject: [PATCH 02/11] Add unit tests --- .../plugins/module_utils/test_mysql_user.py | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/unit/plugins/module_utils/test_mysql_user.py b/tests/unit/plugins/module_utils/test_mysql_user.py index f0a7b32d..30296697 100644 --- a/tests/unit/plugins/module_utils/test_mysql_user.py +++ b/tests/unit/plugins/module_utils/test_mysql_user.py @@ -13,7 +13,8 @@ handle_grant_on_col, has_grant_on_col, normalize_col_grants, - sort_column_order + sort_column_order, + privileges_equal ) from ..utils import dummy_cursor_class @@ -97,3 +98,33 @@ def test_handle_grant_on_col(privileges, start, end, output): def test_normalize_col_grants(input_, expected): """Tests normalize_col_grants function.""" assert normalize_col_grants(input_) == expected + + +@pytest.mark.parametrize( + 'before_privileges,after_privileges,output', + [ + ( + {'*.*': ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'RELOAD', 'SHUTDOWN', 'PROCESS', 'FILE', 'REFERENCES', 'INDEX', 'ALTER', 'SHOW DATABASES', 'SUPER', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE', 'REPLICATION SLAVE', 'REPLICATION CLIENT', 'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'CREATE USER', 'EVENT', 'TRIGGER', 'CREATE TABLESPACE', 'CREATE ROLE', 'DROP ROLE', 'GRANT', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN', 'GRANT'], '`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + {'*.*': ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'RELOAD', 'SHUTDOWN', 'PROCESS', 'FILE', 'REFERENCES', 'INDEX', 'ALTER', 'SHOW DATABASES', 'SUPER', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE', 'REPLICATION SLAVE', 'REPLICATION CLIENT', 'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'CREATE USER', 'EVENT', 'TRIGGER', 'CREATE TABLESPACE', 'CREATE ROLE', 'DROP ROLE', 'GRANT', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN', 'GRANT'], '`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + True + ), + ( + {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + True + ), + ( + {'`sys`.*': ['SELECT'], '`mysql`.*': ['SELECT']}, + {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + True + ), + ( + {'`mysql`.*': ['UPDATE'], '`sys`.*': ['SELECT']}, + {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + False + ), + ] +) +def test_privileges_equal(before_privileges, after_privileges, output): + """Tests privileges_equal function.""" + assert privileges_equal(before_privileges, after_privileges) == output From bd30bf15cc002fe50c385647536dd18d2ac5e8d9 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Mon, 5 Sep 2022 18:26:21 +0200 Subject: [PATCH 03/11] Fix FIXME integration tests related to this issue --- .../integration/targets/test_mysql_user/tasks/test_privs.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml index 3c911a94..b9581f73 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml @@ -179,8 +179,6 @@ assert: that: - result is not changed - when: (install_type == 'mysql' and mysql_version is version('8', '<')) or - (install_type == 'mariadb' and mariadb_version is version('10.5', '<')) - name: remove username mysql_user: @@ -229,8 +227,6 @@ assert: that: - result is not changed - when: (install_type == 'mysql' and mysql_version is version('8', '<')) or - (install_type == 'mariadb') - name: Collect user info by host community.mysql.mysql_info: From 8e5dc90e6f6779febb9c49d229301bd460d66c89 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Tue, 6 Sep 2022 09:33:33 +0200 Subject: [PATCH 04/11] Fix sanity check --- tests/unit/plugins/module_utils/test_mysql_user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/plugins/module_utils/test_mysql_user.py b/tests/unit/plugins/module_utils/test_mysql_user.py index 30296697..4a17c0e8 100644 --- a/tests/unit/plugins/module_utils/test_mysql_user.py +++ b/tests/unit/plugins/module_utils/test_mysql_user.py @@ -104,8 +104,8 @@ def test_normalize_col_grants(input_, expected): 'before_privileges,after_privileges,output', [ ( - {'*.*': ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'RELOAD', 'SHUTDOWN', 'PROCESS', 'FILE', 'REFERENCES', 'INDEX', 'ALTER', 'SHOW DATABASES', 'SUPER', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE', 'REPLICATION SLAVE', 'REPLICATION CLIENT', 'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'CREATE USER', 'EVENT', 'TRIGGER', 'CREATE TABLESPACE', 'CREATE ROLE', 'DROP ROLE', 'GRANT', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN', 'GRANT'], '`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, - {'*.*': ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'RELOAD', 'SHUTDOWN', 'PROCESS', 'FILE', 'REFERENCES', 'INDEX', 'ALTER', 'SHOW DATABASES', 'SUPER', 'CREATE TEMPORARY TABLES', 'LOCK TABLES', 'EXECUTE', 'REPLICATION SLAVE', 'REPLICATION CLIENT', 'CREATE VIEW', 'SHOW VIEW', 'CREATE ROUTINE', 'ALTER ROUTINE', 'CREATE USER', 'EVENT', 'TRIGGER', 'CREATE TABLESPACE', 'CREATE ROLE', 'DROP ROLE', 'GRANT', 'APPLICATION_PASSWORD_ADMIN', 'AUDIT_ABORT_EXEMPT', 'AUDIT_ADMIN', 'AUTHENTICATION_POLICY_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', 'ENCRYPTION_KEY_ADMIN', 'FIREWALL_EXEMPT', 'FLUSH_OPTIMIZER_COSTS', 'FLUSH_STATUS', 'FLUSH_TABLES', 'FLUSH_USER_RESOURCES', 'GROUP_REPLICATION_ADMIN', 'GROUP_REPLICATION_STREAM', 'INNODB_REDO_LOG_ARCHIVE', 'INNODB_REDO_LOG_ENABLE', 'PASSWORDLESS_USER_ADMIN', 'PERSIST_RO_VARIABLES_ADMIN', 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', 'ROLE_ADMIN', 'SENSITIVE_VARIABLES_OBSERVER', 'SERVICE_CONNECTION_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', 'SHOW_ROUTINE', 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'TABLE_ENCRYPTION_ADMIN', 'XA_RECOVER_ADMIN', 'GRANT'], '`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, + {'*.*': ['INSERT', 'UPDATE' 'GRANT'], '`mysql`.*': ['SELECT']}, + {'*.*': ['INSERT', 'UPDATE' 'GRANT'], '`mysql`.*': ['SELECT']}, True ), ( From adeeb1299f72fef85f9ac233fc7f4a168c9131ce Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Wed, 7 Sep 2022 10:33:17 +0200 Subject: [PATCH 05/11] Fix assertion when appending privs in mysql_role_initial integration tests --- .../test_mysql_role/tasks/mysql_role_initial.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml b/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml index 8c81a758..36f2418a 100644 --- a/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml +++ b/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml @@ -1491,16 +1491,10 @@ priv: '{{ test_db1 }}.{{ test_table }}:SELECT,INSERT/{{ test_db2 }}.{{ test_table }}:DELETE' append_privs: yes - # TODO it must be changed. The module uses user_mod function - # taken from mysql_user module. It's a bug / expected behavior - # because I added a similar tasks to mysql_user tests - # https://github.com/ansible-collections/community.mysql/issues/50#issuecomment-871216825 - # and it's also failed. Create an issue after the module is merged to avoid conflicts. - # TODO Fix this after user_mod is fixed. - - name: Check + - name: Check that there's no change assert: that: - - result is changed + - result is not changed - name: Rewrite privs <<: *task_params From 4ad3cbf62fae0470f85f45be25687527a28eab5b Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Wed, 7 Sep 2022 12:56:12 +0200 Subject: [PATCH 06/11] Fix pylint --- tests/unit/plugins/module_utils/test_mysql_user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/plugins/module_utils/test_mysql_user.py b/tests/unit/plugins/module_utils/test_mysql_user.py index 4a17c0e8..34d6741c 100644 --- a/tests/unit/plugins/module_utils/test_mysql_user.py +++ b/tests/unit/plugins/module_utils/test_mysql_user.py @@ -104,8 +104,8 @@ def test_normalize_col_grants(input_, expected): 'before_privileges,after_privileges,output', [ ( - {'*.*': ['INSERT', 'UPDATE' 'GRANT'], '`mysql`.*': ['SELECT']}, - {'*.*': ['INSERT', 'UPDATE' 'GRANT'], '`mysql`.*': ['SELECT']}, + {'*.*': ['INSERT', 'UPDATE', 'GRANT'], '`mysql`.*': ['SELECT']}, + {'*.*': ['INSERT', 'UPDATE', 'GRANT'], '`mysql`.*': ['SELECT']}, True ), ( From 302f685c826e6123803ce9da12b17993c091d622 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Thu, 8 Sep 2022 09:45:01 +0200 Subject: [PATCH 07/11] [ci-skip] Add changelog fragment --- changelogs/fragments/438-fix-privilege-changing-everytime | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelogs/fragments/438-fix-privilege-changing-everytime diff --git a/changelogs/fragments/438-fix-privilege-changing-everytime b/changelogs/fragments/438-fix-privilege-changing-everytime new file mode 100644 index 00000000..da7baa85 --- /dev/null +++ b/changelogs/fragments/438-fix-privilege-changing-everytime @@ -0,0 +1,7 @@ +--- +bugfixes: + - mysql_user, mysql_role - mysql/mariadb recent versions translate 'ALL + PRIVILEGES' to a list of specific privileges. That caused a change every time + we modified user privileges. This fix compares privs before and after user + modification to avoid this infinite change + (https://github.com/ansible-collections/community.mysql/issues/77). From e2b7d0e29b3af0f94a59c3b07e6a90088f3f1d0f Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Thu, 8 Sep 2022 10:33:50 +0200 Subject: [PATCH 08/11] Fix: missing fragment file extension --- ...hanging-everytime => 438-fix-privilege-changing-everytime.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelogs/fragments/{438-fix-privilege-changing-everytime => 438-fix-privilege-changing-everytime.yml} (100%) diff --git a/changelogs/fragments/438-fix-privilege-changing-everytime b/changelogs/fragments/438-fix-privilege-changing-everytime.yml similarity index 100% rename from changelogs/fragments/438-fix-privilege-changing-everytime rename to changelogs/fragments/438-fix-privilege-changing-everytime.yml From b195e71e7cdfd04bf177d34817b15c2cc14af925 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Thu, 8 Sep 2022 10:35:37 +0200 Subject: [PATCH 09/11] Replace privileges_equal() by a comparison --- plugins/module_utils/user.py | 18 ++--------- .../plugins/module_utils/test_mysql_user.py | 30 ------------------- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index 3e56992c..2a96ac5f 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -387,10 +387,8 @@ def user_mod(cursor, user, host, host_all, password, encrypted, privileges_grant(cursor, user, host, db_table, grant_privs, tls_requires, maria_role) # after privilege manipulation, compare privileges from before and now - changed = changed or not privileges_equal( - curr_priv, - privileges_get(cursor, user, host, maria_role) - ) + after_priv = privileges_get(cursor, user, host, maria_role) + changed = changed or not (curr_priv == after_priv) if role: continue @@ -885,15 +883,3 @@ def get_impl(cursor): else: from ansible_collections.community.mysql.plugins.module_utils.implementations.mysql import user as mysqluser impl = mysqluser - - -def privileges_equal(before_privs, after_privs): - """Compare 2 priv dicts - - Args: - before_privs (dict): contains privileges, built with privileges_get() - after_privs (dict): contains privileges, built with privileges_get() - - Returns: True, if equal, False otherwise. - """ - return before_privs == after_privs diff --git a/tests/unit/plugins/module_utils/test_mysql_user.py b/tests/unit/plugins/module_utils/test_mysql_user.py index 34d6741c..fdbfa349 100644 --- a/tests/unit/plugins/module_utils/test_mysql_user.py +++ b/tests/unit/plugins/module_utils/test_mysql_user.py @@ -98,33 +98,3 @@ def test_handle_grant_on_col(privileges, start, end, output): def test_normalize_col_grants(input_, expected): """Tests normalize_col_grants function.""" assert normalize_col_grants(input_) == expected - - -@pytest.mark.parametrize( - 'before_privileges,after_privileges,output', - [ - ( - {'*.*': ['INSERT', 'UPDATE', 'GRANT'], '`mysql`.*': ['SELECT']}, - {'*.*': ['INSERT', 'UPDATE', 'GRANT'], '`mysql`.*': ['SELECT']}, - True - ), - ( - {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, - {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, - True - ), - ( - {'`sys`.*': ['SELECT'], '`mysql`.*': ['SELECT']}, - {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, - True - ), - ( - {'`mysql`.*': ['UPDATE'], '`sys`.*': ['SELECT']}, - {'`mysql`.*': ['SELECT'], '`sys`.*': ['SELECT']}, - False - ), - ] -) -def test_privileges_equal(before_privileges, after_privileges, output): - """Tests privileges_equal function.""" - assert privileges_equal(before_privileges, after_privileges) == output From 7d5a064503aeef177c1de05cccf61320dc6f15c7 Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Thu, 8 Sep 2022 13:27:29 +0200 Subject: [PATCH 10/11] Fix: sanity pylint --- plugins/module_utils/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index 2a96ac5f..7def8c76 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -388,7 +388,7 @@ def user_mod(cursor, user, host, host_all, password, encrypted, # after privilege manipulation, compare privileges from before and now after_priv = privileges_get(cursor, user, host, maria_role) - changed = changed or not (curr_priv == after_priv) + changed = changed or (curr_priv != after_priv) if role: continue From 1005108fb4bf84b75581b2b7a53a939b02bed27a Mon Sep 17 00:00:00 2001 From: "R. Sicart" Date: Thu, 8 Sep 2022 13:29:14 +0200 Subject: [PATCH 11/11] Fix: forgot to remove privileges_equal import from unit tests --- tests/unit/plugins/module_utils/test_mysql_user.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/plugins/module_utils/test_mysql_user.py b/tests/unit/plugins/module_utils/test_mysql_user.py index fdbfa349..f0a7b32d 100644 --- a/tests/unit/plugins/module_utils/test_mysql_user.py +++ b/tests/unit/plugins/module_utils/test_mysql_user.py @@ -13,8 +13,7 @@ handle_grant_on_col, has_grant_on_col, normalize_col_grants, - sort_column_order, - privileges_equal + sort_column_order ) from ..utils import dummy_cursor_class