diff --git a/v2/ansible/parsing/mod_args.py b/v2/ansible/parsing/mod_args.py index d4627800515..5e7c4225dfa 100644 --- a/v2/ansible/parsing/mod_args.py +++ b/v2/ansible/parsing/mod_args.py @@ -198,6 +198,12 @@ class ModuleArgsParser: delegate_to = None args = dict() + + # + # We can have one of action, local_action, or module specified + # + + # action if 'action' in ds: # an old school 'action' statement @@ -205,7 +211,8 @@ class ModuleArgsParser: delegate_to = None action, args = self._normalize_parameters(thing) - elif 'local_action' in ds: + # local_action + if 'local_action' in ds: # local_action is similar but also implies a delegate_to if action is not None: @@ -214,21 +221,17 @@ class ModuleArgsParser: delegate_to = 'localhost' action, args = self._normalize_parameters(thing) - else: - - # module: is the more new-style invocation - if action is not None: - raise AnsibleParserError("conflicting action statements", obj=self._task) - - # walk the input dictionary to see we recognize a module name - for (item, value) in iteritems(ds): - if item in module_finder: - # finding more than one module name is a problem - if action is not None: - raise AnsibleParserError("conflicting action statements", obj=self._task) - action = item - thing = value - action, args = self._normalize_parameters(value, action=action) + # module: is the more new-style invocation + + # walk the input dictionary to see we recognize a module name + for (item, value) in iteritems(ds): + if item in module_finder: + # finding more than one module name is a problem + if action is not None: + raise AnsibleParserError("conflicting action statements", obj=self._task) + action = item + thing = value + action, args = self._normalize_parameters(value, action=action) # if we didn't see any module in the task at all, it's not a task really if action is None: diff --git a/v2/test/parsing/test_mod_args.py b/v2/test/parsing/test_mod_args.py index 8268e6126b9..0f9ee28decb 100644 --- a/v2/test/parsing/test_mod_args.py +++ b/v2/test/parsing/test_mod_args.py @@ -20,6 +20,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible.parsing.mod_args import ModuleArgsParser +from ansible.errors import AnsibleParserError from ansible.compat.tests import unittest @@ -106,3 +107,9 @@ class TestModArgsDwim(unittest.TestCase): self.assertEqual(mod, 'copy') self.assertEqual(args, dict(src='a', dest='b')) self.assertIs(to, 'localhost') + + def test_multiple_actions(self): + self.assertRaises(AnsibleParserError, self.m.parse, dict(action='shell echo hi', local_action='shell echo hi')) + self.assertRaises(AnsibleParserError, self.m.parse, dict(action='shell echo hi', shell='echo hi')) + self.assertRaises(AnsibleParserError, self.m.parse, dict(local_action='shell echo hi', shell='echo hi')) + self.assertRaises(AnsibleParserError, self.m.parse, dict(ping='data=hi', shell='echo hi'))