0
votes

Groups configured in Ansible inventory:

  • Group_A has 30 servers
  • Group_B has 40 Servers
  • Group_C has 15 Servers

I want to take 10 servers from each group and make a new group without editing the inventory manually.

These 10 servers is a variable that can change dynamically. If that works I got another question what if the inventory itself is dynamic

[Group_C]
server-1
server-2
server-3
...
server-10

''' New group created From 3 grouped servers now will be used in a playbook '''

1
Welcome! See How do I ask a good question?. Give an example of "10 servers is a variable that can change dynamically" and make it mcve.Vladimir Botka

1 Answers

0
votes

(ansible 2.8.3)

If the inventory is dynamic we don't know the hosts. Let's assume we could choose any of them. Let's create the list of the selected hosts first and then loop add_hosts. With the inventory

[Group_A]
A-0
A-1
..
A-29

[Group_B]
B-0
B-1
..
B-39

[Group_C]
C-0
C-1
..
C-14

the plays below

- name: Create Group_X
  hosts: localhost
  vars:
    no_of_servers: 2
    my_groups:
      - Group_A
      - Group_B
      - Group_C
  tasks:
    - set_fact:
        my_list: "{{ my_list|default([]) +
                     groups[item][0:no_of_servers] }}"
      loop: "{{ my_groups }}"
    - add_host:
        name: "{{ item }}"
        groups: Group_X
      loop: "{{ my_list }}"
    - debug:
        msg: "{{ groups['Group_X'] }}"

- name: Use Group_X
  hosts: Group_X
  gather_facts: false
  tasks:
    - debug:
        msg: "{{ inventory_hostname }} is member of {{ group_names }}"
      run_once: true

give

ok: [localhost] => {
    "msg": [
        "A-0", 
        "A-1", 
        "B-0", 
        "B-1", 
        "C-0", 
        "C-1"
    ]
}

ok: [A-0] => {
    "msg": "A-0 is member of [u'Group_A', u'Group_X']"
}


It is possible to make the selection of the hosts random with the simple plugin below

$ cat filter_plugins/list_methods.py
import random

def list_sample(l,n):
    return random.sample(l,n)

class FilterModule(object):
    def filters(self):
        return {
            'list_sample' : list_sample
        }

With the modification below

- set_fact:
    my_list: '{{ my_list|default([]) +
                 groups[item]|list_sample(no_of_servers) }}'

the plays give for example

ok: [localhost] => {
    "msg": [
        "A-8", 
        "A-9", 
        "B-8", 
        "B-2", 
        "C-2", 
        "C-5"
    ]
}

ok: [A-8] => {
    "msg": "A-8 is member of [u'Group_A', u'Group_X']"
}