Search code examples
regexansibleansible-inventory

Ansible: adhoc limit hosts


I need to run the play limiting the host by odd or even. Play is running fine when I don't have any number in the group name, but when there is some number in the group name it's running for all hosts.

Here is the sample inventory file

[weblogic]
web_host[01:10]

[weblogic-oel7]
weblogic_host[01:10]

when I run the play for odd it's taking all hosts in the weblogic-oel7 group since that host group name is ending with the number 7.

ansible all -i hosts.yml --limit '*01:*3:*5:*7:*9' --list

I'm unable to find a solution so modified the play to take the host as a variable and when I pass like below it's working fine.

ansible-playbook -i hosts sample.yml -e limit_host="{{ ansible_play_hosts[1::2] }}" --list-hosts
ansible-playbook -i hosts sample.yml -e limit_host="{{ ansible_play_hosts[::2] }}" --list-hosts

Is there any other better solution is there to do so? How can I ignore the group name when I use the limit flag and only take the hostnames?

We do have more than 1000 servers and more than 25 groups. The actual playbook takes the group names and then limits them with odd or even like below.

ansible-playbook playbooks/Patching/OSpatch.yml -i inventories/dev -l *0:*2:*4:*6:*8 -f 10

Playbook

---
- hosts: "{{ lookup('env','hostgroups') }} " 
  become: true
  become_user: root
  any_errors_fatal: false
  gather_facts: yes

Thanks


Solution

  • According Patterns: targeting hosts and groups it should be possible to apply a pattern

    to choose which managed nodes or groups you want to execute against

    Even if there are some limitations of patterns, it might be possible to use advanced pattern options in example using regexes in patterns.

    You can specify a pattern as a regular expression by starting the pattern with ~

    Please take note that according patterns and ad-hoc commands

    single quotes MUST be used to prevent bash interpolation.

    Regarding your question:

    Is there any other better solution is there to do so? How can I ignore the group name when I use the limit flag and only take the hostnames?

    and based on your given sample inventory file hosts.yml, a playbook called with

    ansible-playbook -i hosts.yml sample.yml --limit='~.*[\d]{1}(1|3|5|7|9)$'
    

    would execute on

    PLAY RECAP *******************************************************************************************************
    web_host01                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    web_host03                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    web_host05                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    web_host07                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    web_host09                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    weblogic_host01            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    weblogic_host03            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    weblogic_host05            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    weblogic_host07            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    weblogic_host09            : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    As you can see hosts of the group weblogic-oel7 are catched but not all of them.

    Summary

    The pattern to catch odd numbers

    --limit='~.*[\d]{1}(1|3|5|7|9)$'
    

    and to catch even numbers

    --limit='~.*[\d]{1}(0|2|4|6|8)$'
    

    which can have a one leading digit but not a letter.

    Thanks to


    How to proceed further?

    Regarding

    The actual playbook takes the group names and then limits them with odd or even ...

    you may have a look into How to build your inventory, hosts in multiple groups and inheriting variable values: group variables for groups of groups since it might be possible to introduce

    groups of groups using the :children suffix in INI or the children: entry in YAML.

    With this you create groups like weblogic_odd and weblogic_even. This approach is in example used to address infrastructure (and) locations.


    Further Documentation

    Can be found in the thread of Ansible Issue #79822 where an "Incorrect behavior of regular expression in ansible-playbook --limit option" is assumed but it turned out it is not. It is just

    ... constructing the host pattern, not selecting/excluding the hosts.

    in other words, the parameter limit and his regex capability is to define sets, but it is not mentioned as regex filter for hosts and as I understand from there.