Search for value in variable array

172 views
Skip to first unread message

Rod Oliver

unread,
Jun 8, 2017, 10:29:13 AM6/8/17
to Ansible Project
I have created a couple of arrays using responses from commands via ntc_ansible to a Cisco switch, one containing CDP neighbor information (with keys "local_interface", "neighbor" and "neighbor_interface") and the other from a listing of interfaces on the switch. I want to use the presence of a combination of the "neighbor" and "neighbor_interface" values (from the CDP neighbor array) in the interface list array as a condition on the running of a task.

The playbook currently looks that below.
---
- hosts: production
  gather_facts: no
  connection: local
  vars:
    provider:
      host: "{{ inventory_hostname }}"
      username: "{{ enc_username }}"
      password: "{{ enc_password }}"
      transport: cli
      platform: cisco_nxos
  tasks:
  - include_vars: authentication.yml
  - name: Run SHOW CDP NEI and store output
    ntc_show_command:
      command: "show cdp neig"
      template_dir: "./ntc-templates/templates"
      provider: "{{ provider }}"
    register: cdp_nei
  - name: Run SHOW INT STATUS and store output
    ntc_show_command:
      command: "show int status"
      template_dir: "./ntc-templates/templates"
      provider: "{{ provider }}"
    register: int_stat
  - name: Create interface description statements where needed
    blockinfile:
      dest: ./Output/cdp-output-processed
      insertafter: EOF
      marker: "!"
      block: |
        interface {{ item.local_interface }}
          description ->{{ item.neighbor | regex_replace("\(.*") }}_{{ item.neighbor_interface }}
    with_items: "{{ cdp_nei.response }}"
    when: int_stat.response | search("{{ cdp_nei.response.item.neighbor }}"_"{{ cdp_nei.response.item.local_interface }}")

The last task fails as below
TASK [Create interface description statements where needed] ************************************************************

 [WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found:
int_stat.response | search("{{ cdp_nei.response.item.neighbor }}"_"{{ cdp_nei.response.item.local_interface }}")

fatal: [switch]: FAILED! => {"failed": true, "msg": "The conditional check 'int_stat.response | search(\"{{ cdp_nei.r
esponse.item.neighbor }}\"_\"{{ cdp_nei.response.item.local_interface }}\")' failed. The error was: error while evaluati
ng conditional (int_stat.response | search(\"{{ cdp_nei.response.item.neighbor }}\"_\"{{ cdp_nei.response.item.local_int
erface }}\")): 'list object' has no attribute 'item'\n\nThe error appears to have been in '/home/vagrant/ansible/Automat
ion/cdp-description.yml': line 26, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\
nThe offending line appears to be:\n\n    register: int_stat\n  - name: Create interface description statements where ne
eded\n    ^ here\n"}

Any tips on how to proceed?

Kai Stian Olstad

unread,
Jun 8, 2017, 10:49:07 AM6/8/17
to ansible...@googlegroups.com
Do as the warning say, remove {{ }}. So something like this might work

when: int_stat.response | search(cdp_nei.response.item.neighbor ~ "_" ~
cdp_nei.response.item.local_interface)

--
Kai Stian Olstad

Rod Oliver

unread,
Jun 8, 2017, 11:05:17 AM6/8/17
to Ansible Project, ansible-pr...@olstad.com
Thanks for your respoinse Kai.

I changed the conditional statement to that below. It wasn't what I really wanted but I figured if it worked I could build on it. I got a further error.

Statement:
  when: int_stat.response | search(cdp_nei.response.item.neighbor)

Error:
TASK [Create interface description statements where needed] ************************************************************

fatal: [switch]: FAILED! => {"failed": true, "msg": "The conditional check 'int_stat.response | search(cdp_nei.respon
se.item.neighbor)' failed. The error was: error while evaluating conditional (int_stat.response | search(cdp_nei.respons
e.item.neighbor)): 'list object' has no attribute 'item'\n\nThe error appears to have been in '/home/vagrant/ansible/Aut
omation/cdp-description.yml': line 26, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem
.\n\nThe offending line appears to be:\n\n    register: int_stat\n  - name: Create interface description statements wher
e needed\n    ^ here\n"}

I tried to surround cdp_nei.response.item.neighbor with "" and got yet a different error.

Statement:
  when: int_stat.response | search("cdp_nei.response.item.neighbor")

Error:
TASK [Create interface description statements where needed] ************************************************************

fatal: [switch]: FAILED! => {"failed": true, "msg": "The conditional check 'int_stat.response | search(\"cdp_nei.resp
onse.item.neighbor\")' failed. The error was: Unexpected templating type error occurred on ({% if int_stat.response | se
arch(\"cdp_nei.response.item.neighbor\") %} True {% else %} False {% endif %}): expected string or buffer\n\nThe error a
ppears to have been in '/home/vagrant/ansible/Automation/cdp-description.yml': line 26, column 5, but may\nbe elsewhere
in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n    register: int_stat\n  - n
ame: Create interface description statements where needed\n    ^ here\n"}

Kai Stian Olstad

unread,
Jun 8, 2017, 11:17:51 AM6/8/17
to ansible...@googlegroups.com
On 08. juni 2017 17:05, Rod Oliver wrote:
> Thanks for your respoinse Kai.
>
> I changed the conditional statement to that below. It wasn't what I really
> wanted but I figured if it worked I could build on it. I got a further
> error.
>
> Statement:
> when: int_stat.response | search(cdp_nei.response.item.neighbor)
>
> Error:
> TASK [Create interface description statements where needed]
> ************************************************************
>
> fatal: [switch]: FAILED! => {"failed": true, "msg": "The conditional check
> 'int_stat.response | search(cdp_nei.respon
> se.item.neighbor)' failed. The error was: error while evaluating
> conditional (int_stat.response | search(cdp_nei.respons
> e.item.neighbor)): 'list object' has no attribute 'item'\n\nThe error
> appears to have been in '/home/vagrant/ansible/Aut
> omation/cdp-description.yml': line 26, column 5, but may\nbe elsewhere in
> the file depending on the exact syntax problem
> .\n\nThe offending line appears to be:\n\n register: int_stat\n - name:
> Create interface description statements wher
> e needed\n ^ here\n"}

The message says cdp_nei.response does not contain the attribute item.
So what is the content of cdp_nei.response?

- debug: var=cdp_nei.response

Will give you the content.



> I tried to surround cdp_nei.response.item.neighbor with "" and got yet a
> different error.
>
> Statement:
> when: int_stat.response | search("cdp_nei.response.item.neighbor")

With "" it will be the literal string cdp_nei.response.item.neighbor and
not the content of the variable.


I also suspect that int_stat.response and is not a string but a list.
The search filter need a string.


--
Kai Stian Olstad

Rod Oliver

unread,
Jun 9, 2017, 2:43:34 AM6/9/17
to Ansible Project, ansible-pr...@olstad.com
Thanks again for your reply. I think I have a faulty understanding with the way that loops and conditionals apply in Ansible.

cdp_nei.response is a list of dictionaries (containing values for interface name, neighbor name and neighbor interface) and I'm using that as an input for a loop to build the configuration of the description of the interface of switch ports (a combination of neighbor name and neighbor interface). This works without the conditional.

I want to add a conditional that only runs the loop element when neighbor name is not present in int_stat.response (also a list of dictionaries) which contains the configured state of the interfaces. Basically the idea is to create the configuration template to reconfigure the interface description where it is wrong but not otherwise.

Kai Stian Olstad

unread,
Jun 20, 2017, 2:47:17 PM6/20/17
to ansible...@googlegroups.com
If I understand you correctly you are looking for a loop in a loop.
Do do that in Ansible check out loop control
https://docs.ansible.com/ansible/playbooks_loops.html#loop-control


--
Kai Stian Olstad
Reply all
Reply to author
Forward
0 new messages