Skip to content

Commit

Permalink
write integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
n-cc authored and n-cc committed Jan 11, 2024
1 parent 7012a27 commit 9a8b53d
Show file tree
Hide file tree
Showing 3 changed files with 271 additions and 15 deletions.
39 changes: 24 additions & 15 deletions plugins/module_utils/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,16 @@ def get_existing_authentication(cursor, user, host):
def user_add(cursor, user, host, host_all, password, encrypted,
plugin, plugin_hash_string, plugin_auth_string, new_priv,
attributes, tls_requires, reuse_existing_password, module):
# we cannot create users without a proper hostname
if host_all:
return {'changed': False, 'password_changed': False, 'attributes': {}}

if module.check_mode:
return {'changed': True, 'password_changed': None, 'attributes': {}}

# If attributes are set, perform a sanity check to ensure server supports user attributes before creating user
if attributes and not get_attribute_support(cursor):
module.fail_json(msg="user attributes were specified but the mysql server does not support user attributes")

final_attributes = {}
# we cannot create users without a proper hostname
if host_all:
return {'changed': False, 'password_changed': False, 'attributes': attributes}

Check warning on line 162 in plugins/module_utils/user.py

View check run for this annotation

Codecov / codecov/patch

plugins/module_utils/user.py#L162

Added line #L162 was not covered by tests

if module.check_mode:
return {'changed': True, 'password_changed': None, 'attributes': attributes}

# Determine what user management method server uses
old_user_mgmt = impl.use_old_user_mgmt(cursor)
Expand Down Expand Up @@ -210,12 +208,15 @@ def user_add(cursor, user, host, host_all, password, encrypted,
if new_priv is not None:
for db_table, priv in iteritems(new_priv):
privileges_grant(cursor, user, host, db_table, priv, tls_requires)
if attributes is not None:
cursor.execute("ALTER USER %s@%s ATTRIBUTE %s", (user, host, json.dumps(attributes)))
final_attributes = attributes_get(cursor, user, host)
if tls_requires is not None:
privileges_grant(cursor, user, host, "*.*", get_grants(cursor, user, host), tls_requires)

final_attributes = {}

if attributes:
cursor.execute("ALTER USER %s@%s ATTRIBUTE %s", (user, host, json.dumps(attributes)))
final_attributes = attributes_get(cursor, user, host)

return {'changed': True, 'password_changed': not used_existing_password, 'attributes': final_attributes}


Expand Down Expand Up @@ -426,6 +427,7 @@ def user_mod(cursor, user, host, host_all, password, encrypted,

# Handle attributes
attribute_support = get_attribute_support(cursor)
final_attributes = {}

if attributes:
if not attribute_support:
Expand All @@ -441,14 +443,21 @@ def user_mod(cursor, user, host, host_all, password, encrypted,

if attributes_to_change:
msg = "Attributes updated: %s" % (", ".join(["%s: %s" % (key, value) for key, value in attributes_to_change.items()]))

# Calculate final attributes by re-running attributes_get when not in check mode, and merge dictionaries when in check mode
if not module.check_mode:
cursor.execute("ALTER USER %s@%s ATTRIBUTE %s", (user, host, json.dumps(attributes_to_change)))
final_attributes = attributes_get(cursor, user, host)
else:
# Final if statements excludes items whose values are None in attributes_to_change, i.e. attributes that will be deleted
final_attributes = {k: v for d in (current_attributes, attributes_to_change) for k, v in d.items() if k not in attributes_to_change or
attributes_to_change[k]}
changed = True

if attribute_support:
final_attributes = attributes_get(cursor, user, host)
else:
final_attributes = current_attributes
else:
final_attributes = {}
if attribute_support:
final_attributes = attributes_get(cursor, user, host)

if role:
continue
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/targets/test_mysql_user/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@
tags:
- issue_465

# Tests for user attributes
- include_tasks: test_user_attributes.yml

# Tests for the TLS requires dictionary
- include_tasks: test_tls_requirements.yml

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
---
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'

block:

- when: db_engine == 'mariadb'
block:

- name: Attributes | Attempt to create user with attributes with mariadb in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
password: '{{ user_password_2 }}'
attributes:
key1: "value1"
ignore_errors: yes
register: result
check_mode: yes

- name: Attributes | Assert that creating user with attributes fails with mariadb
assert:
that:
- result is failed

- name: Attributes | Attempt to create user with attributes with mariadb
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
password: '{{ user_password_2 }}'
attributes:
key1: "value1"
ignore_errors: yes
register: result

- name: Attributes | Assert that creating user with attributes fails with mariadb
assert:
that:
- result is failed

- when: db_engine == 'mysql'
block:

# Create user with attributes
- name: Attributes | Test creating a user with attributes in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
password: '{{ user_password_2 }}'
attributes:
key1: "value1"
register: result
check_mode: yes

- name: Attributes | Assert that user would have been created with attributes
assert:
that:
- result is changed
- result.attributes.key1 == "value1"

- name: Attributes | Test creating a user with attributes
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
password: '{{ user_password_2 }}'
attributes:
key1: "value1"
register: result

- name: Attributes | Assert that user was created with attributes
assert:
that:
- result is changed
- result.attributes.key1 == "value1"

# Append attributes on an existing user
- name: Attributes | Test appending attributes to an existing user in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: "value2"
register: result
check_mode: yes

- name: Attributes | Assert that attribute would have been appended and existing attribute stays
assert:
that:
- result is changed
- result.attributes.key1 == "value1"
- result.attributes.key2 == "value2"

- name: Attributes | Test appending attributes to an existing user
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: "value2"
register: result

- name: Attributes | Assert that new attribute was appended and existing attribute stays
assert:
that:
- result is changed
- result.attributes.key1 == "value1"
- result.attributes.key2 == "value2"

# Test updating existing attributes
- name: Attributes | Test updating attributes on an existing user in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: "new_value2"
check_mode: yes
register: result

- name: Attributes | Assert that attribute would have been updated
assert:
that:
- result is changed
- result.attributes.key2 == "new_value2"

- name: Attributes | Test updating attributes on an existing user
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: "new_value2"
register: result

- name: Attributes | Assert that attribute was updated
assert:
that:
- result is changed
- result.attributes.key2 == "new_value2"

# Test deleting attributes
- name: Attributes | Test deleting attributes on an existing user in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: False
register: result
check_mode: yes

- name: Attributes | Assert that attribute would have been deleted
assert:
that:
- result is changed
- "'key2' not in result.attributes"

- name: Attributes | Test deleting attributes on an existing user
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key2: False
register: result

- name: Attributes | Assert that attribute was deleted
assert:
that:
- result is changed
- "'key2' not in result.attributes"

# Test attribute idempotency
- name: Attributes | Test attribute idempotency by trying to change an already correct attribute in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key1: "value1"
register: result
check_mode: yes

- name: Attributes | Assert that attribute would not have been updated
assert:
that:
- result is not changed
- result.attributes.key1 == "value1"

- name: Attributes | Test attribute idempotency by trying to change an already correct attribute
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
attributes:
key1: "value1"
register: result

- name: Attributes | Assert that attribute was not updated
assert:
that:
- result is not changed
- result.attributes.key1 == "value1"

- name: Attributes | Test attribute idempotency by not specifying attribute parameter in check mode
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
register: result
check_mode: yes

- name: Attributes | Assert that attribute is returned in check mode
assert:
that:
- result is not changed
- result.attributes.key1 == "value1"

- name: Attributes | Test attribute idempotency by not specifying attribute parameter
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
host: '%'
register: result

- name: Attributes | Assert that attribute is returned
assert:
that:
- result is not changed
- result.attributes.key1 == "value1"

# Cleanup
- include_tasks: utils/remove_user.yml
vars:
user_name: "{{ user_name_2 }}"

0 comments on commit 9a8b53d

Please sign in to comment.