feat(ansible): enforce run_once tasks
Some checks failed
CI / test (push) Failing after 3s
CI / auto-fix (push) Failing after 0s
CI / auto-merge (push) Failing after 0s

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 06:11:42 +00:00
parent 657c084310
commit dae3b756ed
2 changed files with 44 additions and 0 deletions

View file

@ -282,6 +282,11 @@ func (e *Executor) runRole(ctx context.Context, hosts []string, roleRef *RoleRef
// runTaskOnHosts runs a task on all hosts.
func (e *Executor) runTaskOnHosts(ctx context.Context, hosts []string, task *Task, play *Play) error {
// run_once executes the task only on the first host in the current batch.
if task.RunOnce && len(hosts) > 1 {
hosts = hosts[:1]
}
// Check tags
tags := append(append([]string{}, play.Tags...), task.Tags...)
if !e.matchesTags(tags) {

View file

@ -138,6 +138,45 @@ func TestExecutor_RunPlay_Good_SerialBatchesHosts(t *testing.T) {
}, gathered)
}
func TestExecutor_RunPlay_Good_RunOnceTaskOnlyRunsOnFirstHost(t *testing.T) {
e := NewExecutor("/tmp")
e.SetInventoryDirect(&Inventory{
All: &InventoryGroup{
Hosts: map[string]*Host{
"host1": {},
"host2": {},
},
},
})
var executed []string
e.OnTaskStart = func(host string, task *Task) {
executed = append(executed, host)
}
gatherFacts := false
play := &Play{
Name: "run once",
Hosts: "all",
GatherFacts: &gatherFacts,
Tasks: []Task{
{
Name: "single host",
Module: "debug",
Args: map[string]any{"msg": "ok"},
Register: "result",
RunOnce: true,
},
},
}
require.NoError(t, e.runPlay(context.Background(), play))
assert.Equal(t, []string{"host1"}, executed)
assert.NotNil(t, e.results["host1"]["result"])
_, ok := e.results["host2"]
assert.False(t, ok)
}
func TestExecutor_RunPlay_Good_PlayTagsApplyToUntaggedTasks(t *testing.T) {
e := NewExecutor("/tmp")
e.SetInventoryDirect(&Inventory{