cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
679
Views
2
Helpful
14
Replies

Ansible using Loop with registered variables

Netmart
Level 1
Level 1

 

Hello,

I was wondering, whether it is possible instead of creating three separate tasks, one processing one element of an array, to actually loop through an array.

 

Example:

 

vars:

      ansible_become_pass: "{{ vault_sudo_password }}"

      ansible_python_interpreter: /usr/bin/python3

 

      prefix:

         -  10.0.1.0/25

         -  10.0.3.0/25

         -  10.0.5.0/25

 

 

     - name: Task1- remove prefix

       ios_config:

         commands:

             - no ip prefix-list MTDC-nets permit {{prefix[0]}}

       when: output2.stdout is search ~prefix[0]

 

       become: true

       register: output1

 

 

     - name: Task2- remove prefix

       ios_config:

         commands:

             - no ip prefix-list cisco-nets permit {{prefix[1]}}

       when: output2.stdout is search ~prefix[1]

 

       become: true

       register: output2

 

 

     - name: Task3- remove prefix

       ios_config:

         commands:

             - no ip prefix-list MTDC-nets permit {{prefix[2]}}

       when: output2.stdout is search ~prefix[2]

 

       become: true

       register: output3

 

 

Is it possible to create only one task and looping through the elements of an array:

 

 

  vars:

      ansible_become_pass: "{{ vault_sudo_password }}"

      ansible_python_interpreter: /usr/bin/python3

 

      loop:

         -  10.0.1.0/25

         -  10.0.3.0/25

         -  10.0.5.0/25

register: prefix

 

 

     - name: Task1- remove prefix

       ios_config:

         commands:

             - no ip prefix-list Cisco-nets permit {{prefix}}

       when: output2.stdout is search ~prefix

 

       become: true

       register: output1

 

14 Replies 14

You can, instead of creating separate tasks for each element in the array, use a single task with a loop. Then use a dictionary to store the prefix list and its corresponding network name.

---
vars:
ansible_become_pass: "{{ vault_sudo_password }}"
ansible_python_interpreter: /usr/bin/python3

prefix_list:
- { network: "MTDC-nets", prefix: "10.0.1.0/25" }
- { network: "cisco-nets", prefix: "10.0.3.0/25" }
- { network: "MTDC-nets", prefix: "10.0.5.0/25" }

tasks:
- name: Remove prefix
ios_config:
commands:
- "no ip prefix-list {{ item.network }} permit {{ item.prefix }}"
when: output2.stdout is search ~item.prefix
become: true
register: output
loop: "{{ prefix_list }}"

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Netmart
Level 1
Level 1

Thank you.

I tried to apply it, but it seems still to be an error

 

 

      prefix_list:
         -  {network:"Test-nets",prefix:"10.0.0.0/25"}
         -  {network:"Test-nets",prefix:"10.0.2.0/25"}
         -  {network:"Test-nets",prefix:"10.0.5.0/25"}

:
     - name: Task2 - sh run
       ios_command:
          commands:
              - "sh run | i Test-nets"

       become: true
       register: output2
     
:
     - name: Task3- remove prefix
       ios_config:
         commands:
             - "no ip prefix-list {{ item.network }} permit {{ item.prefix }}"
       when: output2.stdout is search ~item.prefix

       become: true
       register: output3
       loop: "{{ prefix_list }}"

 

\nThe offending line appears to be:\n\n\n     - name: Task3- remove prefix\n       ^ here\n"    
TASK [Task3- remove prefix] ********************************************************************************************

fatal: [cisco.org]: FAILED! => {"msg": "The conditional check 'output2.stdout is search ~item.prefix' failed.
The error was: error while evaluating conditional (output2.stdout is search ~item.prefix):
'dict object' has no attribute 'stdout'. 'dict object' has no attribute 'stdout'\n\nThe error appears to be in
'/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop.yml': line 39, column 8,
but may\nbe elsewhere in the file depending on the exact syntax problem.\n

Looks like the the error is due to the when condition in Task3. The output2 variable is not accessible in the scope of Task3.

Try and use the output variable from Task2 to check the prefix.

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Netmart
Level 1
Level 1

It seems that it is already complaining at Task2

 

TASK [Task2 - sh run] **********************************************************************************************************************
fatal: [cisco.org]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'prefix'. 'dict object'
has no attribute 'prefix'\n\nThe error appears to be in '/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop.yml':
line 28, column 8, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Task2 - sh run\n ^ here\n"}

PLAY RECAP *********************************************************************************************************************************
cisco.org : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

 

site-ios-xe-CE-bgp-prefix-list-update-loop.yml

:
vars:
ansible_become_pass: "{{ vault_sudo_password }}"
ansible_python_interpreter: /usr/bin/python3

prefix_list:
- {network:"Test-nets",prefix:"10.0.0.0/25"}
- {network:"Test-nets",prefix:"10.0.2.0/25"}
- {network:"Test-nets",prefix:"10.0.5.0/25"}

tasks:

- name: Task1 - sh run | count Test-nets
ios_command:
commands:
- sh run | count Test-nets

become: true
register: output1

 

- name: Task2 - sh run [ line 28, column 8,]
ios_command:
commands:
- sh run | i {{ item.prefix }}

become: true
register: output2
loop: "{{ prefix_list }}"



- name: Task3- remove prefix
ios_config:
commands:
- "no ip prefix-list {{ item.network }} permit {{ item.prefix }}"
when: output2.stdout is search ~item.prefix

become: true
register: output2
loop: "{{ prefix_list }}"


- name: Task4 check prefix has been removed
ios_command:
commands:
- "sh run | i {{ item.prefix }}"

become: true
register: output4

 

- name: Task5 - sh run | count Test-nets
ios_command:
commands:
- sh run | count Test-nets

become: true
register: output5


# ******** Output results ********

- name: Result1 prefix count prior to update - sh run | count TestC-nets
debug:
var: output1


- name: Result2.1 check if prefix is configured
debug:
msg: " Prefix is configured @ {{inventory_hostname}}: {{ item.network }} permit {{ item.prefix }}"
when: output2.stdout is search {{ item.network }} permit {{ item.prefix }}


- name: Result2.2 check if prefix is NOT oonfigured
debug:
msg: " Prefix is configured @ {{inventory_hostname}}: {{ item.network }} permit {{ item.prefix }}"
when: output2.stdout is not search {{ item.network }} permit {{ item.prefix }}

 

- name: Result4 check if prefix has been removed
debug:
msg: " Prefix has been removed @ {{inventory_hostname}}: {{ item.network }} permit {{ item.prefix }}"
when: output4.stdout is not search {{ item.network }} permit {{ item.prefix }}


- name: Result5 prefix count post to update - sh run | count Test-nets
debug:
var: output5

Got it, try by adding loop_var: item

- name: Task2 - sh run
  ios_command:
    commands:
      - sh run | i {{ item.prefix }}
    become: true
  register: output2
  loop: "{{ prefix_list }}"
  loop_var: item

 

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Netmart
Level 1
Level 1

Thank you.

I tried, but...

 

ERROR! conflicting action statements: ios_command, loop_vars

The error appears to be in '/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop.yml': line 30, column 8, but may

be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

     - name: Task2 - sh run

       ^ here0

 

======================

Extract playbook:

site-ios-xe-CE-bgp-prefix-list-update-loop.yml

:
vars:
ansible_become_pass: "{{ vault_sudo_password }}"
ansible_python_interpreter: /usr/bin/python3

prefix_list:
- {network:"Test-nets",prefix:"10.0.0.0/25"}
- {network:"Test-nets",prefix:"10.0.2.0/25"}
- {network:"Test-nets",prefix:"10.0.5.0/25"}

tasks:

- name: Task1 - sh run | count Test-nets
ios_command:
commands:
- sh run | count Test-nets

become: true
register: output1

 

- name: Task2 - sh run [ line 30,column 8,]
ios_command:
commands:
- sh run | i {{ item.prefix }}

become: true
register: output2
loop: "{{ prefix_list }}“

loop_var: item

For your error message is indicating that there is a conflict between the ios_command and loop_vars directives in the "Task2".  I would suggest move the loop_var directive inside the loop_control block.

Hope this helps.

 

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Thank you.

I tried the following:

 

  vars:
      ansible_become_pass: "{{ vault_sudo_password }}"
      ansible_python_interpreter: /usr/bin/python3
      network: "{{ item.network }}"
      prefix: "{{ item.prefix }}"  
      prefix_list:
         - {network:"Test-nets",prefix:"10.0.0.0/25"}
         - {network:"Test-nets",prefix:"10.0.2.0/25"}
         - {network:"Test-nets",prefix:"10.0.5.0/25"}
 
     - name: Task2 - sh run
       ios_command:
          commands:
              - sh run | i "{{ item.prefix }}"  


       loop_control:
         loop: "{{ prefix_list }}"
         loop_vars: "{{ item.prefix }}"

And received the following error:

 

ERROR! 'loop' is not a valid attribute for a LoopControl

The error appears to be in '/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop2.yml': line 40, column 10, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

loop_control:
loop: "{{ prefix_list }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:

with_items:
- {{ foo }}

Should be written as:

with_items:
- "{{ foo }}"

 

I would appreciate any advice.

 

Thanks.

 

Torbjørn
Spotlight
Spotlight

Loop control should not contain the loop itself, only other "loop parameters". You can try this:

     - name: Task2 - sh run
       ios_command:
          commands:
              - sh run | i "{{ item.prefix }}"  
       loop: "{{ prefix_list }}"
       loop_control:
         loop_vars: "{{ item.prefix }}"

 

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev

Hi Torbjoern,

Thank you.

I tried, but it seems to still have an issue:

 

FAILED! => {"msg": "The field 'loop_var' has an invalid value, which includes an undefined variable. The error was: 'item' is undefined. 'item' is undefined\n\nThe error appears to be in '/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop2.yml': line 40, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n loop_control:\n loop_var: \"{{item.prefix}}\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"}

Please advise.

 

Thanks.

 

After reading over this again - sorry, my last response wasn't a good response to the original question asked. It was only answering to the specific syntax error you posted.

The simplest way to do this would be to do something like this:

 

     - name: Remove prefix
        ios_command:
          commands:
          - "no ip prefix-list {{ item.name }} permit {{ item.prefix }}"  
        loop: "{{ prefix_list }}"
      

 

If you need to verify that the prefix-list entry exists before removing like in your original playbook you can do something like this:

 

     - name: Get running-config
        ios_command: 
        - "show running-config"
        register: running_config
     - name: Remove prefix
        ios_command:
          commands:
          - "no ip prefix-list {{ item.name }} permit {{ item.prefix }}"  
        loop: "{{ prefix_list }}"
        when: running_config.stdout is search(item.name) | running_config.stdout is search(item.prefix)

 

 

 

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev

Thank you Torbjoern.

The issues remains the same:

The error appears to be in '/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop2.yml': line 44, column 9, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

- "no ip prefix-list {{ item.network }} permit {{ item.prefix }}"
loop: "{{ prefix_list }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:

with_items:
- {{ foo }}

Should be written as:

with_items:
- "{{ foo }}"

 
vars:
      prefix_list:
         - {network:"Test-nets",prefix:"10.0.0.0/25"}
         - {network:"Test-nets",prefix:"10.0.2.0/25"}
         - {network:"Test-nets",prefix:"10.0.5.0/25"}
   
  tasks:
 - name: Task3 - remove prefix
       ios_config:
         commands:
              - "no ip prefix-list {{ item.network }} permit {{ item.prefix }}"  
         loop: "{{ prefix_list }}"
         loop_control:
          loop_var: prefix_list
 
I get:
FAILED! =>
{"msg": "The task includes an option with an undefined variable.
The error was: 'item' is undefined. 'item' is undefined\n\nThe error appears to be in
'/home/cisco/Ansible/library/lib-ios-xe-staging/site-ios-xe-CE-bgp-prefix-list-update-loop2.yml':
line 36, column 8, but may\nbe elsewhere in the file depending on the exact syntax problem.
\n\nThe offending line appears to be:\n\n\n - name: Task3 - remove prefix\n ^ here\n"}
 
 

 

I believe this should work if you remove the whole "loop_control:" portion.

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev