diff --git a/changelogs/fragments/996-postgresql_privs_fix_function_handling.yml b/changelogs/fragments/996-postgresql_privs_fix_function_handling.yml new file mode 100644 index 00000000000..b40b253277e --- /dev/null +++ b/changelogs/fragments/996-postgresql_privs_fix_function_handling.yml @@ -0,0 +1,2 @@ +bugfixes: +- postgresql_privs - fix the module mistakes a procedure for a function (https://github.com/ansible-collections/community.general/issues/994) diff --git a/lib/ansible/modules/database/postgresql/postgresql_privs.py b/lib/ansible/modules/database/postgresql/postgresql_privs.py index 96ba006a13a..c6e138cf0f0 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_privs.py +++ b/lib/ansible/modules/database/postgresql/postgresql_privs.py @@ -481,6 +481,7 @@ class Connection(object): self.connection = psycopg2.connect(**kw) self.cursor = self.connection.cursor() + self.pg_version = self.connection.server_version def commit(self): self.connection.commit() @@ -528,10 +529,15 @@ class Connection(object): def get_all_functions_in_schema(self, schema): if not self.schema_exists(schema): raise Error('Schema "%s" does not exist.' % schema) - query = """SELECT p.proname, oidvectortypes(p.proargtypes) - FROM pg_catalog.pg_proc p - JOIN pg_namespace n ON n.oid = p.pronamespace - WHERE nspname = %s""" + + query = ("SELECT p.proname, oidvectortypes(p.proargtypes) " + "FROM pg_catalog.pg_proc p " + "JOIN pg_namespace n ON n.oid = p.pronamespace " + "WHERE nspname = %s") + + if self.pg_version >= 110000: + query += " and p.prokind = 'f'" + self.cursor.execute(query, (schema,)) return ["%s(%s)" % (t[0], t[1]) for t in self.cursor.fetchall()] @@ -1052,7 +1058,7 @@ def main(): except psycopg2.Error as e: conn.rollback() - module.fail_json(msg=to_native(e.message)) + module.fail_json(msg=to_native(e)) if module.check_mode: conn.rollback() diff --git a/test/integration/targets/postgresql/tasks/postgresql_privs.yml b/test/integration/targets/postgresql/tasks/postgresql_privs.yml index 663ea9aaa41..42aaa66c615 100644 --- a/test/integration/targets/postgresql/tasks/postgresql_privs.yml +++ b/test/integration/targets/postgresql/tasks/postgresql_privs.yml @@ -495,6 +495,43 @@ login_user: "{{ db_user3 }}" login_password: password +# Issue https://github.com/ansible-collections/community.general/issues/994 +- name: Create a procedure for tests + postgresql_query: + query: "CREATE PROCEDURE mock_procedure() LANGUAGE SQL AS $$ SELECT 1; $$;" + db: "{{ db_name }}" + login_user: "{{ db_user3 }}" + login_password: password + when: postgres_version_resp.stdout is version('11', '>=') + +# Issue https://github.com/ansible-collections/community.general/issues/994 +- name: Try to run module against a procedure, not function + postgresql_privs: + type: function + state: present + privs: ALL + roles: "{{ db_user2 }}" + objs: ALL_IN_SCHEMA + schema: public + db: "{{ db_name }}" + login_user: "{{ db_user3 }}" + login_password: password + register: result + when: postgres_version_resp.stdout is version('11', '>=') + +- assert: + that: + - result is not changed + when: postgres_version_resp.stdout is version('11', '>=') + +- name: Drop the procedure for tests + postgresql_query: + query: "DROP PROCEDURE mock_procedure()" + db: "{{ db_name }}" + login_user: "{{ db_user3 }}" + login_password: password + when: postgres_version_resp.stdout is version('11', '>=') + ################################################# # Test ALL_IN_SCHEMA for 'partioned tables type # #################################################