I am moving a lot of old scripts used to configure a computer room into ansible, and it really has improved the workflow. Currently, there I have several playbooks, and I need to share a common config among them. But in one task I have faced a problem: I need a hostname/ip to be a variable in the inventory. I have read a lot of tutorials and docs and maybe I am dumb or very tired, but I have not found yet a solution after many hours, it seems that it is not possible. Dynamics inventories, group_vars and so on look similar but actually are different from what I require here. I have created a mwe to easy showing the case. This mwe is a subset but the main idea remains: vars inside vars/main.yml are going to be shared among various playbooks (easy) and inventories (the question here). Thanks in advance.
[ssh_connection]
pipelining = True
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
[defaults]
interpreter_python = python3
[master]
192.168.10.1 ansible_connection=local
[package_clients]
192.168.10.[3:29]
[package_server]
{{PACKAGE_SERVER}} # <--- This var commes from vars/main.yml
---
- name: Configuring package server (exports spack packages)
hosts: package_server
gather_facts: false
vars_files:
- vars/main.yml
tasks:
- name: Printing package server name
debug:
msg: "PACKAGE_SERVER variable -> {{PACKAGE_SERVER}}"
- name: Creating package dir (this throws an error sin PACKAGE_SERVER is not replaced in inventory)
file:
path: /packages
state: directory
# Server internal ip
BASE_SERVERIP: '192.168.10'
# Package Server: Simply shares a directory with spack and packages
PACKAGE_SERVER: '{{BASE_SERVERIP}}.2'
When I run this as
ansible-playbook -i inventory site.yml --check
I get the following error:
PLAY [Configuring package server (exports spack packages)] *******************************************************************************************
TASK [Printing package server name] ******************************************************************************************************************
ok: [{{PACKAGE_SERVER}}] => { "msg": "PACKAGE_SERVER variable -> 192.168.10.2"
}
TASK [Creating package dir (this throws an error sin PACKAGE_SERVER is not replaced in inventory)] ***************************************************fatal: [{{PACKAGE_SERVER}}]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname {{package_server}}: Name or service not known", "unreachable": true}
PLAY RECAP *******************************************************************************************************************************************
{{PACKAGE_SERVER}} : ok=1 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Use the module add_host and create new group package_server in the first play. Then use it in the second play. For example
shell> cat playbook.yml
---
- name: Create group package_server
hosts: localhost
gather_facts: false
vars:
BASE_SERVERIP: 192.168.10
PACKAGE_SERVER: "{{ BASE_SERVERIP }}.2"
tasks:
- add_host:
hostname: "{{ PACKAGE_SERVER }}"
groups: package_server
- name: Use group package_server
hosts: package_server
gather_facts: false
tasks:
- debug:
msg: Creating package dir
gives
shell> ansible-playbook playbook.yml
PLAY [Create group package_server] **************************************
TASK [add_host] *********************************************************
changed: [localhost]
PLAY [Use group package_server] *****************************************
TASK [debug] ************************************************************
ok: [192.168.10.2] =>
msg: Creating package dir
PLAY RECAP **************************************************************
192.168.10.2: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
List of hosts
If you want to add more hosts to the group create a list. The expansion of slices, e.g. 192.168.10.[3:6], works only in the inventory. Use filters to declare such range in a list, e.g.
- name: Create group package_server
hosts: localhost
gather_facts: false
vars:
clients: "{{ ['192.168.10']|
product(range(3,6))|
map('join', '.')|
list }}"
tasks:
- debug:
var: clients
- add_host:
hostname: "{{ item }}"
groups: package_server
loop: "{{ clients }}"
creates the list below and add the hosts into the group package_server
clients:
- 192.168.10.3
- 192.168.10.4
- 192.168.10.5
Any octet can be declared as a sequence, e.g.
c:
A: [192]
B: [168]
C: [10, 12]
D: [3, 5]
clients: "{{ range(c.A.0, c.A.1|d(c.A.0 + 1))|
product(range(c.B.0, c.B.1|d(c.B.0 + 1)))|map('flatten')|
product(range(c.C.0, c.C.1|d(c.C.0 + 1)))|map('flatten')|
product(range(c.D.0, c.D.1|d(c.D.0 + 1)))|map('flatten')|
map('join', '.')|list }}"
gives
clients:
- 192.168.10.3
- 192.168.10.4
- 192.168.11.3
- 192.168.11.4