Repository: ansible/ansible

Issue:
failed_when directive does not accept lists
##### Issue Type:

Bug Report
##### Ansible Version:

2.0.0.1
##### Environment:

ubuntu 14.04
##### Summary:

The `failed_when` module does not support lists anymore
##### Steps To Reproduce:

```
- hosts: localhost
  tasks:
    - name: hello
      command: "/dev/null"
      register: myresult
      failed_when:
        - "myresult == 1"
        - "myresult == 2"
```
##### Expected Results:

pass
##### Actual Results:

> ERROR! The field 'failed_when' is supposed to be a string type, however the incoming data structure is a <class 'ansible.parsing.yaml.objects.AnsibleSequence'>



Discussion:
need to check all 'when's to make sure they all behave this way

@profhase this is a work around I've implemented

```
- hosts: localhost
  tasks:
    - name: hello
      command: "/dev/null"
      register: myresult
  failed_when: "{{ item }}"
  with_items:
    - "myresult == 1"
    - "myresult == 2"
```


Resolving patch:
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -452,19 +452,23 @@ def _execute(self, variables=None):
 
             # helper methods for use below in evaluating changed/failed_when
             def _evaluate_changed_when_result(result):
-                if self._task.changed_when is not None:
+                if self._task.changed_when:
                     cond = Conditional(loader=self._loader)
-                    cond.when = [ self._task.changed_when ]
+                    cond.when = self._task.changed_when
                     result['changed'] = cond.evaluate_conditional(templar, vars_copy)
+                else:
+                    result['changed'] = False
 
             def _evaluate_failed_when_result(result):
-                if self._task.failed_when is not None:
+                if self._task.failed_when:
                     cond = Conditional(loader=self._loader)
-                    cond.when = [ self._task.failed_when ]
+                    cond.when = self._task.failed_when
                     failed_when_result = cond.evaluate_conditional(templar, vars_copy)
                     result['failed_when_result'] = result['failed'] = failed_when_result
-                    return failed_when_result
-                return False
+                else:
+                    failed_when_result = False
+                    result['failed'] = False
+                return failed_when_result
 
             if 'ansible_facts' in result:
                 vars_copy.update(result['ansible_facts'])
@@ -482,7 +486,7 @@ def _evaluate_failed_when_result(result):
 
             if attempt < retries - 1:
                 cond = Conditional(loader=self._loader)
-                cond.when = [ self._task.until ]
+                cond.when = self._task.until
                 if cond.evaluate_conditional(templar, vars_copy):
                     break
                 else:
diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py
--- a/lib/ansible/playbook/task.py
+++ b/lib/ansible/playbook/task.py
@@ -70,11 +70,11 @@ class Task(Base, Conditional, Taggable, Become):
 
     _any_errors_fatal     = FieldAttribute(isa='bool')
     _async                = FieldAttribute(isa='int', default=0)
-    _changed_when         = FieldAttribute(isa='string')
+    _changed_when         = FieldAttribute(isa='list', default=[])
     _delay                = FieldAttribute(isa='int', default=5)
     _delegate_to          = FieldAttribute(isa='string')
     _delegate_facts       = FieldAttribute(isa='bool', default=False)
-    _failed_when          = FieldAttribute(isa='string')
+    _failed_when          = FieldAttribute(isa='list', default=[])
     _first_available_file = FieldAttribute(isa='list')
     _loop                 = FieldAttribute(isa='string', private=True)
     _loop_args            = FieldAttribute(isa='list', private=True)
@@ -83,7 +83,7 @@ class Task(Base, Conditional, Taggable, Become):
     _poll                 = FieldAttribute(isa='int')
     _register             = FieldAttribute(isa='string')
     _retries              = FieldAttribute(isa='int', default=3)
-    _until                = FieldAttribute(isa='string')
+    _until                = FieldAttribute(isa='list', default=[])
 
     def __init__(self, block=None, role=None, task_include=None):
         ''' constructors a task, without the Task.load classmethod, it will be pretty blank '''


Test patch: