Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions pkg/project/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ func NewProject(injector di.Injector, contextName string, opts ...*Project) (*Pr
if overrides != nil && overrides.Workstation != nil {
ws = overrides.Workstation
} else {
workstationCtx := &workstation.WorkstationRuntime{
Runtime: *rt,
}
ws, err = workstation.NewWorkstation(workstationCtx, rt.Injector)
ws, err = workstation.NewWorkstation(rt)
if err != nil {
return nil, fmt.Errorf("failed to create workstation: %w", err)
}
Expand Down Expand Up @@ -157,8 +154,8 @@ func (p *Project) Configure(flagOverrides map[string]any) error {
// if any step fails.
func (p *Project) Initialize(overwrite bool) error {
if p.Workstation != nil && p.Workstation.NetworkManager != nil {
if err := p.Workstation.NetworkManager.Initialize(p.Workstation.Services); err != nil {
return fmt.Errorf("failed to initialize network manager: %w", err)
if err := p.Workstation.NetworkManager.AssignIPs(p.Workstation.Services); err != nil {
return fmt.Errorf("failed to assign IPs to network manager: %w", err)
}
}

Expand Down
56 changes: 8 additions & 48 deletions pkg/workstation/network/colima_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import (
"strings"

"github.com/windsorcli/cli/pkg/constants"
"github.com/windsorcli/cli/pkg/di"
"github.com/windsorcli/cli/pkg/runtime"
"github.com/windsorcli/cli/pkg/runtime/shell"
"github.com/windsorcli/cli/pkg/runtime/shell/ssh"
"github.com/windsorcli/cli/pkg/workstation/services"
)

// The ColimaNetworkManager is a specialized network manager for Colima-based environments.
Expand All @@ -32,62 +31,23 @@ type ColimaNetworkManager struct {
// =============================================================================

// NewColimaNetworkManager creates a new ColimaNetworkManager
func NewColimaNetworkManager(injector di.Injector) *ColimaNetworkManager {
func NewColimaNetworkManager(rt *runtime.Runtime, sshClient ssh.Client, secureShell shell.Shell, networkInterfaceProvider NetworkInterfaceProvider) *ColimaNetworkManager {
manager := &ColimaNetworkManager{
BaseNetworkManager: *NewBaseNetworkManager(injector),
BaseNetworkManager: *NewBaseNetworkManager(rt),
networkInterfaceProvider: networkInterfaceProvider,
}
if provider, ok := injector.Resolve("networkInterfaceProvider").(NetworkInterfaceProvider); ok {
manager.networkInterfaceProvider = provider
}
return manager
}

// =============================================================================
// Public Methods
// =============================================================================

// Initialize sets up the ColimaNetworkManager by resolving dependencies for
// sshClient, shell, and secureShell from the injector.
func (n *ColimaNetworkManager) Initialize(services []services.Service) error {
if err := n.BaseNetworkManager.Initialize(services); err != nil {
return err
}

sshClient, ok := n.injector.Resolve("sshClient").(ssh.Client)
if !ok {
return fmt.Errorf("resolved ssh client instance is not of type ssh.Client")
}
n.sshClient = sshClient
manager.sshClient = sshClient
manager.secureShell = secureShell

secureShell, ok := n.injector.Resolve("secureShell").(shell.Shell)
if !ok {
return fmt.Errorf("resolved secure shell instance is not of type shell.Shell")
}
n.secureShell = secureShell

networkInterfaceProvider, ok := n.injector.Resolve("networkInterfaceProvider").(NetworkInterfaceProvider)
if !ok {
return fmt.Errorf("failed to resolve network interface provider")
}
n.networkInterfaceProvider = networkInterfaceProvider

// Set docker.NetworkCIDR to the default value if it's not set
if n.configHandler.GetString("network.cidr_block") == "" {
return n.configHandler.Set("network.cidr_block", constants.DefaultNetworkCIDR)
}

return nil
return manager
}

// ConfigureGuest sets up forwarding of guest traffic to the container network.
// It retrieves network CIDR and guest IP from the config, and configures SSH.
// It identifies the Docker bridge interface and ensures iptables rules are set.
// If the rule doesn't exist, it adds a new one to allow traffic forwarding.
func (n *ColimaNetworkManager) ConfigureGuest() error {
networkCIDR := n.configHandler.GetString("network.cidr_block")
if networkCIDR == "" {
return fmt.Errorf("network CIDR is not configured")
}
networkCIDR := n.configHandler.GetString("network.cidr_block", constants.DefaultNetworkCIDR)

guestIP := n.configHandler.GetString("vm.address")
if guestIP == "" {
Expand Down
97 changes: 27 additions & 70 deletions pkg/workstation/network/colima_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,69 +13,30 @@ import (
// Test Public Methods
// =============================================================================

func TestColimaNetworkManager_Initialize(t *testing.T) {
func TestColimaNetworkManager_AssignIPs(t *testing.T) {
setup := func(t *testing.T) (*ColimaNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewColimaNetworkManager(mocks.Injector)
manager := NewColimaNetworkManager(mocks.Runtime, mocks.SSHClient, mocks.SecureShell, mocks.NetworkInterfaceProvider)
manager.shims = mocks.Shims
return manager, mocks
}

t.Run("ErrorResolvingSecureShell", func(t *testing.T) {
// Given a network manager with invalid secure shell
manager, mocks := setup(t)
mocks.Injector.Register("secureShell", "invalid")

// When initializing the network manager
err := manager.Initialize([]services.Service{})

// Then an error should occur
if err == nil {
t.Fatalf("expected an error during Initialize, got nil")
}

// And the error should be about secure shell type
if err.Error() != "resolved secure shell instance is not of type shell.Shell" {
t.Fatalf("unexpected error message: got %v", err)
}
})

t.Run("ErrorResolvingSSHClient", func(t *testing.T) {
// Given a network manager with invalid SSH client
manager, mocks := setup(t)
mocks.Injector.Register("sshClient", "invalid")

// When initializing the network manager
err := manager.Initialize([]services.Service{})

// Then an error should occur
if err == nil {
t.Fatalf("expected an error during Initialize, got nil")
}

// And the error should be about SSH client type
if err.Error() != "resolved ssh client instance is not of type ssh.Client" {
t.Fatalf("unexpected error message: got %v", err)
}
})

t.Run("ErrorResolvingNetworkInterfaceProvider", func(t *testing.T) {
// Given a network manager with invalid network interface provider
manager, mocks := setup(t)
mocks.Injector.Register("networkInterfaceProvider", "invalid")
t.Run("Success", func(t *testing.T) {
// Given a properly configured network manager
manager, _ := setup(t)

// When initializing the network manager
err := manager.Initialize([]services.Service{})
// When assigning IPs to services
err := manager.AssignIPs([]services.Service{})

// Then an error should occur
if err == nil {
t.Fatalf("expected an error during Initialize, got nil")
// Then no error should occur
if err != nil {
t.Fatalf("expected no error during AssignIPs, got %v", err)
}

// And the error should be about network interface provider type
if err.Error() != "failed to resolve network interface provider" {
t.Fatalf("unexpected error message: got %v", err)
// And services should be set
if manager.services == nil {
t.Fatalf("expected services to be set")
}
})
}
Expand All @@ -84,9 +45,9 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
setup := func(t *testing.T) (*ColimaNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewColimaNetworkManager(mocks.Injector)
manager := NewColimaNetworkManager(mocks.Runtime, mocks.SSHClient, mocks.SecureShell, mocks.NetworkInterfaceProvider)
manager.shims = mocks.Shims
manager.Initialize([]services.Service{})
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand All @@ -111,13 +72,9 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
// And configuring the guest
err := manager.ConfigureGuest()

// Then an error should occur
if err == nil {
t.Fatalf("expected error, got nil")
}
expectedError := "network CIDR is not configured"
if err.Error() != expectedError {
t.Fatalf("expected error %q, got %q", expectedError, err.Error())
// Then no error should occur (default CIDR is used automatically)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
})

Expand Down Expand Up @@ -150,7 +107,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand All @@ -176,7 +133,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand Down Expand Up @@ -205,7 +162,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand Down Expand Up @@ -234,7 +191,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand Down Expand Up @@ -269,7 +226,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand All @@ -295,7 +252,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand Down Expand Up @@ -324,7 +281,7 @@ func TestColimaNetworkManager_ConfigureGuest(t *testing.T) {
}

// When initializing the network manager
err := manager.Initialize([]services.Service{})
err := manager.AssignIPs([]services.Service{})
if err != nil {
t.Fatalf("expected no error during initialization, got %v", err)
}
Expand All @@ -346,8 +303,8 @@ func TestColimaNetworkManager_getHostIP(t *testing.T) {
setup := func(t *testing.T) (*ColimaNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewColimaNetworkManager(mocks.Injector)
manager.Initialize([]services.Service{})
manager := NewColimaNetworkManager(mocks.Runtime, mocks.SSHClient, mocks.SecureShell, mocks.NetworkInterfaceProvider)
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/workstation/network/darwin_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ func TestDarwinNetworkManager_ConfigureHostRoute(t *testing.T) {
setup := func(t *testing.T) (*BaseNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewBaseNetworkManager(mocks.Injector)
manager := NewBaseNetworkManager(mocks.Runtime)
manager.shims = mocks.Shims
manager.Initialize([]services.Service{})
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand Down Expand Up @@ -167,9 +167,9 @@ func TestDarwinNetworkManager_ConfigureDNS(t *testing.T) {
setup := func(t *testing.T) (*BaseNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewBaseNetworkManager(mocks.Injector)
manager := NewBaseNetworkManager(mocks.Runtime)
manager.shims = mocks.Shims
manager.Initialize([]services.Service{})
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/workstation/network/linux_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ func TestLinuxNetworkManager_ConfigureHostRoute(t *testing.T) {
setup := func(t *testing.T) (*BaseNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewBaseNetworkManager(mocks.Injector)
manager := NewBaseNetworkManager(mocks.Runtime)
manager.shims = mocks.Shims
manager.Initialize([]services.Service{})
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand Down Expand Up @@ -169,9 +169,9 @@ func TestLinuxNetworkManager_ConfigureDNS(t *testing.T) {
setup := func(t *testing.T) (*BaseNetworkManager, *Mocks) {
t.Helper()
mocks := setupMocks(t)
manager := NewBaseNetworkManager(mocks.Injector)
manager := NewBaseNetworkManager(mocks.Runtime)
manager.shims = mocks.Shims
manager.Initialize([]services.Service{})
manager.AssignIPs([]services.Service{})
return manager, mocks
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/workstation/network/mock_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
// MockNetworkManager is a struct that simulates a network manager for testing purposes.
type MockNetworkManager struct {
NetworkManager
InitializeFunc func([]services.Service) error
AssignIPsFunc func([]services.Service) error
ConfigureHostRouteFunc func() error
ConfigureGuestFunc func() error
ConfigureDNSFunc func() error
Expand All @@ -37,10 +37,10 @@ func NewMockNetworkManager() *MockNetworkManager {
// Public Methods
// =============================================================================

// Initialize calls the custom InitializeFunc if provided.
func (m *MockNetworkManager) Initialize(services []services.Service) error {
if m.InitializeFunc != nil {
return m.InitializeFunc(services)
// AssignIPs calls the custom AssignIPsFunc if provided.
func (m *MockNetworkManager) AssignIPs(services []services.Service) error {
if m.AssignIPsFunc != nil {
return m.AssignIPsFunc(services)
}
return nil
}
Expand Down
16 changes: 8 additions & 8 deletions pkg/workstation/network/mock_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import (
// Test Public Methods
// =============================================================================

func TestMockNetworkManager_Initialize(t *testing.T) {
func TestMockNetworkManager_AssignIPs(t *testing.T) {
t.Run("Success", func(t *testing.T) {
// Given a mock network manager with successful initialization
// Given a mock network manager with successful IP assignment
mockManager := NewMockNetworkManager()
mockManager.InitializeFunc = func([]services.Service) error {
mockManager.AssignIPsFunc = func([]services.Service) error {
return nil
}

// When initializing the manager
err := mockManager.Initialize([]services.Service{})
// When assigning IPs
err := mockManager.AssignIPs([]services.Service{})

// Then no error should occur
if err != nil {
Expand All @@ -28,11 +28,11 @@ func TestMockNetworkManager_Initialize(t *testing.T) {
})

t.Run("NoFuncSet", func(t *testing.T) {
// Given a mock network manager with no initialization function
// Given a mock network manager with no IP assignment function
mockManager := NewMockNetworkManager()

// When initializing the manager
err := mockManager.Initialize([]services.Service{})
// When assigning IPs
err := mockManager.AssignIPs([]services.Service{})

// Then no error should occur
if err != nil {
Expand Down
Loading
Loading