feat(ansible): apply role when defaults to tasks

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 03:04:35 +00:00
parent 6ef54d3e56
commit 290e9b47b1
4 changed files with 53 additions and 0 deletions

View file

@ -1793,6 +1793,9 @@ func (e *Executor) applyRoleTaskDefaults(task *Task, apply *TaskApply) {
if len(apply.Environment) > 0 {
task.Environment = mergeStringMap(apply.Environment, task.Environment)
}
if apply.When != nil {
task.When = mergeConditions(apply.When, task.When)
}
if apply.Become != nil && task.Become == nil {
task.Become = apply.Become
}
@ -1813,6 +1816,16 @@ func (e *Executor) applyRoleTaskDefaults(task *Task, apply *TaskApply) {
}
}
func mergeConditions(parent, child any) any {
merged := make([]string, 0)
merged = append(merged, normalizeConditions(parent)...)
merged = append(merged, normalizeConditions(child)...)
if len(merged) == 0 {
return nil
}
return merged
}
// getHosts returns hosts matching the pattern.
func (e *Executor) getHosts(pattern string) []string {
if e.inventory == nil {

View file

@ -889,6 +889,43 @@ func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleDefaults(t *testing.T) {
assert.Equal(t, "production|from-apply|from-task", e.results["localhost"]["role_result"].Stdout)
}
func TestExecutorExtra_RunIncludeRole_Good_AppliesRoleWhen(t *testing.T) {
dir := t.TempDir()
require.NoError(t, writeTestFile(joinPath(dir, "roles", "app", "tasks", "main.yml"), []byte(`---
- name: Conditional role task
debug:
msg: "role task ran"
when: task_enabled
register: role_result
`), 0644))
e, _ := newTestExecutorWithMock("localhost")
e.parser = NewParser(dir)
e.SetVar("task_enabled", true)
e.SetVar("apply_enabled", false)
gatherFacts := false
play := &Play{
Hosts: "localhost",
Connection: "local",
GatherFacts: &gatherFacts,
}
require.NoError(t, e.runTaskOnHosts(context.Background(), []string{"localhost"}, &Task{
Name: "Load role with conditional apply",
IncludeRole: &RoleRef{
Role: "app",
Apply: &TaskApply{
When: "apply_enabled",
},
},
}, play))
require.NotNil(t, e.results["localhost"]["role_result"])
assert.True(t, e.results["localhost"]["role_result"].Skipped)
assert.Equal(t, "Skipped due to when condition", e.results["localhost"]["role_result"].Msg)
}
func TestExecutorExtra_RunIncludeRole_Good_PublicVarsPersist(t *testing.T) {
dir := t.TempDir()
require.NoError(t, writeTestFile(joinPath(dir, "roles", "shared", "tasks", "main.yml"), []byte(`---

View file

@ -158,6 +158,7 @@ type TaskApply struct {
Tags []string `yaml:"tags,omitempty"`
Vars map[string]any `yaml:"vars,omitempty"`
Environment map[string]string `yaml:"environment,omitempty"`
When any `yaml:"when,omitempty"`
Become *bool `yaml:"become,omitempty"`
BecomeUser string `yaml:"become_user,omitempty"`
Delegate string `yaml:"delegate_to,omitempty"`

View file

@ -618,6 +618,7 @@ include_role:
apply:
tags:
- deploy
when: apply_enabled
become: true
become_user: root
environment:
@ -636,6 +637,7 @@ include_role:
assert.True(t, task.IncludeRole.Public)
require.NotNil(t, task.IncludeRole.Apply)
assert.Equal(t, []string{"deploy"}, task.IncludeRole.Apply.Tags)
assert.Equal(t, "apply_enabled", task.IncludeRole.Apply.When)
require.NotNil(t, task.IncludeRole.Apply.Become)
assert.True(t, *task.IncludeRole.Apply.Become)
assert.Equal(t, "root", task.IncludeRole.Apply.BecomeUser)