test: verify repair isolation without prolonged fixture waits
This commit is contained in:
parent
bbcf285514
commit
c73b8fe8fd
@ -1,7 +1,14 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"scm.bstein.dev/bstein/ananke/internal/cluster"
|
||||||
|
"scm.bstein.dev/bstein/ananke/internal/execx"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -55,3 +62,28 @@ func TestDaemonMaybeRunPostStartAutoHeal(t *testing.T) {
|
|||||||
t.Fatalf("expected second allowed auto-heal call, got %d", calls)
|
t.Fatalf("expected second allowed auto-heal call, got %d", calls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDaemonRecoveryFailureDoesNotStopMonitoring exercises optional repair isolation.
|
||||||
|
// Signature: TestDaemonRecoveryFailureDoesNotStopMonitoring(t *testing.T).
|
||||||
|
// Why: a missing or failed repair helper must not terminate UPS monitoring.
|
||||||
|
func TestDaemonRecoveryFailureDoesNotStopMonitoring(t *testing.T) {
|
||||||
|
var messages bytes.Buffer
|
||||||
|
d := &Daemon{cfg: config.Config{Startup: config.Startup{PostStartAutoHealSeconds: 60}}, log: log.New(&messages, "", 0)}
|
||||||
|
var last time.Time
|
||||||
|
d.maybeRunPostStartAutoHeal(context.Background(), &last, false)
|
||||||
|
if !last.IsZero() {
|
||||||
|
t.Fatal("missing helper must not consume an interval")
|
||||||
|
}
|
||||||
|
if err := d.runPostStartAutoHeal(context.Background()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d.orch = cluster.New(config.Config{}, &execx.Runner{DryRun: true}, nil, d.log)
|
||||||
|
if err := d.runPostStartAutoHeal(context.Background()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
d.postStartAutoHealOverride = func(context.Context) error { return errors.New("synthetic repair failure") }
|
||||||
|
d.maybeRunPostStartAutoHeal(context.Background(), &last, false)
|
||||||
|
if last.IsZero() || !strings.Contains(messages.String(), "synthetic repair failure") {
|
||||||
|
t.Fatal("failed repair must be logged and rate limited")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ func TestHookVaultLifecycleBranchMatrix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("workload-ready-no-value-and-ensure-error", func(t *testing.T) {
|
t.Run("workload-ready-no-value-and-ensure-cancel", func(t *testing.T) {
|
||||||
cfg := lifecycleConfig(t)
|
cfg := lifecycleConfig(t)
|
||||||
runNoValue := func(ctx context.Context, timeout time.Duration, name string, args ...string) (string, error) {
|
runNoValue := func(ctx context.Context, timeout time.Duration, name string, args ...string) (string, error) {
|
||||||
command := name + " " + strings.Join(args, " ")
|
command := name + " " + strings.Join(args, " ")
|
||||||
@ -111,6 +111,8 @@ func TestHookVaultLifecycleBranchMatrix(t *testing.T) {
|
|||||||
t.Fatalf("expected no-value readiness branch, ready=%v err=%v", ready, err)
|
t.Fatalf("expected no-value readiness branch, ready=%v err=%v", ready, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitCtx, cancelWait := context.WithCancel(context.Background())
|
||||||
|
defer cancelWait()
|
||||||
runEnsureErr := func(ctx context.Context, timeout time.Duration, name string, args ...string) (string, error) {
|
runEnsureErr := func(ctx context.Context, timeout time.Duration, name string, args ...string) (string, error) {
|
||||||
command := name + " " + strings.Join(args, " ")
|
command := name + " " + strings.Join(args, " ")
|
||||||
switch {
|
switch {
|
||||||
@ -119,14 +121,15 @@ func TestHookVaultLifecycleBranchMatrix(t *testing.T) {
|
|||||||
case name == "kubectl" && strings.Contains(command, "get pods -o custom-columns"):
|
case name == "kubectl" && strings.Contains(command, "get pods -o custom-columns"):
|
||||||
return "", nil
|
return "", nil
|
||||||
case name == "kubectl" && strings.Contains(command, "rollout status statefulset/victoria-metrics-single-server"):
|
case name == "kubectl" && strings.Contains(command, "rollout status statefulset/victoria-metrics-single-server"):
|
||||||
|
cancelWait()
|
||||||
return "", errors.New("rollout failed")
|
return "", errors.New("rollout failed")
|
||||||
default:
|
default:
|
||||||
return lifecycleDispatcher(&commandRecorder{})(ctx, timeout, name, args...)
|
return lifecycleDispatcher(&commandRecorder{})(ctx, timeout, name, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
orchEnsureErr, _ := newHookOrchestratorWithRunnerMode(t, cfg, false, runEnsureErr, runEnsureErr)
|
orchEnsureErr, _ := newHookOrchestratorWithRunnerMode(t, cfg, false, runEnsureErr, runEnsureErr)
|
||||||
if err := orchEnsureErr.TestHookEnsureCriticalStartupWorkloads(context.Background()); err == nil || !strings.Contains(err.Error(), "rollout failed") {
|
if err := orchEnsureErr.TestHookEnsureCriticalStartupWorkloads(waitCtx); !errors.Is(err, context.Canceled) {
|
||||||
t.Fatalf("expected ensureCriticalStartupWorkloads wait error branch, got %v", err)
|
t.Fatalf("expected ensureCriticalStartupWorkloads cancellation after failed rollout, got %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user