0

I have a list of hosts using aws_ec2 and I want to find the first host where the ec2 instance has a specific docker container.

I created a play book with a list of tasks, which ultimately executes a curl command. I only want to execute it on one host but first I have to find that host based on if the host is running a specific docker image. I'm using a shell task to execute docker ps | grep my-filter to see if the host has the docker container named "my-filter", once that container is found on that particular host, I'd like to execute the rest of my tasks on that particular host.

I was looking at with_first_found but that seems to only apply to files.

Any help/pointers would be appreciated.

2

Let's test the use-case with 10 remote hosts (test_01 - test_10) in the group test and user my-user in the hosts test_03 and test_07. To test the existence of the user, use the shell command

shell> cat /etc/passwd|grep my-user

For example the playbook

shell> cat playbook.yml
- hosts: test
  tasks:
    - shell: cat /etc/passwd|grep my-user
      register: result
      ignore_errors: true
    - set_fact:
        results: "{{ results|default({})|
                     combine({item: hostvars[item].result.rc}) }}"
      loop: "{{ ansible_play_hosts }}"
      run_once: true
    - debug:
        var: results
      run_once: true

gives

ok: [test_01] => 
  results:
    test_01: 1
    test_02: 1
    test_03: 0
    test_04: 1
    test_05: 1
    test_06: 1
    test_07: 0
    test_08: 1
    test_09: 1
    test_10: 1

To skip the rest of the hosts, when the first host is found, iterate the list of the hosts and test rc. Then add the host to a new group and run the next play with this group. For example,

shell> cat playbook.yml
- hosts: test
  vars:
    dresult:
      rc: 1
  tasks:
    - block:
        - shell: cat /etc/passwd|grep my-user
          register: result
          loop: "{{ ansible_play_hosts }}"
          delegate_to: "{{ item }}"
          ignore_errors: true
          when: (result|default(dresult)).rc == 1
        - set_fact:
            my_host: "{{ result.results|json_query('[?rc == `0`].item')|first }}"
        - debug:
            var: my_host
        - add_host:
            name: "{{ my_host }}"
            groups: my_group
      run_once: true


- hosts: my_group
  tasks:
    - debug:
        var: inventory_hostname

gives

shell> ansible-playbook playbook.yml 

PLAY [test] ****

TASK [shell] ****
failed: [test_01 -> test_01] (item=test_01) => changed=true 
  ansible_loop_var: item
  cmd: cat /etc/passwd|grep my-user
  delta: '0:00:00.023271'
  end: '2020-09-25 08:20:31.823168'
  item: test_01
  msg: non-zero return code
  rc: 1
  start: '2020-09-25 08:20:31.799897'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
failed: [test_01 -> test_02] (item=test_02) => changed=true 
  ansible_loop_var: item
  cmd: cat /etc/passwd|grep my-user
  delta: '0:00:00.017642'
  end: '2020-09-25 08:20:33.386657'
  item: test_02
  msg: non-zero return code
  rc: 1
  start: '2020-09-25 08:20:33.369015'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
changed: [test_01 -> test_03] => (item=test_03)
skipping: [test_01] => (item=test_04) 
skipping: [test_01] => (item=test_05) 
skipping: [test_01] => (item=test_06) 
skipping: [test_01] => (item=test_07) 
skipping: [test_01] => (item=test_08) 
skipping: [test_01] => (item=test_09) 
skipping: [test_01] => (item=test_10) 
...ignoring

TASK [set_fact] ****
ok: [test_01]

TASK [debug] ****
ok: [test_01] => 
  my_host: test_03

TASK [add_host] ****
changed: [test_01]

PLAY [my_group] ****

TASK [debug] ****
ok: [test_03] => 
  inventory_hostname: test_03

PLAY RECAP *****
test_01: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1   
test_03: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
| improve this answer | |

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.