Templated include_role resolution

This commit is contained in:
Virgil 2026-04-02 00:08:24 +00:00
parent 4bba5ef00e
commit 4b884f67d6
2 changed files with 72 additions and 8 deletions

View file

@ -1508,6 +1508,28 @@ func (e *Executor) runIncludeTasks(ctx context.Context, hosts []string, task *Ta
// runIncludeRole handles include_role/import_role.
func (e *Executor) runIncludeRole(ctx context.Context, hosts []string, task *Task, play *Play) error {
if len(hosts) == 0 {
return nil
}
for _, host := range hosts {
roleRef := e.resolveIncludeRoleRef(host, task)
if roleRef == nil || roleRef.Role == "" {
continue
}
if err := e.runRole(ctx, []string{host}, roleRef, play); err != nil {
return err
}
}
return nil
}
func (e *Executor) resolveIncludeRoleRef(host string, task *Task) *RoleRef {
if task == nil {
return nil
}
var roleName, tasksFrom, defaultsFrom, varsFrom string
var roleVars map[string]any
@ -1517,23 +1539,30 @@ func (e *Executor) runIncludeRole(ctx context.Context, hosts []string, task *Tas
defaultsFrom = task.IncludeRole.DefaultsFrom
varsFrom = task.IncludeRole.VarsFrom
roleVars = task.IncludeRole.Vars
} else {
} else if task.ImportRole != nil {
roleName = task.ImportRole.Name
tasksFrom = task.ImportRole.TasksFrom
defaultsFrom = task.ImportRole.DefaultsFrom
varsFrom = task.ImportRole.VarsFrom
roleVars = task.ImportRole.Vars
} else {
return nil
}
roleRef := &RoleRef{
Role: roleName,
TasksFrom: tasksFrom,
DefaultsFrom: defaultsFrom,
VarsFrom: varsFrom,
Vars: mergeTaskVars(roleVars, task.Vars),
renderedVars := mergeTaskVars(roleVars, task.Vars)
if len(renderedVars) > 0 {
renderedVars = e.templateArgs(renderedVars, host, task)
}
return e.runRole(ctx, hosts, roleRef, play)
return &RoleRef{
Role: e.templateString(roleName, host, task),
TasksFrom: e.templateString(tasksFrom, host, task),
DefaultsFrom: e.templateString(defaultsFrom, host, task),
VarsFrom: e.templateString(varsFrom, host, task),
Vars: renderedVars,
When: task.When,
Tags: task.Tags,
}
}
// mergeTaskVars combines include-task vars with child task vars.

View file

@ -638,6 +638,41 @@ role_value: vars-custom
assert.Equal(t, "vars-custom|include-value", e.results["host1"]["role_result"].Msg)
}
func TestExecutor_RunIncludeRole_Good_TemplatesRoleName(t *testing.T) {
dir := t.TempDir()
require.NoError(t, writeTestFile(joinPath(dir, "roles", "webserver", "tasks", "main.yml"), []byte(`---
- name: templated role task
debug:
msg: role ran
register: role_result
`), 0644))
e := NewExecutor(dir)
e.SetVar("role_name", "webserver")
var started []string
e.OnTaskStart = func(host string, task *Task) {
started = append(started, host+":"+task.Name)
}
err := e.runIncludeRole(context.Background(), []string{"localhost"}, &Task{
IncludeRole: &struct {
Name string `yaml:"name"`
TasksFrom string `yaml:"tasks_from,omitempty"`
DefaultsFrom string `yaml:"defaults_from,omitempty"`
VarsFrom string `yaml:"vars_from,omitempty"`
Vars map[string]any `yaml:"vars,omitempty"`
}{
Name: "{{ role_name }}",
},
}, &Play{})
require.NoError(t, err)
assert.Equal(t, []string{"localhost:templated role task"}, started)
require.NotNil(t, e.results["localhost"]["role_result"])
assert.Equal(t, "role ran", e.results["localhost"]["role_result"].Msg)
}
func TestExecutor_RunPlay_Good_AppliesPlayTagsToTasks(t *testing.T) {
e := NewExecutor("/tmp")
e.Tags = []string{"deploy"}