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