From 40855a5b968e9f7edbbc258b54e58ce28751eb20 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 07:35:52 +0200 Subject: [PATCH 1/6] postgresql_privs: grant usage on schemas --- plugins/modules/postgresql_privs.py | 5 +++-- .../tasks/postgresql_privs_general.yml | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/modules/postgresql_privs.py b/plugins/modules/postgresql_privs.py index 42bdf205..75ab61ae 100644 --- a/plugins/modules/postgresql_privs.py +++ b/plugins/modules/postgresql_privs.py @@ -461,11 +461,12 @@ VALID_PRIVS = frozenset(('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'CREATE', 'CONNECT', - 'TEMPORARY', 'TEMP', 'EXECUTE', 'USAGE', 'ALL', 'USAGE')) + 'TEMPORARY', 'TEMP', 'EXECUTE', 'USAGE', 'ALL')) VALID_DEFAULT_OBJS = {'TABLES': ('ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER'), 'SEQUENCES': ('ALL', 'SELECT', 'UPDATE', 'USAGE'), 'FUNCTIONS': ('ALL', 'EXECUTE'), - 'TYPES': ('ALL', 'USAGE')} + 'TYPES': ('ALL', 'USAGE'), + 'SCHEMAS': ('CREATE', 'USAGE'),} executed_queries = [] diff --git a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml index 530e0d1e..e21736b0 100644 --- a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml +++ b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml @@ -1476,6 +1476,24 @@ that: - result is not changed +############## +# Issue https://github.com/ansible-collections/community.postgresql/issues/332 +- name: Test community.postgresql issue 332 + become: yes + become_user: "{{ pg_user }}" + postgresql_privs: + login_user: "{{ pg_user }}" + login_db: "{{ db_name }}" + roles: "{{ db_user3 }}" + objs: schemas + type: default_privs + privs: usage + register: result + +- assert: + that: + - result is changed + # Cleanup - name: Remove privs become: yes From cc8086a903b89a51db7a0729d932879a709674f3 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 08:57:43 +0200 Subject: [PATCH 2/6] issue 332 --- plugins/modules/postgresql_privs.py | 66 ++++++++++--------- .../tasks/postgresql_privs_general.yml | 9 ++- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/plugins/modules/postgresql_privs.py b/plugins/modules/postgresql_privs.py index 75ab61ae..8fb3aad2 100644 --- a/plugins/modules/postgresql_privs.py +++ b/plugins/modules/postgresql_privs.py @@ -681,11 +681,14 @@ def get_group_memberships(self, groups): return self.cursor.fetchall() def get_default_privs(self, schema, *args): - query = """SELECT defaclacl - FROM pg_default_acl a - JOIN pg_namespace b ON a.defaclnamespace=b.oid - WHERE b.nspname = %s;""" - self.cursor.execute(query, (schema,)) + if schema is None: + self.cursor.execute("SELECT defaclacl FROM pg_default_acl;"); + else: + query = """SELECT defaclacl + FROM pg_default_acl a + JOIN pg_namespace b ON a.defaclnamespace=b.oid + WHERE b.nspname = %s;""" + self.cursor.execute(query, (schema,)) return [t[0] for t in self.cursor.fetchall()] def get_foreign_data_wrapper_acls(self, fdws): @@ -876,7 +879,7 @@ def for_objs(self, objs): return self def for_schema(self, schema): - self._schema = schema + self._schema = ' IN SCHEMA %s' % schema if schema is not None else '' return self def with_grant_option(self, option): @@ -916,13 +919,13 @@ def add_default_revoke(self): for obj in self._objs: if self._as_who: self.query.append( - 'ALTER DEFAULT PRIVILEGES FOR ROLE {0} IN SCHEMA {1} REVOKE ALL ON {2} FROM {3};'.format(self._as_who, - self._schema, obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES FOR ROLE {0}{1} REVOKE ALL ON {2} FROM {3};'.format(self._as_who, + self._schema, obj, + self._for_whom)) else: self.query.append( - 'ALTER DEFAULT PRIVILEGES IN SCHEMA {0} REVOKE ALL ON {1} FROM {2};'.format(self._schema, obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES{0} REVOKE ALL ON {1} FROM {2};'.format(self._schema, obj, + self._for_whom)) def add_grant_option(self): if self._grant_option: @@ -943,29 +946,29 @@ def add_default_priv(self): for obj in self._objs: if self._as_who: self.query.append( - 'ALTER DEFAULT PRIVILEGES FOR ROLE {0} IN SCHEMA {1} GRANT {2} ON {3} TO {4}'.format(self._as_who, - self._schema, - self._set_what, - obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES FOR ROLE {0}{1} GRANT {2} ON {3} TO {4}'.format(self._as_who, + self._schema, + self._set_what, + obj, + self._for_whom)) else: self.query.append( - 'ALTER DEFAULT PRIVILEGES IN SCHEMA {0} GRANT {1} ON {2} TO {3}'.format(self._schema, - self._set_what, - obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES{0} GRANT {1} ON {2} TO {3}'.format(self._schema, + self._set_what, + obj, + self._for_whom)) self.add_grant_option() if self._usage_on_types: if self._as_who: self.query.append( - 'ALTER DEFAULT PRIVILEGES FOR ROLE {0} IN SCHEMA {1} GRANT USAGE ON TYPES TO {2}'.format(self._as_who, - self._schema, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES FOR ROLE {0}{1} GRANT USAGE ON TYPES TO {2}'.format(self._as_who, + self._schema, + self._for_whom)) else: self.query.append( - 'ALTER DEFAULT PRIVILEGES IN SCHEMA {0} GRANT USAGE ON TYPES TO {1}'.format(self._schema, self._for_whom)) + 'ALTER DEFAULT PRIVILEGES{0} GRANT USAGE ON TYPES TO {1}'.format(self._schema, self._for_whom)) self.add_grant_option() def build_present(self): @@ -982,13 +985,13 @@ def build_absent(self): for obj in ['TABLES', 'SEQUENCES', 'TYPES']: if self._as_who: self.query.append( - 'ALTER DEFAULT PRIVILEGES FOR ROLE {0} IN SCHEMA {1} REVOKE ALL ON {2} FROM {3};'.format(self._as_who, - self._schema, obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES FOR ROLE {0}{1} REVOKE ALL ON {2} FROM {3};'.format(self._as_who, + self._schema, obj, + self._for_whom)) else: self.query.append( - 'ALTER DEFAULT PRIVILEGES IN SCHEMA {0} REVOKE ALL ON {1} FROM {2};'.format(self._schema, obj, - self._for_whom)) + 'ALTER DEFAULT PRIVILEGES{0} REVOKE ALL ON {1} FROM {2};'.format(self._schema, obj, + self._for_whom)) else: self.query.append('REVOKE {0} FROM {1};'.format(self._set_what, self._for_whom)) @@ -1041,7 +1044,10 @@ def main(): p = type('Params', (), module.params) # param "schema": default, allowed depends on param "type" if p.type in ['table', 'sequence', 'function', 'procedure', 'type', 'default_privs']: - p.schema = p.schema or 'public' + if p.objs == 'schemas': + p.schema = None + else: + p.schema = p.schema or 'public' elif p.schema: module.fail_json(msg='Argument "schema" is not allowed ' 'for type "%s".' % p.type) diff --git a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml index e21736b0..4e4ac097 100644 --- a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml +++ b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml @@ -1478,7 +1478,7 @@ ############## # Issue https://github.com/ansible-collections/community.postgresql/issues/332 -- name: Test community.postgresql issue 332 +- name: Test community.postgresql issue 332 grant usage become: yes become_user: "{{ pg_user }}" postgresql_privs: @@ -1521,6 +1521,13 @@ - "{{ db_user2 }}" - "{{ db_user3 }}" +- name: Drop a role for which the default privileges have been altered + become: yes + become_user: "{{ pg_user }}" + postgresql_query: + login_db: "{{ db_name }}" + query: "DROP OWNED BY {{ db_user3 }};" + - name: Remove user given permissions become: yes become_user: "{{ pg_user }}" From c2d2f1a43adbb8b2e861f1ae95425d7c9ec7d0b1 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 09:04:16 +0200 Subject: [PATCH 3/6] add changelog fragment --- changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml diff --git a/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml b/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml new file mode 100644 index 00000000..969da64c --- /dev/null +++ b/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml @@ -0,0 +1,2 @@ +bugfixes: +- postgresql_privs - add support for alter default privileges grant usage on schemas (https://github.com/ansible-collections/community.postgresql/issues/332). From 2225bb258f3ea3be851d40d990c8d9bd86856190 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 09:42:11 +0200 Subject: [PATCH 4/6] issue 333 --- plugins/modules/postgresql_privs.py | 151 +++++++++++------- .../tasks/postgresql_privs_general.yml | 50 ++++++ 2 files changed, 144 insertions(+), 57 deletions(-) diff --git a/plugins/modules/postgresql_privs.py b/plugins/modules/postgresql_privs.py index 8fb3aad2..3bcc8e1d 100644 --- a/plugins/modules/postgresql_privs.py +++ b/plugins/modules/postgresql_privs.py @@ -466,7 +466,7 @@ 'SEQUENCES': ('ALL', 'SELECT', 'UPDATE', 'USAGE'), 'FUNCTIONS': ('ALL', 'EXECUTE'), 'TYPES': ('ALL', 'USAGE'), - 'SCHEMAS': ('CREATE', 'USAGE'),} + 'SCHEMAS': ('CREATE', 'USAGE'), } executed_queries = [] @@ -562,53 +562,70 @@ def schema_exists(self, schema): return self.cursor.fetchone()[0] > 0 def get_all_tables_in_schema(self, schema): - if not self.schema_exists(schema): - raise Error('Schema "%s" does not exist.' % schema) - query = """SELECT relname - FROM pg_catalog.pg_class c - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE nspname = %s AND relkind in ('r', 'v', 'm', 'p')""" - self.cursor.execute(query, (schema,)) + if schema: + if not self.schema_exists(schema): + raise Error('Schema "%s" does not exist.' % schema) + + query = """SELECT relname + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE nspname = %s AND relkind in ('r', 'v', 'm', 'p')""" + self.cursor.execute(query, (schema,)) + else: + query = ("SELECT relname FROM pg_catalog.pg_class " + "WHERE relkind in ('r', 'v', 'm', 'p')") + self.cursor.execute(query) return [t[0] for t in self.cursor.fetchall()] def get_all_sequences_in_schema(self, schema): - if not self.schema_exists(schema): - raise Error('Schema "%s" does not exist.' % schema) - query = """SELECT relname - FROM pg_catalog.pg_class c - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE nspname = %s AND relkind = 'S'""" - self.cursor.execute(query, (schema,)) + if schema: + if not self.schema_exists(schema): + raise Error('Schema "%s" does not exist.' % schema) + query = """SELECT relname + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE nspname = %s AND relkind = 'S'""" + self.cursor.execute(query, (schema,)) + else: + self.cursor.execute("SELECT relname FROM pg_catalog.pg_class WHERE relkind = 'S'") return [t[0] for t in self.cursor.fetchall()] def get_all_functions_in_schema(self, schema): - if not self.schema_exists(schema): - raise Error('Schema "%s" does not exist.' % schema) + if 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'" + if self.pg_version >= 110000: + query += " and p.prokind = 'f'" - self.cursor.execute(query, (schema,)) + self.cursor.execute(query, (schema,)) + else: + self.cursor.execute("SELECT p.proname, oidvectortypes(p.proargtypes) FROM pg_catalog.pg_proc p") return ["%s(%s)" % (t[0], t[1]) for t in self.cursor.fetchall()] def get_all_procedures_in_schema(self, schema): if self.pg_version < 110000: raise Error("PostgreSQL verion must be >= 11 for type=procedure. Exit") - if not self.schema_exists(schema): - raise Error('Schema "%s" does not exist.' % schema) + if 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 and p.prokind = 'p'") + 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 and p.prokind = 'p'") - self.cursor.execute(query, (schema,)) + self.cursor.execute(query, (schema,)) + else: + query = ("SELECT p.proname, oidvectortypes(p.proargtypes) " + "FROM pg_catalog.pg_proc p WHERE p.prokind = 'p'") + self.cursor.execute(query) return ["%s(%s)" % (t[0], t[1]) for t in self.cursor.fetchall()] # Methods for getting access control lists and group membership info @@ -620,31 +637,47 @@ def get_all_procedures_in_schema(self, schema): # The same should apply to group membership information. def get_table_acls(self, schema, tables): - query = """SELECT relacl - FROM pg_catalog.pg_class c - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE nspname = %s AND relkind in ('r','p','v','m') AND relname = ANY (%s) - ORDER BY relname""" - self.cursor.execute(query, (schema, tables)) + if schema: + query = """SELECT relacl + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE nspname = %s AND relkind in ('r','p','v','m') AND relname = ANY (%s) + ORDER BY relname""" + self.cursor.execute(query, (schema, tables)) + else: + query = ("SELECT relacl FROM pg_catalog.pg_class " + "WHERE relkind in ('r','p','v','m') AND relname = ANY (%s) " + "ORDER BY relname") + self.cursor.execute(query) return [t[0] for t in self.cursor.fetchall()] def get_sequence_acls(self, schema, sequences): - query = """SELECT relacl - FROM pg_catalog.pg_class c - JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE nspname = %s AND relkind = 'S' AND relname = ANY (%s) - ORDER BY relname""" - self.cursor.execute(query, (schema, sequences)) + if schema: + query = """SELECT relacl + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE nspname = %s AND relkind = 'S' AND relname = ANY (%s) + ORDER BY relname""" + self.cursor.execute(query, (schema, sequences)) + else: + query = ("SELECT relacl FROM pg_catalog.pg_class " + "WHERE relkind = 'S' AND relname = ANY (%s) ORDER BY relname") + self.cursor.execute(query) return [t[0] for t in self.cursor.fetchall()] def get_function_acls(self, schema, function_signatures): funcnames = [f.split('(', 1)[0] for f in function_signatures] - query = """SELECT proacl - FROM pg_catalog.pg_proc p - JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace - WHERE nspname = %s AND proname = ANY (%s) - ORDER BY proname, proargtypes""" - self.cursor.execute(query, (schema, funcnames)) + if schema: + query = """SELECT proacl + FROM pg_catalog.pg_proc p + JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace + WHERE nspname = %s AND proname = ANY (%s) + ORDER BY proname, proargtypes""" + self.cursor.execute(query, (schema, funcnames)) + else: + query = ("SELECT proacl FROM pg_catalog.pg_proc WHERE proname = ANY (%s) " + "ORDER BY proname, proargtypes") + self.cursor.execute(query) return [t[0] for t in self.cursor.fetchall()] def get_schema_acls(self, schemas): @@ -681,14 +714,14 @@ def get_group_memberships(self, groups): return self.cursor.fetchall() def get_default_privs(self, schema, *args): - if schema is None: - self.cursor.execute("SELECT defaclacl FROM pg_default_acl;"); - else: + if schema: query = """SELECT defaclacl FROM pg_default_acl a JOIN pg_namespace b ON a.defaclnamespace=b.oid WHERE b.nspname = %s;""" self.cursor.execute(query, (schema,)) + else: + self.cursor.execute("SELECT defaclacl FROM pg_default_acl;") return [t[0] for t in self.cursor.fetchall()] def get_foreign_data_wrapper_acls(self, fdws): @@ -704,10 +737,14 @@ def get_foreign_server_acls(self, fs): return [t[0] for t in self.cursor.fetchall()] def get_type_acls(self, schema, types): - query = """SELECT t.typacl FROM pg_catalog.pg_type t - JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace - WHERE n.nspname = %s AND t.typname = ANY (%s) ORDER BY typname""" - self.cursor.execute(query, (schema, types)) + if schema: + query = """SELECT t.typacl FROM pg_catalog.pg_type t + JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace + WHERE n.nspname = %s AND t.typname = ANY (%s) ORDER BY typname""" + self.cursor.execute(query, (schema, types)) + else: + query = "SELECT typacl FROM pg_catalog.pg_type WHERE typname = ANY (%s) ORDER BY typname" + self.cursor.execute(query) return [t[0] for t in self.cursor.fetchall()] # Manipulating privileges @@ -1044,7 +1081,7 @@ def main(): p = type('Params', (), module.params) # param "schema": default, allowed depends on param "type" if p.type in ['table', 'sequence', 'function', 'procedure', 'type', 'default_privs']: - if p.objs == 'schemas': + if p.objs == 'schemas' or p.schema == 'not-specified': p.schema = None else: p.schema = p.schema or 'public' diff --git a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml index 4e4ac097..99456a59 100644 --- a/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml +++ b/tests/integration/targets/postgresql_privs/tasks/postgresql_privs_general.yml @@ -1494,6 +1494,56 @@ that: - result is changed +- name: Test community.postgresql issue 332 grant usage, run again + become: yes + become_user: "{{ pg_user }}" + postgresql_privs: + login_user: "{{ pg_user }}" + login_db: "{{ db_name }}" + roles: "{{ db_user3 }}" + objs: schemas + type: default_privs + privs: usage + register: result + +- assert: + that: + - result is not changed + +- name: Test community.postgresql issue 333 grant usage + become: yes + become_user: "{{ pg_user }}" + postgresql_privs: + login_user: "{{ pg_user }}" + login_db: "{{ db_name }}" + roles: "{{ db_user3 }}" + objs: tables + type: default_privs + schema: not-specified + privs: select + register: result + +- assert: + that: + - result is changed + +- name: Test community.postgresql issue 333 grant usage, run again + become: yes + become_user: "{{ pg_user }}" + postgresql_privs: + login_user: "{{ pg_user }}" + login_db: "{{ db_name }}" + roles: "{{ db_user3 }}" + objs: tables + type: default_privs + schema: not-specified + privs: select + register: result + +- assert: + that: + - result is not changed + # Cleanup - name: Remove privs become: yes From dad1f241a60da8b020dad8c808f532bcb891d65d Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 09:51:52 +0200 Subject: [PATCH 5/6] update changelog and documentation --- .../fragments/332-postgresql_privs_def_privs_schemas.yml | 1 + plugins/modules/postgresql_privs.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml b/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml index 969da64c..0a82e007 100644 --- a/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml +++ b/changelogs/fragments/332-postgresql_privs_def_privs_schemas.yml @@ -1,2 +1,3 @@ bugfixes: - postgresql_privs - add support for alter default privileges grant usage on schemas (https://github.com/ansible-collections/community.postgresql/issues/332). +- postgresql_privs - cannot grant select on objects in all schemas; add the ``not-specified`` value to the ``schema`` parameter to make this possible (https://github.com/ansible-collections/community.postgresql/issues/332). diff --git a/plugins/modules/postgresql_privs.py b/plugins/modules/postgresql_privs.py index 3bcc8e1d..8af04db9 100644 --- a/plugins/modules/postgresql_privs.py +++ b/plugins/modules/postgresql_privs.py @@ -75,6 +75,7 @@ or C(default_privs). Defaults to C(public) in these cases. - Pay attention, for embedded types when I(type=type) I(schema) can be C(pg_catalog) or C(information_schema) respectively. + - If not specified, uses C(public). To avoid this, use C(not-specified). type: str roles: description: @@ -430,6 +431,14 @@ objs: numeric schema: pg_catalog db: acme + +- name: Alter default privileges grant usage on schemas to datascience + community.postgresql.postgresql_privs: + database: test + type: default_privs + privs: usage + objs: schemas + role: datascience ''' RETURN = r''' From a782fa7e4f78386f44193653a8e8d0af22b34f36 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 09:54:20 +0200 Subject: [PATCH 6/6] Fix --- plugins/modules/postgresql_privs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/postgresql_privs.py b/plugins/modules/postgresql_privs.py index 8af04db9..8fd4ee9d 100644 --- a/plugins/modules/postgresql_privs.py +++ b/plugins/modules/postgresql_privs.py @@ -75,7 +75,7 @@ or C(default_privs). Defaults to C(public) in these cases. - Pay attention, for embedded types when I(type=type) I(schema) can be C(pg_catalog) or C(information_schema) respectively. - - If not specified, uses C(public). To avoid this, use C(not-specified). + - If not specified, uses C(public). Not to pass any schema, use C(not-specified). type: str roles: description: