Repository: ansible/ansible

Issue:
any_errors_fatal still broken in ansible/stable-2.4
##### ISSUE TYPE
 - Bug Report


##### COMPONENT NAME
any_errors_fatal feature

##### ANSIBLE VERSION
```
ansible 2.4.0.0 (detached HEAD 6f461fbfd0) last updated 2017/09/21 14:10:44 (GMT +200)
```

##### CONFIGURATION

Default configuration

##### OS / ENVIRONMENT

macOS Sierra 10.12.6 (16G29)

##### SUMMARY
any_errors_fatal doesn't stop task execution. Basic usage

##### STEPS TO REPRODUCE
Create the following playbook:
```yaml
- hosts: all
  gather_facts: no
  any_errors_fatal: true

  tasks:
    - name: Fail a single host
      fail:
      when: inventory_hostname=="host0"
 
    - name: Run on both host
      debug: msg='Run on both host'
```

The accompanying hosts file is:
```
host0 ansible_host=127.0.0.1
host1 ansible_host=127.0.1.1
```
##### EXPECTED RESULTS

The playbook should stop at the first task for both host.

##### ACTUAL RESULTS

Playbook stops for host0, and continues to run the second task for host1 :

```
$ ansible-playbook playbook.yaml 

PLAY [all] ***************************************************************************************************************************************************************************************************************

TASK [Fail a single host] ************************************************************************************************************************************************************************************************
skipping: [host1]
fatal: [host0]: FAILED! => {"changed": false, "failed": true, "msg": "Failed as requested from task"}

TASK [Run on both host] **************************************************************************************************************************************************************************************************
ok: [host1] => {
    "msg": "Run on both host"
}

PLAY RECAP ***************************************************************************************************************************************************************************************************************
host0                      : ok=0    changed=0    unreachable=0    failed=1   
host1                      : ok=1    changed=0    unreachable=0    failed=0   
```
any_errors_fatal still broken in ansible/stable-2.4
##### ISSUE TYPE
 - Bug Report


##### COMPONENT NAME
any_errors_fatal feature

##### ANSIBLE VERSION
```
ansible 2.4.0.0 (detached HEAD 6f461fbfd0) last updated 2017/09/21 14:10:44 (GMT +200)
```

##### CONFIGURATION

Default configuration

##### OS / ENVIRONMENT

macOS Sierra 10.12.6 (16G29)

##### SUMMARY
any_errors_fatal doesn't stop task execution. Basic usage

##### STEPS TO REPRODUCE
Create the following playbook:
```yaml
- hosts: all
  gather_facts: no
  any_errors_fatal: true

  tasks:
    - name: Fail a single host
      fail:
      when: inventory_hostname=="host0"
 
    - name: Run on both host
      debug: msg='Run on both host'
```

The accompanying hosts file is:
```
host0 ansible_host=127.0.0.1
host1 ansible_host=127.0.1.1
```
##### EXPECTED RESULTS

The playbook should stop at the first task for both host.

##### ACTUAL RESULTS

Playbook stops for host0, and continues to run the second task for host1 :

```
$ ansible-playbook playbook.yaml 

PLAY [all] ***************************************************************************************************************************************************************************************************************

TASK [Fail a single host] ************************************************************************************************************************************************************************************************
skipping: [host1]
fatal: [host0]: FAILED! => {"changed": false, "failed": true, "msg": "Failed as requested from task"}

TASK [Run on both host] **************************************************************************************************************************************************************************************************
ok: [host1] => {
    "msg": "Run on both host"
}

PLAY RECAP ***************************************************************************************************************************************************************************************************************
host0                      : ok=0    changed=0    unreachable=0    failed=1   
host1                      : ok=1    changed=0    unreachable=0    failed=0   
```


Discussion:
Just ran into this as well.
Just ran into this as well.

Resolving patch:
diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py
--- a/lib/ansible/playbook/base.py
+++ b/lib/ansible/playbook/base.py
@@ -165,7 +165,7 @@ class Base(with_metaclass(BaseMeta, object)):
     _ignore_errors       = FieldAttribute(isa='bool')
     _check_mode          = FieldAttribute(isa='bool')
     _diff                = FieldAttribute(isa='bool')
-    _any_errors_fatal     = FieldAttribute(isa='bool', default=C.ANY_ERRORS_FATAL, always_post_validate=True)
+    _any_errors_fatal    = FieldAttribute(isa='bool')
 
     # param names which have been deprecated/removed
     DEPRECATED_ATTRIBUTES = [
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
@@ -21,6 +21,7 @@
 
 import os
 
+from ansible import constants as C
 from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable
 from ansible.module_utils.six import iteritems, string_types
 from ansible.module_utils._text import to_native
@@ -422,6 +423,14 @@ def _get_parent_attribute(self, attr, extend=False, prepend=False):
 
         return value
 
+    def _get_attr_any_errors_fatal(self):
+        value = self._attributes['any_errors_fatal']
+        if value is None:
+            value = self._get_parent_attribute('any_errors_fatal')
+        if value is None:
+            value = C.ANY_ERRORS_FATAL
+        return value
+
     def _get_attr_environment(self):
         '''
         Override for the 'tags' getattr fetcher, used from Base.


Test patch: