I am stuck with a looping situation using jinja template with Ansible.
My jinja template:
{% for int in interfaces | difference(existing_conf) %}
interface {{ int }}
{% for ip in dhcp_servers | difference(existing_conf) %}
ip dhcp relay address {{ ip }}
{% endfor %}
{% endfor %}
TASK [view the existing config] *******************************************************************************************************************************************************************************************************************************************************************************
ok: [nxos-1] => {
"existing_conf": [
"Vlan1",
"10.1.1.2",
"10.1.1.3",
"10.1.1.4",
"Ethernet1/49",
"10.1.1.2",
"Ethernet1/50",
"10.1.1.2"
]
}
TASK [Needed config] *****************************************************************************************************************************************************************************************************************************************************************
ok: [nxos-1]
TASK [View the needed config] ************************************************************************************************************************************************************************************************************************************************************************************
ok: [nxos-1] => {
"needed_conf": [
"Vlan1",
"10.1.1.2",
"10.1.1.3",
"10.1.1.4",
"Ethernet1/49",
"10.1.1.2",
"10.1.1.3",
"10.1.1.4",
"Ethernet1/50",
"10.1.1.2",
"10.1.1.3",
"10.1.1.4"
]
}
My variables:
interfaces=["Vlan1", "Ethernet1/49", "Ethernet1/50"]
dhcp_servers=["10.1.1.2", "10.1.1.3", "10.1.1.4"]
With my template, I am getting an empty config.
Config I want:
interface Ethernet1/49
ip dhcp relay address 10.1.1.3
ip dhcp relay address 10.1.1.4
interface Ethernet1/50
ip dhcp relay address 10.1.1.3
ip dhcp relay address 10.1.1.4
Note: I only want to add the config which is not in the running-config of switch.
Q: "... I am getting an empty config."
A: There are no items to iterate over. The difference
- debug:
msg: "{{ interfaces|difference(existing_conf) }}"
gives an empty list
msg: []
Related
We're running ansible 2.9.27 on Red Hat Linux 7.9. In my playbook, I have the following code:
- name: DEBUG THIS THING1
debug:
msg: "FOUND HOME: {{ found_service_accounts['svclinux']['home'] }}"
- name: DEBUG THIS THING2
debug:
msg: "FOUND: {{ found_service_accounts['svclinux']['home'] | selectattr('path', 'defined') | list }}"
The output looks like this:
TASK [service_accounts : DEBUG THIS THING1] ***************************************************************************
ok: [myhost.example.com] => {
"msg": "FOUND HOME: {u'owner': u'svclinux', u'path': u'/home/svclinux', u'group': u'svc-linux', u'permissions': u'755'}"
}
TASK [service_accounts : DEBUG THIS THING2] ***************************************************************************
ok: [myhost.example.com] => {
"msg": "FOUND: []"
}
I can't figure out why Ansible isn't printing the path attribute of my home. It just prints the empty list. Can you see my obvious mistake?
Thanks.
Note: found_service_accounts is a dict that was set as follows. The homes.results...stdout_lines[n] are simple strings gleaned from a shell command:
- name: set found_service_accounts
set_fact:
found_service_accounts: |
{% set j2fsa = { } %}
{%- for user in service_account_names -%}
{% set _ = j2fsa.update(
{ user : { 'home' : { 'path' : homes.results[loop.index0].stdout_lines[0],
'owner' : homes.results[loop.index0].stdout_lines[1],
'group' : homes.results[loop.index0].stdout_lines[2],
'permissions' : homes.results[loop.index0].stdout_lines[3]
},
'ssh_subdirectory' : {
'owner' : ssh_subdir.results[loop.index0].stdout_lines[0],
'permissions' : ssh_subdir.results[loop.index0].stdout_lines[1]
}
}
})
%}
{%- endfor %}
{{ j2fsa }}
and service_account_names is just a list like: [ 'svclinux' ]
found_service_accounts['svclinux']['home'] is a dictionary, not a list. You should directly access the value of path:
- name: DEBUG THIS THING2
debug:
msg: "FOUND: {{ found_service_accounts['svclinux']['home']['path'] }}"
What happens in your original attempt is that iterating over a dictionary returns just the dictionary keys (["owner", "path", "group", "permissions"]), and strings do not have an attribute named path.
I tried to combine the below dictionaries to one but struggling to pass the condition when one of the variable is not defined.
ok: [vm1.nodekite.com]] => {
"containeruplist": {
"service": "service-test-app",
"platform-service": "service-dev-app"
}
}
ok: [vm1.nodekite.com] => {
"containerexitedlist": {
"nginx": "www-service"
}
}
Here is my code.
- set_fact:
final_list: "{{ final_list|default({}) | combine( {item.key:item.value} ) }}"
with_dict:
- "{{ containeruplist }}"
- "{{ containerexitedlist }}"
when: (containeruplist is defined) or (containerexitedlist is defined)
Here is the output
ok: [vm1.nodekite.com] => {
"final_list": {
"service": "service-test-app",
"platform-service": "service-dev-app"
"nginx": "www-service"
}
}
but how to pass all the 3 conditionals when one of the variable is not defined.
containeruplist is populated or containerexitedlist is undefined
containeruplist is undefined or containerexitedlist is populated
containeruplist is populated or containerexitedlist is populated
I tried with when: (containeruplist is defined) or (containerexitedlist is defined) which still throws {"msg": "'containerexitedlist' is undefined"}
I have one ansible var list defined in group_vars
member_list:
- a
- b
I have one proxy.j2 template
{% for var in members_list %}
server {
server_name {{ var }}-{{ server_name }};
{% endfor %}
How could I loop through that list to get the value in .j2 file?
You should be using {{ item }} instead of {{ var }}.
I'm trying to write a role to configure a keepalived cluster. I was hoping to pass unique info into the a template based on the IP of the target box.
In this scenario: Server A is 192.168.1.140 and Server B is 192.182.1.141 and the VIP would be 192.168.1.142
the dictionary would look something like this:
---
192.168.1.140:
peer: 192.168.1.141
priority: 110
vip: 192.168.1.142
192.1.168.1.141
peer:192.168.1.140
priority: 100
vip: 192.168.1.142
I was hoping the task would look like this:
---
- name: keepalived template
template:
src: keepalived.j2
dest: /etc/keepalived/keepalived.conf
owner: root
group: root
mode: 0644
with_dict: '{{ ansible_default_ipv4.address }}'
and the template would look like this:
}
vrrp_instance VI_1 {
interface eth0
priority {{ item.value.priority }}
...
unicast_scr {{ ansible_default_ipv4.address }}
unicast_peer {
{{ item.value.peer }}
}
virtual_ipaddresses {
{{ item.value.vip }} }
}
Any insight would be greatly appreciated
John
Group your peers details under some common dictionary:
---
peer_configs:
192.168.1.140:
peer: 192.168.1.141
priority: 110
vip: 192.168.1.142
192.1.168.1.141
peer:192.168.1.140
priority: 100
vip: 192.168.1.142
with_... is generally for looping, you don't need any loop, as I see, so use:
- name: keepalived template
template:
src: keepalived.j2
dest: /etc/keepalived/keepalived.conf
owner: root
group: root
mode: 0644
vars:
peer_config: '{{ peer_configs[ansible_default_ipv4.address] }}'
and template:
vrrp_instance VI_1 {
interface eth0
priority {{ peer_config.priority }}
...
unicast_scr {{ ansible_default_ipv4.address }}
unicast_peer {
{{ peer_config.peer }}
}
virtual_ipaddresses {
{{ peer_config.vip }} }
}
I am creating an ansible playbook using version 2.0.0-0.3.beta1
I'd like to get the subnet id after i create a subnet. I'm refering the official ansible docs : http://docs.ansible.com/ansible/ec2_vpc_route_table_module.html
- name: Create VPC Public Subnet
ec2_vpc_subnet:
state: present
resource_tags: '{"Name":"{{ prefix }}_subnet_public_0"}'
vpc_id: "{{ vpc.vpc_id }}"
az: "{{ az0 }}"
cidr: 172.16.0.0/24
register: public
- name: Create Public Subnet Route Table
ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc_id }}"
region: "{{ region }}"
tags:
Name: Public
subnets:
- "{{ public.subnet_id }}"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ igw.gateway_id }}"
after running the playbook i received following error:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "ERROR! 'dict object' has no attribute 'subnet_id'"}
Try using: public.subnet.id instead of public.subnet-id
Its useful to debug by running this task:
- debug: msg="{{ public }}"