In our playbook we have a host named: backupserver
Lets assume we have a big list of inventories +- 100.
Now we have a new backupserver, so we end up with 2 different hosts:
backupserver-1
backupserver-2
Per inventory we want to specify which one to use.
e.g.
- inventory-1 should connect to backupserver-1
- inventory-2 should connect to backupserver-2
- inventory-3 should connect to backupserver-2
- inventory-4 should connect to backupserver-1
However they use the same playbook, in which we point to backupserver.
e.g.
delegate_to: backupserver
Our goal is to only setup the correct backupserver in the inventory files, we do not want to change the playbooks.
Is it possible to make something like an alias to point to from the inventories?
What I have in mind (The following is a group, so not a single delegate option and will not work)
in Inventory 1
hosts:
backupserver:
backupserver1
Inventory 2
hosts:
backupserver:
backupserver2
Lets say we want to change the backupserver2’s ip address, we do not want to update all the inventory files, but want to have 1 definintion of backupserver2 that is shared, so we can update it from 1 spot, for example with host_vars
.
What I have in mind visualized:
Or is there another way that makes sense, where we can have different targets in the inventory files but the same name in the playbook.
Lets say we want to change the backupserver2’s ip address, we do not want to
update all the inventory files, but want to have 1 definintion of
backupserver2 that is shared, so we can update it from 1 spot, for example
with host_vars.
If backupserver-1
and backupserver-2
are names, not ip addresses, the syntax you suggest is close but not correct; you would want tomsething like this in inventory 1:
all:
hosts:
backupserver:
ansible_host: backupserver-1
And in inventory 2:
all:
hosts:
backupserver:
ansible_host: backupserver-2
Etc.
If you are using an ip address (why are you doing that?), you can take advantage of the fact that your “inventory file” can actually be multiple files. Put the entry for the backup servers in separate files. That is, create backupserver1.yaml
with:
all:
hosts:
backupserver:
ansible_host: backupserver-1
Now you can run ansible like this:
ansible-playbook playbook.yaml -i inventory1.yaml -i backupserver1.yaml
Or if you’re working with inventory 2 instead:
ansible-playbook playbook.yaml -i inventory2.yaml -i backupserver2.yaml
In either case, if the address of backupserver1
changes, you only need to update the value in one place, and similarly for your other servers.
Alternately, if your only interaction with the backup server is via delegation, then there is potentially a much simpler solution. Just put all the backup servers in one inventory file:
backupservers:
hosts:
backupserver1:
backupserver2:
Set an inventory variable to identify the appropriate backup server for that inventory, e.g. in inventory1.yaml
:
servers:
hosts:
node0:
node1:
vars:
backupserver: backupserver1
In your playbook, using the variable in your delegate_to
option:
- hosts: servers
tasks:
- name: mumble backup server mumble
delegate_to: "{{ backupserver }}"
command: date
And then always include your “target” inventory and your backupservers inventory:
ansible-playbook playbook.yaml -i inventory1.yaml -i backupservers.yaml
2
Merge all inventory files. For example,
shell> cat hosts
backupserver_1 ansible_host=10.1.0.61 ansible_user=admin
backupserver_2 ansible_host=10.1.0.62 ansible_user=admin
[inventory_1]
host_1a
host_1b
[inventory_2]
host_2a
host_2b
[inventory_3]
host_3a
host_3b
[inventory_4]
host_4a
host_4b
and declare the logic in group_vars/all
shell> cat group_vars/all
backupservers:
inventory_1: backupserver_1
inventory_2: backupserver_2
inventory_3: backupserver_2
inventory_4: backupserver_1
backupserver: |
{% for k,v in backupservers.items() %}
{% if inventory_hostname in k %}
{{ v }}
{% endif %}
Then, given the playbook for testing
shell> cat pb.yml
- hosts: all
tasks:
- debug:
var: backupserver
- command: hostname
register: out
delegate_to: "{{ backupserver }}"
- debug:
var: out.stdout
Limit the inventory on the command line
shell> ansible-playbook pb.yml -l inventory_3
PLAY [all] **********************************************************************************************************
TASK [debug] ********************************************************************************************************
ok: [host_3a] =>
backupserver: backupserver_2
ok: [host_3b] =>
backupserver: backupserver_2
TASK [command] ******************************************************************************************************
changed: [host_3b -> backupserver_2(10.1.0.62)]
changed: [host_3a -> backupserver_2(10.1.0.62)]
TASK [debug] ********************************************************************************************************
ok: [host_3a] =>
out.stdout: test_12
ok: [host_3b] =>
out.stdout: test_12
PLAY RECAP **********************************************************************************************************
host_3a : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_3b : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Note: Add a pretask block to make sure a host is a member of a single group
pre_tasks:
- name: Any host can be a member of a single group only
when: group_names | length > 1
block:
- debug:
msg: >
[ERR] Any host can be a single group member only.
{{ inventory_hostname }} is a member of groups: {{ group_names | join(',') }}.
End of host.
- meta: end_host