Answers: <p>The thing that makes this complicated is that ansible registers variables and facts locally, on the target remote host - and then has a different set of variables and facts once it moves to the next host. So it would require a bit of fiddling to do this exactly the way you want.</p>
  
  <p>One way to approach this would be to just use run_once, but it doesn't work with <code>serial: 1</code> which you are asking for (check one host at a time);</p>
  
  <pre><code>---
    - name: test
      hosts: all
      vars:
        mem_to_look_for: 62950
      tasks:
        - name: do things
          debug:
            msg: "hello"
          run_once: true
          when: ansible_memory_mb.real.total==mem_to_look_for
  
  </code></pre>
  
  <p>If you really want it to run serially, we could borrow some of the knowledge out of this article <a href="https://stackoverflow.com/questions/42376123/how-to-terminate-an-ansible-playbook-run-when-it-is-successful-on-one-host">https://stackoverflow.com/questions/42376123/how-to-terminate-an-ansible-playbook-run-when-it-is-successful-on-one-host</a> and tweak it a little.. and it works great!</p>
  
  <pre><code>---
    - name: "test"
      hosts: all
      gather_facts: no
      serial: 1
      vars:
        mem_to_look_for: 62950
      tasks:
        - meta: end_play
          when: "{% for item in hostvars.values() %}{% if item.done|default(False) %}True{% endif %}{% endfor %}"
  
        - name: gather facts
          setup:
  
        - name: ensure host has the memory we're looking for
          set_fact:
            done: true
          when: ansible_memory_mb.real.total==mem_to_look_for
  
        - name: skip this host if it doesn't have the memory we're looking for
          meta: end_play
          when: ansible_memory_mb.real.total!=mem_to_look_for
  
        - name: run this thing only on one host
          debug:
            msg: "running the thing"
  </code></pre>
  
  <p>I set the playbook to gather_facts: no because we don't want to continue gathering facts once we found the host we're looking for. It doesn't abort the playbook unfortunately, but just kind of runs a no-op on the remainder of hosts. You could also probably speed things up by tweaking the <code>setup:</code> module by specifying which subset of facts you want to collect, but I left it to collect all the facts in this example. <a href="https://docs.ansible.com/ansible/latest/modules/setup_module.html" rel="nofollow noreferrer">https://docs.ansible.com/ansible/latest/modules/setup_module.html</a> you may also want to just move the host selection to the setup module by adding <code>failed_when: ansible_memory_mb.real.total!=mem_to_look_for</code> at the end of the setup module, but then the hosts would be marked as failed. I'm not sure if that's what you're looking for, but it's really up to you on if you want them to be failed or just skipped. </p>
  
  <p>Additionally, if you want it to completely stop checking hosts as soon as its done I think the any_errors_fatal property will do that. <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#aborting-the-play" rel="nofollow noreferrer">https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#aborting-the-play</a></p>
  
Answers: CC BY-SA 4.0
Answers: 2019-05-24T19:40:49.663Z
Answers: 2019-05-26T01:27:49.873Z
Answers: 2019-05-26T01:27:49.873Z
Answers: Albert Autin
Body: <p>Basically, my use case is that I want to run on list of hosts (group from inventory).</p>
  
  <p>It will run one by one, until it finds machine answer my standards,
  when it find the one with free RAM as I say e.g 40GB free,
  stop looping host, continue the next role/task with the IP address of this machine.</p>
  
Tags: <ansible><ansible-inventory>
Title: Ansible - stop when host is success, exit with IP
UserDisplayName: UnityNewb
ThreadText: # Ansible - stop when host is success, exit with IP
  
  (Asked by: username_0 on 2019-05-23)
  
  Basically, my use case is that I want to run on list of hosts (group from inventory).
  
  It will run one by one, until it finds machine answer my standards,
  when it find the one with free RAM as I say e.g 40GB free,
  stop looping host, continue the next role/task with the IP address of this machine.
  
  **Tags:** ansible, ansible-inventory
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-05-24. Score: 1
  
  The thing that makes this complicated is that ansible registers variables and facts locally, on the target remote host - and then has a different set of variables and facts once it moves to the next host. So it would require a bit of fiddling to do this exactly the way you want.
  
  One way to approach this would be to just use run\_once, but it doesn't work with `serial: 1` which you are asking for (check one host at a time);
  
  ```
  ---
    - name: test
      hosts: all
      vars:
        mem_to_look_for: 62950
      tasks:
        - name: do things
          debug:
            msg: "hello"
          run_once: true
          when: ansible_memory_mb.real.total==mem_to_look_for
  
  ```
  
  If you really want it to run serially, we could borrow some of the knowledge out of this article <https://stackoverflow.com/questions/42376123/how-to-terminate-an-ansible-playbook-run-when-it-is-successful-on-one-host> and tweak it a little.. and it works great!
  
  ```
  ---
    - name: "test"
      hosts: all
      gather_facts: no
      serial: 1
      vars:
        mem_to_look_for: 62950
      tasks:
        - meta: end_play
          when: "{% for item in hostvars.values() %}{% if item.done|default(False) %}True{% endif %}{% endfor %}"
  
        - name: gather facts
          setup:
  
        - name: ensure host has the memory we're looking for
          set_fact:
            done: true
          when: ansible_memory_mb.real.total==mem_to_look_for
  
        - name: skip this host if it doesn't have the memory we're looking for
          meta: end_play
          when: ansible_memory_mb.real.total!=mem_to_look_for
  
        - name: run this thing only on one host
          debug:
            msg: "running the thing"
  
  ```
  
  I set the playbook to gather\_facts: no because we don't want to continue gathering facts once we found the host we're looking for. It doesn't abort the playbook unfortunately, but just kind of runs a no-op on the remainder of hosts. You could also probably speed things up by tweaking the `setup:` module by specifying which subset of facts you want to collect, but I left it to collect all the facts in this example. <https://docs.ansible.com/ansible/latest/modules/setup_module.html> you may also want to just move the host selection to the setup module by adding `failed_when: ansible_memory_mb.real.total!=mem_to_look_for` at the end of the setup module, but then the hosts would be marked as failed. I'm not sure if that's what you're looking for, but it's really up to you on if you want them to be failed or just skipped.
  
  Additionally, if you want it to completely stop checking hosts as soon as its done I think the any\_errors\_fatal property will do that. <https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#aborting-the-play>
  
  
  ---
  
  