Issue 1:
Issue Type:

Bug Report

Ansible Version:

user@h0$ ansible-playbook --version
ansible-playbook 2.1.0
config file =
configured module search path = Default w/o overrides

Installed from GitHub at approximately:

Thu Feb 25 18:43:33 UTC 2016

Ansible Configuration:

No configuration file modifications

Environment:

Debian 8

user@h0$ uname -a
Linux h0 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 GNU/Linux

Summary:

Given a playbook with multiple plays run against two target hosts (host1 and host2). If a task in the first play fails for host2, but succeeds for host1, subsequent tasks (and handlers) in the same play are executed on host1, but tasks in subsequent plays are NOT executed on host1. The message "NO MORE HOSTS LEFT" is printed even though host1 has not had any failed tasks.

This is different than the behavior observed on version 1.9.4. On 1.9.4, the tasks in subsequent plays are executed for host1. The behavior also appears to conflict with the documentation and I haven't found any record that this change was intentional.

Steps To Reproduce:

user@h0$ cat two_plays.pb.yaml

---
- name: Play 1
hosts: all
connection: local
gather_facts: no
tasks:
- name: Task 1
command: /bin/true
failed_when: "'host2' in inventory_hostname"
notify: Handler 1
- name: Task 2
command: /bin/true
handlers:
- name: Handler 1
command: /bin/true

- name: Play 2
hosts: all
connection: local
gather_facts: no
tasks:
- name: Task 3
command: /bin/true

Expected Results:

I expect the same result as seen on version 1.9.4 in the output below.

user@h0$ ansible-playbook --version
ansible-playbook 1.9.4
configured module search path = None

user@h0$ ansible-playbook two_plays.pb.yaml

PLAY [Play 1] *****************************************************************

TASK: [Task 1] ****************************************************************
failed: [host2] => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.004436", "end": "2016-02-25 12:04:28.139206", "failed": true, "failed_when_result": true, "rc": 0, "start": "2016-02-25 12:04:28.134770", "warnings": []}
changed: [host1]

TASK: [Task 2] ****************************************************************
changed: [host1]

NOTIFIED: [Handler 1] *********************************************************
changed: [host1]

PLAY [Play 2] *****************************************************************

TASK: [Task 3] ****************************************************************
changed: [host1]

PLAY RECAP ********************************************************************
to retry, use: --limit @/home/user/two_plays.pb.yaml.retry

host1 : ok=4 changed=4 unreachable=0 failed=0
host2 : ok=0 changed=0 unreachable=0 failed=1

Actual Results:

Instead, Task 3 from Play 2 is not executed on host1. The message "NO MORE HOSTS LEFT" is displayed.

user@h0$ ansible-playbook --version
ansible-playbook 2.1.0
config file =
configured module search path = Default w/o overrides

user@h0$ ansible-playbook two_plays.pb.yaml

PLAY [Play 1] ******************************************************************

TASK [Task 1] ******************************************************************
fatal: [host2]: FAILED! => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.006471", "end": "2016-02-25 12:08:15.874254", "failed": true, "failed_when_result": true, "rc": 0, "start": "2016-02-25 12:08:15.867783", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
changed: [host1]

TASK [Task 2] ******************************************************************
changed: [host1]

RUNNING HANDLER [Handler 1] ****************************************************
changed: [host1]

NO MORE HOSTS LEFT *************************************************************

PLAY RECAP *********************************************************************
host1 : ok=3 changed=3 unreachable=0 failed=0
host2 : ok=0 changed=0 unreachable=0 failed=1

user@h0$ ansible-playbook --version
ansible-playbook 2.1.0
config file =
configured module search path = Default w/o overrides

user@h0$ ansible-playbook -vvv two_plays.pb.yaml
No config file found; using defaults

PLAYBOOK: two_plays.pb.yaml ****************************************************
2 plays in two_plays.pb.yaml

PLAY [Play 1] ******************************************************************

TASK [Task 1] ******************************************************************
task path: /home/user/playbooks/two_plays.pb.yaml:7
ESTABLISH LOCAL CONNECTION FOR USER: user
host1 EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.4-181448891920162 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.4-181448891920162 `" )'
ESTABLISH LOCAL CONNECTION FOR USER: user
host2 EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.41-67699306413194 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.41-67699306413194 `" )'
host1 PUT /tmp/tmp_1kdGb TO /home/user/.ansible/tmp/ansible-tmp-1456427335.4-181448891920162/command
host1 EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/user/.ansible/tmp/ansible-tmp-1456427335.4-181448891920162/command; rm -rf "/home/user/.ansible/tmp/ansible-tmp-1456427335.4-181448891920162/" > /dev/null 2>&1'
host2 PUT /tmp/tmpeUisOu TO /home/user/.ansible/tmp/ansible-tmp-1456427335.41-67699306413194/command
host2 EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/user/.ansible/tmp/ansible-tmp-1456427335.41-67699306413194/command; rm -rf "/home/user/.ansible/tmp/ansible-tmp-1456427335.41-67699306413194/" > /dev/null 2>&1'
fatal: [host2]: FAILED! => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.005199", "end": "2016-02-25 12:08:55.458196", "failed": true, "failed_when_result": true, "invocation": {"module_args": {"_raw_params": "/bin/true", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 0, "start": "2016-02-25 12:08:55.452997", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}
NOTIFIED HANDLER Handler 1
changed: [host1] => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.008875", "end": "2016-02-25 12:08:55.466677", "failed": false, "failed_when_result": false, "invocation": {"module_args": {"_raw_params": "/bin/true", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 0, "start": "2016-02-25 12:08:55.457802", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}

TASK [Task 2] ******************************************************************
task path: /home/user/playbooks/two_plays.pb.yaml:11
ESTABLISH LOCAL CONNECTION FOR USER: user
host1 EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.51-149718488385002 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.51-149718488385002 `" )'
host1 PUT /tmp/tmpatPQZV TO /home/user/.ansible/tmp/ansible-tmp-1456427335.51-149718488385002/command
host1 EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/user/.ansible/tmp/ansible-tmp-1456427335.51-149718488385002/command; rm -rf "/home/user/.ansible/tmp/ansible-tmp-1456427335.51-149718488385002/" > /dev/null 2>&1'
changed: [host1] => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.005788", "end": "2016-02-25 12:08:55.568887", "invocation": {"module_args": {"_raw_params": "/bin/true", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 0, "start": "2016-02-25 12:08:55.563099", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}

RUNNING HANDLER [Handler 1] ****************************************************
ESTABLISH LOCAL CONNECTION FOR USER: user
host1 EXEC /bin/sh -c '( umask 22 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.6-154968896387882 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1456427335.6-154968896387882 `" )'
host1 PUT /tmp/tmpoh615S TO /home/user/.ansible/tmp/ansible-tmp-1456427335.6-154968896387882/command
host1 EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/user/.ansible/tmp/ansible-tmp-1456427335.6-154968896387882/command; rm -rf "/home/user/.ansible/tmp/ansible-tmp-1456427335.6-154968896387882/" > /dev/null 2>&1'
changed: [host1] => {"changed": true, "cmd": ["/bin/true"], "delta": "0:00:00.005483", "end": "2016-02-25 12:08:55.646776", "invocation": {"module_args": {"_raw_params": "/bin/true", "_uses_shell": false, "chdir": null, "creates": null, "executable": null, "removes": null, "warn": true}, "module_name": "command"}, "rc": 0, "start": "2016-02-25 12:08:55.641293", "stderr": "", "stdout": "", "stdout_lines": [], "warnings": []}

NO MORE HOSTS LEFT *************************************************************

PLAY RECAP *********************************************************************
host1 : ok=3 changed=3 unreachable=0 failed=0
host2 : ok=0 changed=0 unreachable=0 failed=1

Issue 2:
ISSUE TYPE

Feature Idea

COMPONENT NAME

patterns, group of groups, static inventory file

ANSIBLE VERSION

ansible 2.2.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides

CONFIGURATION

Empty files for ansible.cfg, and no ANSIBLE_ environment variables

OS / ENVIRONMENT

CentOS 6.9

SUMMARY

ansible is used in our environment to manage cluster servers. The cluster in our environment is formed by 3 servers. However, in daily operation, we usually have to run some specific tasks regarding to the nodes. Thus we have to define another 3 groups to represent the first, the second and the third server of each cluster. For example (inventory file):

[ha-cluster-1]
node-a.de
node-b.de
node-c.de

[ha-cluster-2]
node-x.us
node-y.us
node-z.us

# ... 100+ similar ha-cluster- section

[ha-cluster-129]
server-a.fr
server-b.fr
server-c.fr

[all-ha-cluster:children]
ha-cluster-1
ha-cluster-2
# ... 100+ group names
ha-cluster-129

[all-ha-cluster-1st-node]
node-a.de
node-x.us
# ... 100+ hosts from the first server of each ha-cluster section
server-a.fr

[all-ha-cluster-2nd-node]
node-b.de
node-y.us
# ... 100+ hosts from the first server of each ha-cluster section
server-b.fr

As the example illustrates, all-ha-cluster-1st-node and all-ha-cluster-2nd-node just duplicate the hostnames which have been listed above. This just makes the inventory file hard to be managed.

So I'm thinking if pattern is supported by "group of groups", this file can be more simple. For example:

[all-ha-cluster:children]
ha-cluster-* # represent all groups which start with "ha-cluster-"
[all-ha-cluster-1st-node:children]
ha-cluster-*[0] # represent all first node in the groups which start with "ha-cluster-"
[all-ha-cluster-2nd-node:children]
ha-cluster-*[1] # represent all second node in the groups which start with "ha-cluster-"

In that case lots of lines can be save and the inventory file becomes more tidy.

STEPS TO REPRODUCE

n/a

EXPECTED RESULTS

n/a

ACTUAL RESULTS

n/a