# Ansible loop with include\_tasks preserves variables from other iterations

**URL:** <https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829>\
**Category:** Get Help\
**Created:** [November 11, 2024, 3:20pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829 "2024-11-11T15:20:16Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Edvinas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/edvinas/32/5406_2.png) [@Edvinas](https://forum.ansible.com/u/Edvinas)\
**Post date:** [November 11, 2024, 3:20pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/1 "2024-11-11T15:20:16Z")

</div>

Trying to use include\_tasks with looping over the variables.

```auto
- name: Wrapper playbook to loop over interfaces
  hosts: HYKNET01,HYKNET02
  tasks:
    - name: Include network configuration tasks
      include_tasks: network_port_channel.yml
      loop: "{{ interfaces }}"
      loop_control:
        loop_var: interface_vars
      vars:
        interfaces:
          - full_fex_interface_number: "101/1/28"
            port_profile_name_prior: "LA2:Openstack-Nova"
            interface_description: "test"
          - full_fex_interface_number: "101/1/29"
            port_profile_name_prior: "LA2:Openstack-Nova"
            interface_description: "test2"    

```

The task _(network\_port\_channel.yml -_ [ansible\_various/port\_channel\_2ints.yml at main · edvinaskairys/ansible\_various · GitHub](https://github.com/edvinaskairys/ansible_various/blob/main/port_channel_2ints.yml)\*)\*

I’m including is quite complex, has lots of set\_facts and always works with couple of network hosts defined (HYKNET01,HYKNET02). I’m noticing quite strange behaviour with set\_fact modules inside network\_port\_channel.yml. Its hard to explain, but seems when using combination of include\_tasks and loop, Ansible processes the facts from other iterations, while current iteration doesn’t have that fact. I don’t understand if this somekind a bug or something. I saw some people has problems with set\_fact and include\_tasks, but didn’t saw exact my case. Maybe someone has some odd behaviour like i’m trying to describe ? When running the mentioned tasks separately - without looping with the same arguments everything works good.

I did find a solution for that - meta: clear\_facts, but that still doesn’t clear all facts which are generated by previous.

I think i’ve tried everything, and i don’t see a way to make this loop work without preserving any set\_facts from previous iterations. I think the workaround for that would be to use some kind of separate CI/CD tool to run standalone playbook [ansible\_various/port\_channel\_2ints.yml at main · edvinaskairys/ansible\_various · GitHub](https://github.com/edvinaskairys/ansible_various/blob/main/port_channel_2ints.yml) separately everytime…

Maybe you have some advices ?

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [November 11, 2024, 8:22pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/2 "2024-11-11T20:22:22Z")

</div>

First, `facts` are HOST scoped and not the same thing as `vars` which are play object scoped (play/role/block/task), so they will be available for the host they were defined in or via `hostvars['hostdefinedin']`, `include_tasks` in a loop will not restrict playbook vars scopes too much, it is mostly the same as including the file N times (once per loop item) in succession and a block scoping the ‘loop var’. You also have to take into account that you are running 2 loops, one per host and in each per host loop the include loop and ansible does parallelization by default, you don’t always have the results of another host’s task unless you can guarantee the other host ran first (see serial keyword).

---

<div class="post-metadata">

**Author:** ![Edvinas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/edvinas/32/5406_2.png) [@Edvinas](https://forum.ansible.com/u/Edvinas)\
**Post date:** [November 11, 2024, 9:46pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/3 "2024-11-11T21:46:13Z")

</div>

> [@bcoca](#):
>
> parallelization

thanks, whats my options here ? I’ve tried to unset the facts at the top of the playbook, but seems it’s not possible to completely delete the facts, i can convert them to `null` but on even it’s null - it hits the when statement.  
ofcourse i can edit my when statements, but the code gets even more dirty..

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [November 11, 2024, 9:57pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/4 "2024-11-11T21:57:21Z")

</div>

You should not need to ‘unset’ facts that were not set for the current host, but Ansible allows for a variable in the ‘current’ context to come from both scopes, so it might not be an issue with facts but other variables set with the same name. so depending on how you define and/or reference a variable you might get one or the other.

---

<div class="post-metadata">

**Author:** ![Edvinas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/edvinas/32/5406_2.png) [@Edvinas](https://forum.ansible.com/u/Edvinas)\
**Post date:** [November 12, 2024, 2:47pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/5 "2024-11-12T14:47:56Z")

</div>

Thanks, so do i understand correctly that i should write a playbook where i wouldn’t need to use include\_task with loop like here. But honestly i don’t know if that’s possible. I’m thinking of trying to use Anbile AWX webhook, if that will not help, then maybe some CI/CD tool

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [November 12, 2024, 3:29pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/6 "2024-11-12T15:29:54Z")

</div>

No, that is not what I’m trying to say, the issue you are describing is not how facts should work and I suspect you are masking the facts with other types of variables. This should not be a problem with `include_tasks` itself nor `set_fact`.

---

<div class="post-metadata">

**Author:** ![pieterjanv](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/pieterjanv/32/5401_2.png) [@pieterjanv](https://forum.ansible.com/u/pieterjanv)\
**Post date:** [November 13, 2024, 12:29pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/7 "2024-11-13T12:29:29Z")

</div>

I take it you want facts defined in `network_port_channel.yml` to be local to that file. If that file were a role it would be a special case of a problem I attempted to solve very recently (see [my post on the topic](http://forum.ansible.com/t/a-simple-approach-to-locally-scoped-facts-asking-for-feedback/10797/6)), so I have a suggestion.

While you can refactor to a role and use my collection, I wouldn’t bet on it being production ready. Instead, since I believe you are in control of all the code, you can set a dictionary as a fact at the start of each iteration, and set any local facts on that dictionary fact.

```yaml
--- # network_port_channel.yml
- name: reset the fact to serve as a local namespace
  ansible.builtin.set_fact:
    local: {}
- name: set `my_fact` key on `local`
  ansible.builtin.set_fact:
    local: "{{ local | combine({ 'my_fact': my_value }) }}"
- name: use the local fact
  ansible.builtin.debug:
    var: local.my_fact
- ...

```

---

<div class="post-metadata">

**Author:** ![pieterjanv](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/pieterjanv/32/5401_2.png) [@pieterjanv](https://forum.ansible.com/u/pieterjanv)\
**Post date:** [November 13, 2024, 1:19pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/8 "2024-11-13T13:19:58Z")

</div>

I’m a bit confused if [your reaction under my topic](http://forum.ansible.com/t/a-simple-approach-to-locally-scoped-facts-asking-for-feedback/10797/7) is about that topic or this one.

My suggestion at the bottom of my previous reaction should allow resetting your facts on each iteration. (No knowledge of internals necessary, `local` is just a name, you could call it anything.)

---

<div class="post-metadata">

**Author:** ![Edvinas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/edvinas/32/5406_2.png) [@Edvinas](https://forum.ansible.com/u/Edvinas)\
**Post date:** [November 13, 2024, 1:56pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/9 "2024-11-13T13:56:02Z")

</div>

sorry, i deleted the reply it was meant to this topic:

> Thank you, Pieter
> 
> Looks nice, but for me the solution you provided, looks too complex, because i’m not that into Ansible internals to understand fully what that does:)
> 
> so i’m trying to stick to the easiest workaround i think, is try to set all important facts to null, and then will try to modify the when clauses.

You mean i can just add this:

```auto
--- # network_port_channel.yml
- name: reset the fact to serve as a local namespace
  ansible.builtin.set_fact:
    local: {}
- name: set `my_fact` key on `local`
  ansible.builtin.set_fact:
    local: "{{ local | combine({ 'my_fact': my_value }) }}"
- name: use the local fact
  ansible.builtin.debug:
    var: local.my_fact

```

at the end of the playbook and it will reset the facts ?

---

<div class="post-metadata">

**Author:** ![pieterjanv](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/pieterjanv/32/5401_2.png) [@pieterjanv](https://forum.ansible.com/u/pieterjanv)\
**Post date:** [November 13, 2024, 2:05pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/10 "2024-11-13T14:05:28Z")

</div>

The idea is to put

```yaml
- name: reset the fact to serve as a local namespace
  ansible.builtin.set_fact:
    local: {}

```

at the _start_ of `network_port_channel.yml`, and change every use of `set_fact` to add the fact to `local` instead. So:

```yaml
- set_fact:
    some_var: some_value

```

Should turn into

```yaml
- set_fact:
    local: "{{ local | combine({ 'some_var': some_value }) }}"

```

See the [`combine` filter](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/combine_filter.html) for more.

Now you can you use the fact as `local.some_var` within the current iteration, but on the next it will be gone.

---

<div class="post-metadata">

**Author:** ![Edvinas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/edvinas/32/5406_2.png) [@Edvinas](https://forum.ansible.com/u/Edvinas)\
**Post date:** [November 13, 2024, 2:26pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/11 "2024-11-13T14:26:27Z")

</div>

thanks, understood, seems very interesting.

The problem i see, that if i will set those facts, then i will need accordingly tune when statements to be able to access the facts, which will take more effort than to just clear the set\_facts and then add some when statements which will compare the lenght of the set\_facts…

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [November 29, 2024, 5:39pm UTC](https://forum.ansible.com/t/ansible-loop-with-include-tasks-preserves-variables-from-other-iterations/10829/12 "2024-11-29T17:39:29Z")

</div>

I still cannot reproduce having facts from one host be available on the next, so I’m not sure that you are solving a problem with Ansible or creating an issue in the play and then removing it in the same play.
