Variable leaking between hosts when concurrency > 1

This is probably going to be long as I haven’t figured out a way to explain and show the issue in a summarized fashion. From the testing I’ve performed so far, it looks like there may be an issue/limit with nesting includes and/or roles and loops or with set_fact. Just looking for insight or confirmation so that it can be taken into consideration int he future

Let me first attempt a problem statement: while in a loop and including tasks within that loop (include_task) where the include itself includes a role. variables are passed to the role (using vars) from the include. The role calls another role along with passing variables to the second role. This second role sometimes will end up with variables from the previous host. This has been confirmed by simply displaying the variables before calling the role by displaying the variables in the first role right before calling the role and then displaying the variables in the second role as part of the first task. It does not appear that this happens for all loop items or all hosts. Removing the include and calling the first role directly (and it calling the second role) in the playbook seems to work around this issue.

Here’s the playbooks - somewhat simplified for purposes of explanation:

==== main.yml ====

  • name: Concurrency test
    gather_facts: no
    hosts: “{{inventoryGroup|default(‘all’)}}”
    strategy: “{{runStrategy|default(‘free’)}}”
    tasks:

  • name: Load the variables
    include_role:
    name: load-variables

This is the include_tasks which was mentioned. It calls the first role

with that role then calling the second. If this include is removed and

the first role is called here instead, the problem disappears

  • name: Include the first file (level 1) for
    include_tasks: “{{includeDir}}/set-dir-option-helper.yml”
    vars:
    thisKey: “{{optionItem.name}}”
    thisValue: “{{optionItem.value}}”
    thisSearchBase: “{{optionItem.searchBase}}”
    thisSearchScope: “{{optionItem.scope|default(‘base’)}}”
    thisUserPass: “{{rhdsDirMgrPass}}”
    loop:
  • {name: nsslapd-sizelimit, value: “{{resLimitSizelimit}}”,searchBase: “cn=config”}
  • {name: nsslapd-idletimeout, value: “{{resLimitIdletimeout}}”,searchBase: “cn=config”}
  • {name: nsslapd-lookthroughlimit, value: “{{resLimitLookthroughlimit}}”, searchBase: “cn=config,cn=ldbm database,cn=plugins,cn=config”}
    loop_control:

loop_var: optionItem

==== set-dir-option-helper.yml ====

  • name: Call set-dir-option
    include_role:
    name: set-dir-option
    vars:
    setDirOptionKey: “{{thisKey}}”
    setDirOptionValue: “{{thisValue}}”
    setDirOptionSearchBase: “{{thisSearchBase}}”
    setDirOptionSearchScope: “{{thisSearchScope|default(‘sub’)}}”
    setDirOptionUserPass: “{{thisUserPass}}”
    setDirOptionLdapPort: “{{portNumberPlain}}”

  • name: Set changed value
    set_fact:
    setDirOptionChangedInLoop: true
    when: setDirOptionChanged|default(“false”)|bool

==== simplified set-dir-option (aka “role 1”) ====

these are used to check the variable values which will be passed into the

ldapsearch role (aka role 2) and are used as the bases of "these are the

correct variable values"

  • name: Display variables received (debug 1) on {{inventory_hostname}}
    debug:
    msg:

  • “Display variables received (debug 1) on {{inventory_hostname}}”

  • “setDirOptionLdapHost: {{setDirOptionLdapHost}}”

  • “setDirOptionLdapPort: {{setDirOptionLdapPort}}”

  • “setDirOptionLdapUser: {{setDirOptionLdapUser}}”

  • “setDirOptionKey: {{setDirOptionKey}}”

  • “setDirOptionSearchBase: {{setDirOptionSearchBase}}”

  • “setDirOptionSearchScope: {{setDirOptionSearchScope}}”

  • “setDirOptionDelegateTo: {{setDirOptionDelegateTo}}”
    verbosity: 1

  • name: Reset setDirOptionChanged on {{inventory_hostname}}
    set_fact:
    setDirOptionChanged: false

  • name: Get current value ({{setDirOptionKey}} on {{inventory_hostname}})
    include_role:
    name: ldapsearch
    vars:
    ldapsearchHost: “{{setDirOptionLdapHost}}”
    ldapsearchPort: “{{setDirOptionLdapPort}}”
    ldapsearchBindUser: “{{setDirOptionLdapUser}}”
    ldapsearchBindPass: “{{setDirOptionUserPass}}”
    ldapsearchFilter: “{{setDirOptionKey}}=*”
    ldapsearchBase: “{{setDirOptionSearchBase}}”
    ldapsearchReturnAttrs: “{{setDirOptionKey}}”
    ldapsearchScope: “{{setDirOptionSearchScope}}”
    ldapsearchTempIsChange: false
    ldapsearchSearchIsChange: false
    ldapsearchDelegateTo: “{{setDirOptionDelegateTo}}”

  • name: Save the returned LDAP Results
    set_fact:
    setDirOptionResults: “{{ldapsearchResult}}”

==== Simplified ldapsearch (aka role 2) ====

This is the confirmation of the issue - sometimes the variables are the

from a another host which is concurrently running. I am going to call that

the “previous host” as in the output the other host’s processing appears

first in the output/logs. There is a lot more to this role which has not

been included here. Parts further down make a change if the values are not

what are expected and I used that change as an indicator of the situation

that I am reporting since a change is unexpected

  • name: Received ldapsearch information for {{inventory_hostname}}
    debug:
    msg:
  • “Received ldapsearch information for {{inventory_hostname}}”
  • “ldapsearchHost: {{ldapsearchHost|default(‘not set’)}}”
  • “ldapsearchPort: {{ldapsearchPort|default(‘not set’)}}”
  • “ldapsearchBindUser: {{ldapsearchBindUser|default(‘not set’)}}”
  • “ldapsearchBase: {{ldapsearchBase|default(‘not set’)}}”
  • “ldapsearchFilter: {{ldapsearchFilter|default(‘not set’)}}”
  • “ldapsearchScope: {{ldapsearchScope|default(‘not set’)}}”
  • “ldapsearchReturnAttrs: {{ldapsearchReturnAttrs|default(‘not set’)}}”
  • “ldapsearchDelegateTo: {{ldapsearchDelegateTo|default(‘not set’)}}”
    verbosity: 1

FWIW. There are a dozen "include and import issues".
https://github.com/ansible/ansible/projects/19#card-9047818

Similar syndromes were positively tested also in "Ansible variable has
inconsistent values".
https://stackoverflow.com/questions/60420127/ansible-variable-has-inconsistent-values/

HTH,
  -vlado