diff --git a/changelogs/fragments/84238-fix-reset_connection-ssh_executable-templated.yml b/changelogs/fragments/84238-fix-reset_connection-ssh_executable-templated.yml new file mode 100644 index 00000000000..7bf013a0616 --- /dev/null +++ b/changelogs/fragments/84238-fix-reset_connection-ssh_executable-templated.yml @@ -0,0 +1,2 @@ +minor_changes: + - ssh - connection options were incorrectly templated during ``reset_connection`` tasks (https://github.com/ansible/ansible/pull/84238). diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index ff1c33871f2..ec3509ea756 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -1073,18 +1073,6 @@ class TaskExecutor: option_vars = C.config.get_plugin_vars('connection', self._connection._load_name) varnames.extend(option_vars) - # create dict of 'templated vars' - options = {'_extras': {}} - for k in option_vars: - if k in variables: - options[k] = templar.template(variables[k]) - - # add extras if plugin supports them - if getattr(self._connection, 'allow_extras', False): - for k in variables: - if k.startswith('ansible_%s_' % self._connection.extras_prefix) and k not in options: - options['_extras'][k] = templar.template(variables[k]) - task_keys = self._task.dump_attrs() # The task_keys 'timeout' attr is the task's timeout, not the connection timeout. @@ -1102,7 +1090,8 @@ class TaskExecutor: del task_keys['retries'] # set options with 'templated vars' specific to this plugin and dependent ones - self._connection.set_options(task_keys=task_keys, var_options=options) + var_options = self._connection._var_options(variables, templar) + self._connection.set_options(task_keys=task_keys, var_options=var_options) varnames.extend(self._set_plugin_options('shell', variables, templar, task_keys)) if self._connection.become is not None: diff --git a/lib/ansible/plugins/connection/__init__.py b/lib/ansible/plugins/connection/__init__.py index de4a79e9818..77384306b0b 100644 --- a/lib/ansible/plugins/connection/__init__.py +++ b/lib/ansible/plugins/connection/__init__.py @@ -285,6 +285,24 @@ class ConnectionBase(AnsiblePlugin): display.debug('Set connection var {0} to {1}'.format(varname, value)) variables[varname] = value + # TODO find better name and place for this. Public API? On AnsiblePlugin? + def _var_options(self, variables, templar): + # create dict of 'templated vars' + var_options = { + '_extras': {}, + } + for var_name in C.config.get_plugin_vars('connection', self._load_name): + if var_name in variables: + var_options[var_name] = templar.template(variables[var_name]) + + # add extras if plugin supports them + if getattr(self, 'allow_extras', False): + for var_name in variables: + if var_name.startswith(f'ansible_{self.extras_prefix}_') and var_name not in var_options: + var_options['_extras'][var_name] = templar.template(variables[var_name]) + + return var_options + class NetworkConnectionBase(ConnectionBase): """ diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py index 3eb5538b96d..c58ea7663d8 100644 --- a/lib/ansible/plugins/strategy/__init__.py +++ b/lib/ansible/plugins/strategy/__init__.py @@ -1068,7 +1068,8 @@ class StrategyBase: del self._active_connections[target_host] else: connection = plugin_loader.connection_loader.get(play_context.connection, play_context, os.devnull) - connection.set_options(task_keys=task.dump_attrs(), var_options=all_vars) + var_options = connection._var_options(all_vars, templar) + connection.set_options(task_keys=task.dump_attrs(), var_options=var_options) play_context.set_attributes_from_plugin(connection) if connection: