From 3a5b813ef16cade2c811866852046f932a2a0802 Mon Sep 17 00:00:00 2001 From: Ryan VanGundy Date: Mon, 30 Dec 2024 21:31:14 -0500 Subject: [PATCH 1/4] Extend verbosity flag to shell --- cmd/root.go | 6 ++ cmd/root_test.go | 38 ++++++++++ docs/install/install.md | 6 +- go.mod | 4 -- go.sum | 4 -- pkg/network/windows_network.go | 2 +- pkg/network/windows_network_test.go | 2 +- pkg/shell/mock_shell.go | 8 +++ pkg/shell/mock_shell_test.go | 69 ++++++++++++++++++ pkg/shell/shell.go | 32 +++++++-- pkg/shell/shell_test.go | 104 ++++++++++++++++++++++++++++ 11 files changed, 256 insertions(+), 19 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 46dd3826..5ce672a2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -63,6 +63,12 @@ func preRunEInitializeCommonComponents(cmd *cobra.Command, args []string) error return fmt.Errorf("No config handler found") } + // Set the verbosity + shell := controller.ResolveShell() + if shell != nil { + shell.SetVerbosity(verbose) + } + // If the context is local or starts with "local-", set the defaults to the default local config if contextName == "local" || len(contextName) > 6 && contextName[:6] == "local-" { err := configHandler.SetDefault(config.DefaultLocalConfig) diff --git a/cmd/root_test.go b/cmd/root_test.go index 35098415..aa812375 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -215,6 +215,44 @@ func TestRoot_preRunEInitializeCommonComponents(t *testing.T) { } }) + t.Run("SetVerbositySuccess", func(t *testing.T) { + // Mock the global controller + originalController := controller + defer func() { controller = originalController }() + + // Mock the injector + injector := di.NewInjector() + + // Mock the controller + mockController := ctrl.NewMockController(injector) + controller = mockController + + // Mock ResolveShell to return a mock shell + mockShell := &shell.MockShell{} + mockController.ResolveShellFunc = func() shell.Shell { + return mockShell + } + + // Mock SetVerbosity to verify it is called with the correct argument + var verbositySet bool + mockShell.SetVerbosityFunc = func(v bool) { + if v { + verbositySet = true + } + } + + // Set the verbosity + shell := controller.ResolveShell() + if shell != nil { + shell.SetVerbosity(true) + } + + // Then the verbosity should be set + if !verbositySet { + t.Fatalf("Expected verbosity to be set, but it was not") + } + }) + t.Run("ErrorLoadingConfig", func(t *testing.T) { // Mock the global controller originalController := controller diff --git a/docs/install/install.md b/docs/install/install.md index 59e248de..e17d52ec 100644 --- a/docs/install/install.md +++ b/docs/install/install.md @@ -6,18 +6,18 @@ This document describes how to install the windsor CLI on your development works === "MacOS" ```bash - curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.0/windsor-darwin-arm64 + curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-darwin-arm64 chmod +x /usr/local/bin/windsor ``` === "Windows" ```powershell - Invoke-WebRequest -Uri "https://github.com/windsorcli/cli/releases/download/v0.2.0/windsor-windows-amd64.exe" -OutFile "C:\Program Files\Windsor\windsor.exe" + Invoke-WebRequest -Uri "https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-windows-amd64.exe" -OutFile "C:\Program Files\Windsor\windsor.exe" ``` === "Linux" ```bash - curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.0/windsor-linux-amd64 + curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-linux-amd64 chmod +x /usr/local/bin/windsor ``` diff --git a/go.mod b/go.mod index b47c7211..6761e267 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.23.1 require ( github.com/briandowns/spinner v1.23.1 github.com/compose-spec/compose-go v1.20.2 - github.com/compose-spec/compose-go/v2 v2.4.6 github.com/getsops/sops/v3 v3.9.2 github.com/goccy/go-yaml v1.15.13 github.com/google/go-jsonnet v0.20.0 @@ -41,7 +40,6 @@ require ( github.com/ProtonMail/go-crypto v1.1.3 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - github.com/apparentlymart/go-textseg/v16 v16.0.0 // indirect github.com/aws/aws-sdk-go-v2 v1.32.7 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect github.com/aws/aws-sdk-go-v2/config v1.28.7 // indirect @@ -64,7 +62,6 @@ require ( github.com/aws/smithy-go v1.22.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cenkalti/backoff/v5 v5.0.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect @@ -118,7 +115,6 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/urfave/cli v1.22.16 // indirect - github.com/urfave/cli/v2 v2.27.5 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.33.0 // indirect diff --git a/go.sum b/go.sum index 0357e1f8..7434e065 100644 --- a/go.sum +++ b/go.sum @@ -65,7 +65,6 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/apparentlymart/go-textseg/v16 v16.0.0/go.mod h1:wCrfQB/AReGqD1ECqVHhhsq7BV2AxUhnirsBLInYHvE= github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw= github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= @@ -112,7 +111,6 @@ github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Pt github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cenkalti/backoff/v5 v5.0.0/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= @@ -121,7 +119,6 @@ github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 h1:boJj011Hh+874zpIySe github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ= github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= -github.com/compose-spec/compose-go/v2 v2.4.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -303,7 +300,6 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= -github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= diff --git a/pkg/network/windows_network.go b/pkg/network/windows_network.go index 27daafc6..ac9aaeb7 100644 --- a/pkg/network/windows_network.go +++ b/pkg/network/windows_network.go @@ -38,7 +38,7 @@ func (n *BaseNetworkManager) ConfigureHostRoute() error { // Add route on the host to VM guest using PowerShell command fmt.Println("🔐 Adding route on the host to VM guest") - output, err = n.shell.Exec( + output, err = n.shell.ExecSilent( "powershell", "-Command", fmt.Sprintf("New-NetRoute -DestinationPrefix %s -NextHop %s -RouteMetric 1", networkCIDR, guestIP), diff --git a/pkg/network/windows_network_test.go b/pkg/network/windows_network_test.go index 85648638..3be1ede5 100644 --- a/pkg/network/windows_network_test.go +++ b/pkg/network/windows_network_test.go @@ -34,7 +34,7 @@ func setupWindowsNetworkManagerMocks() *WindowsNetworkManagerMocks { // Create a mock shell mockShell := shell.NewMockShell() - mockShell.ExecFunc = func(command string, args ...string) (string, error) { + mockShell.ExecSilentFunc = func(command string, args ...string) (string, error) { if command == "powershell" && args[0] == "-Command" { return "Route added successfully", nil } diff --git a/pkg/shell/mock_shell.go b/pkg/shell/mock_shell.go index 1b9c2c6c..d1c28dbb 100644 --- a/pkg/shell/mock_shell.go +++ b/pkg/shell/mock_shell.go @@ -16,6 +16,7 @@ type MockShell struct { ExecProgressFunc func(message string, command string, args ...string) (string, error) ExecSudoFunc func(message string, command string, args ...string) (string, error) InstallHookFunc func(shellName string) error + SetVerbosityFunc func(verbose bool) } // NewMockShell creates a new instance of MockShell. If injector is provided, it sets the injector on MockShell. @@ -103,5 +104,12 @@ func (s *MockShell) InstallHook(shellName string) error { return nil } +// SetVerbosity calls the custom SetVerbosityFunc if provided. +func (s *MockShell) SetVerbosity(verbose bool) { + if s.SetVerbosityFunc != nil { + s.SetVerbosityFunc(verbose) + } +} + // Ensure MockShell implements the Shell interface var _ Shell = (*MockShell)(nil) diff --git a/pkg/shell/mock_shell_test.go b/pkg/shell/mock_shell_test.go index c04b32f4..8b00511f 100644 --- a/pkg/shell/mock_shell_test.go +++ b/pkg/shell/mock_shell_test.go @@ -363,3 +363,72 @@ func TestMockShell_ExecSudo(t *testing.T) { } }) } + +func TestMockShell_InstallHook(t *testing.T) { + t.Run("Success", func(t *testing.T) { + // Given a mock shell with a custom InstallHookFunc implementation + injector := di.NewInjector() + mockShell := NewMockShell(injector) + mockShell.InstallHookFunc = func(shellName string) error { + return nil + } + // When calling InstallHook + err := mockShell.InstallHook("bash") + // Then no error should be returned + if err != nil { + t.Errorf("InstallHook() error = %v, want nil", err) + } + }) + + t.Run("NotImplemented", func(t *testing.T) { + // Given a mock shell with no InstallHookFunc implementation + mockShell := NewMockShell() + // When calling InstallHook + err := mockShell.InstallHook("bash") + // Then no error should be returned + assertError(t, err, false) + }) +} + +func TestMockShell_SetVerbosity(t *testing.T) { + t.Run("SetVerbosityTrue", func(t *testing.T) { + // Given a mock shell with a custom SetVerbosityFunc implementation + injector := di.NewInjector() + mockShell := NewMockShell(injector) + var verbositySet bool + mockShell.SetVerbosityFunc = func(verbose bool) { + verbositySet = verbose + } + // When setting verbosity to true + mockShell.SetVerbosity(true) + // Then verbosity should be set to true + if !verbositySet { + t.Errorf("Expected verbosity to be set to true, but it was not") + } + }) + + t.Run("SetVerbosityFalse", func(t *testing.T) { + // Given a mock shell with a custom SetVerbosityFunc implementation + injector := di.NewInjector() + mockShell := NewMockShell(injector) + var verbositySet bool + mockShell.SetVerbosityFunc = func(verbose bool) { + verbositySet = verbose + } + // When setting verbosity to false + mockShell.SetVerbosity(false) + // Then verbosity should be set to false + if verbositySet { + t.Errorf("Expected verbosity to be set to false, but it was not") + } + }) + + t.Run("NotImplemented", func(t *testing.T) { + // Given a mock shell with no SetVerbosityFunc implementation + injector := di.NewInjector() + mockShell := NewMockShell(injector) + // When calling SetVerbosity + mockShell.SetVerbosity(true) + // Then no panic or error should occur + }) +} diff --git a/pkg/shell/shell.go b/pkg/shell/shell.go index b5148b0a..dd7eb754 100644 --- a/pkg/shell/shell.go +++ b/pkg/shell/shell.go @@ -24,15 +24,12 @@ type HookContext struct { SelfPath string } -type InstallHook interface { - Execute() error - // Add other methods as needed -} - // Shell interface defines methods for shell operations type Shell interface { // Initialize initializes the shell environment Initialize() error + // SetVerbosity sets the verbosity flag + SetVerbosity(verbose bool) // PrintEnvVars prints the provided environment variables PrintEnvVars(envVars map[string]string) error // PrintAlias retrieves the shell alias @@ -56,6 +53,7 @@ type DefaultShell struct { projectRoot string injector di.Injector configHandler config.ConfigHandler + verbose bool } // NewDefaultShell creates a new instance of DefaultShell @@ -76,6 +74,11 @@ func (s *DefaultShell) Initialize() error { return nil } +// SetVerbosity sets the verbosity flag +func (s *DefaultShell) SetVerbosity(verbose bool) { + s.verbose = verbose +} + // GetProjectRoot retrieves the project root directory func (s *DefaultShell) GetProjectRoot() (string, error) { // Return cached project root if available @@ -128,7 +131,7 @@ func (s *DefaultShell) GetProjectRoot() (string, error) { } } -// Exec executes a command and returns its output as a string +// Exec executes a command, prints its output, and returns it as a string func (s *DefaultShell) Exec(command string, args ...string) (string, error) { cmd := execCommand(command, args...) @@ -147,11 +150,19 @@ func (s *DefaultShell) Exec(command string, args ...string) (string, error) { return "", fmt.Errorf("command execution failed: %w", err) } + // Print the captured stdout to the user + fmt.Print(stdoutBuf.String()) + return stdoutBuf.String(), nil } // ExecSudo executes a command with sudo if not already present and returns its output while suppressing it from being printed func (s *DefaultShell) ExecSudo(message string, command string, args ...string) (string, error) { + if s.verbose { + fmt.Println(message) + return s.Exec("sudo", append([]string{command}, args...)...) + } + // If the command is not sudo, add sudo to the command if command != "sudo" { args = append([]string{command}, args...) @@ -198,6 +209,10 @@ func (s *DefaultShell) ExecSudo(message string, command string, args ...string) // ExecSilent executes a command and returns its output as a string without printing to stdout or stderr func (s *DefaultShell) ExecSilent(command string, args ...string) (string, error) { + if s.verbose { + return s.Exec(command, args...) + } + var stdoutBuf, stderrBuf bytes.Buffer cmd := execCommand(command, args...) @@ -214,6 +229,11 @@ func (s *DefaultShell) ExecSilent(command string, args ...string) (string, error // ExecProgress executes a command and returns its output as a string while displaying progress status func (s *DefaultShell) ExecProgress(message string, command string, args ...string) (string, error) { + if s.verbose { + fmt.Println(message) + return s.Exec(command, args...) + } + cmd := execCommand(command, args...) // Set up pipes to capture stdout and stderr diff --git a/pkg/shell/shell_test.go b/pkg/shell/shell_test.go index 960cf0ba..4df52682 100644 --- a/pkg/shell/shell_test.go +++ b/pkg/shell/shell_test.go @@ -51,6 +51,24 @@ func TestShell_Initialize(t *testing.T) { }) } +func TestShell_SetVerbosity(t *testing.T) { + t.Run("Set to True", func(t *testing.T) { + shell := NewDefaultShell(nil) + shell.SetVerbosity(true) + if !shell.verbose { + t.Fatalf("Expected verbosity to be true, got false") + } + }) + + t.Run("Set to False", func(t *testing.T) { + shell := NewDefaultShell(nil) + shell.SetVerbosity(false) + if shell.verbose { + t.Fatalf("Expected verbosity to be false, got true") + } + }) +} + func TestShell_GetProjectRoot(t *testing.T) { t.Run("GitRepo", func(t *testing.T) { injector := di.NewInjector() @@ -392,6 +410,30 @@ func TestShell_ExecSudo(t *testing.T) { t.Fatalf("Expected error to contain %q, got %q", expectedError, err.Error()) } }) + + t.Run("VerboseOutput", func(t *testing.T) { + command := "echo" + args := []string{"hello"} + + shell := NewDefaultShell(nil) + shell.SetVerbosity(true) + + stdout, _ := captureStdoutAndStderr(t, func() { + output, err := shell.ExecSudo("Test Sudo Command", command, args...) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + expectedOutput := "hello\n" + if output != expectedOutput { + t.Fatalf("Expected output %q, got %q", expectedOutput, output) + } + }) + + expectedVerboseOutput := "Test Sudo Command\n" + if !strings.Contains(stdout, expectedVerboseOutput) { + t.Fatalf("Expected verbose output %q, got %q", expectedVerboseOutput, stdout) + } + }) } func TestShell_ExecSilent(t *testing.T) { @@ -429,6 +471,30 @@ func TestShell_ExecSilent(t *testing.T) { t.Fatalf("Expected error to contain %q, got %q", expectedError, err.Error()) } }) + + t.Run("VerboseOutput", func(t *testing.T) { + command := "go" + args := []string{"version"} + + shell := NewDefaultShell(nil) + shell.SetVerbosity(true) + + stdout, _ := captureStdoutAndStderr(t, func() { + output, err := shell.ExecSilent(command, args...) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + expectedOutputPrefix := "go version" + if !strings.HasPrefix(output, expectedOutputPrefix) { + t.Fatalf("Expected output to start with %q, got %q", expectedOutputPrefix, output) + } + }) + + expectedVerboseOutput := "go version" + if !strings.Contains(stdout, expectedVerboseOutput) { + t.Fatalf("Expected verbose output to contain %q, got %q", expectedVerboseOutput, stdout) + } + }) } func TestShell_ExecProgress(t *testing.T) { @@ -655,6 +721,44 @@ func TestShell_ExecProgress(t *testing.T) { t.Fatalf("Expected error to contain %q, got %q", expectedError, err.Error()) } }) + + t.Run("VerboseOutput", func(t *testing.T) { + command := "go" + args := []string{"version"} + + shell := NewDefaultShell(nil) + shell.SetVerbosity(true) + + // Mock cmdStart to prevent hanging + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + return nil + } + defer func() { cmdStart = originalCmdStart }() // Restore original function after test + + // Mock cmdWait to prevent hanging + originalCmdWait := cmdWait + cmdWait = func(cmd *exec.Cmd) error { + return nil + } + defer func() { cmdWait = originalCmdWait }() // Restore original function after test + + stdout, _ := captureStdoutAndStderr(t, func() { + output, err := shell.ExecProgress("Test Progress Command", command, args...) + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + expectedOutputPrefix := "go version" + if !strings.HasPrefix(output, expectedOutputPrefix) { + t.Fatalf("Expected output to start with %q, got %q", expectedOutputPrefix, output) + } + }) + + expectedVerboseOutput := "Test Progress Command\n" + if !strings.Contains(stdout, expectedVerboseOutput) { + t.Fatalf("Expected verbose output %q, got %q", expectedVerboseOutput, stdout) + } + }) } func TestShell_InstallHook(t *testing.T) { From a3801956e24f3630532eceef6e17b015d0fcad42 Mon Sep 17 00:00:00 2001 From: Ryan VanGundy Date: Mon, 30 Dec 2024 23:18:03 -0500 Subject: [PATCH 2/4] Successfull added verbose --- cmd/down.go | 3 +- cmd/down_test.go | 2 +- cmd/init.go | 3 +- cmd/init_test.go | 42 +++++----- cmd/up.go | 3 +- cmd/up_test.go | 2 +- docs/install/install.md | 4 +- pkg/shell/shell.go | 49 ++++++----- pkg/shell/shell_test.go | 181 +++++++++++++++++++++++++++++++--------- 9 files changed, 204 insertions(+), 85 deletions(-) diff --git a/cmd/down.go b/cmd/down.go index 844d07cd..9804cfc8 100644 --- a/cmd/down.go +++ b/cmd/down.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" "github.com/spf13/cobra" ) @@ -58,7 +59,7 @@ var downCmd = &cobra.Command{ } // Print success message - fmt.Println("Windsor environment torn down successfully.") + fmt.Fprintln(os.Stderr, "Windsor environment torn down successfully.") return nil }, diff --git a/cmd/down_test.go b/cmd/down_test.go index bb923be7..6f101e3c 100644 --- a/cmd/down_test.go +++ b/cmd/down_test.go @@ -100,7 +100,7 @@ func TestDownCmd(t *testing.T) { mocks := setupSafeDownCmdMocks() // When the down command is executed - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"down"}) if err := Execute(mocks.MockController); err != nil { t.Fatalf("Execute() error = %v", err) diff --git a/cmd/init.go b/cmd/init.go index 8315c6be..f7d0c9f7 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" "github.com/spf13/cobra" ) @@ -119,7 +120,7 @@ var initCmd = &cobra.Command{ } // Print the success message - fmt.Println("Initialization successful") + fmt.Fprintln(os.Stderr, "Initialization successful") return nil }, } diff --git a/cmd/init_test.go b/cmd/init_test.go index c9fe4acd..55c9befa 100644 --- a/cmd/init_test.go +++ b/cmd/init_test.go @@ -73,7 +73,7 @@ func TestInitCmd(t *testing.T) { controller := setupSafeInitCmdMocks() // Execute the init command and capture output - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"init", "test-context"}) if err := Execute(controller); err != nil { t.Fatalf("Execute() error = %v", err) @@ -92,7 +92,7 @@ func TestInitCmd(t *testing.T) { controller := setupSafeInitCmdMocks() // When the init command is executed with all flags set - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{ "init", "test-context", "--aws-endpoint-url", "http://localhost:4566", @@ -123,7 +123,7 @@ func TestInitCmd(t *testing.T) { controller := setupSafeInitCmdMocks() // When the init command is executed without a context - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"init"}) err := Execute(controller) if err != nil { @@ -143,7 +143,7 @@ func TestInitCmd(t *testing.T) { controller := setupSafeInitCmdMocks() // When the init command is executed with an empty context name - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"init", ""}) err := Execute(controller) if err != nil { @@ -163,7 +163,7 @@ func TestInitCmd(t *testing.T) { controller := setupSafeInitCmdMocks() // When the init command is executed with a context name provided - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"init", "test-context"}) err := Execute(controller) if err != nil { @@ -438,16 +438,18 @@ func TestInitCmd(t *testing.T) { } // When the init command is executed - rootCmd.SetArgs([]string{"init", "test-context"}) - err := Execute(controller) - if err == nil { - t.Fatalf("Expected error, got nil") - } + output := captureStderr(func() { + rootCmd.SetArgs([]string{"init", "test-context"}) + err := Execute(controller) + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) // Then the output should indicate the error expectedOutput := "Error initializing components: initialize components error" - if err.Error() != expectedOutput { - t.Errorf("Expected error %q, got %q", expectedOutput, err.Error()) + if !strings.Contains(output, expectedOutput) { + t.Errorf("Expected output to contain %q, got %q", expectedOutput, output) } }) @@ -461,16 +463,18 @@ func TestInitCmd(t *testing.T) { } // When the init command is executed - rootCmd.SetArgs([]string{"init", "test-context"}) - err := Execute(controller) - if err == nil { - t.Fatalf("Expected error, got nil") - } + output := captureStderr(func() { + rootCmd.SetArgs([]string{"init", "test-context"}) + err := Execute(controller) + if err == nil { + t.Fatalf("Expected error, got nil") + } + }) // Then the output should indicate the error expectedOutput := "Error writing configuration files: write configuration files error" - if err.Error() != expectedOutput { - t.Errorf("Expected error %q, got %q", expectedOutput, err.Error()) + if !strings.Contains(output, expectedOutput) { + t.Errorf("Expected output to contain %q, got %q", expectedOutput, output) } }) } diff --git a/cmd/up.go b/cmd/up.go index 4181fc9b..0f57689a 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" "github.com/spf13/cobra" ) @@ -125,7 +126,7 @@ var upCmd = &cobra.Command{ } // Print success message - fmt.Println("Windsor environment set up successfully.") + fmt.Fprintln(os.Stderr, "Windsor environment set up successfully.") return nil }, diff --git a/cmd/up_test.go b/cmd/up_test.go index 2c517f31..e9a5d76c 100644 --- a/cmd/up_test.go +++ b/cmd/up_test.go @@ -101,7 +101,7 @@ func TestUpCmd(t *testing.T) { mocks := setupSafeUpCmdMocks() // When the up command is executed - output := captureStdout(func() { + output := captureStderr(func() { rootCmd.SetArgs([]string{"up"}) if err := Execute(mocks.MockController); err != nil { t.Fatalf("Execute() error = %v", err) diff --git a/docs/install/install.md b/docs/install/install.md index e17d52ec..926e6c3e 100644 --- a/docs/install/install.md +++ b/docs/install/install.md @@ -6,7 +6,7 @@ This document describes how to install the windsor CLI on your development works === "MacOS" ```bash - curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-darwin-arm64 + curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-darwin-arm64 && \ chmod +x /usr/local/bin/windsor ``` @@ -17,7 +17,7 @@ This document describes how to install the windsor CLI on your development works === "Linux" ```bash - curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-linux-amd64 + curl -L -o /usr/local/bin/windsor https://github.com/windsorcli/cli/releases/download/v0.2.1/windsor-linux-amd64 && \ chmod +x /usr/local/bin/windsor ``` diff --git a/pkg/shell/shell.go b/pkg/shell/shell.go index dd7eb754..9c3ad1b6 100644 --- a/pkg/shell/shell.go +++ b/pkg/shell/shell.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "io" "os" "path/filepath" "strings" @@ -135,31 +136,41 @@ func (s *DefaultShell) GetProjectRoot() (string, error) { func (s *DefaultShell) Exec(command string, args ...string) (string, error) { cmd := execCommand(command, args...) - // Capture stdout and stderr in buffers - var stdoutBuf, stderrBuf bytes.Buffer - cmd.Stdout = &stdoutBuf - cmd.Stderr = &stderrBuf + // Buffer to capture stdout + var stdoutBuf bytes.Buffer + // Use MultiWriter to write to both os.Stdout and stdoutBuf + stdoutWriter := io.MultiWriter(os.Stdout, &stdoutBuf) + cmd.Stdout = stdoutWriter + + // Buffer to capture stderr + var stderrBuf bytes.Buffer + // Use MultiWriter to write to both os.Stderr and stderrBuf + stderrWriter := io.MultiWriter(os.Stderr, &stderrBuf) + cmd.Stderr = stderrWriter // Handle sudo commands if command == "sudo" { cmd.Stdin = os.Stdin // Allow password input for sudo } - // Run the command - if err := cmdRun(cmd); err != nil { - return "", fmt.Errorf("command execution failed: %w", err) + // Start the command + if err := cmdStart(cmd); err != nil { + return "", fmt.Errorf("command start failed: %w", err) } - // Print the captured stdout to the user - fmt.Print(stdoutBuf.String()) + // Wait for the command to complete + if err := cmdWait(cmd); err != nil { + return "", fmt.Errorf("command execution failed: %w", err) + } + // Return the captured stdout as a string return stdoutBuf.String(), nil } // ExecSudo executes a command with sudo if not already present and returns its output while suppressing it from being printed func (s *DefaultShell) ExecSudo(message string, command string, args ...string) (string, error) { if s.verbose { - fmt.Println(message) + fmt.Fprintln(os.Stderr, message) return s.Exec("sudo", append([]string{command}, args...)...) } @@ -188,7 +199,7 @@ func (s *DefaultShell) ExecSudo(message string, command string, args ...string) // Start the command if err := cmdStart(cmd); err != nil { - fmt.Printf("\033[31m✗ %s - Failed\033[0m\n", message) + fmt.Fprintf(os.Stderr, "\033[31m✗ %s - Failed\033[0m\n", message) return "", err } @@ -196,12 +207,12 @@ func (s *DefaultShell) ExecSudo(message string, command string, args ...string) err = cmdWait(cmd) if err != nil { - fmt.Printf("\033[31m✗ %s - Failed\033[0m\n", message) + fmt.Fprintf(os.Stderr, "\033[31m✗ %s - Failed\033[0m\n", message) return "", fmt.Errorf("command execution failed: %w", err) } // Print success message with a green checkbox and "Done" - fmt.Printf("\033[32m✔\033[0m %s - \033[32mDone\033[0m\n", message) + fmt.Fprintf(os.Stderr, "\033[32m✔\033[0m %s - \033[32mDone\033[0m\n", message) // Return the captured stdout as a string return stdoutBuf.String(), nil @@ -230,7 +241,7 @@ func (s *DefaultShell) ExecSilent(command string, args ...string) (string, error // ExecProgress executes a command and returns its output as a string while displaying progress status func (s *DefaultShell) ExecProgress(message string, command string, args ...string) (string, error) { if s.verbose { - fmt.Println(message) + fmt.Fprintln(os.Stderr, message) return s.Exec(command, args...) } @@ -290,16 +301,16 @@ func (s *DefaultShell) ExecProgress(message string, command string, args ...stri // Wait for the command to complete if err := cmdWait(cmd); err != nil { - spin.Stop() // Stop the spinner - fmt.Printf("\033[31m✗ %s - Failed\033[0m\n%s", message, stderrBuf.String()) // Print failure message in red + spin.Stop() // Stop the spinner + fmt.Fprintf(os.Stderr, "\033[31m✗ %s - Failed\033[0m\n%s", message, stderrBuf.String()) // Print failure message in red return "", fmt.Errorf("command execution failed: %w\n%s", err, stderrBuf.String()) } // Check for errors from the stdout and stderr goroutines for i := 0; i < 2; i++ { if err := <-errChan; err != nil { - spin.Stop() // Stop the spinner - fmt.Printf("\033[31m✗ %s - Failed\033[0m\n%s", message, stderrBuf.String()) // Print failure message in red + spin.Stop() // Stop the spinner + fmt.Fprintf(os.Stderr, "\033[31m✗ %s - Failed\033[0m\n%s", message, stderrBuf.String()) // Print failure message in red return "", err } } @@ -307,7 +318,7 @@ func (s *DefaultShell) ExecProgress(message string, command string, args ...stri spin.Stop() // Stop the spinner // Print success message with a green checkbox and "Done" - fmt.Printf("\033[32m✔\033[0m %s - \033[32mDone\033[0m\n", message) + fmt.Fprintf(os.Stderr, "\033[32m✔\033[0m %s - \033[32mDone\033[0m\n", message) return stdoutBuf.String(), nil // Return the captured stdout as a string } diff --git a/pkg/shell/shell_test.go b/pkg/shell/shell_test.go index 4df52682..dde85203 100644 --- a/pkg/shell/shell_test.go +++ b/pkg/shell/shell_test.go @@ -229,17 +229,33 @@ func TestShell_GetProjectRoot(t *testing.T) { func TestShell_Exec(t *testing.T) { t.Run("Success", func(t *testing.T) { - expectedOutput := "command output" + expectedOutput := "hello\n" command := "echo" args := []string{"hello"} - // Mock cmdRun to simulate command execution - originalCmdRun := cmdRun - cmdRun = func(cmd *exec.Cmd) error { - _, _ = cmd.Stdout.Write([]byte("command output")) + // Mock execCommand to simulate command execution + originalExecCommand := execCommand + execCommand = func(name string, arg ...string) *exec.Cmd { + cmd := exec.Command("echo", "hello") + cmd.Stdout = &bytes.Buffer{} + return cmd + } + defer func() { execCommand = originalExecCommand }() + + // Mock cmdStart to simulate successful command start + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + return nil + } + defer func() { cmdStart = originalCmdStart }() + + // Mock cmdWait to simulate successful command execution + originalCmdWait := cmdWait + cmdWait = func(cmd *exec.Cmd) error { + cmd.Stdout.Write([]byte("hello\n")) return nil } - defer func() { cmdRun = originalCmdRun }() + defer func() { cmdWait = originalCmdWait }() injector := di.NewInjector() shell := NewDefaultShell(injector) @@ -253,48 +269,58 @@ func TestShell_Exec(t *testing.T) { } }) - t.Run("SuccessWithSudo", func(t *testing.T) { - expectedOutput := "hello\n" - command := "sudo" - args := []string{"echo", "hello"} + t.Run("ErrorRunningCommand", func(t *testing.T) { + command := "nonexistentcommand" + args := []string{} - // Mock cmdRun to simulate command execution - originalCmdRun := cmdRun - cmdRun = func(cmd *exec.Cmd) error { - _, _ = cmd.Stdout.Write([]byte("hello\n")) - return nil + // Mock cmdStart to simulate command execution failure + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + return fmt.Errorf("command start failed: exec: \"%s\": executable file not found in $PATH", command) } - defer func() { cmdRun = originalCmdRun }() + defer func() { cmdStart = originalCmdStart }() shell := NewDefaultShell(nil) - output, err := shell.Exec(command, args...) - if err != nil { - t.Fatalf("Failed to execute command: %v", err) + _, err := shell.Exec(command, args...) + if err == nil { + t.Fatalf("Expected error when executing nonexistent command, got nil") } - if output != expectedOutput { - t.Fatalf("Expected output %q, got %q", expectedOutput, output) + expectedError := fmt.Sprintf("command start failed: exec: \"%s\": executable file not found in $PATH", command) + if !strings.Contains(err.Error(), expectedError) { + t.Fatalf("Expected error to contain %q, got %q", expectedError, err.Error()) } }) - t.Run("ErrorRunningCommand", func(t *testing.T) { - command := "nonexistentcommand" - args := []string{} + t.Run("ErrorWaitingForCommand", func(t *testing.T) { + command := "echo" + args := []string{"hello"} - // Mock cmdRun to simulate command execution failure - originalCmdRun := cmdRun - cmdRun = func(cmd *exec.Cmd) error { - return fmt.Errorf("command not found") + // Mock execCommand to simulate command execution + originalExecCommand := execCommand + execCommand = mockExecCommandError + defer func() { execCommand = originalExecCommand }() + + // Mock cmdStart to simulate successful command start + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + return nil } - defer func() { cmdRun = originalCmdRun }() + defer func() { cmdStart = originalCmdStart }() - shell := NewDefaultShell(nil) + // Mock cmdWait to simulate an error when waiting for the command + originalCmdWait := cmdWait + cmdWait = func(cmd *exec.Cmd) error { + return fmt.Errorf("failed to wait for command") + } + defer func() { cmdWait = originalCmdWait }() + shell := NewDefaultShell(nil) _, err := shell.Exec(command, args...) if err == nil { - t.Fatalf("Expected error when executing nonexistent command, got nil") + t.Fatalf("Expected error, got nil") } - expectedError := "command not found" + expectedError := "failed to wait for command" if !strings.Contains(err.Error(), expectedError) { t.Fatalf("Expected error to contain %q, got %q", expectedError, err.Error()) } @@ -418,7 +444,33 @@ func TestShell_ExecSudo(t *testing.T) { shell := NewDefaultShell(nil) shell.SetVerbosity(true) - stdout, _ := captureStdoutAndStderr(t, func() { + // Mock execCommand to simulate command execution + originalExecCommand := execCommand + execCommand = func(name string, arg ...string) *exec.Cmd { + cmd := &exec.Cmd{ + Stdout: &bytes.Buffer{}, + Stderr: &bytes.Buffer{}, + } + return cmd + } + defer func() { execCommand = originalExecCommand }() + + // Mock cmdStart to simulate successful command start + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + _, _ = cmd.Stdout.Write([]byte("hello\n")) + return nil + } + defer func() { cmdStart = originalCmdStart }() + + // Mock cmdWait to simulate successful command completion + originalCmdWait := cmdWait + cmdWait = func(cmd *exec.Cmd) error { + return nil + } + defer func() { cmdWait = originalCmdWait }() + + stdout, stderr := captureStdoutAndStderr(t, func() { output, err := shell.ExecSudo("Test Sudo Command", command, args...) if err != nil { t.Fatalf("Expected no error, got %v", err) @@ -429,9 +481,15 @@ func TestShell_ExecSudo(t *testing.T) { } }) + // Validate stdout and stderr + expectedStdout := "hello\n" + if stdout != expectedStdout { + t.Fatalf("Expected stdout %q, got %q", expectedStdout, stdout) + } + expectedVerboseOutput := "Test Sudo Command\n" - if !strings.Contains(stdout, expectedVerboseOutput) { - t.Fatalf("Expected verbose output %q, got %q", expectedVerboseOutput, stdout) + if !strings.Contains(stderr, expectedVerboseOutput) { + t.Fatalf("Expected verbose output %q, got stderr: %q", expectedVerboseOutput, stderr) } }) } @@ -476,6 +534,32 @@ func TestShell_ExecSilent(t *testing.T) { command := "go" args := []string{"version"} + // Mock execCommand to simulate command execution + originalExecCommand := execCommand + execCommand = func(name string, arg ...string) *exec.Cmd { + cmd := &exec.Cmd{ + Stdout: &bytes.Buffer{}, + Stderr: &bytes.Buffer{}, + } + cmd.Stdout.Write([]byte("go version go1.16.3\n")) + return cmd + } + defer func() { execCommand = originalExecCommand }() + + // Mock cmdStart and cmdWait to simulate command execution without hanging + originalCmdStart := cmdStart + cmdStart = func(cmd *exec.Cmd) error { + cmd.Stdout.Write([]byte("go version go1.16.3\n")) + return nil + } + defer func() { cmdStart = originalCmdStart }() + + originalCmdWait := cmdWait + cmdWait = func(cmd *exec.Cmd) error { + return nil + } + defer func() { cmdWait = originalCmdWait }() + shell := NewDefaultShell(nil) shell.SetVerbosity(true) @@ -729,21 +813,32 @@ func TestShell_ExecProgress(t *testing.T) { shell := NewDefaultShell(nil) shell.SetVerbosity(true) - // Mock cmdStart to prevent hanging + // Mock execCommand to simulate command execution + originalExecCommand := execCommand + execCommand = func(name string, arg ...string) *exec.Cmd { + cmd := &exec.Cmd{ + Stdout: &bytes.Buffer{}, + Stderr: &bytes.Buffer{}, + } + return cmd + } + defer func() { execCommand = originalExecCommand }() // Restore original function after test + + // Mock cmdStart and cmdWait to simulate command execution without hanging originalCmdStart := cmdStart cmdStart = func(cmd *exec.Cmd) error { + cmd.Stdout.Write([]byte("go version go1.16.3 darwin/amd64\n")) return nil } defer func() { cmdStart = originalCmdStart }() // Restore original function after test - // Mock cmdWait to prevent hanging originalCmdWait := cmdWait cmdWait = func(cmd *exec.Cmd) error { return nil } defer func() { cmdWait = originalCmdWait }() // Restore original function after test - stdout, _ := captureStdoutAndStderr(t, func() { + stdout, stderr := captureStdoutAndStderr(t, func() { output, err := shell.ExecProgress("Test Progress Command", command, args...) if err != nil { t.Fatalf("Expected no error, got %v", err) @@ -755,8 +850,14 @@ func TestShell_ExecProgress(t *testing.T) { }) expectedVerboseOutput := "Test Progress Command\n" - if !strings.Contains(stdout, expectedVerboseOutput) { - t.Fatalf("Expected verbose output %q, got %q", expectedVerboseOutput, stdout) + if !strings.Contains(stderr, expectedVerboseOutput) { + t.Fatalf("Expected verbose output %q, got %q", expectedVerboseOutput, stderr) + } + + // Check the stdout value + expectedStdoutPrefix := "go version" + if !strings.HasPrefix(stdout, expectedStdoutPrefix) { + t.Fatalf("Expected stdout to start with %q, got %q", expectedStdoutPrefix, stdout) } }) } From 3cc20d9cbcb65891e3d0ed1d66d00b5192f88245 Mon Sep 17 00:00:00 2001 From: Ryan VanGundy Date: Mon, 30 Dec 2024 23:26:33 -0500 Subject: [PATCH 3/4] tidy --- go.sum | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go.sum b/go.sum index e2012083..8020650e 100644 --- a/go.sum +++ b/go.sum @@ -363,16 +363,10 @@ golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= google.golang.org/api v0.214.0 h1:h2Gkq07OYi6kusGOaT/9rnNljuXmqPnaig7WGPmKbwA= google.golang.org/api v0.214.0/go.mod h1:bYPpLG8AyeMWwDU6NXoB00xC0DFkikVvd5MfwoxjLqE= -google.golang.org/genproto v0.0.0-20241223144023-3abc09e42ca8 h1:e26eS1K69yxjjNNHYqjN49y95kcaQLJ3TL5h68dcA1E= -google.golang.org/genproto v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:i5btTErZyoKCCubju3HS5LVho4nZd3yFnEp6moqeUjE= google.golang.org/genproto v0.0.0-20241230172942-26aa7a208def h1:uz2w9bZTljGBXc3ugqrL/KOsVhQuODYyLNYXUTKrh6M= google.golang.org/genproto v0.0.0-20241230172942-26aa7a208def/go.mod h1:zNtPaqLK0Wbf5PaSZDYDR+1t5rQoBAIMh06tpzkjvY8= -google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8 h1:st3LcW/BPi75W4q1jJTEor/QWwbNlPlDG0JTn6XhZu0= -google.golang.org/genproto/googleapis/api v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:klhJGKFyG8Tn50enBn7gizg4nXGXJ+jqEREdCWaPcV4= google.golang.org/genproto/googleapis/api v0.0.0-20241230172942-26aa7a208def h1:0Km0hi+g2KXbXL0+riZzSCKz23f4MmwicuEb00JeonI= google.golang.org/genproto/googleapis/api v0.0.0-20241230172942-26aa7a208def/go.mod h1:u2DoMSpCXjrzqLdobRccQMc9wrnMAJ1DLng0a2yqM2Q= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= google.golang.org/genproto/googleapis/rpc v0.0.0-20241230172942-26aa7a208def h1:4P81qv5JXI/sDNae2ClVx88cgDDA6DPilADkG9tYKz8= google.golang.org/genproto/googleapis/rpc v0.0.0-20241230172942-26aa7a208def/go.mod h1:bdAgzvd4kFrpykc5/AC2eLUiegK9T/qxZHD4hXYf/ho= google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= From 63a5af5499665b2df85223cbf59c6de05819b13a Mon Sep 17 00:00:00 2001 From: Ryan VanGundy Date: Mon, 30 Dec 2024 23:35:07 -0500 Subject: [PATCH 4/4] Fix windows test --- pkg/network/windows_network_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/network/windows_network_test.go b/pkg/network/windows_network_test.go index 3be1ede5..4ba5ba9c 100644 --- a/pkg/network/windows_network_test.go +++ b/pkg/network/windows_network_test.go @@ -250,8 +250,11 @@ func TestWindowsNetworkManager_ConfigureHostRoute(t *testing.T) { } return "" } - mocks.MockShell.ExecFunc = func(command string, args ...string) (string, error) { + mocks.MockShell.ExecSilentFunc = func(command string, args ...string) (string, error) { if command == "powershell" && args[0] == "-Command" { + if args[1] == fmt.Sprintf("Get-NetRoute -DestinationPrefix %s | Where-Object { $_.NextHop -eq '%s' }", "192.168.1.0/24", "192.168.1.2") { + return "", nil // Simulate that the route does not exist + } if args[1] == fmt.Sprintf("New-NetRoute -DestinationPrefix %s -NextHop %s -RouteMetric 1", "192.168.1.0/24", "192.168.1.2") { return "", fmt.Errorf("mocked shell execution error") }