diff --git a/changelogs/fragments/58704_postgresql_query_add-autocommit-param.yml b/changelogs/fragments/58704_postgresql_query_add-autocommit-param.yml new file mode 100644 index 00000000000..9af22bf668d --- /dev/null +++ b/changelogs/fragments/58704_postgresql_query_add-autocommit-param.yml @@ -0,0 +1,2 @@ +minor_changes: +- postgresql_query - add autocommit parameter to support commands that can't be run inside a transaction block (https://github.com/ansible/ansible/pull/58704) diff --git a/lib/ansible/modules/database/postgresql/postgresql_query.py b/lib/ansible/modules/database/postgresql/postgresql_query.py index 0957bda98d9..60ba9551d9e 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_query.py +++ b/lib/ansible/modules/database/postgresql/postgresql_query.py @@ -56,6 +56,13 @@ options: type: str aliases: - login_db + autocommit: + description: + - Execute in autocommit mode when the query can't be run inside a transaction block + (e.g., VACUUM). + - Mutually exclusive with I(check_mode). + type: bool + version_added: '2.9' author: - Felix Archambault (@archf) - Andrew Klychkov (@Andersson007) @@ -98,6 +105,12 @@ EXAMPLES = r''' path_to_script: /var/lib/pgsql/test.sql positional_args: - 1 + +- name: Example of using autocommit parameter + postgresql_query: + db: test_db + query: VACUUM + autocommit: yes ''' RETURN = r''' @@ -156,6 +169,7 @@ def main(): named_args=dict(type='dict'), session_role=dict(type='str'), path_to_script=dict(type='path'), + autocommit=dict(type='bool'), ) module = AnsibleModule( @@ -168,6 +182,10 @@ def main(): positional_args = module.params["positional_args"] named_args = module.params["named_args"] path_to_script = module.params["path_to_script"] + autocommit = module.params["autocommit"] + + if autocommit and module.check_mode: + module.fail_json(msg="Using autocommit is mutually exclusive with check_mode") if positional_args and named_args: module.fail_json(msg="positional_args and named_args params are mutually exclusive") @@ -182,7 +200,7 @@ def main(): module.fail_json(msg="Cannot read file '%s' : %s" % (path_to_script, to_native(e))) 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=autocommit) cursor = db_connection.cursor(cursor_factory=DictCursor) # Prepare args: @@ -236,7 +254,8 @@ def main(): if module.check_mode: db_connection.rollback() else: - db_connection.commit() + if not autocommit: + db_connection.commit() kw = dict( changed=changed, diff --git a/test/integration/targets/postgresql/tasks/postgresql_query.yml b/test/integration/targets/postgresql/tasks/postgresql_query.yml index 88a04e87471..6bdfeb28318 100644 --- a/test/integration/targets/postgresql/tasks/postgresql_query.yml +++ b/test/integration/targets/postgresql/tasks/postgresql_query.yml @@ -184,6 +184,53 @@ - result.statusmessage == 'UPDATE 1' - result.query_result == {} +# Check: +- name: check the previous update + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: SELECT * FROM test_table WHERE story = 'new' AND id = 3 + register: result + +- assert: + that: + - result.rowcount == 1 + +# Test check_mode: +- name: postgresql_query - simple update query in check_mode + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: UPDATE test_table SET story = 'CHECK_MODE' WHERE id = 3 + register: result + check_mode: yes + +- assert: + that: + - result.changed == true + - result.query == "UPDATE test_table SET story = 'CHECK_MODE' WHERE id = 3" + - result.rowcount == 1 + - result.statusmessage == 'UPDATE 1' + - result.query_result == {} + +# Check: +- name: check the previous update that nothing has been changed + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: SELECT * FROM test_table WHERE story = 'CHECK_MODE' AND id = 3 + register: result + +- assert: + that: + - result.rowcount == 0 + # Try to update not existing row: - name: postgresql_query - try to update not existing row become_user: "{{ pg_user }}" @@ -261,3 +308,55 @@ - result.query == "ALTER TABLE test_table ADD COLUMN foo int" - result.rowcount == 0 - result.statusmessage == 'ALTER TABLE' + +############################# +# Test autocommit parameter # +############################# +- name: postgresql_query - vacuum without autocommit must fail + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: VACUUM + register: result + ignore_errors: yes + +- assert: + that: + - result.failed == true + +- name: postgresql_query - autocommit in check_mode must fail + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: VACUUM + autocommit: yes + check_mode: yes + register: result + ignore_errors: yes + +- assert: + that: + - result.failed == true + - result.msg == "Using autocommit is mutually exclusive with check_mode" + +- name: postgresql_query - vacuum with autocommit + become_user: "{{ pg_user }}" + become: yes + postgresql_query: + login_user: "{{ pg_user }}" + db: postgres + query: VACUUM + autocommit: yes + register: result + +- assert: + that: + - result.changed == true + - result.query == "VACUUM" + - result.rowcount == 0 + - result.statusmessage == 'VACUUM' + - result.query_result == {}