diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 6765c8fb5..136f9a301 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -94,7 +94,7 @@ const DefaultNetworkCIDR = "10.5.0.0/16" const KubernetesShortTimeout = 200 * time.Millisecond -const MinimumVersionColima = "0.7.0" +const MinimumVersionColima = "0.9.0" const MinimumVersionDocker = "23.0.0" diff --git a/pkg/runtime/tools/tools_manager_test.go b/pkg/runtime/tools/tools_manager_test.go index 4dbc5cee1..36adad75c 100644 --- a/pkg/runtime/tools/tools_manager_test.go +++ b/pkg/runtime/tools/tools_manager_test.go @@ -650,7 +650,7 @@ func TestToolsManager_checkColima(t *testing.T) { } mocks.Shell.ExecSilentFunc = func(name string, args ...string) (string, error) { if name == "colima" && args[0] == "version" { - return "Colima version 0.7.0", nil + return fmt.Sprintf("Colima version %s", constants.MinimumVersionColima), nil } return "", fmt.Errorf("command not found") } @@ -669,7 +669,7 @@ func TestToolsManager_checkColima(t *testing.T) { return "Invalid version response", nil } if name == "colima" && args[0] == "version" { - return "Colima version 0.7.0", nil + return fmt.Sprintf("Colima version %s", constants.MinimumVersionColima), nil } return "", fmt.Errorf("command not found") } @@ -688,7 +688,7 @@ func TestToolsManager_checkColima(t *testing.T) { return "Limactl version 0.5.0", nil } if name == "colima" && args[0] == "version" { - return "Colima version 0.7.0", nil + return fmt.Sprintf("Colima version %s", constants.MinimumVersionColima), nil } return "", fmt.Errorf("command not found") } @@ -909,7 +909,7 @@ func Test_extractVersion(t *testing.T) { {"VersionWithPrefix", "Client Version: v1.32.0", "1.32.0"}, {"VersionWithText", "Terraform v1.7.0", "1.7.0"}, {"VersionWithMultipleNumbers", "1Password CLI 2.25.0", "2.25.0"}, - {"VersionWithColima", "Colima version 0.7.0", "0.7.0"}, + {"VersionWithColima", fmt.Sprintf("Colima version %s", constants.MinimumVersionColima), constants.MinimumVersionColima}, {"VersionWithLima", "limactl version 1.0.0", "1.0.0"}, {"NoVersion", "Invalid version response", ""}, {"EmptyString", "", ""}, diff --git a/pkg/workstation/virt/colima_virt.go b/pkg/workstation/virt/colima_virt.go index 1f3af40ae..6f36776d0 100644 --- a/pkg/workstation/virt/colima_virt.go +++ b/pkg/workstation/virt/colima_virt.go @@ -160,10 +160,13 @@ func (v *ColimaVirt) WriteConfig() error { }, ActivateRuntime: ptrBool(true), Network: colimaConfig.Network{ - Address: true, - DNSResolvers: []net.IP{}, - DNSHosts: map[string]string{}, - HostAddresses: false, + Address: true, + DNSResolvers: []net.IP{}, + DNSHosts: map[string]string{}, + HostAddresses: false, + Mode: "shared", + BridgeInterface: "", + PreferredRoute: false, }, ForwardAgent: false, VMType: vmType, diff --git a/pkg/workstation/virt/colima_virt_test.go b/pkg/workstation/virt/colima_virt_test.go index 0b24fd532..7631f746c 100644 --- a/pkg/workstation/virt/colima_virt_test.go +++ b/pkg/workstation/virt/colima_virt_test.go @@ -458,6 +458,52 @@ func TestColimaVirt_WriteConfig(t *testing.T) { t.Errorf("Expected MountType to be virtiofs, got %s", capturedConfig.MountType) } }) + + t.Run("NetworkConfiguration", func(t *testing.T) { + // Given a ColimaVirt with mock components + colimaVirt, mocks := setup(t) + + // And a config capture mechanism + var capturedConfig *colimaConfig.Config + mocks.Shims.NewYAMLEncoder = func(w io.Writer, opts ...yaml.EncodeOption) YAMLEncoder { + return &mockYAMLEncoder{ + encodeFunc: func(v any) error { + if cfg, ok := v.(*colimaConfig.Config); ok { + capturedConfig = cfg + } + return nil + }, + closeFunc: func() error { + return nil + }, + } + } + + // When calling WriteConfig + err := colimaVirt.WriteConfig() + + // Then no error should be returned + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + + // And the network configuration should have the correct values + if capturedConfig == nil { + t.Fatal("Expected config to be captured") + } + if !capturedConfig.Network.Address { + t.Error("Expected Network.Address to be true") + } + if capturedConfig.Network.Mode != "shared" { + t.Errorf("Expected Network.Mode to be 'shared', got %s", capturedConfig.Network.Mode) + } + if capturedConfig.Network.BridgeInterface != "" { + t.Errorf("Expected Network.BridgeInterface to be empty, got %s", capturedConfig.Network.BridgeInterface) + } + if capturedConfig.Network.PreferredRoute { + t.Error("Expected Network.PreferredRoute to be false") + } + }) } func TestColimaVirt_Up(t *testing.T) { diff --git a/pkg/workstation/workstation.go b/pkg/workstation/workstation.go index f4d841078..5fd3fdb8f 100644 --- a/pkg/workstation/workstation.go +++ b/pkg/workstation/workstation.go @@ -141,6 +141,9 @@ func (w *Workstation) Up() error { vmDriver := w.ConfigHandler.GetString("vm.driver") if vmDriver == "colima" && w.VirtualMachine != nil { + if err := w.VirtualMachine.WriteConfig(); err != nil { + return fmt.Errorf("error writing virtual machine config: %w", err) + } if err := w.VirtualMachine.Up(); err != nil { return fmt.Errorf("error running virtual machine Up command: %w", err) } diff --git a/pkg/workstation/workstation_test.go b/pkg/workstation/workstation_test.go index 70d57ee01..978969c6f 100644 --- a/pkg/workstation/workstation_test.go +++ b/pkg/workstation/workstation_test.go @@ -451,10 +451,19 @@ func TestWorkstation_Up(t *testing.T) { // Given a workstation with a virtual machine configured and a tracking flag for Up() calls mocks := setupWorkstationMocks(t) vmUpCalled := false + vmWriteConfigCalled := false + callOrder := []string{} + mocks.VirtualMachine.WriteConfigFunc = func() error { + vmWriteConfigCalled = true + callOrder = append(callOrder, "WriteConfig") + return nil + } mocks.VirtualMachine.UpFunc = func(verbose ...bool) error { vmUpCalled = true + callOrder = append(callOrder, "Up") return nil } + mocks.ConfigHandler.Set("vm.driver", "colima") workstation, err := NewWorkstation(mocks.Runtime, &Workstation{ VirtualMachine: mocks.VirtualMachine, ContainerRuntime: mocks.ContainerRuntime, @@ -472,10 +481,18 @@ func TestWorkstation_Up(t *testing.T) { if err != nil { t.Errorf("Expected success, got error: %v", err) } + // And VirtualMachine.WriteConfig() should be called + if !vmWriteConfigCalled { + t.Error("Expected VirtualMachine.WriteConfig to be called") + } // And VirtualMachine.Up() should be called if !vmUpCalled { t.Error("Expected VirtualMachine.Up to be called") } + // And WriteConfig should be called before Up + if len(callOrder) != 2 || callOrder[0] != "WriteConfig" || callOrder[1] != "Up" { + t.Errorf("Expected WriteConfig to be called before Up, got call order: %v", callOrder) + } }) t.Run("StartsContainerRuntime", func(t *testing.T) { @@ -592,12 +609,45 @@ func TestWorkstation_Up(t *testing.T) { } }) + t.Run("VirtualMachineWriteConfigError", func(t *testing.T) { + // Given a workstation with a virtual machine that will fail when writing config + mocks := setupWorkstationMocks(t) + mocks.VirtualMachine.WriteConfigFunc = func() error { + return fmt.Errorf("VM config write failed") + } + mocks.ConfigHandler.Set("vm.driver", "colima") + workstation, err := NewWorkstation(mocks.Runtime, &Workstation{ + VirtualMachine: mocks.VirtualMachine, + ContainerRuntime: mocks.ContainerRuntime, + NetworkManager: mocks.NetworkManager, + Services: convertToServiceSlice(mocks.Services), + }) + if err != nil { + t.Fatalf("Failed to create workstation: %v", err) + } + + // When calling Up() to start the workstation + err = workstation.Up() + + // Then an error should be returned + if err == nil { + t.Fatal("Expected error, got nil") + } + if !strings.Contains(err.Error(), "error writing virtual machine config") { + t.Errorf("Expected error about writing VM config, got: %v", err) + } + }) + t.Run("VirtualMachineUpError", func(t *testing.T) { // Given a workstation with a virtual machine that will fail when starting mocks := setupWorkstationMocks(t) + mocks.VirtualMachine.WriteConfigFunc = func() error { + return nil + } mocks.VirtualMachine.UpFunc = func(verbose ...bool) error { return fmt.Errorf("VM start failed") } + mocks.ConfigHandler.Set("vm.driver", "colima") workstation, err := NewWorkstation(mocks.Runtime, &Workstation{ VirtualMachine: mocks.VirtualMachine, ContainerRuntime: mocks.ContainerRuntime,