RIBO46
RIBO46

Reputation: 11

Dynamic variables from hosts

When executing the role, it is necessary that the names of hostnames be substituted into the variables. It is also important to take into account the number of hosts and the places in the variables where they are substituted. Is it possible to do this only by means of ansible?

Example: (host.ini)

host1 ansible_host='10.33.15.15' ansible_ssh_user='ben'

host2 ansible_host='10.33.15.16' ansible_ssh_user='ben'

host3 ansible_host='10.33.15.17' ansible_ssh_user='ben'

host4 ansible_host='10.33.15.18' ansible_ssh_user='ben'

host5 ansible_host='10.33.15.19' ansible_ssh_user='ben'
...
...

Example: (roles/post_install/defaults/main.yml)

if the input is Only: host1 - only monitoring was deployed

  monitoring:
    nodes: ['host1']
  logging:
    nodes: []

If the input is host1 / host2 In this case, these same sections were:

  monitoring:
    nodes: ['host1']
  logging:
    nodes: ['host2']

if the input is host1 / host2 / host3 In this case, these same sections were:

monitoring:
    nodes: ['host1', 'host2']
  logging:
    nodes: ['host3']

if the input is host1 / host2 / host3 / host4 In this case, these same sections were:

monitoring:
    nodes: ['host1', 'host2']
  logging:
    nodes: ['host3', 'host4']

if the input is host1 / host2 / host3 / host4 / host5 In this case, these same sections were:

monitoring:
    nodes: ['host1', 'host2', 'host5']
  logging:
    nodes: ['host3', 'host4']

if the input is host1 / host2 / host3 / host4 / host5 / ... / ... / ... In this case, these same sections were:

monitoring:
    nodes: ['host1', 'host2', 'host5', ...]
  logging:
    nodes: ['host3', 'host4' ...]

Upvotes: 1

Views: 220

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67959

Put the declarations below into the vars. For example, into the group_vars/all

shell> cat group_vars/all/nodes.yml 
len: "{{ ansible_play_hosts_all|length }}"
rem: "{{ len|int % 4 }}"
bat: "{{ range(len|int - rem|int)|batch(2) }}"
_idx: |
  0:
    mon: []
    log: []
  1:
    mon: [-1]
    log: []
  2:
    mon: [-2]
    log: [-1]
  3:
    mon: [-3, -2]
    log: [-1]
  default:
    mon: {{ bat[0::2]|flatten }}
    log: {{ bat[1::2]|flatten }}
idx: "{{ _idx|from_yaml }}"
nodes: "{{ (len|int > 3)|
           ternary([idx[rem|int], idx.default]|combine(list_merge='prepend'),
                    idx[rem|int]) }}"
monitoring:
  nodes: "{{ nodes.mon|map('extract', ansible_play_hosts_all)|list }}"
logging:
  nodes: "{{ nodes.log|map('extract', ansible_play_hosts_all)|list }}"

Then, given the inventory

shell> cat hosts
[test]
host1
host2
host3
...
host17

the playbook

shell> cat pb.yml
- hosts: all
  gather_facts: false
  tasks:
    - debug:
        msg: |
          monitoring:
            nodes: {{ monitoring.nodes|to_yaml }}
          logging:
            nodes: {{ logging.nodes|to_yaml }}
      run_once: true

gives (abridged)

shell> ansible-playbook pb.yml --limit test[0:8]

TASK [debug] ******************************************************************
ok: [host1] => 
  msg: |-
    monitoring:
      nodes: [host1, host2, host5, host6, host9]
  
    logging:
      nodes: [host3, host4, host7, host8]

The maximal number of hosts is limited by the inventory

shell> ansible-playbook pb.yml --limit test[0:99]

TASK [debug] ******************************************************************
ok: [host1] => 
  msg: |-
    monitoring:
      nodes: [host1, host2, host5, host6, host9, host10, host13, host14, host17]
  
    logging:
      nodes: [host3, host4, host7, host8, host11, host12, host15, host16]

Upvotes: 1

Related Questions