Permalink
Browse files

Fixes for module param counting and additional shell quoting issues

  • Loading branch information...
1 parent 091b76e commit 2cc602beeaca6ce696c882ce7e59348c39a81330 @jimi-c jimi-c committed Jul 24, 2014
Showing with 24 additions and 16 deletions.
  1. +14 −11 lib/ansible/runner/__init__.py
  2. +10 −5 library/commands/command
@@ -389,7 +389,7 @@ def _compute_delegate_user(self, host, inject):
return actual_user
- def _count_module_args(self, args):
+ def _count_module_args(self, args, allow_dupes=False):
'''
Count the number of k=v pairs in the supplied module args. This is
basically a specialized version of parse_kv() from utils with a few
@@ -399,23 +399,26 @@ def _count_module_args(self, args):
if args is not None:
args = args.encode('utf-8')
try:
- lexer = shlex.shlex(args, posix=True)
+ lexer = shlex.shlex(args)
+ lexer.whitespace = '\t '
lexer.whitespace_split = True
- lexer.quotes = '"'
- lexer.ignore_quotes = "'"
- vargs = list(lexer)
+ vargs = [x.decode('utf-8') for x in lexer]
except ValueError, ve:
if 'no closing quotation' in str(ve).lower():
raise errors.AnsibleError("error parsing argument string '%s', try quoting the entire line." % args)
else:
raise
- vargs = [x.decode('utf-8') for x in vargs]
for x in vargs:
- if "=" in x:
+ quoted = x.startswith('"') and x.endswith('"') or x.startswith("'") and x.endswith("'")
+ if "=" in x and not quoted:
k, v = x.split("=",1)
- if k in options:
- raise errors.AnsibleError("a duplicate parameter was found in the argument string (%s)" % k)
- options[k] = v
+ is_shell_module = self.module_name in ('command', 'shell')
+ is_shell_param = k in ('creates', 'removes', 'chdir', 'executable')
+ if k in options and not allow_dupes:
+ if not(is_shell_module and not is_shell_param):
+ raise errors.AnsibleError("a duplicate parameter was found in the argument string (%s)" % k)
+ if is_shell_module and is_shell_param or not is_shell_module:
+ options[k] = v
return len(options)
@@ -863,7 +866,7 @@ def _executor_internal_inner(self, host, module_name, module_args, inject, port,
# that no variables inadvertantly (or maliciously) add params
# to the list of args. We do this by counting the number of k=v
# pairs before and after templating.
- num_args_pre = self._count_module_args(module_args)
+ num_args_pre = self._count_module_args(module_args, allow_dupes=True)
module_args = template.template(self.basedir, module_args, inject, fail_on_undefined=self.error_on_undefined_vars)
num_args_post = self._count_module_args(module_args)
if num_args_pre != num_args_post:
View
@@ -213,16 +213,21 @@ class CommandModule(AnsibleModule):
# use shlex to split up the args, while being careful to preserve
# single quotes so they're not removed accidentally
- lexer = shlex.shlex(args, posix=True)
+ lexer = shlex.shlex(args)
+ lexer.whitespace = '\t '
lexer.whitespace_split = True
- lexer.quotes = '"'
- lexer.ignore_quotes = "'"
items = list(lexer)
for x in items:
- if '=' in x:
+ quoted = x.startswith('"') and x.endswith('"') or x.startswith("'") and x.endswith("'")
+ if '=' in x and not quoted:
# check to see if this is a special parameter for the command
k, v = x.split('=', 1)
+ # because we're not breaking out quotes in the shlex split
+ # above, the value of the k=v pair may still be quoted. If
+ # so, remove them.
+ if len(v) > 1 and (v.startswith('"') and v.endswith('"') or v.startswith("'") and v.endswith("'")):
+ v = v[1:-1]
if k in ('creates', 'removes', 'chdir', 'executable', 'NO_LOG'):
if k == "chdir":
v = os.path.abspath(os.path.expanduser(v))
@@ -235,7 +240,7 @@ class CommandModule(AnsibleModule):
params[k] = v
# Remove any of the above k=v params from the args string
args = PARAM_REGEX.sub('', args)
- params['args'] = args
+ params['args'] = args.strip()
return (params, params['args'])
main()

0 comments on commit 2cc602b

Please sign in to comment.