mysql_user: priv parameter can also be a dictionary (#66801)

* mysql_user: add priv_dict parameter

* add changelog

* priv can be string or dictionary

* fix example
This commit is contained in:
Andrew Klychkov 2020-01-31 18:32:31 +03:00 committed by GitHub
parent 813091cf94
commit 54520c4685
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 2 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- mysql_user - ``priv`` parameter can be string or dictionary (https://github.com/ansible/ansible/issues/57533).

View file

@ -60,7 +60,8 @@ options:
exactly as returned by a C(SHOW GRANT) statement. If not followed, exactly as returned by a C(SHOW GRANT) statement. If not followed,
the module will always report changes. It includes grouping columns the module will always report changes. It includes grouping columns
by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))). by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))).
type: str - Can be passed as a dictionary (see the examples).
type: raw
append_privs: append_privs:
description: description:
- Append the privileges defined by priv to the existing ones for this - Append the privileges defined by priv to the existing ones for this
@ -167,6 +168,15 @@ EXAMPLES = r'''
priv: '*.*:ALL,GRANT' priv: '*.*:ALL,GRANT'
state: present state: present
- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2
mysql_user:
state: present
name: bob
password: 12345dd
priv:
'db1.*': 'ALL,GRANT'
'db2.*': 'ALL,GRANT'
# Note that REQUIRESSL is a special privilege that should only apply to *.* by itself. # Note that REQUIRESSL is a special privilege that should only apply to *.* by itself.
- name: Modify user to require SSL connections. - name: Modify user to require SSL connections.
mysql_user: mysql_user:
@ -651,6 +661,20 @@ def privileges_grant(cursor, user, host, db_table, priv):
query = ' '.join(query) query = ' '.join(query)
cursor.execute(query, (user, host)) cursor.execute(query, (user, host))
def convert_priv_dict_to_str(priv):
"""Converts privs dictionary to string of certain format.
Args:
priv (dict): Dict of privileges that needs to be converted to string.
Returns:
priv (str): String representation of input argument.
"""
priv_list = ['%s:%s' % (key, val) for key, val in iteritems(priv)]
return '/'.join(priv_list)
# =========================================== # ===========================================
# Module execution. # Module execution.
# #
@ -670,7 +694,7 @@ def main():
host=dict(type='str', default='localhost'), host=dict(type='str', default='localhost'),
host_all=dict(type="bool", default=False), host_all=dict(type="bool", default=False),
state=dict(type='str', default='present', choices=['absent', 'present']), state=dict(type='str', default='present', choices=['absent', 'present']),
priv=dict(type='str'), priv=dict(type='raw'),
append_privs=dict(type='bool', default=False), append_privs=dict(type='bool', default=False),
check_implicit_admin=dict(type='bool', default=False), check_implicit_admin=dict(type='bool', default=False),
update_password=dict(type='str', default='always', choices=['always', 'on_create']), update_password=dict(type='str', default='always', choices=['always', 'on_create']),
@ -708,6 +732,11 @@ def main():
plugin = module.params["plugin"] plugin = module.params["plugin"]
plugin_hash_string = module.params["plugin_hash_string"] plugin_hash_string = module.params["plugin_hash_string"]
plugin_auth_string = module.params["plugin_auth_string"] plugin_auth_string = module.params["plugin_auth_string"]
if priv and not (isinstance(priv, str) or isinstance(priv, dict)):
module.fail_json(msg="priv parameter must be str or dict but %s was passed" % type(priv))
if priv and isinstance(priv, dict):
priv = convert_priv_dict_to_str(priv)
if mysql_driver is None: if mysql_driver is None:
module.fail_json(msg=mysql_driver_fail_msg) module.fail_json(msg=mysql_driver_fail_msg)

View file

@ -3,9 +3,11 @@
db_name: 'data' db_name: 'data'
user_name_1: 'db_user1' user_name_1: 'db_user1'
user_name_2: 'db_user2' user_name_2: 'db_user2'
user_name_3: 'db_user3'
user_password_1: 'gadfFDSdtTU^Sdfuj' user_password_1: 'gadfFDSdtTU^Sdfuj'
user_password_2: 'jkFKUdfhdso78yi&td' user_password_2: 'jkFKUdfhdso78yi&td'
user_password_3: 'jkFKUdfhdso78yi&tk'
root_password: 'zevuR6oPh7' root_password: 'zevuR6oPh7'

View file

@ -208,6 +208,9 @@
# #
- include: test_privs.yml current_privilege='INSERT,DELETE' current_append_privs=yes - include: test_privs.yml current_privilege='INSERT,DELETE' current_append_privs=yes
# Tests for the priv parameter with dict value (https://github.com/ansible/ansible/issues/57533)
- include: test_priv_dict.yml
- import_tasks: issue-29511.yaml - import_tasks: issue-29511.yaml
tags: tags:
- issue-29511 - issue-29511

View file

@ -0,0 +1,46 @@
# Tests for priv parameter value passed as a dict
- name: Create test databases
mysql_db:
name: '{{ item }}'
state: present
login_unix_socket: '{{ mysql_socket }}'
loop:
- data1
- data2
- name: Create user with privileges
mysql_user:
name: '{{ user_name_3 }}'
password: '{{ user_password_3 }}'
priv:
"data1.*": "SELECT"
"data2.*": "SELECT"
state: present
login_unix_socket: '{{ mysql_socket }}'
- name: Run command to show privileges for user (expect privileges in stdout)
command: mysql "-e SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost';"
register: result
- name: Assert user has giving privileges
assert:
that:
- "'GRANT SELECT ON `data1`.*' in result.stdout"
- "'GRANT SELECT ON `data2`.*' in result.stdout"
##########
# Clean up
- name: Drop test databases
mysql_db:
name: '{{ item }}'
state: present
login_unix_socket: '{{ mysql_socket }}'
loop:
- data1
- data2
- name: Drop test user
mysql_user:
name: '{{ user_name_3 }}'
state: absent
login_unix_socket: '{{ mysql_socket }}'