diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 997353a..3f1f941 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -665,7 +665,14 @@ def user_mod(cursor, user, host, host_all, password, encrypted, # and in the new privileges, then we need to see if there's a difference. db_table_intersect = set(new_priv.keys()) & set(curr_priv.keys()) for db_table in db_table_intersect: - priv_diff = set(new_priv[db_table]) ^ set(curr_priv[db_table]) + + # If appending privileges, only the set difference between new privileges and current privileges matter. + # The symmetric difference isn't relevant for append because existing privileges will not be revoked. + if append_privs: + priv_diff = set(new_priv[db_table]) - set(curr_priv[db_table]) + else: + priv_diff = set(new_priv[db_table]) ^ set(curr_priv[db_table]) + if len(priv_diff) > 0: msg = "Privileges updated" if module.check_mode: diff --git a/tests/integration/targets/test_mysql_user/defaults/main.yml b/tests/integration/targets/test_mysql_user/defaults/main.yml index 4f90633..5cf9074 100644 --- a/tests/integration/targets/test_mysql_user/defaults/main.yml +++ b/tests/integration/targets/test_mysql_user/defaults/main.yml @@ -9,10 +9,12 @@ db_name: 'data' user_name_1: 'db_user1' user_name_2: 'db_user2' user_name_3: 'db_user3' +user_name_4: 'db_user4' user_password_1: 'gadfFDSdtTU^Sdfuj' user_password_2: 'jkFKUdfhdso78yi&td' user_password_3: 'jkFKUdfhdso78yi&tk' +user_password_4: 's2R#7pLV31!ZJrXPa3' root_password: 'zevuR6oPh7' diff --git a/tests/integration/targets/test_mysql_user/tasks/main.yml b/tests/integration/targets/test_mysql_user/tasks/main.yml index 6755a35..1e201a0 100644 --- a/tests/integration/targets/test_mysql_user/tasks/main.yml +++ b/tests/integration/targets/test_mysql_user/tasks/main.yml @@ -261,6 +261,10 @@ # Tests for the priv parameter with dict value (https://github.com/ansible/ansible/issues/57533) - include: test_priv_dict.yml + # Test that append_privs will not attempt to make a change where current privileges are a superset of new privileges + # (https://github.com/ansible-collections/community.mysql/issues/69) + - include: test_priv_append_no_change.yml + # Tests for the TLS requires dictionary - include: tls_requirements.yml diff --git a/tests/integration/targets/test_mysql_user/tasks/test_priv_append_no_change.yml b/tests/integration/targets/test_mysql_user/tasks/test_priv_append_no_change.yml new file mode 100644 index 0000000..3ef1c30 --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_priv_append_no_change.yml @@ -0,0 +1,79 @@ +# Test code to ensure that appending privileges will not result in unnecessary changes when the current privileges +# are a superset of the new privileges that have been defined. +- vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + + block: + + - name: Create test databases + mysql_db: + <<: *mysql_params + name: '{{ item }}' + state: present + loop: + - data1 + - data2 + + - name: Create user with privileges + mysql_user: + <<: *mysql_params + name: '{{ user_name_4 }}' + password: '{{ user_password_4 }}' + priv: 'data1.*:SELECT,INSERT/data2.*:SELECT,DELETE' + state: present + + - name: Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" + register: result + + - name: Assert user given privileges + assert: + that: + - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" + - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" + + - name: Append privileges that are a subset of the current privileges, which should be a no-op + mysql_user: + <<: *mysql_params + name: '{{ user_name_4 }}' + password: '{{ user_password_4 }}' + priv: 'data1.*:SELECT/data2.*:SELECT' + append_privs: yes + state: present + register: result + + - name: Assert that there wasn't a change and that the permissions are still the same + assert: + that: + - "result.changed == false" + + - name: Run command to show privileges for user once more (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" + register: result + + - name: Assert user given privileges once more + assert: + that: + - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" + - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" + + ########## + # Clean up + - name: Drop test databases + mysql_db: + <<: *mysql_params + name: '{{ item }}' + state: present + loop: + - data1 + - data2 + + - name: Drop test user + mysql_user: + <<: *mysql_params + name: '{{ user_name_4 }}' + state: absent