Ansible角色重复规则仅对绝对参数生效,变量传参致重复执行
Great question—this is a super common gotcha with Ansible's role dependency logic, and it all boils down to the timing of playbook parsing vs. variable templating.
The Core Issue: Parsing Happens Before Variable Substitution
Ansible decides whether a role is a duplicate (and should be skipped) very early in the workflow, during playbook parsing—long before any variables are rendered or substituted with their actual values.
Here's the breakdown for your two scenarios:
- When using absolute values like
["3"]:
Ansible sees identical raw parameter strings every time you calldep_test_a. It recognizes these as the exact same role invocation, so it follows the duplication rule and only runs the role once. - When using template variables like
["{{ python_version }}"]:
During parsing, Ansible only sees the raw template text—not the final value it will resolve to at runtime. Even if two variable references end up being the same value later, if their raw template strings are different (like["{{ python_version }}"]vs"{{ python_versions }}"in your setup), Ansible treats them as separate role calls. That's whydep_test_aruns twice.
Let's Tie This to Your Exact Setup
In your modified configuration:
dep_testcallsdep_test_awith the raw parameter string["{{ python_version }}"]dep_testthen callsdep_test_b, which in turn callsdep_test_awith the raw parameter string"{{ python_versions }}"
Even though both of these resolve to ["3"] when variables are finally processed, the raw strings don't match. Ansible can't predict the final value during parsing, so it has no way to know these are supposed to be the same role invocation.
How to Fix This (and Get the Duplication Rule Working)
To make the duplication rule kick in with variables, you need to ensure the raw parameter strings are identical across all invocations of the role:
- Update
dep_test_b's dependency to directly reference{{ python_version }}instead of the intermediatepython_versionsvariable:# roles/dep_test_b/meta/main.yaml dependencies: - role: dep_test_a pyenv_versions: ["{{ python_version }}"]
Now both calls to dep_test_a use the exact same raw template string, so Ansible will recognize them as duplicates and only run the role once.
Another option is to define the parameter value in a shared variable (like in group_vars/all or your playbook's vars section) and reference that same variable in all dependency calls—this guarantees the raw template string is identical everywhere.
内容的提问来源于stack exchange,提问作者NPatel

