Repository: ansible/ansible

Issue:
set_fact skipping
The following code works under ansible 1.9 but fails on the latest devel checkout. It runs the same rules, but skips the set_fact command.

```
- name: Set zookeeper ID facts
  gather_facts: True
  hosts: zookeeper
  user: username
  sudo: True
  tasks:
    - set_fact: zkid={{ item.0 | int + 1 }}
      when: hostvars[item.1]['ansible_hostname'] == ansible_hostname
      with_indexed_items: groups['zookeeper']
```

This assigns a unique id to each zookeeper instance dynamically.



Discussion:
Output from 1.9:

```
TASK: [set_fact zkid={{ item.0 | int + 1 }}] ********************************** 
skipping: [172.20.121.14] => (item=(0, u'172.20.121.13'))
skipping: [172.20.121.12] => (item=(0, u'172.20.121.13'))
ok: [172.20.121.13] => (item=(0, u'172.20.121.13'))
skipping: [172.20.121.12] => (item=(1, u'172.20.121.14'))
skipping: [172.20.121.13] => (item=(1, u'172.20.121.14'))
ok: [172.20.121.14] => (item=(1, u'172.20.121.14'))
skipping: [172.20.121.13] => (item=(2, u'172.20.121.12'))
ok: [172.20.121.12] => (item=(2, u'172.20.121.12'))
skipping: [172.20.121.14] => (item=(2, u'172.20.121.12'))
```

+1 Same issue, working in 1.9 not working latest dev branch.

```
- name: Set facts for api subnet
  set_fact:
    api_subnet_id: "{{item.id}}"
  when: item.resource_tags.tier == "{{pipeline_env}}-api"
  with_items: vpc.subnets
  tags:
    - provision

- debug: var=api_subnet_id
```

expected debug: "subnet-xxxxxxxx"
given debug: "api_subnet_id"

@rncry, looks like a bug in with_indexed_items in v2 

@RXminuS you should not be using {{ }} in when.

It's not just `with_indexed_items`. Same problem with `with_items`.

This works:

``` yaml
---
-
  hosts: localhost
  connection: local
  gather_facts: false
  vars:
    networks:
      v4:
        - ip_address: 10.128.X.X
          type: private
        - ip_address: 104.131.X.X
          type: public
  tasks:
    - file:
        path: ./public_ip_address.txt
        state: absent
    - shell: echo -n "{{ item.ip_address }}" >> ./public_ip_address.txt
      when: item.type == "public"
      with_items: networks.v4
    - shell: cat ./public_ip_address.txt
      register: public_ip_address_cat
    - set_fact:
        public_ip_address: "{{ public_ip_address_cat.stdout }}"
    - debug:
        msg: "{{ public_ip_address }}"
```

And this doesn't:

``` yaml
---
-
  hosts: localhost
  connection: local
  gather_facts: false
  vars:
    networks:
      v4:
        - ip_address: 10.128.X.X
          type: private
        - ip_address: 104.131.X.X
          type: public
  tasks:
    - set_fact:
        public_ip_address: "{{ item.ip_address }}"
      when: item.type == "public"
      with_items: networks.v4
    - debug: msg="{{ hostvars.localhost }}"
```

The latter fails with:

```
PLAY: ***************************************************************************

TASK [set_fact public_ip_address={{ item.ip_address }}] *************************
{'skip_reason': 'Conditional check failed', 'item': {u'ip_address': u'10.128.X.X', u'type': u'private'}, 'skipped': True, 'changed': False}
{'item': {u'ip_address': u'104.131.X.X', u'type': u'public'}, 'changed': False, 'ansible_facts': {u'public_ip_address': u'104.131.X.X'}}
skipping: [localhost]

TASK [debug msg={{ public_ip_address }}] ****************************************
fatal: [localhost]: FAILED! => {
    "failed": true, 
    "msg": "ERROR! the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'public_ip_address' is undefined"
}

PLAY RECAP **********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1   
```


Resolving patch:
diff --git a/lib/ansible/executor/task_result.py b/lib/ansible/executor/task_result.py
--- a/lib/ansible/executor/task_result.py
+++ b/lib/ansible/executor/task_result.py
@@ -40,7 +40,14 @@ def is_changed(self):
         return self._check_key('changed')
 
     def is_skipped(self):
-        return self._check_key('skipped')
+        if 'results' in self._result:
+            flag = True
+            for res in self._result.get('results', []):
+                if isinstance(res, dict):
+                    flag &= res.get('skipped', False)
+            return flag
+        else:
+            return self._result.get('skipped', False)
 
     def is_failed(self):
         if 'failed_when_result' in self._result or \


Test patch: