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

"first_available_file" does not work with fatal message "One or more undefined variables: 'item' is undefined" #8220

Closed
dragon3 opened this issue Jul 21, 2014 · 6 comments
Labels
bug This issue/PR relates to a bug. P2 Priority 2 - Issue Blocks Release

Comments

@dragon3
Copy link
Contributor

dragon3 commented Jul 21, 2014

Issue Type:

Bug Report

Ansible Version:

1.6.3 - 1.6.6

Environment:

Mac OSX 10.9.4, Linux

Summary:

I use "first_available_file" on copy and template modules, but since 1.6.3 it's does not work.
When I tried "git bisect" to find a commit which made this problem, I found it:

b99ea2723a793c3e81c8319b9d8db7828f881839 is the first bad commit

This commit was related #7535.

And I tried to fix this problem, so I found that the following change on release1.6.6 works for me.

diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
index d2a09ec..1af9b07 100644
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -572,6 +572,7 @@ class Play(object):
                     new_role = x['role_name']

                 mv = task_vars.copy()
+                mv['item'] = ''
                 for t in tokens[1:]:
                     (k,v) = t.split("=", 1)
                     mv[k] = template(self.basedir, v, mv)

But I'm not sure it is correct and it has side effects.

Steps To Reproduce:

I create a following simple inventroy structure to reproduce this.

.
├── hosts
├── roles
│   └── role1
│       ├── files
│       │   ├── file1.txt
│       │   └── file2.txt
│       └── tasks
│           └── main.yml
└── site.yml

hosts

[local]
localhost

site.yml


---
- name: test
  hosts: local
  connection: local
  gather_facts: false
  roles:
    - role1

roles/roles1/tasks/main.yml


---
- name: copy file
  copy: src={{ item }} dest=/tmp/{{ item }}
  first_available_file:
    - file2.txt
    - file1.txt
Expected Results:
$ ansible-playbook -i hosts site.yml -v

PLAY [test] *******************************************************************

TASK: [role1 | copy file] *****************************************************
ok: [localhost] => {"changed": false, "dest": "/tmp/file2.txt", "gid": 20, "group": "staff", "item": "", "md5sum": "5149d403009a139c7e085405ef762e1a", "mode": "0644", "owner": "foobar", "path": "/tmp/file2.txt", "size": 6, "state": "file", "uid": 501}

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0
Actual Results:
$ ansible-playbook -i hosts site.yml -v

PLAY [test] *******************************************************************

TASK: [role1 | copy file] *****************************************************
fatal: [localhost] => One or more undefined variables: 'item' is undefined

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/Users/foobar/site.retry

localhost                  : ok=0    changed=0    unreachable=1    failed=0
@jimi-c jimi-c added P3 labels Jul 21, 2014
@jimi-c
Copy link
Member

jimi-c commented Jul 21, 2014

I have a slightly different fix for this, to ensure that we don't re-break 7535 or anything else similar:

diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py
index bd9b0d0..3865349 100644
--- a/lib/ansible/playbook/task.py
+++ b/lib/ansible/playbook/task.py
@@ -257,6 +257,10 @@ class Task(object):
         # make first_available_file accessable to Runner code
         if self.first_available_file:
             self.module_vars['first_available_file'] = self.first_available_file
+            # make sure that the 'item' variable is set when using
+            # first_available_file (issue #8220)
+            if 'item' not in module_vars:
+                module_vars['item'] = ''
 
         if self.items_lookup_plugin is not None:
             self.module_vars['items_lookup_plugin'] = self.items_lookup_plugin

If you can test that, I'll get it merged in.

@dragon3
Copy link
Contributor Author

dragon3 commented Jul 22, 2014

@jimi-c Thank you for your quick reply.

I tried to apply your patch to release1.6.6 branch, so I confirmed it works correctly.
👍

@jimi-c jimi-c added P2 and removed P3 labels Jul 22, 2014
@tksmd
Copy link
Contributor

tksmd commented Jul 23, 2014

@jimi-c and @dragon3 Great thanks, this patch worked well for me too.

BTW, it doesn't change the result but should we update self.module_vars instead of module_vars to clarify which variable to be updated ?

            if 'item' not in self.module_vars:
                self.module_vars['item'] = ''

@jimi-c
Copy link
Member

jimi-c commented Jul 24, 2014

@tksmd yes you're correct, that was a typo on my part. I'll correct that before I merge it in.

@jimi-c jimi-c closed this as completed in b21875d Jul 24, 2014
@jimi-c
Copy link
Member

jimi-c commented Jul 24, 2014

Fixed and merged, thanks!

@dragon3
Copy link
Contributor Author

dragon3 commented Jul 24, 2014

Thanks!

@ansibot ansibot added bug This issue/PR relates to a bug. and removed bug_report labels Mar 6, 2018
@ansible ansible locked and limited conversation to collaborators Apr 25, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue/PR relates to a bug. P2 Priority 2 - Issue Blocks Release
Projects
None yet
Development

No branches or pull requests

4 participants