Ansible loop over inventory file (two dimensional list) - ansible

I would like to parse a two dimensional list from the inventory file with ansible playbook
Inventory file: .ini would have a list of macs and IPs
mac1=b8:27:eb:12:53:1b ip1=192.168.8.101
mac2=b8:27:eb:f1:65:32 ip2=192.168.8.102
...
and the ansible task would be to add a line everytime in the `/etc/ethers``file in this form
b8:27:eb:f1:65:32 192.168.8.102
this is the task
- name: Assign static IPs to MACs
lineinfile:
path: /etc/ethers
line: "{{ mac }} {{ ip }}"
mode: 0644
loop: "{{ listname }}"
become: yes
Any recommendations please on how to set my list in the inventory that it will work with the playbook?
Thank you!

I would add the list as a variable in group_var folder or in your playbook.
list:
- mac: b8:27:eb:12:53:1b
ip: 192.168.8.101
- mac: b8:27:eb:f1:65:32
ip: 192.168.8.102
Your task can then look something like this:
- name: Assign static IPs to MACs
lineinfile:
path: /etc/ethers
line: "{{ item.mac }} {{ item.ip }}"
mode: 0644
loop: "{{ list }}"
become: yes

Related

How to include variables from roles (vars) directory ansible?

I have my ansible playbook which basically create a new Virtual machine from template in esxi what , i have to convert the playbook into roles. I am new to ansible so i don't know how to call my hard coded variables from roles(install)->vars directory .
This is my playbook
---
# create a new VM from a template
- name: VM from template
hosts: localhost
gather_facts: false
connection: local
vars:
vcenter_hostname: vcenter-app
vcenter_user: john#doe
vcenter_pass: blabla6
esxhost: esx-4.cbalo.fr
datastore: VM-PROD-02-NORMAL
vmtemplate: Centos7-template
name: "newvm2"
notes: Ansible Test
dumpfacts: False
tasks:
- name: Create VM from template
vmware_guest:
validate_certs: False
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_pass }}"
esxi_hostname: "{{ esxhost }}"
datacenter: CD06
folder: Test
name: "{{ name }}"
template: "{{ vmtemplate }}"
hardware:
memory_mb: "{{ vm_memory | default(1024) }}"
wait_for_ip_address: True
state: present
register: newvm2
I have divide this into my role(install)->tasks->main.yml like this
---
- name: Create VM from template
vmware_guest:
validate_certs: False
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_user }}"
password: "{{ vcenter_pass }}"
esxi_hostname: "{{ esxhost }}"
datacenter: CD06
folder: Test
name: "{{ name }}"
template: "{{ vmtemplate }}"
hardware:
memory_mb: "{{ vm_memory | default(1024) }}"
wait_for_ip_address: True
state: present
register: newvm2
Then in my main directory i create new file run.yml and include my role
---
# create a new VM from a template
- name: VM from template
hosts: localhost
gather_facts: false
connection: local
roles:
- install
The issue is i don't know how to call vars from roles->vars directory as you can see in my playbook i have hard code variables. I need to get or set the variable in file and call it from that file.
**vcenter_hostname: vcenter-app
vcenter_user: john#doe
vcenter_pass: blabla6
esxhost: esx-4.cbalo.fr
datastore: VM-PROD-02-NORMAL
vmtemplate: Centos7-template
name: "newvm2"
datacenter: CD06
folder: Test**
Variables in ansible are a set of values that will replace certain place-holders. You supply them when running your playbook and they will "trickle down" if you include roles etc. Check the documentation to find out about variable precedence in ansible.
So what you want to do is to put your variable-assignments in your inventory (you can split out variables in separate files as well, using group_vars) and then use the -i path/to/inventory.yml on your ansible-playbook command.
A structure could look like that:
my-ansible/
roles/
my-role/
tasks/
main.yaml
defaults/
main.yaml # contains default values for your variables
inventory/
inventory.yaml # contains hosts and variable assignments
run.yaml
Then, you can run it like that:
ansible-playbook -i inventory/inventory.yaml run.yaml
Hints:
Don't use my-role/vars as it is very hard to override variable assignments in there. (See variable precedence)
defaults/main.yaml is not necessary, but can be handy for variables you rarely change

add_host - divide by os

I want to create playbook that going on the entire inventory file and divide the servers to 2 groups: Windows and Linux (add-host going only on the first server on the inv)
I tried this code:
- name: Linux Group
add_host:
name: "{{ item }}"
group: LinuxGroup
when: hostvars[" {{ item }} "]['ansible_system'] == 'Linux'
with_items: "{{ ansible_play_hosts_all }} "
This code suppose to create the linux group
and I tried with other conditions of when but non was a succsess. I would like to get your help please.
PS:
I changed the code to this:
tasks:
- name: Create linux group
add_host:
name: "{{ item }}"
group: LinuxGroup
when: hostvars[item].ansible_system == 'Linux'
with_items: "{{ ansible_play_hosts_all }} "
ignore_errors: yes
- name: ping to Linux
ping:
with_items: LinuxGroup
and when I run the code the windows servers are skipped in the "Create linux group" task, but I used the module debug to print to group's items and there are the windows servers.
The fact ansible_system is a key under the host, not a list of keys. Also, conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}, use hostvars[item] instead of hostvars[ "{{ item }}" ].
Make sure gather_facts is set to true.
Note that the add_host module does not update the inventory file but updates the in-memory inventory. I have included a debug task to print the groups from the in-memory inventory of ansible.
gather_facts: true
tasks:
- name: Linux Group
add_host:
name: "{{ item }}"
group: LinuxGroup
when: hostvars[item].ansible_system == 'Linux'
with_items: "{{ ansible_play_hosts_all }}"
- debug: msg="{{ groups }}"

printing the host name from group in inventory

I have below inventory file:
[web]
10.0.1.0
[db]
10.0.3.0
[frontend]
10.0.5.0
[X_all:children]
web
db
frontend
Now in my playbook: I'm trying to print the hostname under X_all group in the name line.
- name: "Copying the output of Registry run to local machine from {{ hostvars[item]['inventory_hostname'] }}"
become: true
become_user: "{{ login }}"
fetch:
src: /tmp/DeploymentRegistry.txt
dest: /tmp/DeploymentRegistry-{{ inventory_hostname }}.txt
flat: yes
with_items:
- "{{ groups['X_all'] }}"
Is it even possible to add the hostname in the name line?
I tried replacing {{ hostvars[item]['inventory_hostname'] }} with inventory_hostname but it's also not working.
Regarding your requirement
I'm trying to print the hostname under test group in the name line.
take note that the group has more than one member and therefore more than one hostname, but a list of hostnames.
- name: Show hosts {{ groups['test'] }}
delegate_to: localhost
debug:
msg: "{{ item }}" # will show the group member hostname(s)
with_items:
- "{{ groups['test'] }}"
Is it even possible to add the hostname in the name line? I tried ... with inventory_hostname but it's also not working.
Yes, it is.
- name: Show host {{ inventory_hostname }}
debug:
msg: "{{ item }}"
with_items:
- "{{ groups['test'] }}"
But it will print the first hostname from list only.

Iterating over vars **only** defined in inventory for a host

I would like to iterate over the vars defined in the inventory file of an ansible playbook. Indeed, in my inventory I define some vars to put in a .ini
file on the target host. I have something like this in my inventory file:
[myhost:vars]
VAR1=VALUE1
VAR2=VALUE2
I tried something like this:
- name: fill ini file with variables
ini_file:
path: "{{ myfile.ini }}"
section: vars
option: "{{ item.key }}"
value: "{{ item.value }}"
create: yes
with_dict: "{{ hostvars[inventory_hostname] }}"
myfile.ini should look like this at the end:
[vars]
VAR1=VALUE1
VAR2=VALUE2
The problem is: I properly have 'VAR1' and 'VAR2', but also all the Ansible variables for the host. I would like to iterate only on those defined in
the inventory (inventory_vars ? Does not exist).
Any help would be appreciated :)
There is no way to determine were a certain fact/variable was set, or filter them by their origin.
Instead, you can define a dictionary (JSON) in your inventory:
[myhost]
localhost
[myhost:vars]
my_dict={"VAR1": "VALUE1", "VAR2": "VALUE2"}
and use it in the iterator:
with_dict: "{{ my_dict }}"
Mind that in your example with_dict is wrongly indented.

Iterate over a array in with_items loop

Based on this question
Ansible recursive checks in playbooks
I have another one.
We need to go through this structure
Zone spec https://gist.github.com/git001/9230f041aaa34d22ec82eb17d444550c
Now I can adress the hostnames via the array index but can I also iterate over the array "hosts"?
playbook
--
- hosts: all
gather_facts: no
vars_files:
- "../doc/application-zone-spec.yml"
roles:
- { role: ingress_add, customers: "{{ application_zone_spec }}" }
role
- name: Print ingress hostnames
debug: msg="{{ item.hosts.0.hostname }} {{ item.hosts.1.hostname }}"
with_items: "{{ customers.ingress }}"
We use.
ansible-playbook --version
ansible-playbook 2.1.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
Use with_subelements:
- name: Print ingress hostnames
debug: msg="{{ item.0.type }} {{ item.1.hostname }}"
with_subelements:
- "{{ customers.ingress }}"
- "hosts"
There is quite a bit of examples for different loops in the Loops section of the documentation.

Resources