Better info sourcing (#77511)

Task is  authoritative
   also includes latest per loop info
   and fix tests
pull/77544/head
Brian Coca 3 years ago committed by GitHub
parent 793bb200ec
commit f2ab920822
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- action plugins now pass cannonical info to modules instead of 'temporary' info from play_context

@ -103,9 +103,9 @@ class ActionBase(ABC):
if self._task.async_val and not self._supports_async: if self._task.async_val and not self._supports_async:
raise AnsibleActionFail('async is not supported for this task.') raise AnsibleActionFail('async is not supported for this task.')
elif self._play_context.check_mode and not self._supports_check_mode: elif self._task.check_mode and not self._supports_check_mode:
raise AnsibleActionSkip('check mode is not supported for this task.') raise AnsibleActionSkip('check mode is not supported for this task.')
elif self._task.async_val and self._play_context.check_mode: elif self._task.async_val and self._task.check_mode:
raise AnsibleActionFail('check mode and async cannot be used on same task.') raise AnsibleActionFail('check mode and async cannot be used on same task.')
# Error if invalid argument is passed # Error if invalid argument is passed
@ -395,6 +395,20 @@ class ActionBase(ABC):
return self.get_shell_option('admin_users', ['root']) return self.get_shell_option('admin_users', ['root'])
def _get_remote_addr(self, tvars):
''' consistently get the 'remote_address' for the action plugin '''
remote_addr = tvars.get('delegated_vars', {}).get('ansible_host', tvars.get('ansible_host', tvars.get('inventory_hostname', None)))
for variation in ('remote_addr', 'host'):
try:
remote_addr = self._connection.get_option(variation)
except KeyError:
continue
break
else:
# plugin does not have, fallback to play_context
remote_addr = self._play_context.remote_addr
return remote_addr
def _get_remote_user(self): def _get_remote_user(self):
''' consistently get the 'remote_user' for the action plugin ''' ''' consistently get the 'remote_user' for the action plugin '''
# TODO: use 'current user running ansible' as fallback when moving away from play_context # TODO: use 'current user running ansible' as fallback when moving away from play_context
@ -929,7 +943,7 @@ class ActionBase(ABC):
expanded = initial_fragment expanded = initial_fragment
if '..' in os.path.dirname(expanded).split('/'): if '..' in os.path.dirname(expanded).split('/'):
raise AnsibleError("'%s' returned an invalid relative home directory path containing '..'" % self._play_context.remote_addr) raise AnsibleError("'%s' returned an invalid relative home directory path containing '..'" % self._get_remote_addr({}))
return expanded return expanded
@ -944,7 +958,7 @@ class ActionBase(ABC):
def _update_module_args(self, module_name, module_args, task_vars): def _update_module_args(self, module_name, module_args, task_vars):
# set check mode in the module arguments, if required # set check mode in the module arguments, if required
if self._play_context.check_mode: if self._task.check_mode:
if not self._supports_check_mode: if not self._supports_check_mode:
raise AnsibleError("check mode is not supported for this operation") raise AnsibleError("check mode is not supported for this operation")
module_args['_ansible_check_mode'] = True module_args['_ansible_check_mode'] = True
@ -953,13 +967,13 @@ class ActionBase(ABC):
# set no log in the module arguments, if required # set no log in the module arguments, if required
no_target_syslog = C.config.get_config_value('DEFAULT_NO_TARGET_SYSLOG', variables=task_vars) no_target_syslog = C.config.get_config_value('DEFAULT_NO_TARGET_SYSLOG', variables=task_vars)
module_args['_ansible_no_log'] = self._play_context.no_log or no_target_syslog module_args['_ansible_no_log'] = self._task.no_log or no_target_syslog
# set debug in the module arguments, if required # set debug in the module arguments, if required
module_args['_ansible_debug'] = C.DEFAULT_DEBUG module_args['_ansible_debug'] = C.DEFAULT_DEBUG
# let module know we are in diff mode # let module know we are in diff mode
module_args['_ansible_diff'] = self._play_context.diff module_args['_ansible_diff'] = self._task.diff
# let module know our verbosity # let module know our verbosity
module_args['_ansible_verbosity'] = display.verbosity module_args['_ansible_verbosity'] = display.verbosity
@ -1395,7 +1409,7 @@ class ActionBase(ABC):
diff['after_header'] = u'dynamically generated' diff['after_header'] = u'dynamically generated'
diff['after'] = source diff['after'] = source
if self._play_context.no_log: if self._task.no_log:
if 'before' in diff: if 'before' in diff:
diff["before"] = u"" diff["before"] = u""
if 'after' in diff: if 'after' in diff:

@ -283,6 +283,9 @@ class TestActionBase(unittest.TestCase):
play_context.become = True play_context.become = True
play_context.become_user = 'foo' play_context.become_user = 'foo'
mock_task.become = True
mock_task.become_user = True
# our test class # our test class
action_base = DerivedActionBase( action_base = DerivedActionBase(
task=mock_task, task=mock_task,
@ -654,6 +657,9 @@ class TestActionBase(unittest.TestCase):
mock_task = MagicMock() mock_task = MagicMock()
mock_task.action = 'copy' mock_task.action = 'copy'
mock_task.args = dict(a=1, b=2, c=3) mock_task.args = dict(a=1, b=2, c=3)
mock_task.diff = False
mock_task.check_mode = False
mock_task.no_log = False
# create a mock connection, so we don't actually try and connect to things # create a mock connection, so we don't actually try and connect to things
def build_module_command(env_string, shebang, cmd, arg_path=None): def build_module_command(env_string, shebang, cmd, arg_path=None):
@ -728,6 +734,8 @@ class TestActionBase(unittest.TestCase):
play_context.become = True play_context.become = True
play_context.become_user = 'foo' play_context.become_user = 'foo'
mock_task.become = True
mock_task.become_user = True
self.assertEqual(action_base._execute_module(), dict(_ansible_parsed=True, rc=0, stdout="ok", stdout_lines=['ok'])) self.assertEqual(action_base._execute_module(), dict(_ansible_parsed=True, rc=0, stdout="ok", stdout_lines=['ok']))
# test an invalid shebang return # test an invalid shebang return
@ -739,6 +747,7 @@ class TestActionBase(unittest.TestCase):
# test with check mode enabled, once with support for check # test with check mode enabled, once with support for check
# mode and once with support disabled to raise an error # mode and once with support disabled to raise an error
play_context.check_mode = True play_context.check_mode = True
mock_task.check_mode = True
action_base._configure_module.return_value = ('new', '#!/usr/bin/python', 'this is the module data', 'path') action_base._configure_module.return_value = ('new', '#!/usr/bin/python', 'this is the module data', 'path')
self.assertEqual(action_base._execute_module(), dict(_ansible_parsed=True, rc=0, stdout="ok", stdout_lines=['ok'])) self.assertEqual(action_base._execute_module(), dict(_ansible_parsed=True, rc=0, stdout="ok", stdout_lines=['ok']))
action_base._supports_check_mode = False action_base._supports_check_mode = False
@ -777,6 +786,7 @@ class TestActionBase(unittest.TestCase):
def test__remote_expand_user_relative_pathing(self): def test__remote_expand_user_relative_pathing(self):
action_base = _action_base() action_base = _action_base()
action_base._play_context.remote_addr = 'bar' action_base._play_context.remote_addr = 'bar'
action_base._connection.get_option.return_value = 'bar'
action_base._low_level_execute_command = MagicMock(return_value={'stdout': b'../home/user'}) action_base._low_level_execute_command = MagicMock(return_value={'stdout': b'../home/user'})
action_base._connection._shell.join_path.return_value = '../home/user/foo' action_base._connection._shell.join_path.return_value = '../home/user/foo'
with self.assertRaises(AnsibleError) as cm: with self.assertRaises(AnsibleError) as cm:

Loading…
Cancel
Save