postgresql_lang: add owner parameter (#62999)

* postgresql_lang: add owner parameter

* postgresql_lang: add owner parameter, add changelog fragment
This commit is contained in:
Andrey Klychkov 2019-10-03 15:33:06 +03:00 committed by Abhijit Menon-Sen
parent ea86b2c2f7
commit ad5200a7c0
4 changed files with 251 additions and 1 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- postgresql_lang - add ``owner`` parameter (https://github.com/ansible/ansible/pull/62999).

View file

@ -103,6 +103,12 @@ options:
type: str type: str
aliases: [ ssl_rootcert ] aliases: [ ssl_rootcert ]
version_added: '2.8' version_added: '2.8'
owner:
description:
- Set an owner for the language.
- Ignored when I(state=absent).
type: str
version_added: '2.10'
seealso: seealso:
- name: PostgreSQL languages - name: PostgreSQL languages
description: General information about PostgreSQL languages. description: General information about PostgreSQL languages.
@ -156,6 +162,12 @@ EXAMPLES = r'''
lang: pltclu lang: pltclu
state: absent state: absent
fail_on_drop: no fail_on_drop: no
- name: In testdb change owner of mylang to alice
postgresql_lang:
db: testdb
lang: mylang
owner: alice
''' '''
RETURN = r''' RETURN = r'''
@ -228,6 +240,34 @@ def lang_drop(cursor, lang, cascade):
return True return True
def get_lang_owner(cursor, lang):
"""Get language owner.
Args:
cursor (cursor): psycopg2 cursor object.
lang (str): language name.
"""
query = ("SELECT r.rolname FROM pg_language l "
"JOIN pg_roles r ON l.lanowner = r.oid "
"WHERE l.lanname = '%s'" % lang)
cursor.execute(query)
return cursor.fetchone()[0]
def set_lang_owner(cursor, lang, owner):
"""Set language owner.
Args:
cursor (cursor): psycopg2 cursor object.
lang (str): language name.
owner (str): name of new owner.
"""
query = "ALTER LANGUAGE %s OWNER TO %s" % (lang, owner)
executed_queries.append(query)
cursor.execute(query)
return True
def main(): def main():
argument_spec = postgres_common_argument_spec() argument_spec = postgres_common_argument_spec()
argument_spec.update( argument_spec.update(
@ -239,6 +279,7 @@ def main():
cascade=dict(type="bool", default="no"), cascade=dict(type="bool", default="no"),
fail_on_drop=dict(type="bool", default="yes"), fail_on_drop=dict(type="bool", default="yes"),
session_role=dict(type="str"), session_role=dict(type="str"),
owner=dict(type="str"),
) )
module = AnsibleModule( module = AnsibleModule(
@ -253,6 +294,7 @@ def main():
force_trust = module.params["force_trust"] force_trust = module.params["force_trust"]
cascade = module.params["cascade"] cascade = module.params["cascade"]
fail_on_drop = module.params["fail_on_drop"] fail_on_drop = module.params["fail_on_drop"]
owner = module.params["owner"]
conn_params = get_conn_params(module, module.params) conn_params = get_conn_params(module, module.params)
db_connection = connect_to_db(module, conn_params, autocommit=False) db_connection = connect_to_db(module, conn_params, autocommit=False)
@ -285,10 +327,16 @@ def main():
else: else:
changed = lang_drop(cursor, lang, cascade) changed = lang_drop(cursor, lang, cascade)
if fail_on_drop and not changed: if fail_on_drop and not changed:
msg = "unable to drop language, use cascade to delete dependencies or fail_on_drop=no to ignore" msg = ("unable to drop language, use cascade "
"to delete dependencies or fail_on_drop=no to ignore")
module.fail_json(msg=msg) module.fail_json(msg=msg)
kw['lang_dropped'] = changed kw['lang_dropped'] = changed
if owner and state == 'present':
if lang_exists(cursor, lang):
if owner != get_lang_owner(cursor, lang):
changed = set_lang_owner(cursor, lang, owner)
if changed: if changed:
if module.check_mode: if module.check_mode:
db_connection.rollback() db_connection.rollback()

View file

@ -1,3 +1,7 @@
# Initial CI tests of postgresql_lang module # Initial CI tests of postgresql_lang module
- import_tasks: postgresql_lang_initial.yml - import_tasks: postgresql_lang_initial.yml
when: ansible_distribution == 'CentOS' when: ansible_distribution == 'CentOS'
# CI tests of owner param
- import_tasks: postgresql_lang_add_owner_param.yml
when: ansible_distribution == 'CentOS'

View file

@ -0,0 +1,196 @@
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
- vars:
test_user1: alice
test_user2: bob
test_lang: plperl
non_existent_role: fake_role
task_parameters: &task_parameters
become_user: '{{ pg_user }}'
become: yes
register: result
pg_parameters: &pg_parameters
login_user: '{{ pg_user }}'
login_db: postgres
block:
- name: Create roles for tests
<<: *task_parameters
postgresql_user:
<<: *pg_parameters
name: '{{ item }}'
loop:
- '{{ test_user1 }}'
- '{{ test_user2 }}'
- name: Create lang with owner in check_mode
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
owner: '{{ test_user1 }}'
check_mode: yes
- assert:
that:
- result is changed
- result.queries == []
- name: Check that nothing was actually changed
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
AND r.rolname = '{{ test_user1 }}'
- assert:
that:
- result.rowcount == 0
- name: Create lang with owner
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
owner: '{{ test_user1 }}'
- assert:
that:
- result is changed
- result.queries == ['CREATE LANGUAGE "{{ test_lang }}"', 'ALTER LANGUAGE {{ test_lang }} OWNER TO {{ test_user1 }}']
- name: Check
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
AND r.rolname = '{{ test_user1 }}'
- assert:
that:
- result.rowcount == 1
- name: Change lang owner in check_mode
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
owner: '{{ test_user2 }}'
check_mode: yes
- assert:
that:
- result is changed
- result.queries == ["ALTER LANGUAGE {{ test_lang }} OWNER TO {{ test_user2 }}"]
- name: Check that nothing was actually changed
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
AND r.rolname = '{{ test_user2 }}'
- assert:
that:
- result.rowcount == 0
- name: Change lang owner
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
owner: '{{ test_user2 }}'
- assert:
that:
- result is changed
# TODO: the first elem of the returned list below
# looks like a bug, not related with the option owner, needs to be checked
- result.queries == ["UPDATE pg_language SET lanpltrusted = 'False' WHERE lanname = '{{ test_lang }}'", "ALTER LANGUAGE {{ test_lang }} OWNER TO {{ test_user2 }}"]
- name: Check
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
AND r.rolname = '{{ test_user2 }}'
- assert:
that:
- result.rowcount == 1
- name: Try to change lang owner again to the same role
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
owner: '{{ test_user2 }}'
- assert:
that:
- result is not changed
- result.queries == []
- name: Check
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
AND r.rolname = '{{ test_user2 }}'
- assert:
that:
- result.rowcount == 1
- name: Drop test lang with owner, must ignore
<<: *task_parameters
postgresql_lang:
<<: *pg_parameters
name: '{{ test_lang }}'
state: absent
owner: '{{ non_existent_role }}'
- assert:
that:
- result is changed
- result.queries == ["DROP LANGUAGE \"{{ test_lang }}\""]
- name: Check
<<: *task_parameters
postgresql_query:
<<: *pg_parameters
query: >
SELECT r.rolname FROM pg_language l
JOIN pg_roles r ON l.lanowner = r.oid
WHERE l.lanname = '{{ test_lang }}'
- assert:
that:
- result.rowcount == 0
# Clean up
- name: Drop test roles
<<: *task_parameters
postgresql_user:
<<: *pg_parameters
name: '{{ item }}'
state: absent
loop:
- '{{ test_user1 }}'
- '{{ test_user2 }}'