Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable lists broken in only_if and debug #1348

Closed
jkleint opened this issue Oct 16, 2012 · 6 comments
Closed

Variable lists broken in only_if and debug #1348

jkleint opened this issue Oct 16, 2012 · 6 comments

Comments

@jkleint
Copy link

jkleint commented Oct 16, 2012

I have lots of playbooks that use list vars:

- hosts: localhost
  vars:
    stuff: [a, b, c]

  tasks: 
  - local_action: command echo $item
    with_items: [c, d, e]
    only_if: "'$item' not in $stuff"

But they have broken recently:

$ ansible-playbook -v only_if.yml 

PLAY [localhost] ********************* 

GATHERING FACTS ********************* 
ok: [localhost]

TASK: [command echo $item] ********************* 
fatal: [localhost] => Traceback (most recent call last):
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 253, in _executor
    exec_rc = self._executor_internal(host)
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 327, in _executor_internal
    result = self._executor_internal_inner(host, self.module_name, self.module_args, inject, port)
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 368, in _executor_internal_inner
    if not utils.check_conditional(conditional):
  File "/shared/software/ansible/lib/ansible/utils.py", line 146, in check_conditional
    return eval(conditional.replace("\n", "\\n"))
  File "<string>", line 1, in <module>
NameError: name 'a' is not defined

It seems it's trying to join my list:


---
- hosts: localhost
  vars:
    stuff: [1, 2, 3]

  tasks: 
  - local_action: command echo $item
    with_items: [3, 4, 5]
    only_if: "$item not in $stuff"
$ ansible-playbook -v only_if.yml 

PLAY [localhost] ********************* 

GATHERING FACTS ********************* 
ok: [localhost]

TASK: [command echo $item] ********************* 
fatal: [localhost] => Traceback (most recent call last):
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 253, in _executor
    exec_rc = self._executor_internal(host)
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 327, in _executor_internal
    result = self._executor_internal_inner(host, self.module_name, self.module_args, inject, port)
  File "/shared/software/ansible/lib/ansible/runner/__init__.py", line 367, in _executor_internal_inner
    conditional = utils.template(self.basedir, self.conditional, inject)
  File "/shared/software/ansible/lib/ansible/utils.py", line 387, in template
    text = varReplace(unicode(text), vars)
  File "/shared/software/ansible/lib/ansible/utils.py", line 304, in varReplace
    replacement = ",".join(replacement)
TypeError: sequence item 0: expected string, int found

I would expect the only_if condition to end up 3 not in [3, 4, 5], which evals to False. Is this an intended change, or can I have my repr back?

@mpdehaan
Copy link
Contributor

Trying to join your list makes it possible to use variables in things like:

vars:
packages = [ "a", "b", "c" ]

tasks:
yum: name=$packages state=installed

And cleans up some other things as well.

I'm not sure I understand your above question entirely, but I'm not willing to stringify everything in with_items as that breaks iteration over hash and list variables (which also works).

Most people are not going crazy with only_if and the new "when" in 0.9 will clean it up nicely, so I think this is a bit of an edge case.

i.e, I want to be able to say:

when: in($item,$list) as one of many operators to the proposed 'when'

It's clearly only_if is a problem relative to templating and we need other options. I don't think we can fix this now in a clean way that doesn't break the other case, and when will eliminate the need for it.

Sorry... not sure how to resolve immediately.

@mpdehaan
Copy link
Contributor

See my latest comment on #1354, we probably can pass in different parameters when templating only_if to restore this and include that in 0.8

TBD.

@jkleint
Copy link
Author

jkleint commented Oct 17, 2012

I'm all for making a comma-separated list when you need one, like yum: name=$packages state=installed. Perhaps we could delay joining lists to those locations that need them, maintaining flexibility for those that need lists. There is of course also the issue of what happens when your list items contain commas.

I guess what I'm saying is utils.varReplace() didn't used to do this:

if isinstance(replacement, (list, tuple)):
    replacement = ",".join(replacement)

And I'm suggesting it shouldn't; maybe we can provide an easy way to do that for places that need strings. I know you're big on backward compatibility, and not only does this break my playbooks, it leaves me no way to fix them. :(

Viewed another way, what's the point of lists if you're always going to join them? I can write a comma-separated string myself, but I can't make a list. Let's not take real data structures from people who need them.

@mpdehaan
Copy link
Contributor

I've got a solution in mind.

@mpdehaan
Copy link
Contributor

See if 25162c9 (now pushed) fixes this for you. It should.

@jkleint
Copy link
Author

jkleint commented Oct 18, 2012

Thanks, works!

@ansible ansible locked and limited conversation to collaborators Apr 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants