I'm trying to create an idempotent playbook in a cisco router. I read the examples on the web and I think the problem is with the parameter "with_item".
Here's the play:
- name: Configurar subinterfaces para las VLAN 10,20 y 30
ios_config:
provider: "{{ cli }}"
parents:
- interface GigabitEthernet0/0
lines:
- interface GigabitEthernet0/0.{{ item.subinterface }}
after:
- description {{ item.name }}
- encapsulation dot1q {{ item.subinterface }}
- ip address {{ item.ip_add }} 255.255.255.0
with_items:
- { subinterface: 10, name: Ventas, ip_add: 192.168.10.1 }
- { subinterface: 20, name: RRHH, ip_add: 192.168.20.1 }
- { subinterface: 30, name: Contabilidad, ip_add: 192.168.30.1 }
Here's the output:
PLAY [Configurar Router 1 Cisco] ***********************************************
TASK [config_r1_cisco : Configurar subinterfaces para las VLAN 10,20 y 30] *****
changed: [R1] => (item={u'subinterface': 10, u'ip_add': u'192.168.10.1', u'name': u'Ventas'})
changed: [R1] => (item={u'subinterface': 20, u'ip_add': u'192.168.20.1', u'name': u'RRHH'})
changed: [R1] => (item={u'subinterface': 30, u'ip_add': u'192.168.30.1', u'name': u'Contabilidad'})
PLAY RECAP *********************************************************************
R1 : ok=1 changed=1 unreachable=0 failed=0
When I run the playbook again and again, the output always change instead of ok. Could it be because when using variables in the "with_items" parameter the idempotence is not carried out?
There are many reasons why you might be getting an idempotent command, but they are not related to the with_items
options.
A possible issue would be using abbreviated commands (shut
instead of shutdown
for example). On the section "Why do the config
modules always return true" of the "Ansible Network FAQ" there it this snippet:
Ansible Network *_config modules compare the text of the commands you specify in lines to the text in the configuration. If you use shut in the lines section of your task, and the configuration reads shutdown, the module returns changed=true even though the configuration is already correct. Your task will update the configuration every time it runs.
I don't believe this is your case.
Another reason could be that you are not using the same commands as those found on the running_config
. And so the checks between the lines are not matching exactly, even though they produce the same output.
Also probably not your issue, though you should check.
There is also the way the module compares the updated lines with the running_config
. By default, the module checks each line, but there are other options. The documentation says:
Instructs the module on the way to perform the matching of the set of commands against the current device config. If match is set to line, commands are matched line by line. If match is set to strict, command lines are matched with respect to position. If match is set to exact, command lines must be an equal match. Finally, if match is set to none, the module will not attempt to compare the source configuration with the running configuration on the remote device.
That might be your issue.
I also have a personal opinion as to what may be affecting the way the module works and is the fact that you are using the after
option to apply the changes to the interfaces. Its actual usage is:
The ordered set of commands to append to the end of the command stack if a change needs to be made. Just like with before this allows the playbook designer to append a set of commands to be executed after the command set.
Along with the before
option, they are used to apply commands before and after the actual changes are made. For example, setting a reset in five minutes to avoid a disconnection because of a configuration issue, or writing the changes to the ROM (though, you probably do this through the save_when
option). I have no evidence that this is the case, but you should try it. Just move the lines in the after
option to the lines
option.
Finally, you might see what is changing by running the playbook
with the --check --diff
flag.
I hope it helps.
Here's the final play to my question:
---
- name: Configurar subinterfaces para las VLAN 10,20 y 30
ios_config:
provider: "{{ cli }}"
parents:
- interface GigabitEthernet0/0.{{ item.subinterface }}
lines:
- description {{ item.name }}
- encapsulation dot1Q {{ item.subinterface }}
- ip address {{ item.ip_add }} 255.255.255.0
match: strict
with_items:
- { subinterface: 10, name: Ventas, ip_add: 192.168.10.1 }
- { subinterface: 20, name: RRHH, ip_add: 192.168.20.1 }
- { subinterface: 30, name: Contabilidad, ip_add: 192.168.30.1 }
Thanks to guzmonne