So, We have a scenario, where we need the ability to execute a custom command on a single or multiple hosts from a group with various possible values of the same variable.
For example-
#Inventory:
[ServerGroup_1]
abc0001 node=node1
abc0002 node=node2
[ServerGroup_2]
abc0001 node=node3
abc0002 node=node4
[ServersGroups: children]
ServerGroup_1
ServerGroup_2
group_vars/ServerGroup_1
JAVA_HOME: /home/java
PORT: 9998
group_vars/ServerGroup_2
JAVA_HOME: /home/java
PORT: 9999
The goal is to execute below shell command on host abc0001 with Ports as 9998 and 9999 within a single playbook run.
shell: {{ JAVA_HOME }} -Dprocess.port={{ PORT }}
Currently every time as per Ansible default variable behavior it is only getting executed for port 9999. Now, as an alternative, we could manually separate out the tasks and call it twice inside our playbook as explained here.
But, if we have 50 different ports that would be tedious to write and also we would want the configuration in such a way that it dynamically picks up from either inventory file or variable files, so for adding any new instance or running the command on different port, we just have to add it to our inventory/variable files rather than writing a separate task covering the port. The end configuration should work for all possible scenarios of running that command on one host of a group or all hosts from a group or a particular host and node combination....
ansible-playbook -i staging test_multinode.yml --limit=ServersGroups -l abc0001
The above playbook run should execute the shell command for both the ports 9998 and 9999 on abc0001 and the playbook needs to be flexible enough if just want to say start the process only for port 9998 on abc0001.
Note: We have tried the with_items block by setting a Port variable in inventory file for the host, but that set up is very rigid and will not work for other scenarios. We have also tried hash_behavior=merge and hash_behavior=replace settings in ansible.cfg, did not notice any change.
Hope this makes sense and We have not over-complicated things! Please suggest few options!!!
Short Answer- Rewrite the inventory file using aliases
#Inventory:
[ServerGroup_1]
#variable with name PORT on host abc0001 from group1
group1_node1 ansible_host=abc0001 PORT=9998
group1_node2 ansible_host=abc0002 PORT=9999
[ServerGroup_2]
#same variable name Port on the same host abc0001 present in a different group
group2_node1 ansible_host=abc0001 PORT=9998
group2_node2 ansible_host=abc0002 PORT=9999
[ServersGroups: children]
ServerGroup_1
ServerGroup_2
We are using group1_node1 as an alias, so by doing this Ansible will register group1_node1 and group2_node1 as two different hosts even though it’s the same host abc0001.
Now, we will be able to start two processes on the same host abc0001 using different parameters for the same variable name PORT.
ansible-playbook -i staging test_multinode.yml --limit=ServersGroups -l group1_node1:group2_node1
Hope this is clear.