From 6cd90d30d79594a93509ab1aa311eb59b95402f5 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 20:48:59 +0100 Subject: [PATCH] [PR #7976/beacd54b backport][stable-8] Added transactional(rollback/commit) support to mssql_script module (#8017) Added transactional(rollback/commit) support to mssql_script module (#7976) * Added transactional(rollback/commit) support to mssql_script module via optional boolean param 'transaction' * Added changelog fragment * Implemented PR Review comments by felixfontein (cherry picked from commit beacd54b7b334837b57052197bbbbdf5c1c58699) Co-authored-by: Udit Yadav <36297285+BlackHat786000@users.noreply.github.com> --- ...add-mssql_script-transactional-support.yml | 2 ++ plugins/modules/mssql_script.py | 34 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/7976-add-mssql_script-transactional-support.yml diff --git a/changelogs/fragments/7976-add-mssql_script-transactional-support.yml b/changelogs/fragments/7976-add-mssql_script-transactional-support.yml new file mode 100644 index 0000000000..dc6f335247 --- /dev/null +++ b/changelogs/fragments/7976-add-mssql_script-transactional-support.yml @@ -0,0 +1,2 @@ +minor_changes: + - mssql_script - adds transactional (rollback/commit) support via optional boolean param ``transaction`` (https://github.com/ansible-collections/community.general/pull/7976). diff --git a/plugins/modules/mssql_script.py b/plugins/modules/mssql_script.py index 00b92e7312..b1713092c8 100644 --- a/plugins/modules/mssql_script.py +++ b/plugins/modules/mssql_script.py @@ -56,6 +56,14 @@ options: - Each batch must return at least one result set. required: true type: str + transaction: + description: + - If transactional mode is requested, start a transaction and commit the change only if the script succeed. + Otherwise, rollback the transaction. + - If transactional mode is not requested (default), automatically commit the change. + type: bool + default: false + version_added: 8.4.0 output: description: - With V(default) each row will be returned as a list of values. See RV(query_results). @@ -105,6 +113,19 @@ EXAMPLES = r''' - result_params.query_results[0][0][0][0] == 'msdb' - result_params.query_results[0][0][0][1] == 'ONLINE' +- name: Query within a transaction + community.general.mssql_script: + login_user: "{{ mssql_login_user }}" + login_password: "{{ mssql_login_password }}" + login_host: "{{ mssql_host }}" + login_port: "{{ mssql_port }}" + script: | + UPDATE sys.SomeTable SET desc = 'some_table_desc' WHERE name = %(dbname)s + UPDATE sys.AnotherTable SET desc = 'another_table_desc' WHERE name = %(dbname)s + transaction: true + params: + dbname: msdb + - name: two batches with default output community.general.mssql_script: login_user: "{{ mssql_login_user }}" @@ -230,6 +251,7 @@ def run_module(): script=dict(required=True), output=dict(default='default', choices=['dict', 'default']), params=dict(type='dict'), + transaction=dict(type='bool', default=False), ) result = dict( @@ -252,6 +274,8 @@ def run_module(): script = module.params['script'] output = module.params['output'] sql_params = module.params['params'] + # Added param to set the transactional mode (true/false) + transaction = module.params['transaction'] login_querystring = login_host if login_port != 1433: @@ -273,7 +297,8 @@ def run_module(): module.fail_json(msg="unable to connect, check login_user and login_password are correct, or alternatively check your " "@sysconfdir@/freetds.conf / ${HOME}/.freetds.conf") - conn.autocommit(True) + # If transactional mode is requested, start a transaction + conn.autocommit(not transaction) query_results_key = 'query_results' if output == 'dict': @@ -322,9 +347,16 @@ def run_module(): ): query_results.append([]) else: + # Rollback transaction before failing the module in case of error + if transaction: + conn.rollback() error_msg = '%s: %s' % (type(e).__name__, str(e)) module.fail_json(msg="query failed", query=query, error=error_msg, **result) + # Commit transaction before exiting the module in case of no error + if transaction: + conn.commit() + # ensure that the result is json serializable qry_results = json.loads(json.dumps(query_results, default=clean_output))