5

I have a group of two hosts. I want to delegate a task to the one that is not the current host.

The following doesn't match anything and just returns a list of my initial two hosts.

  - debug: msg="{{ groups['web-servers'] | select('match', '^(?!\{\{\ inventory_hostname\ \}\}$).+') | list }}"

I think it's escaping that's the issue but I can't figure it out.

6

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 }}"
3

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 }}"
0

I think the problem is with the variable substitution (or lack thereof) in the regex pattern. You can define the pattern separately, and pass that to the filter (note that I did modify your regex a bit):

- set_fact: pattern="^(?!{{ inventory_hostname }}).+$"
- debug: msg="{{ groups['web-servers'] | select('match', pattern) | list }}"

Result:

TASK [debug : debug] ******************************************
ok: [foo] => {
    "msg": [
        "bar",
        "baz"
    ]
}
ok: [bar] => {
    "msg": [
        "foo",
        "baz"
    ]
}
ok: [baz] => {
    "msg": [
        "foo",
        "bar"
    ]
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.