summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--changelogs/fragments/38803-postgresql_privs_fdw_and_fs_obj_types.yaml3
-rw-r--r--lib/ansible/modules/database/postgresql/postgresql_privs.py43
-rw-r--r--test/integration/targets/postgresql/tasks/main.yml3
-rw-r--r--test/integration/targets/postgresql/tasks/postgresql_privs.yml239
4 files changed, 285 insertions, 3 deletions
diff --git a/changelogs/fragments/38803-postgresql_privs_fdw_and_fs_obj_types.yaml b/changelogs/fragments/38803-postgresql_privs_fdw_and_fs_obj_types.yaml
new file mode 100644
index 0000000000..87f0e0d970
--- /dev/null
+++ b/changelogs/fragments/38803-postgresql_privs_fdw_and_fs_obj_types.yaml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+ - "postgresql_privs - introduces support for FOREIGN DATA WRAPPER and FOREIGN SERVER as object types in postgresql_privs module. (https://github.com/ansible/ansible/issues/38801)"
diff --git a/lib/ansible/modules/database/postgresql/postgresql_privs.py b/lib/ansible/modules/database/postgresql/postgresql_privs.py
index 95f5fca886..201694ed60 100644
--- a/lib/ansible/modules/database/postgresql/postgresql_privs.py
+++ b/lib/ansible/modules/database/postgresql/postgresql_privs.py
@@ -41,10 +41,11 @@ options:
description:
- Type of database object to set privileges on.
- The `default_prives` choice is available starting at version 2.7.
+ - The 'foreign_data_wrapper' and 'foreign_server' object types are available from Ansible version '2.8'.
default: table
choices: [table, sequence, function, database,
schema, language, tablespace, group,
- default_privs]
+ default_privs, foreign_data_wrapper, foreign_server]
objs:
description:
- Comma separated list of database objects to set privileges on.
@@ -272,6 +273,23 @@ EXAMPLES = """
type: default_privs
role: reader
+# Available since version 2.8
+# GRANT ALL PRIVILEGES ON FOREIGN DATA WRAPPER fdw TO reader
+- postgresql_privs:
+ db: test
+ objs: fdw
+ privs: ALL
+ type: foreign_data_wrapper
+ role: reader
+
+# GRANT ALL PRIVILEGES ON FOREIGN SERVER fdw_server TO reader
+- postgresql_privs:
+ db: test
+ objs: fdw_server
+ privs: ALL
+ type: foreign_server
+ role: reader
+
"""
import traceback
@@ -484,6 +502,18 @@ class Connection(object):
self.cursor.execute(query, (schema,))
return [t[0] for t in self.cursor.fetchall()]
+ def get_foreign_data_wrapper_acls(self, fdws):
+ query = """SELECT fdwacl FROM pg_catalog.pg_foreign_data_wrapper
+ WHERE fdwname = ANY (%s) ORDER BY fdwname"""
+ self.cursor.execute(query, (fdws,))
+ return [t[0] for t in self.cursor.fetchall()]
+
+ def get_foreign_server_acls(self, fs):
+ query = """SELECT srvacl FROM pg_catalog.pg_foreign_server
+ WHERE srvname = ANY (%s) ORDER BY srvname"""
+ self.cursor.execute(query, (fs,))
+ return [t[0] for t in self.cursor.fetchall()]
+
# Manipulating privileges
def manipulate_privs(self, obj_type, privs, objs, roles,
@@ -525,6 +555,10 @@ class Connection(object):
get_status = self.get_group_memberships
elif obj_type == 'default_privs':
get_status = partial(self.get_default_privs, schema_qualifier)
+ elif obj_type == 'foreign_data_wrapper':
+ get_status = self.get_foreign_data_wrapper_acls
+ elif obj_type == 'foreign_server':
+ get_status = self.get_foreign_server_acls
else:
raise Error('Unsupported database object type "%s".' % obj_type)
@@ -559,7 +593,8 @@ class Connection(object):
obj_ids = [pg_quote_identifier(i, 'table') for i in obj_ids]
# Note: obj_type has been checked against a set of string literals
# and privs was escaped when it was parsed
- set_what = '%s ON %s %s' % (','.join(privs), obj_type,
+ # Note: Underscores are replaced with spaces to support multi-word obj_type
+ set_what = '%s ON %s %s' % (','.join(privs), obj_type.replace('_', ' '),
','.join(obj_ids))
# for_whom: SQL-fragment specifying for whom to set the above
@@ -706,7 +741,9 @@ def main():
'language',
'tablespace',
'group',
- 'default_privs']),
+ 'default_privs',
+ 'foreign_data_wrapper',
+ 'foreign_server']),
objs=dict(required=False, aliases=['obj']),
schema=dict(required=False),
roles=dict(required=True, aliases=['role']),
diff --git a/test/integration/targets/postgresql/tasks/main.yml b/test/integration/targets/postgresql/tasks/main.yml
index 5dd45350a7..2f35a61fd9 100644
--- a/test/integration/targets/postgresql/tasks/main.yml
+++ b/test/integration/targets/postgresql/tasks/main.yml
@@ -777,6 +777,9 @@
# Test postgresql_tablespace module
- include: postgresql_tablespace.yml
+# Test postgresql_privs
+- include: postgresql_privs.yml
+
# dump/restore tests per format
# ============================================================
- include: state_dump_restore.yml test_fixture=user file=dbdata.sql
diff --git a/test/integration/targets/postgresql/tasks/postgresql_privs.yml b/test/integration/targets/postgresql/tasks/postgresql_privs.yml
new file mode 100644
index 0000000000..f77cd0ea6f
--- /dev/null
+++ b/test/integration/targets/postgresql/tasks/postgresql_privs.yml
@@ -0,0 +1,239 @@
+---
+
+######################################################
+# Test foreign data wrapper and foreign server privs #
+######################################################
+
+- name: Create DB
+ become_user: "{{ pg_user }}"
+ become: True
+ postgresql_db:
+ state: present
+ name: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+
+- name: Create test role
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "CREATE ROLE fdw_test" | psql -d "{{ db_name }}"
+
+- name: Create fdw extension
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "CREATE EXTENSION postgres_fdw" | psql -d "{{ db_name }}"
+
+- name: Create foreign data wrapper
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "CREATE FOREIGN DATA WRAPPER dummy" | psql -d "{{ db_name }}"
+
+- name: Create foreign server
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "CREATE SERVER dummy_server FOREIGN DATA WRAPPER dummy" | psql -d "{{ db_name }}"
+
+- name: Grant foreign data wrapper privileges
+ postgresql_privs:
+ state: present
+ type: foreign_data_wrapper
+ roles: fdw_test
+ privs: ALL
+ objs: dummy
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == true"
+
+- name: Get foreign data wrapper privileges
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "{{ fdw_query }}" | psql -d "{{ db_name }}"
+ vars:
+ fdw_query: >
+ SELECT fdwacl FROM pg_catalog.pg_foreign_data_wrapper
+ WHERE fdwname = ANY (ARRAY['dummy']) ORDER BY fdwname
+ register: fdw_result
+
+- assert:
+ that:
+ - "fdw_result.stdout_lines[-1] == '(1 row)'"
+ - "'fdw_test' in fdw_result.stdout_lines[-2]"
+
+- name: Grant foreign data wrapper privileges second time
+ postgresql_privs:
+ state: present
+ type: foreign_data_wrapper
+ roles: fdw_test
+ privs: ALL
+ objs: dummy
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == false"
+
+- name: Revoke foreign data wrapper privileges
+ postgresql_privs:
+ state: absent
+ type: foreign_data_wrapper
+ roles: fdw_test
+ privs: ALL
+ objs: dummy
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == true"
+
+- name: Get foreign data wrapper privileges
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "{{ fdw_query }}" | psql -d "{{ db_name }}"
+ vars:
+ fdw_query: >
+ SELECT fdwacl FROM pg_catalog.pg_foreign_data_wrapper
+ WHERE fdwname = ANY (ARRAY['dummy']) ORDER BY fdwname
+ register: fdw_result
+
+- assert:
+ that:
+ - "fdw_result.stdout_lines[-1] == '(1 row)'"
+ - "'fdw_test' not in fdw_result.stdout_lines[-2]"
+
+- name: Revoke foreign data wrapper privileges for second time
+ postgresql_privs:
+ state: absent
+ type: foreign_data_wrapper
+ roles: fdw_test
+ privs: ALL
+ objs: dummy
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == false"
+
+- name: Grant foreign server privileges
+ postgresql_privs:
+ state: present
+ type: foreign_server
+ roles: fdw_test
+ privs: ALL
+ objs: dummy_server
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == true"
+
+- name: Get foreign server privileges
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "{{ fdw_query }}" | psql -d "{{ db_name }}"
+ vars:
+ fdw_query: >
+ SELECT srvacl FROM pg_catalog.pg_foreign_server
+ WHERE srvname = ANY (ARRAY['dummy_server']) ORDER BY srvname
+ register: fs_result
+
+- assert:
+ that:
+ - "fs_result.stdout_lines[-1] == '(1 row)'"
+ - "'fdw_test' in fs_result.stdout_lines[-2]"
+
+- name: Grant foreign server privileges for second time
+ postgresql_privs:
+ state: present
+ type: foreign_server
+ roles: fdw_test
+ privs: ALL
+ objs: dummy_server
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == false"
+
+- name: Revoke foreign server privileges
+ postgresql_privs:
+ state: absent
+ type: foreign_server
+ roles: fdw_test
+ privs: ALL
+ objs: dummy_server
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == true"
+
+- name: Get foreign server privileges
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "{{ fdw_query }}" | psql -d "{{ db_name }}"
+ vars:
+ fdw_query: >
+ SELECT srvacl FROM pg_catalog.pg_foreign_server
+ WHERE srvname = ANY (ARRAY['dummy_server']) ORDER BY srvname
+ register: fs_result
+
+- assert:
+ that:
+ - "fs_result.stdout_lines[-1] == '(1 row)'"
+ - "'fdw_test' not in fs_result.stdout_lines[-2]"
+
+- name: Revoke foreign server privileges for second time
+ postgresql_privs:
+ state: absent
+ type: foreign_server
+ roles: fdw_test
+ privs: ALL
+ objs: dummy_server
+ db: "{{ db_name }}"
+ login_user: "{{ pg_user }}"
+ register: result
+ ignore_errors: yes
+
+- assert:
+ that:
+ - "result.changed == false"
+
+- name: Cleanup
+ become: True
+ become_user: "{{ pg_user }}"
+ shell: echo "{{ item }}" | psql -d "{{ db_name }}"
+ with_items:
+ - DROP ROLE fdw_test
+ - DROP FOREIGN DATA WRAPPER dummy
+ - DROP SERVER dummy_server
+
+- name: Destroy DB
+ become_user: "{{ pg_user }}"
+ become: True
+ postgresql_db:
+ state: absent
+ name: "{{ db_name }}"
+ login_user: "{{ pg_user }}"