feat(ansible): implement run_once task handling
Co-authored-by: Virgil <virgil@lethean.io>
This commit is contained in:
parent
a973604e95
commit
acf0a16349
2 changed files with 93 additions and 0 deletions
53
executor.go
53
executor.go
|
|
@ -234,6 +234,20 @@ func (e *Executor) runTaskOnHosts(ctx context.Context, hosts []string, task *Tas
|
|||
return nil
|
||||
}
|
||||
|
||||
// run_once executes the task against a single host, then shares any
|
||||
// registered result with the rest of the host set.
|
||||
if task.RunOnce && len(hosts) > 0 {
|
||||
single := *task
|
||||
single.RunOnce = false
|
||||
|
||||
if err := e.runTaskOnHosts(ctx, hosts[:1], &single, play); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.copyRegisteredResultToHosts(hosts, hosts[0], task.Register)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle block tasks
|
||||
if len(task.Block) > 0 {
|
||||
return e.runBlock(ctx, hosts, task, play)
|
||||
|
|
@ -258,6 +272,45 @@ func (e *Executor) runTaskOnHosts(ctx context.Context, hosts []string, task *Tas
|
|||
return nil
|
||||
}
|
||||
|
||||
// copyRegisteredResultToHosts shares a registered task result from one host to
|
||||
// the rest of the current host set.
|
||||
func (e *Executor) copyRegisteredResultToHosts(hosts []string, sourceHost, register string) {
|
||||
if register == "" {
|
||||
return
|
||||
}
|
||||
|
||||
sourceResults := e.results[sourceHost]
|
||||
if sourceResults == nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, ok := sourceResults[register]
|
||||
if !ok || result == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, host := range hosts {
|
||||
if host == sourceHost {
|
||||
continue
|
||||
}
|
||||
if e.results[host] == nil {
|
||||
e.results[host] = make(map[string]*TaskResult)
|
||||
}
|
||||
|
||||
clone := *result
|
||||
if result.Results != nil {
|
||||
clone.Results = append([]TaskResult(nil), result.Results...)
|
||||
}
|
||||
if result.Data != nil {
|
||||
clone.Data = make(map[string]any, len(result.Data))
|
||||
for k, v := range result.Data {
|
||||
clone.Data[k] = v
|
||||
}
|
||||
}
|
||||
e.results[host][register] = &clone
|
||||
}
|
||||
}
|
||||
|
||||
// runTaskOnHost runs a task on a single host.
|
||||
func (e *Executor) runTaskOnHost(ctx context.Context, host string, task *Task, play *Play) error {
|
||||
start := time.Now()
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package ansible
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// --- NewExecutor ---
|
||||
|
|
@ -166,6 +168,44 @@ func TestExecutor_HandleNotify_Good_AnyList(t *testing.T) {
|
|||
assert.True(t, e.notified["reload config"])
|
||||
}
|
||||
|
||||
// --- run_once ---
|
||||
|
||||
func TestExecutor_RunTaskOnHosts_Good_RunOnceSharesRegisteredResult(t *testing.T) {
|
||||
e := NewExecutor("/tmp")
|
||||
e.SetInventoryDirect(&Inventory{
|
||||
All: &InventoryGroup{
|
||||
Hosts: map[string]*Host{
|
||||
"host1": {},
|
||||
"host2": {},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
var started []string
|
||||
task := &Task{
|
||||
Name: "Run once debug",
|
||||
Module: "debug",
|
||||
Args: map[string]any{"msg": "hello"},
|
||||
Register: "debug_result",
|
||||
RunOnce: true,
|
||||
}
|
||||
|
||||
e.OnTaskStart = func(host string, _ *Task) {
|
||||
started = append(started, host)
|
||||
}
|
||||
|
||||
err := e.runTaskOnHosts(context.Background(), []string{"host1", "host2"}, task, &Play{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Len(t, started, 1)
|
||||
assert.Len(t, e.results["host1"], 1)
|
||||
assert.Len(t, e.results["host2"], 1)
|
||||
require.NotNil(t, e.results["host1"]["debug_result"])
|
||||
require.NotNil(t, e.results["host2"]["debug_result"])
|
||||
assert.Equal(t, "hello", e.results["host1"]["debug_result"].Msg)
|
||||
assert.Equal(t, "hello", e.results["host2"]["debug_result"].Msg)
|
||||
}
|
||||
|
||||
// --- normalizeConditions ---
|
||||
|
||||
func TestExecutor_NormalizeConditions_Good_String(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue