feat(ansible): support wait_for sleep
Some checks are pending
CI / test (push) Waiting to run
CI / auto-fix (push) Waiting to run
CI / auto-merge (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-03 16:06:00 +00:00
parent 56d532885d
commit b91ad5d485
2 changed files with 58 additions and 7 deletions

View file

@ -2888,7 +2888,12 @@ func (e *Executor) moduleWaitFor(ctx context.Context, client sshExecutorClient,
searchRegex := getStringArg(args, "search_regex", "")
timeoutMsg := getStringArg(args, "msg", "wait_for timed out")
delay := getIntArg(args, "delay", 0)
sleep := getIntArg(args, "sleep", 1)
timeout := getIntArg(args, "timeout", 300)
pollInterval := time.Duration(sleep) * time.Second
if pollInterval <= 0 {
pollInterval = 250 * time.Millisecond
}
var compiledRegex *regexp.Regexp
if searchRegex != "" {
var err error
@ -2910,7 +2915,7 @@ func (e *Executor) moduleWaitFor(ctx context.Context, client sshExecutorClient,
if path != "" {
deadline := time.NewTimer(time.Duration(timeout) * time.Second)
ticker := time.NewTicker(250 * time.Millisecond)
ticker := time.NewTicker(pollInterval)
defer deadline.Stop()
defer ticker.Stop()
@ -2958,24 +2963,24 @@ func (e *Executor) moduleWaitFor(ctx context.Context, client sshExecutorClient,
if port > 0 {
switch state {
case "started", "present":
cmd := sprintf("timeout %d bash -c 'until nc -z %s %d; do sleep 1; done'",
timeout, host, port)
cmd := sprintf("timeout %d bash -c 'until nc -z %s %d; do sleep %d; done'",
timeout, host, port, sleep)
stdout, stderr, rc, err := client.Run(ctx, cmd)
if err != nil || rc != 0 {
return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil
}
return &TaskResult{Changed: false}, nil
case "stopped", "absent":
cmd := sprintf("timeout %d bash -c 'until ! nc -z %s %d; do sleep 1; done'",
timeout, host, port)
cmd := sprintf("timeout %d bash -c 'until ! nc -z %s %d; do sleep %d; done'",
timeout, host, port, sleep)
stdout, stderr, rc, err := client.Run(ctx, cmd)
if err != nil || rc != 0 {
return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil
}
return &TaskResult{Changed: false}, nil
case "drained":
cmd := sprintf("timeout %d bash -c 'until ! ss -Htan state established \"( sport = :%d or dport = :%d )\" | grep -q .; do sleep 1; done'",
timeout, port, port)
cmd := sprintf("timeout %d bash -c 'until ! ss -Htan state established \"( sport = :%d or dport = :%d )\" | grep -q .; do sleep %d; done'",
timeout, port, port, sleep)
stdout, stderr, rc, err := client.Run(ctx, cmd)
if err != nil || rc != 0 {
return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil

View file

@ -1246,6 +1246,52 @@ func TestModulesAdv_ModuleWaitFor_Good_WaitsForPortDrained(t *testing.T) {
assert.True(t, mock.hasExecuted(`ss -Htan state established`))
}
func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInterval(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
mock.addFile("/tmp/slow-ready", []byte("ready=false\n"))
go func() {
time.Sleep(150 * time.Millisecond)
mock.mu.Lock()
mock.files["/tmp/slow-ready"] = []byte("ready=true\n")
mock.mu.Unlock()
}()
start := time.Now()
result, err := e.moduleWaitFor(context.Background(), mock, map[string]any{
"path": "/tmp/slow-ready",
"search_regex": "ready=true",
"sleep": 2,
"timeout": 3,
})
elapsed := time.Since(start)
require.NoError(t, err)
assert.NotNil(t, result)
assert.False(t, result.Failed)
assert.False(t, result.Changed)
assert.GreaterOrEqual(t, elapsed, 2*time.Second)
}
func TestModulesAdv_ModuleWaitFor_Good_UsesCustomSleepInPortLoop(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
mock.expectCommand(`timeout 5 bash -c 'until nc -z 127.0.0.1 8080; do sleep 3; done'`, "", "", 0)
result, err := e.moduleWaitFor(context.Background(), mock, map[string]any{
"host": "127.0.0.1",
"port": 8080,
"state": "started",
"timeout": 5,
"sleep": 3,
})
require.NoError(t, err)
assert.NotNil(t, result)
assert.False(t, result.Failed)
assert.False(t, result.Changed)
assert.True(t, mock.hasExecuted(`sleep 3`))
}
func TestModulesAdv_ModuleWaitFor_Good_AcceptsStringNumericArgs(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
mock.expectCommand(`timeout 0 bash -c 'until ! nc -z 127.0.0.1 8080; do sleep 1; done'`, "", "", 0)