I'm trying to create a text file which goes through the CSV file and populates variables into specific fields.
playbook.yml:
- hosts: localhost
tasks:
- name: "Reading user information"
read_csv:
path: /home/test/vlans.csv
delimiter: ','
register: vlans
- debug: var=vlans
- name: Creating VLANs configuration
template:
src: vlan.conf.j2
dest: /tmp/vlan.conf
Jinja2 Template vlan.conf.j2:
{% for item in vlans %}
!
vlan {{ item.VLAN }}
name {{ item.Description }}
vn-segment {{ item.VNI }}
interface nve1
member vni {{ item.VNI }}
{% endfor %}
and this is a test vlans.csv file:
Tenant,VRF ,VLAN,VNI,Subnet,Description,Good to go
Test,,5,20005,,LAB-Checkpoint-FW-Mgmt,Yes
Test,,208,20208,,LAB-DMZ,Yes Test,,209,20209,,LAB-CSR-MGMT,Yes
Test,10000,210,20210,192.168.12.1/28,LAB-VRF-to-FW,Yes
Prod,,761,20761,,PROD-CORE,Yes
Prod,105,840,20840,172.18.33.1/24,Backups,Yes
Prod,,841,20841,,Transport,Yes
I want to end up with file like in jinja2 template and not repeating line "interface nve 1"
In your question, interface nve1 is inside a loop. It will repeat multiple times in the resulting vlan.conf file.
Use multiple loops in the jinja template to decide what is repeated and what isn't:
{% for item in vlans.list %}
vlan {{ item.VLAN }}
name {{ item.Description }}
vn-segment {{ item.VNI }}
{% endfor %}
interface nve1
{% for item in vlans.list %}
member vni {{ item.VNI }}
{% endfor %}
Note that I've referred to vlans.list in the start of the loops instead of vlans. This is correct as per documentation, but different to the example in the question so it may need adjusting.
I have a playbook to initiate a conf to servers that requires hostname. I want to pass my hosts that define in playbook as group so as to loop the variables in my jinja2 template. And I don't want to set the hosts in vars(because that was already define in playbook, I don't know the reason for re-define)
For example:
host file:
[test_servers]
t1
t2
t3
[test2_servers]
t2
t4
playbook:
- hosts: test_servers
tasks:
- name: generate my conf
template:
src: templates/temp.conf.j2
dest: "test.conf"
force: True
vars:
hosts: test_servers # So far I need to declare the var here duplicately, I've group my server in host file and I just want to use the current group.
temp.conf
....
{% for host in groups[hosts] %}
Entry.{{ loop.index }} = {{ host }}
{% endfor %}
....
I wonder if there is a better way to pass the hosts that set in playbook to my jinja2 template so I can re-use the playbook for different hosts. For example, I just need to reset the playbook hosts to test2, no need to rewrite the vars.
There is no special variable with the name of the group, but there is ansible_play_hosts_all
List of all the hosts that were targeted by the play
Remove vars and use ansible_play_hosts_all in the template
- hosts: test_servers
tasks:
- name: generate my conf
template:
src: templates/temp.conf.j2
dest: "test.conf"
force: True
{% for host in ansible_play_hosts_all %}
Entry.{{ loop.index }} = {{ host }}
{% endfor %}
I would like to filter hosts by a variable set on them. For example:
I have a group of hosts, one is master, the rest are slaves. On the master the variable replica_type: master is set. I would now like to get the master server dynamically.
My working aproach is:
- set_fact:
master_server_string: >-
{% for server in groups.my_servers %}
{% if hostvars[server]['replica_type']=='master' -%}
{{ server }}
{% endif %}
{% endfor %}
- set_fact:
master_server: "{{ master_server_string|trim }}"
Is there a way to perform the same with a filter (or at least in a single task)?
e.g. something like
"{{ server for server in groups.my_servers if hostvars[server]['replica_type'] == 'master' }}"
I believe you are looking for the group_by module.
https://docs.ansible.com/ansible/latest/modules/group_by_module.html
- group_by:
key: {{ replica_type }}
You can pull a value out of a group of hosts by a property by looping the group and checking for a matching value like this too:
- set_fact:
master_server: "{{ item }}"
with_items: "{{ groups.my_servers }}"
when: hostvars[item].replica_type == 'master'
Suppose we have an ansible inventory like this:
[somegroup]
host1 secondaryIp=1.0.0.0
host2 secondaryIp=1.0.0.1
host3 secondaryIp=1.0.0.2
While running a task (specifically template module) is there a way to get the list of secondaryIp's for "all other hosts" in the group [somegroup] ??
I tried searching ansible filters: http://docs.ansible.com/ansible/latest/playbooks_filters.html#list-filters
My only working idea was to do this in inventory:
[somegroup]
host1 secondaryIp=1.0.0.0 otherIps="1.0.0.1,1.0.0.2"
host2 secondaryIp=1.0.0.1 otherIps="1.0.0.0,1.0.0.2"
host3 secondaryIp=1.0.0.2 otherIps="1.0.0.0,1.0.0.1"
You can get a list of hosts in the group using groups['somegroup'] and access their variables using hostvars. To exclude the host ansible is currently running on you just need to check if the current host in the list equals inventory_hostname. Here's how it works in practice.
In a template
{% for host in groups['somegroup'] %}
{% if host != inventory_hostname %}
{{ hostvars[host]['secondaryIp'] }}
{% endif %}
{% endfor %}
In a task
- name: debug
debug:
msg: "{{ hostvars[item]['secondaryIp'] }}"
when: item != inventory_hostname
with_items: "{{ groups['somegroup'] }}"
how can i loop in an ansible playbook over gathered facts?
I tried:
...
haproxy_backends:
- name: 'backend'
servers:
{% for host in groups['app-servers'] %}
- name: "{{ hostvars[host]['ansible_hostname'] }}"
ip: "{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}"
{% endfor %}
But this doesn't work, it results in a Syntax Error. Is it even possible to use jinja in a playbook?
I use a ansible galaxy role (info.haproxy) and i don't want to change the provided templates.
No you can't do this.
This has to be done in a template, something like :
template/haproxy.cfg.j2 :
...
{% for host in groups['app-servers'] %}
backend {{ hostvars[host]['ansible_hostname'] }}
server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}:1234 check inter 5000 slowstart 2m
{% endfor %}
...
and use :
tasks:
- name: Deploy haproxy config
template: src=templatepath/haproxy.cfg.j2 dest=/etc/haproxy/haproxy.cfg
You get the idea, YMMV.
Good luck.