From e89259dbd060b407e76c1c47fc0545c7ad9c9da4 Mon Sep 17 00:00:00 2001 From: Wilfrido Vidana Date: Wed, 15 Feb 2017 12:47:15 -0600 Subject: [PATCH] Fixes #19835: enable role attribute change when not changing password (#19834) Fixes #19835 --- .../database/postgresql/postgresql_user.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lib/ansible/modules/database/postgresql/postgresql_user.py b/lib/ansible/modules/database/postgresql/postgresql_user.py index e2df5a809a0..9b166fd5b69 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_user.py +++ b/lib/ansible/modules/database/postgresql/postgresql_user.py @@ -349,6 +349,56 @@ def user_alter(cursor, module, user, password, role_attr_flags, encrypted, expir if current_role_attrs[i] != new_role_attrs[i]: changed = True + elif no_password_changes and role_attr_flags != '': + # Grab role information from pg_roles instead of pg_authid + select = "SELECT * FROM pg_roles where rolname=%(user)s" + cursor.execute(select, {"user": user}) + # Grab current role attributes. + current_role_attrs = cursor.fetchone() + + role_attr_flags_changing = False + + if role_attr_flags: + role_attr_flags_dict = {} + for r in role_attr_flags.split(' '): + if r.startswith('NO'): + role_attr_flags_dict[r.replace('NO', '', 1)] = False + else: + role_attr_flags_dict[r] = True + + for role_attr_name, role_attr_value in role_attr_flags_dict.items(): + if current_role_attrs[PRIV_TO_AUTHID_COLUMN[role_attr_name]] != role_attr_value: + role_attr_flags_changing = True + + if not role_attr_flags_changing: + return False + + alter = ['ALTER USER %(user)s' % {"user": pg_quote_identifier(user, 'role')}] + if role_attr_flags: + alter.append('WITH %s' % role_attr_flags) + + try: + cursor.execute(' '.join(alter)) + except psycopg2.InternalError: + e = get_exception() + if e.pgcode == '25006': + # Handle errors due to read-only transactions indicated by pgcode 25006 + # ERROR: cannot execute ALTER ROLE in a read-only transaction + changed = False + module.fail_json(msg=e.pgerror) + return changed + else: + raise psycopg2.InternalError(e) + + # Grab new role attributes. + cursor.execute(select, {"user": user}) + new_role_attrs = cursor.fetchone() + + # Detect any differences between current_ and new_role_attrs. + for i in range(len(current_role_attrs)): + if current_role_attrs[i] != new_role_attrs[i]: + changed = True + return changed def user_delete(cursor, user):