How to select all hosts except the inventory_hostname from a group?

Solution 1:

An option would be to use the difference filter. Below is an example of how to use the filter

shell> cat test-difference-01.yml
- hosts: localhost
  gather_facts: no
  vars:
    web_servers:
      - web-server-01
      - web-server-02
      - web-server-09
    inventory_hostname:
      - web-server-02
  tasks:
    - set_fact:
        delegate_to_hosts: "{{ web_servers|difference(inventory_hostname) }}"
    - debug:
        msg : "{{ delegate_to_hosts }}"
shell> ansible-playbook test-difference-01.yml | grep -A 3 msg
    "msg": [
        "web-server-01", 
        "web-server-09"
    ]

Q: "group of two hosts ... delegate a task to the one that is not the current host"

Given the inventory

shell> cat hosts
[webservers]
web-server-01
web-server-02

The playbook

- hosts: webservers
  tasks:
    - debug:
        msg: "{{ inventory_hostname }} {{ item }}"
      loop: "{{ groups.webservers|difference([inventory_hostname]) }}"
      delegate_to: "{{ item }}"

gives (abridged)

ok: [web-server-01 -> web-server-02] => (item=web-server-02) => 
  msg: web-server-01 web-server-02
ok: [web-server-02 -> web-server-01] => (item=web-server-01) => 
  msg: web-server-02 web-server-01

The code can be generalized by running on all hosts listed in ansible_play_hosts_all

- hosts: all
  tasks:
    - debug:
        msg: "{{ inventory_hostname }} {{ item }}"
      loop: "{{ ansible_play_hosts_all|difference([inventory_hostname]) }}"
      delegate_to: "{{ item }}"

Solution 2:

You don't need to specify a regex with negative lookahead. Instead, use the reject filter.

Also, with equalto test, you don't need to enclose the string in ^ and $:

- debug:
    msg: "{{ groups['web-servers'] | reject('equalto', inventory_hostname) | list }}"