0

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.

1 Answer 1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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