From 3eff72e886c46c07f99fb94fbf3df755915d71ee Mon Sep 17 00:00:00 2001 From: Andrey Klychkov Date: Thu, 4 Apr 2019 12:02:23 +0300 Subject: [PATCH] postgresql_user: fix doc formatting, added return value, aliases, misc code changes (#54768) * postgresql_user: refactoring * postgresql_user: removed line from ignore.txt * postgresql_user: removed lines from ignore.txt * postgresql_user: removed lines from ignore.txt, fixes * postgresql_user: removed lines from ignore.txt, fixes * postgresql_user: removed lines from ignore.txt, fixes --- .../database/postgresql/postgresql_ext.py | 16 +- .../database/postgresql/postgresql_lang.py | 5 - .../database/postgresql/postgresql_schema.py | 4 +- .../database/postgresql/postgresql_user.py | 321 ++++++++++-------- .../tasks/test_no_password_change.yml | 2 +- test/sanity/validate-modules/ignore.txt | 7 - 6 files changed, 195 insertions(+), 160 deletions(-) diff --git a/lib/ansible/modules/database/postgresql/postgresql_ext.py b/lib/ansible/modules/database/postgresql/postgresql_ext.py index 1a0a6b1493..e34a72b9e4 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_ext.py +++ b/lib/ansible/modules/database/postgresql/postgresql_ext.py @@ -24,6 +24,8 @@ options: - Name of the extension to add or remove. required: true type: str + aliases: + - ext db: description: - Name of the database to add or remove the extension to/from. @@ -40,6 +42,7 @@ options: description: - The username used to authenticate with. type: str + default: postgres login_password: description: - The password used to authenticate with. @@ -48,7 +51,6 @@ options: description: - Host running the database. type: str - default: localhost login_unix_socket: description: - Path to a Unix domain socket for local connections. @@ -70,7 +72,7 @@ options: - Specifies the name of a file containing SSL certificate authority (CA) certificate(s). If the file exists, the server's certificate will be verified to be signed by one of these authorities. - type: path + type: str version_added: '2.8' aliases: [ ssl_rootcert ] port: @@ -78,6 +80,8 @@ options: - Database port to connect to. default: 5432 type: int + aliases: + - login_port session_role: description: - Switch to session_role after connecting. @@ -219,14 +223,10 @@ def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", required=True, aliases=["login_db"]), - port=dict(type="int", default=5432, aliases=["login_port"]), - ext=dict(type="str", required=True, aliases=['name']), + ext=dict(type="str", required=True, aliases=["name"]), schema=dict(type="str"), state=dict(type="str", default="present", choices=["absent", "present"]), - cascade=dict(type='bool', default=False), - ssl_mode=dict(type='str', default='prefer', choices=[ - 'disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']), - ca_cert=dict(type="path", default=None, aliases=['ssl_rootcert']), + cascade=dict(type="bool", default=False), session_role=dict(type="str"), ) diff --git a/lib/ansible/modules/database/postgresql/postgresql_lang.py b/lib/ansible/modules/database/postgresql/postgresql_lang.py index 4d3e29d29b..527fc8d6bc 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_lang.py +++ b/lib/ansible/modules/database/postgresql/postgresql_lang.py @@ -93,7 +93,6 @@ options: description: - Host running PostgreSQL where you want to execute the actions. type: str - default: localhost session_role: version_added: '2.8' description: @@ -267,16 +266,12 @@ def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", required=True, aliases=["login_db"]), - port=dict(type="int", default=5432, aliases=["login_port"]), lang=dict(type="str", required=True, aliases=["name"]), state=dict(type="str", default="present", choices=["absent", "present"]), trust=dict(type="bool", default="no"), force_trust=dict(type="bool", default="no"), cascade=dict(type="bool", default="no"), fail_on_drop=dict(type="bool", default="yes"), - ssl_mode=dict(default='prefer', choices=[ - 'allow', 'disable', 'prefer', 'require', 'verify-ca', 'verify-full']), - ca_cert=dict(default=None, aliases=["ssl_rootcert"]), session_role=dict(type="str"), ) diff --git a/lib/ansible/modules/database/postgresql/postgresql_schema.py b/lib/ansible/modules/database/postgresql/postgresql_schema.py index 85f2f8d424..365fe553af 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_schema.py +++ b/lib/ansible/modules/database/postgresql/postgresql_schema.py @@ -24,6 +24,8 @@ options: - Name of the schema to add or remove. required: true type: str + aliases: + - schema database: description: - Name of the database to connect to and add or remove the schema. @@ -36,6 +38,7 @@ options: description: - The username used to authenticate with. type: str + default: postgres login_password: description: - The password used to authenticate with. @@ -44,7 +47,6 @@ options: description: - Host running the database. type: str - default: localhost login_unix_socket: description: - Path to a Unix domain socket for local connections. diff --git a/lib/ansible/modules/database/postgresql/postgresql_user.py b/lib/ansible/modules/database/postgresql/postgresql_user.py index e1f316b432..861c0a4e0e 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_user.py +++ b/lib/ansible/modules/database/postgresql/postgresql_user.py @@ -1,208 +1,235 @@ #!/usr/bin/python # -*- coding: utf-8 -*- + # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = { 'metadata_version': '1.1', 'status': ['stableinterface'], 'supported_by': 'community' } - -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: postgresql_user -short_description: Adds or removes a user (role) from a remote PostgreSQL server instance. +short_description: Add or remove a user (role) from a PostgreSQL server instance description: - - Adds or removes a user (role) from a remote PostgreSQL server instance - ("cluster" in PostgreSQL terminology) and, optionally, - grants the user access to an existing database or tables. - A user is a role with login privilege (see U(https://www.postgresql.org/docs/11/role-attributes.html) for more information). - - The fundamental function of the module is to create, or delete, users from - a PostgreSQL instances. Privilege assignment, or removal, is an optional - step, which works on one database at a time. This allows for the module to - be called several times in the same module to modify the permissions on - different databases, or to grant permissions to already existing users. - - A user cannot be removed until all the privileges have been stripped from - the user. In such situation, if the module tries to remove the user it - will fail. To avoid this from happening the fail_on_user option signals - the module to try to remove the user, but if not possible keep going; the - module will report if changes happened and separately if the user was - removed or not. -version_added: "0.6" +- Adds or removes a user (role) from a PostgreSQL server instance + ("cluster" in PostgreSQL terminology) and, optionally, + grants the user access to an existing database or tables. + A user is a role with login privilege + (see U(https://www.postgresql.org/docs/11/role-attributes.html) for more information). +- The fundamental function of the module is to create, or delete, users from + a PostgreSQL instances. Privilege assignment, or removal, is an optional + step, which works on one database at a time. This allows for the module to + be called several times in the same module to modify the permissions on + different databases, or to grant permissions to already existing users. +- A user cannot be removed until all the privileges have been stripped from + the user. In such situation, if the module tries to remove the user it + will fail. To avoid this from happening the fail_on_user option signals + the module to try to remove the user, but if not possible keep going; the + module will report if changes happened and separately if the user was + removed or not. +version_added: '0.6' options: name: description: - - Name of the user (role) to add or remove. + - Name of the user (role) to add or remove. + type: str required: true + aliases: + - user password: description: - - Set the user's password, before 1.4 this was required. - - Password can be passed unhashed or hashed (MD5-hashed). - - Unhashed password will automatically be hashed when saved into the - database if C(encrypted) parameter is set, otherwise it will be save in - plain text format. - - When passing a hashed password it must be generated with the format - C('str["md5"] + md5[ password + username ]'), resulting in a total of - 35 characters. An easy way to do this is C(echo "md5$(echo -n - 'verysecretpasswordJOE' | md5sum | awk '{print $1}')"). - - Note that if the provided password string is already in MD5-hashed - format, then it is used as-is, regardless of C(encrypted) parameter. + - Set the user's password, before 1.4 this was required. + - Password can be passed unhashed or hashed (MD5-hashed). + - Unhashed password will automatically be hashed when saved into the + database if C(encrypted) parameter is set, otherwise it will be save in + plain text format. + - When passing a hashed password it must be generated with the format + C('str["md5"] + md5[ password + username ]'), resulting in a total of + 35 characters. An easy way to do this is C(echo "md5$(echo -n + 'verysecretpasswordJOE' | md5sum | awk '{print $1}')"). + - Note that if the provided password string is already in MD5-hashed + format, then it is used as-is, regardless of C(encrypted) parameter. + type: str db: description: - - Name of database to connect to and where user's permissions will be granted. + - Name of database to connect to and where user's permissions will be granted. + type: str + aliases: + - login_db fail_on_user: description: - - If C(yes), fail when user (role) can't be removed. Otherwise just log and - continue. + - If C(yes), fail when user (role) can't be removed. Otherwise just log and continue. default: 'yes' type: bool + aliases: + - fail_on_role port: description: - - Database port to connect to. + - Database port to connect to. + type: int default: 5432 + aliases: + - login_port login_user: description: - - User (role) used to authenticate with PostgreSQL. + - User (role) used to authenticate with PostgreSQL. + type: str default: postgres login_password: description: - - Password used to authenticate with PostgreSQL. + - Password for U(login_user) used to authenticate with PostgreSQL. + type: str login_host: description: - - Host running PostgreSQL. - default: localhost + - Host running PostgreSQL. + type: str login_unix_socket: description: - - Path to a Unix domain socket for local connections. + - Path to a Unix domain socket for local connections. + type: str priv: description: - - "Slash-separated PostgreSQL privileges string: C(priv1/priv2), where - privileges can be defined for database ( allowed options - 'CREATE', - 'CONNECT', 'TEMPORARY', 'TEMP', 'ALL'. For example C(CONNECT) ) or - for table ( allowed options - 'SELECT', 'INSERT', 'UPDATE', 'DELETE', - 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'ALL'. For example - C(table:SELECT) ). Mixed example of this string: - C(CONNECT/CREATE/table1:SELECT/table2:INSERT)." + - "Slash-separated PostgreSQL privileges string: C(priv1/priv2), where + privileges can be defined for database ( allowed options - 'CREATE', + 'CONNECT', 'TEMPORARY', 'TEMP', 'ALL'. For example C(CONNECT) ) or + for table ( allowed options - 'SELECT', 'INSERT', 'UPDATE', 'DELETE', + 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'ALL'. For example + C(table:SELECT) ). Mixed example of this string: + C(CONNECT/CREATE/table1:SELECT/table2:INSERT)." + type: str role_attr_flags: description: - - "PostgreSQL user attributes string in the format: CREATEDB,CREATEROLE,SUPERUSER." - - Note that '[NO]CREATEUSER' is deprecated. - choices: ["[NO]SUPERUSER", "[NO]CREATEROLE", "[NO]CREATEDB", "[NO]INHERIT", "[NO]LOGIN", "[NO]REPLICATION", "[NO]BYPASSRLS"] + - "PostgreSQL user attributes string in the format: CREATEDB,CREATEROLE,SUPERUSER." + - Note that '[NO]CREATEUSER' is deprecated. + - To create a simple role for using it like a group, use C(NOLOGIN) flag. + type: str + choices: [ '[NO]SUPERUSER', '[NO]CREATEROLE', '[NO]CREATEDB', + '[NO]INHERIT', '[NO]LOGIN', '[NO]REPLICATION', '[NO]BYPASSRLS' ] session_role: - version_added: "2.8" - description: | - Switch to session_role after connecting. The specified session_role must be a role that the current login_user is a member of. - Permissions checking for SQL commands is carried out as though the session_role were the one that had logged in originally. + version_added: '2.8' + description: + - Switch to session_role after connecting. + - The specified session_role must be a role that the current login_user is a member of. + - Permissions checking for SQL commands is carried out as though the session_role were the one that had logged in originally. + type: str state: description: - - The user (role) state. + - The user (role) state. + type: str default: present - choices: ["present", "absent"] + choices: [ absent, present ] encrypted: description: - - Whether the password is stored hashed in the database. Passwords can be - passed already hashed or unhashed, and postgresql ensures the stored - password is hashed when C(encrypted) is set. - - "Note: Postgresql 10 and newer doesn't support unhashed passwords." - - Previous to Ansible 2.6, this was C(no) by default. + - Whether the password is stored hashed in the database. + - Passwords can be passed already hashed or unhashed, and postgresql + ensures the stored password is hashed when C(encrypted) is set. + - "Note: Postgresql 10 and newer doesn't support unhashed passwords." + - Previous to Ansible 2.6, this was C(no) by default. default: 'yes' type: bool version_added: '1.4' expires: description: - - The date at which the user's password is to expire. - - If set to C('infinity'), user's password never expire. - - Note that this value should be a valid SQL date and time type. + - The date at which the user's password is to expire. + - If set to C('infinity'), user's password never expire. + - Note that this value should be a valid SQL date and time type. + type: str version_added: '1.4' no_password_changes: description: - - If C(yes), don't inspect database for password changes. Effective when - C(pg_authid) is not accessible (such as AWS RDS). Otherwise, make - password changes as necessary. + - If C(yes), don't inspect database for password changes. Effective when + C(pg_authid) is not accessible (such as AWS RDS). Otherwise, make + password changes as necessary. default: 'no' type: bool version_added: '2.0' ssl_mode: description: - - Determines whether or with what priority a secure SSL TCP/IP connection - will be negotiated with the server. - - See U(https://www.postgresql.org/docs/current/static/libpq-ssl.html) for - more information on the modes. - - Default of C(prefer) matches libpq default. + - Determines whether or with what priority a secure SSL TCP/IP connection + will be negotiated with the server. + - See U(https://www.postgresql.org/docs/current/static/libpq-ssl.html) for + more information on the modes. + - Default of C(prefer) matches libpq default. default: prefer - choices: ["disable", "allow", "prefer", "require", "verify-ca", "verify-full"] + choices: [ allow, disable, prefer, require, verify-ca, verify-full ] version_added: '2.3' ca_cert: description: - - Specifies the name of a file containing SSL certificate authority (CA) - certificate(s). If the file exists, the server's certificate will be - verified to be signed by one of these authorities. + - Specifies the name of a file containing SSL certificate authority (CA) + certificate(s). If the file exists, the server's certificate will be + verified to be signed by one of these authorities. + type: str version_added: '2.3' aliases: [ ssl_rootcert ] conn_limit: description: - - Specifies the user (role) connection limit. - version_added: '2.4' + - Specifies the user (role) connection limit. type: int + version_added: '2.4' + notes: - - The module creates a user (role) with login privilege by default. - Use NOLOGIN role_attr_flags to change this behaviour. - - The default authentication assumes that you are either logging in as or - sudo'ing to the postgres account on the host. - - This module uses psycopg2, a Python PostgreSQL database adapter. You must - ensure that psycopg2 is installed on the host before using this module. If - the remote host is the PostgreSQL server (which is the default case), then - PostgreSQL must also be installed on the remote host. For Ubuntu-based - systems, install the postgresql, libpq-dev, and python-psycopg2 packages - on the remote host before using this module. - - If you specify PUBLIC as the user (role), then the privilege changes will apply - to all users (roles). You may not specify password or role_attr_flags when the - PUBLIC user is specified. - - The ca_cert parameter requires at least Postgres version 8.4 and - I(psycopg2) version 2.4.3. -requirements: [ psycopg2 ] -author: "Ansible Core Team" +- The module creates a user (role) with login privilege by default. + Use NOLOGIN role_attr_flags to change this behaviour. +- The default authentication assumes that you are either logging in as or + sudo'ing to the postgres account on the host. +- This module uses psycopg2, a Python PostgreSQL database adapter. You must + ensure that psycopg2 is installed on the host before using this module. If + the remote host is the PostgreSQL server (which is the default case), then + PostgreSQL must also be installed on the remote host. For Ubuntu-based + systems, install the postgresql, libpq-dev, and python-psycopg2 packages + on the remote host before using this module. +- If you specify PUBLIC as the user (role), then the privilege changes will apply to all users (roles). + You may not specify password or role_attr_flags when the PUBLIC user is specified. +- The ca_cert parameter requires at least Postgres version 8.4 and I(psycopg2) version 2.4.3. + +requirements: +- psycopg2 + +author: +- Ansible Core Team ''' -EXAMPLES = ''' -# Connect to acme database, create django user, and grant access to database and products table -- postgresql_user: +EXAMPLES = r''' +- name: Connect to acme database, create django user, and grant access to database and products table + postgresql_user: db: acme name: django password: ceec4eif7ya priv: "CONNECT/products:ALL" expires: "Jan 31 2020" -# Connect to default database, create rails user, set its password (MD5-hashed), and grant privilege to create other -# databases and demote rails from super user status if user exists -- postgresql_user: +# Connect to default database, create rails user, set its password (MD5-hashed), +# and grant privilege to create other databases and demote rails from super user status if user exists +- name: Create rails user, set MD5-hashed password, grant privs + postgresql_user: name: rails password: md59543f1d82624df2b31672ec0f7050460 role_attr_flags: CREATEDB,NOSUPERUSER -# Connect to acme database and remove test user privileges from there -- postgresql_user: +- name: Connect to acme database and remove test user privileges from there + postgresql_user: db: acme name: test priv: "ALL/products:ALL" state: absent fail_on_user: no -# Connect to test database, remove test user from cluster -- postgresql_user: +- name: Connect to test database, remove test user from cluster + postgresql_user: db: test name: test priv: ALL state: absent -# Connect to acme database and set user's password with no expire date -- postgresql_user: +- name: Connect to acme database and set user's password with no expire date + postgresql_user: db: acme name: django password: mysupersecretword @@ -212,13 +239,22 @@ EXAMPLES = ''' # Example privileges string format # INSERT,UPDATE/table:SELECT/anothertable:ALL -# Connect to test database and remove an existing user's password -- postgresql_user: +- name: Connect to test database and remove an existing user's password + postgresql_user: db: test user: test password: "" ''' +RETURN = r''' +queries: + description: List of executed queries. + returned: always + type: list + sample: ['CREATE USER "alice"', 'GRANT CONNECT ON DATABASE "acme" TO "alice"'] + version_added: '2.8' +''' + import itertools import re import traceback @@ -228,15 +264,14 @@ PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras + HAS_PSYCOPG2 = True except ImportError: PSYCOPG2_IMP_ERR = traceback.format_exc() - postgresqldb_found = False -else: - postgresqldb_found = True + HAS_PSYCOPG2 = False -import ansible.module_utils.postgres as pgutils from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import pg_quote_identifier, SQLParseError +from ansible.module_utils.postgres import postgres_common_argument_spec from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils.six import iteritems @@ -254,6 +289,8 @@ PRIV_TO_AUTHID_COLUMN = dict(SUPERUSER='rolsuper', CREATEROLE='rolcreaterole', CREATEDB='rolcreatedb', INHERIT='rolinherit', LOGIN='rolcanlogin', REPLICATION='rolreplication', BYPASSRLS='rolbypassrls') +executed_queries = [] + class InvalidFlagsError(Exception): pass @@ -292,6 +329,7 @@ def user_add(cursor, user, password, role_attr_flags, encrypted, expires, conn_l query.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit}) query.append(role_attr_flags) query = ' '.join(query) + executed_queries.append(query) cursor.execute(query, query_password_data) return True @@ -484,7 +522,9 @@ def user_delete(cursor, user): """Try to remove a user. Returns True if successful otherwise False""" cursor.execute("SAVEPOINT ansible_pgsql_user_delete") try: - cursor.execute("DROP USER %s" % pg_quote_identifier(user, 'role')) + query = "DROP USER %s" % pg_quote_identifier(user, 'role') + executed_queries.append(query) + cursor.execute(query) except Exception: cursor.execute("ROLLBACK TO SAVEPOINT ansible_pgsql_user_delete") cursor.execute("RELEASE SAVEPOINT ansible_pgsql_user_delete") @@ -516,9 +556,9 @@ def get_table_privileges(cursor, user, table): schema, table = table.split('.', 1) else: schema = 'public' - query = '''SELECT privilege_type FROM information_schema.role_table_grants - WHERE grantee=%s AND table_name=%s AND table_schema=%s''' - cursor.execute(query, (user, table, schema)) + query = ("SELECT privilege_type FROM information_schema.role_table_grants " + "WHERE grantee='%s' AND table_name='%s' AND table_schema='%s'" % (user, table, schema)) + cursor.execute(query) return frozenset([x[0] for x in cursor.fetchall()]) @@ -527,6 +567,7 @@ def grant_table_privileges(cursor, user, table, privs): privs = ', '.join(privs) query = 'GRANT %s ON TABLE %s TO %s' % ( privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role')) + executed_queries.append(query) cursor.execute(query) @@ -535,6 +576,7 @@ def revoke_table_privileges(cursor, user, table, privs): privs = ', '.join(privs) query = 'REVOKE %s ON TABLE %s FROM %s' % ( privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role')) + executed_queries.append(query) cursor.execute(query) @@ -585,6 +627,8 @@ def grant_database_privileges(cursor, user, db, privs): query = 'GRANT %s ON DATABASE %s TO %s' % ( privs, pg_quote_identifier(db, 'database'), pg_quote_identifier(user, 'role')) + + executed_queries.append(query) cursor.execute(query) @@ -598,6 +642,8 @@ def revoke_database_privileges(cursor, user, db, privs): query = 'REVOKE %s ON DATABASE %s FROM %s' % ( privs, pg_quote_identifier(db, 'database'), pg_quote_identifier(user, 'role')) + + executed_queries.append(query) cursor.execute(query) @@ -746,24 +792,21 @@ def get_valid_flags_by_version(cursor): def main(): - argument_spec = pgutils.postgres_common_argument_spec() - argument_spec.update(dict( - user=dict(required=True, aliases=['name']), - password=dict(default=None, no_log=True), - state=dict(default="present", choices=["absent", "present"]), - priv=dict(default=None), - db=dict(default=''), - fail_on_user=dict(type='bool', default='yes'), - role_attr_flags=dict(default=''), + argument_spec = postgres_common_argument_spec() + argument_spec.update( + user=dict(type='str', required=True, aliases=['name']), + password=dict(type='str', default=None, no_log=True), + state=dict(type='str', default='present', choices=['absent', 'present']), + priv=dict(type='str', default=None), + db=dict(type='str', default='', aliases=['login_db']), + fail_on_user=dict(type='bool', default='yes', aliases=['fail_on_role']), + role_attr_flags=dict(type='str', default=''), encrypted=dict(type='bool', default='yes'), no_password_changes=dict(type='bool', default='no'), - expires=dict(default=None), - ssl_mode=dict(default='prefer', choices=[ - 'disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']), - ca_cert=dict(default=None, aliases=['ssl_rootcert']), + expires=dict(type='str', default=None), conn_limit=dict(type='int', default=None), - session_role=dict(), - )) + session_role=dict(type='str'), + ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True @@ -786,8 +829,9 @@ def main(): expires = module.params["expires"] sslrootcert = module.params["ca_cert"] conn_limit = module.params["conn_limit"] + role_attr_flags = module.params["role_attr_flags"] - if not postgresqldb_found: + if not HAS_PSYCOPG2: module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) # To use defaults values, keyword arguments must be absent, so @@ -823,10 +867,10 @@ def main(): if 'sslrootcert' in e.args[0]: module.fail_json( msg='Postgresql server must be at least version 8.4 to support sslrootcert') - module.fail_json(msg="unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) + module.fail_json(msg="Unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) except Exception as e: - module.fail_json(msg="unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) + module.fail_json(msg="Unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) if session_role: try: @@ -835,7 +879,7 @@ def main(): module.fail_json(msg="Could not switch role: %s" % to_native(e), exception=traceback.format_exc()) try: - role_attr_flags = parse_role_attrs(cursor, module.params["role_attr_flags"]) + role_attr_flags = parse_role_attrs(cursor, role_attr_flags) except InvalidFlagsError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) @@ -877,7 +921,7 @@ def main(): module.fail_json(msg=to_native(e), exception=traceback.format_exc()) changed = changed or user_removed if fail_on_user and not user_removed: - msg = "unable to remove user" + msg = "Unable to remove user" module.fail_json(msg=msg) kw['user_removed'] = user_removed @@ -888,6 +932,7 @@ def main(): db_connection.commit() kw['changed'] = changed + kw['queries'] = executed_queries module.exit_json(**kw) diff --git a/test/integration/targets/postgresql/tasks/test_no_password_change.yml b/test/integration/targets/postgresql/tasks/test_no_password_change.yml index a3acac45bb..1f3d9d3681 100644 --- a/test/integration/targets/postgresql/tasks/test_no_password_change.yml +++ b/test/integration/targets/postgresql/tasks/test_no_password_change.yml @@ -15,7 +15,7 @@ postgresql_user: <<: *parameters state: "present" - role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,login{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}" + role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,LOGIN{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}" no_password_changes: '{{ no_password_changes }}' # no_password_changes is ignored when user doesn't already exist - name: Check that the user has the requested role attributes diff --git a/test/sanity/validate-modules/ignore.txt b/test/sanity/validate-modules/ignore.txt index 008d92b0d9..d5e6e261c8 100644 --- a/test/sanity/validate-modules/ignore.txt +++ b/test/sanity/validate-modules/ignore.txt @@ -334,13 +334,6 @@ lib/ansible/modules/database/mongodb/mongodb_user.py E322 lib/ansible/modules/database/mysql/mysql_db.py E210 lib/ansible/modules/database/mysql/mysql_user.py E322 lib/ansible/modules/database/postgresql/postgresql_db.py E210 -lib/ansible/modules/database/postgresql/postgresql_ext.py E322 -lib/ansible/modules/database/postgresql/postgresql_ext.py E324 -lib/ansible/modules/database/postgresql/postgresql_lang.py E324 -lib/ansible/modules/database/postgresql/postgresql_schema.py E322 -lib/ansible/modules/database/postgresql/postgresql_schema.py E324 -lib/ansible/modules/database/postgresql/postgresql_user.py E322 -lib/ansible/modules/database/postgresql/postgresql_user.py E324 lib/ansible/modules/database/postgresql/postgresql_user.py E326 lib/ansible/modules/database/proxysql/proxysql_backend_servers.py E322 lib/ansible/modules/database/proxysql/proxysql_global_variables.py E322