diff --git a/pkg/event/bus_test.go b/pkg/event/bus_test.go index feb4eb2a..26c4b0f3 100644 --- a/pkg/event/bus_test.go +++ b/pkg/event/bus_test.go @@ -1,8 +1,10 @@ package event import ( + "errors" "fmt" "io" + "strings" "testing" "go.uber.org/zap" @@ -13,6 +15,11 @@ import ( ) type runner struct { + executeCalls []struct { + cmd string + args []string + env map[string]string + } } func (r *runner) ExecuteStdIn(cmd string, args []string, env map[string]string, stdin io.Reader) ([]byte, error) { @@ -20,6 +27,11 @@ func (r *runner) ExecuteStdIn(cmd string, args []string, env map[string]string, } func (r *runner) Execute(cmd string, args []string, env map[string]string, enableLiveOutput bool) ([]byte, error) { + r.executeCalls = append(r.executeCalls, struct { + cmd string + args []string + env map[string]string + }{cmd: cmd, args: args, env: env}) if cmd == "ng" { return nil, fmt.Errorf("cmd failed due to invalid cmd: %s", cmd) } @@ -188,3 +200,119 @@ func TestTrigger(t *testing.T) { } } } + +func TestTriggerCleanupEventWithError(t *testing.T) { + runner := &runner{} + + core, _ := observer.New(zap.InfoLevel) + logger := zap.New(core).Sugar() + + testError := errors.New("sync failed: release error") + + hooks := []Hook{ + { + Name: "cleanup-with-error", + Events: []string{"cleanup"}, + Command: "echo", + Args: []string{"error is '{{ .Event.Error }}'"}, + ShowLogs: true, + }, + } + + bus := &Bus{ + Hooks: hooks, + StateFilePath: "/path/to/helmfile.yaml", + BasePath: ".", + Namespace: "default", + Env: environment.Environment{Name: "default"}, + Logger: logger, + Fs: ffs.DefaultFileSystem(), + Runner: runner, + } + + data := map[string]any{ + "HelmfileCommand": "sync", + } + + executed, err := bus.Trigger("cleanup", testError, data) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !executed { + t.Fatal("expected cleanup hook to be executed") + } + + if len(runner.executeCalls) != 1 { + t.Fatalf("expected 1 execute call, got %d", len(runner.executeCalls)) + } + + call := runner.executeCalls[0] + if call.cmd != "echo" { + t.Errorf("expected command 'echo', got %q", call.cmd) + } + + if len(call.args) != 1 { + t.Fatalf("expected 1 arg, got %d", len(call.args)) + } + + expectedArg := "error is 'sync failed: release error'" + if !strings.Contains(call.args[0], "error is") { + t.Errorf("expected arg to contain 'error is', got %q", call.args[0]) + } + + if call.args[0] != expectedArg { + t.Errorf("expected arg %q, got %q", expectedArg, call.args[0]) + } +} + +func TestTriggerCleanupEventWithNilError(t *testing.T) { + runner := &runner{} + + core, _ := observer.New(zap.InfoLevel) + logger := zap.New(core).Sugar() + + hooks := []Hook{ + { + Name: "cleanup-nil-error", + Events: []string{"cleanup"}, + Command: "echo", + Args: []string{"error is '{{ .Event.Error }}'"}, + ShowLogs: true, + }, + } + + bus := &Bus{ + Hooks: hooks, + StateFilePath: "/path/to/helmfile.yaml", + BasePath: ".", + Namespace: "default", + Env: environment.Environment{Name: "default"}, + Logger: logger, + Fs: ffs.DefaultFileSystem(), + Runner: runner, + } + + data := map[string]any{ + "HelmfileCommand": "sync", + } + + executed, err := bus.Trigger("cleanup", nil, data) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !executed { + t.Fatal("expected cleanup hook to be executed") + } + + if len(runner.executeCalls) != 1 { + t.Fatalf("expected 1 execute call, got %d", len(runner.executeCalls)) + } + + call := runner.executeCalls[0] + expectedArg := "error is ''" + if call.args[0] != expectedArg { + t.Errorf("expected arg %q, got %q", expectedArg, call.args[0]) + } +} diff --git a/pkg/state/cleanup_hooks_test.go b/pkg/state/cleanup_hooks_test.go deleted file mode 100644 index 22190e90..00000000 --- a/pkg/state/cleanup_hooks_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package state - -import ( - "errors" - "io" - "strings" - "testing" - - "go.uber.org/zap" - "go.uber.org/zap/zaptest/observer" - - "github.com/helmfile/helmfile/pkg/environment" - "github.com/helmfile/helmfile/pkg/event" - ffs "github.com/helmfile/helmfile/pkg/filesystem" - "github.com/helmfile/helmfile/pkg/helmexec" -) - -type mockRunner struct { - executeCalls []struct { - cmd string - args []string - env map[string]string - } -} - -func (r *mockRunner) Execute(cmd string, args []string, env map[string]string, _ bool) ([]byte, error) { - r.executeCalls = append(r.executeCalls, struct { - cmd string - args []string - env map[string]string - }{cmd: cmd, args: args, env: env}) - return []byte(""), nil -} - -func (r *mockRunner) ExecuteStdIn(cmd string, args []string, env map[string]string, _ io.Reader) ([]byte, error) { - return []byte(""), nil -} - -func TestEventBusTriggerCleanupEventWithError(t *testing.T) { - runner := &mockRunner{} - - core, _ := observer.New(zap.InfoLevel) - logger := zap.New(core).Sugar() - - testError := errors.New("sync failed: release error") - - hooks := []event.Hook{ - { - Name: "cleanup-with-error", - Events: []string{"cleanup"}, - Command: "echo", - Args: []string{"error is '{{ .Event.Error }}'"}, - ShowLogs: true, - }, - } - - bus := &event.Bus{ - Hooks: hooks, - StateFilePath: "/path/to/helmfile.yaml", - BasePath: ".", - Namespace: "default", - Env: environment.Environment{Name: "default"}, - Logger: logger, - Fs: ffs.DefaultFileSystem(), - Runner: runner, - } - - data := map[string]any{ - "HelmfileCommand": "sync", - } - - executed, err := bus.Trigger("cleanup", testError, data) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if !executed { - t.Fatal("expected cleanup hook to be executed") - } - - if len(runner.executeCalls) != 1 { - t.Fatalf("expected 1 execute call, got %d", len(runner.executeCalls)) - } - - call := runner.executeCalls[0] - if call.cmd != "echo" { - t.Errorf("expected command 'echo', got %q", call.cmd) - } - - if len(call.args) != 1 { - t.Fatalf("expected 1 arg, got %d", len(call.args)) - } - - expectedArg := "error is 'sync failed: release error'" - if !strings.Contains(call.args[0], "error is") { - t.Errorf("expected arg to contain 'error is', got %q", call.args[0]) - } - - if call.args[0] != expectedArg { - t.Errorf("expected arg %q, got %q", expectedArg, call.args[0]) - } -} - -func TestEventBusTriggerCleanupEventWithNilError(t *testing.T) { - runner := &mockRunner{} - - core, _ := observer.New(zap.InfoLevel) - logger := zap.New(core).Sugar() - - hooks := []event.Hook{ - { - Name: "cleanup-nil-error", - Events: []string{"cleanup"}, - Command: "echo", - Args: []string{"error is '{{ .Event.Error }}'"}, - ShowLogs: true, - }, - } - - bus := &event.Bus{ - Hooks: hooks, - StateFilePath: "/path/to/helmfile.yaml", - BasePath: ".", - Namespace: "default", - Env: environment.Environment{Name: "default"}, - Logger: logger, - Fs: ffs.DefaultFileSystem(), - Runner: runner, - } - - data := map[string]any{ - "HelmfileCommand": "sync", - } - - executed, err := bus.Trigger("cleanup", nil, data) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if !executed { - t.Fatal("expected cleanup hook to be executed") - } - - if len(runner.executeCalls) != 1 { - t.Fatalf("expected 1 execute call, got %d", len(runner.executeCalls)) - } - - call := runner.executeCalls[0] - expectedArg := "error is ''" - if call.args[0] != expectedArg { - t.Errorf("expected arg %q, got %q", expectedArg, call.args[0]) - } -} - -var _ helmexec.Runner = &mockRunner{}