Skip to content

Commit 061d687

Browse files
committed
Add VirtualMachine interface to abstract out crc virtual machine interaction
Add a VirtualMachine interface and make the CRC `machine` package client use the VirtualMachine interface instead of a concrete implementation. This way we can inject a dummy test FakeVirtualMachine implementation into client tests that can ease writing tests for this package. - Add some additional methods in VirtualMachine interface so that we can replace direct usage of struct fields with interface methods - `Bundle()` - `Driver()` - `API()` - `Host()` - `Kill()`
1 parent b6d4459 commit 061d687

File tree

7 files changed

+84
-44
lines changed

7 files changed

+84
-44
lines changed

pkg/crc/machine/console.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (client *client) GetConsoleURL() (*types.ConsoleResult, error) {
2121
return nil, errors.Wrap(err, "Error getting the state for virtual machine")
2222
}
2323

24-
clusterConfig, err := getClusterConfig(vm.bundle)
24+
clusterConfig, err := getClusterConfig(vm.Bundle())
2525
if err != nil {
2626
return nil, errors.Wrap(err, "Error loading cluster configuration")
2727
}

pkg/crc/machine/generate_bundle.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func loadVM(client *client) (*bundle.CrcBundleInfo, *crcssh.Runner, error) {
111111
}
112112
defer vm.Close()
113113

114-
currentState, err := vm.Driver.GetState()
114+
currentState, err := vm.Driver().GetState()
115115
if err != nil {
116116
return nil, nil, errors.Wrap(err, "Cannot get machine state")
117117
}
@@ -124,5 +124,5 @@ func loadVM(client *client) (*bundle.CrcBundleInfo, *crcssh.Runner, error) {
124124
return nil, nil, errors.Wrap(err, "Error creating the ssh client")
125125
}
126126

127-
return vm.bundle, sshRunner, nil
127+
return vm.Bundle(), sshRunner, nil
128128
}

pkg/crc/machine/ip.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ func (client *client) ConnectionDetails() (*types.ConnectionDetails, error) {
2121
IP: ip,
2222
SSHPort: vm.SSHPort(),
2323
SSHUsername: constants.DefaultSSHUser,
24-
SSHKeys: []string{constants.GetPrivateKeyPath(), constants.GetECDSAPrivateKeyPath(), vm.bundle.GetSSHKeyPath()},
24+
SSHKeys: []string{constants.GetPrivateKeyPath(), constants.GetECDSAPrivateKeyPath(), vm.Bundle().GetSSHKeyPath()},
2525
}, nil
2626
}

pkg/crc/machine/start.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,48 +60,48 @@ func getCrcBundleInfo(preset crcPreset.Preset, bundleName, bundlePath string, en
6060
return bundle.Use(bundleName)
6161
}
6262

63-
func (client *client) updateVMConfig(startConfig types.StartConfig, vm *virtualMachine) error {
63+
func (client *client) updateVMConfig(startConfig types.StartConfig, vm VirtualMachine) error {
6464
/* Memory */
6565
logging.Debugf("Updating CRC VM configuration")
66-
if err := setMemory(vm.Host, startConfig.Memory); err != nil {
66+
if err := setMemory(vm.Host(), startConfig.Memory); err != nil {
6767
logging.Debugf("Failed to update CRC VM configuration: %v", err)
6868
if err == drivers.ErrNotImplemented {
6969
logging.Warn("Memory configuration change has been ignored as the machine driver does not support it")
7070
} else {
7171
return err
7272
}
7373
}
74-
if err := setVcpus(vm.Host, startConfig.CPUs); err != nil {
74+
if err := setVcpus(vm.Host(), startConfig.CPUs); err != nil {
7575
logging.Debugf("Failed to update CRC VM configuration: %v", err)
7676
if err == drivers.ErrNotImplemented {
7777
logging.Warn("CPU configuration change has been ignored as the machine driver does not support it")
7878
} else {
7979
return err
8080
}
8181
}
82-
if err := vm.api.Save(vm.Host); err != nil {
82+
if err := vm.API().Save(vm.Host()); err != nil {
8383
return err
8484
}
8585

8686
/* Disk size */
8787
if startConfig.DiskSize != constants.DefaultDiskSize {
88-
if err := setDiskSize(vm.Host, startConfig.DiskSize); err != nil {
88+
if err := setDiskSize(vm.Host(), startConfig.DiskSize); err != nil {
8989
logging.Debugf("Failed to update CRC disk configuration: %v", err)
9090
if err == drivers.ErrNotImplemented {
9191
logging.Warn("Disk size configuration change has been ignored as the machine driver does not support it")
9292
} else {
9393
return err
9494
}
9595
}
96-
if err := vm.api.Save(vm.Host); err != nil {
96+
if err := vm.API().Save(vm.Host()); err != nil {
9797
return err
9898
}
9999
}
100100

101101
// we want to set the shared dir password on-the-fly to be used
102102
// we do not want this value to be persisted to disk
103103
if startConfig.SharedDirPassword != "" {
104-
if err := setSharedDirPassword(vm.Host, startConfig.SharedDirPassword); err != nil {
104+
if err := setSharedDirPassword(vm.Host(), startConfig.SharedDirPassword); err != nil {
105105
return fmt.Errorf("Failed to set shared dir password: %w", err)
106106
}
107107
}
@@ -206,9 +206,9 @@ func growLVForMicroshift(sshRunner *crcssh.Runner, lvFullName string, rootPart s
206206
return nil
207207
}
208208

209-
func configureSharedDirs(vm *virtualMachine, sshRunner *crcssh.Runner) error {
209+
func configureSharedDirs(vm VirtualMachine, sshRunner *crcssh.Runner) error {
210210
logging.Debugf("Configuring shared directories")
211-
sharedDirs, err := vm.Driver.GetSharedDirs()
211+
sharedDirs, err := vm.Driver().GetSharedDirs()
212212
if err != nil {
213213
// the libvirt machine driver uses net/rpc, which wraps errors
214214
// in rpc.ServerError, but without using golang 1.13 error
@@ -334,7 +334,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
334334
}
335335
defer vm.Close()
336336

337-
currentBundleName := vm.bundle.GetBundleName()
337+
currentBundleName := vm.Bundle().GetBundleName()
338338
if currentBundleName != bundleName {
339339
logging.Debugf("Bundle '%s' was requested, but the existing VM is using '%s'",
340340
bundleName, currentBundleName)
@@ -347,8 +347,8 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
347347
return nil, errors.Wrap(err, "Error getting the machine state")
348348
}
349349
if vmState == state.Running {
350-
logging.Infof("A CRC VM for %s %s is already running", startConfig.Preset.ForDisplay(), vm.bundle.GetVersion())
351-
clusterConfig, err := getClusterConfig(vm.bundle)
350+
logging.Infof("A CRC VM for %s %s is already running", startConfig.Preset.ForDisplay(), vm.Bundle().GetVersion())
351+
clusterConfig, err := getClusterConfig(vm.Bundle())
352352
if err != nil {
353353
return nil, errors.Wrap(err, "Cannot create cluster configuration")
354354
}
@@ -365,7 +365,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
365365
return nil, err
366366
}
367367

368-
logging.Infof("Starting CRC VM for %s %s...", startConfig.Preset, vm.bundle.GetVersion())
368+
logging.Infof("Starting CRC VM for %s %s...", startConfig.Preset, vm.Bundle().GetVersion())
369369

370370
if client.useVSock() {
371371
if err := exposePorts(startConfig.Preset, startConfig.IngressHTTPPort, startConfig.IngressHTTPSPort); err != nil {
@@ -457,7 +457,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
457457
return nil, errors.Wrap(err, "Failed to change permissions to root podman socket")
458458
}
459459

460-
proxyConfig, err := getProxyConfig(vm.bundle)
460+
proxyConfig, err := getProxyConfig(vm.Bundle())
461461
if err != nil {
462462
return nil, errors.Wrap(err, "Error getting proxy configuration")
463463
}
@@ -472,7 +472,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
472472
SSHRunner: sshRunner,
473473
IP: instanceIP,
474474
// TODO: should be more finegrained
475-
BundleMetadata: *vm.bundle,
475+
BundleMetadata: *vm.Bundle(),
476476
NetworkMode: client.networkMode(),
477477
}
478478

@@ -502,7 +502,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
502502
logging.Warn(fmt.Sprintf("Failed to query DNS from host: %v", err))
503503
}
504504

505-
if vm.bundle.IsMicroshift() {
505+
if vm.Bundle().IsMicroshift() {
506506
// **************************
507507
// END OF MICROSHIFT START CODE
508508
// **************************
@@ -547,7 +547,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
547547
ocConfig := oc.UseOCWithSSH(sshRunner)
548548

549549
if err := cluster.ApproveCSRAndWaitForCertsRenewal(ctx, sshRunner, ocConfig, certsExpired[cluster.KubeletClientCert], certsExpired[cluster.KubeletServerCert], certsExpired[cluster.AggregatorClientCert]); err != nil {
550-
logBundleDate(vm.bundle)
550+
logBundleDate(vm.Bundle())
551551
return nil, errors.Wrap(err, "Failed to renew TLS certificates: please check if a newer CRC release is available")
552552
}
553553

@@ -596,7 +596,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
596596
}
597597
}
598598

599-
if err := updateKubeconfig(ctx, ocConfig, sshRunner, vm.bundle.GetKubeConfigPath()); err != nil {
599+
if err := updateKubeconfig(ctx, ocConfig, sshRunner, vm.Bundle().GetKubeConfigPath()); err != nil {
600600
return nil, errors.Wrap(err, "Failed to update kubeconfig file")
601601
}
602602

@@ -607,7 +607,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
607607

608608
waitForProxyPropagation(ctx, ocConfig, proxyConfig)
609609

610-
clusterConfig, err := getClusterConfig(vm.bundle)
610+
clusterConfig, err := getClusterConfig(vm.Bundle())
611611
if err != nil {
612612
return nil, errors.Wrap(err, "Cannot get cluster configuration")
613613
}
@@ -694,17 +694,17 @@ func createHost(machineConfig config.MachineConfig, preset crcPreset.Preset) err
694694
return nil
695695
}
696696

697-
func startHost(ctx context.Context, vm *virtualMachine) error {
698-
if err := vm.Driver.Start(); err != nil {
697+
func startHost(ctx context.Context, vm VirtualMachine) error {
698+
if err := vm.Driver().Start(); err != nil {
699699
return fmt.Errorf("Error in driver during machine start: %s", err)
700700
}
701701

702-
if err := vm.api.Save(vm.Host); err != nil {
702+
if err := vm.API().Save(vm.Host()); err != nil {
703703
return fmt.Errorf("Error saving virtual machine to store after attempting creation: %s", err)
704704
}
705705

706706
logging.Debug("Waiting for machine to be running, this may take a few minutes...")
707-
if err := crcerrors.Retry(ctx, 3*time.Minute, host.MachineInState(vm.Driver, libmachinestate.Running), 3*time.Second); err != nil {
707+
if err := crcerrors.Retry(ctx, 3*time.Minute, host.MachineInState(vm.Driver(), libmachinestate.Running), 3*time.Second); err != nil {
708708
return fmt.Errorf("Error waiting for machine to be running: %s", err)
709709
}
710710

pkg/crc/machine/status.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ func (client *client) Status() (*types.ClusterStatusResult, error) {
3737
CrcStatus: vmStatus,
3838
}
3939
switch {
40-
case vm.bundle.IsMicroshift():
40+
case vm.Bundle().IsMicroshift():
4141
clusterStatusResult.OpenshiftStatus = types.OpenshiftStopped
42-
clusterStatusResult.OpenshiftVersion = vm.bundle.GetVersion()
42+
clusterStatusResult.OpenshiftVersion = vm.Bundle().GetVersion()
4343
clusterStatusResult.Preset = preset.Microshift
4444
default:
4545
clusterStatusResult.OpenshiftStatus = types.OpenshiftStopped
46-
clusterStatusResult.OpenshiftVersion = vm.bundle.GetVersion()
46+
clusterStatusResult.OpenshiftVersion = vm.Bundle().GetVersion()
4747
clusterStatusResult.Preset = preset.OpenShift
4848
}
4949

@@ -62,10 +62,10 @@ func (client *client) Status() (*types.ClusterStatusResult, error) {
6262
clusterStatusResult.DiskSize = diskSize
6363

6464
switch {
65-
case vm.bundle.IsMicroshift():
65+
case vm.Bundle().IsMicroshift():
6666
clusterStatusResult.OpenshiftStatus = getMicroShiftStatus(context.Background(), ip)
6767
clusterStatusResult.PersistentVolumeUse, clusterStatusResult.PersistentVolumeSize = client.getPVCSize(vm)
68-
case vm.bundle.IsOpenShift():
68+
case vm.Bundle().IsOpenShift():
6969
clusterStatusResult.OpenshiftStatus = getOpenShiftStatus(context.Background(), ip)
7070
}
7171

@@ -112,7 +112,7 @@ func (client *client) GetClusterLoad() (*types.ClusterLoadResult, error) {
112112
}, nil
113113
}
114114

115-
func (client *client) getDiskDetails(vm *virtualMachine) (int64, int64) {
115+
func (client *client) getDiskDetails(vm VirtualMachine) (int64, int64) {
116116
disk, err, _ := client.diskDetails.Memoize("disks", func() (interface{}, error) {
117117
sshRunner, err := vm.SSHRunner()
118118
if err != nil {
@@ -162,7 +162,7 @@ func getStatus(status *cluster.Status) types.OpenshiftStatus {
162162
return types.OpenshiftStopped
163163
}
164164

165-
func (client *client) getRAMStatus(vm *virtualMachine) (int64, int64) {
165+
func (client *client) getRAMStatus(vm VirtualMachine) (int64, int64) {
166166
ram, err, _ := client.ramDetails.Memoize("ram", func() (interface{}, error) {
167167
sshRunner, err := vm.SSHRunner()
168168
if err != nil {
@@ -184,7 +184,7 @@ func (client *client) getRAMStatus(vm *virtualMachine) (int64, int64) {
184184
return ram.([]int64)[0], ram.([]int64)[1]
185185
}
186186

187-
func (client *client) getCPUStatus(vm *virtualMachine) []int64 {
187+
func (client *client) getCPUStatus(vm VirtualMachine) []int64 {
188188
sshRunner, err := vm.SSHRunner()
189189
if err != nil {
190190
logging.Debugf("Cannot get SSH runner: %v", err)
@@ -202,7 +202,7 @@ func (client *client) getCPUStatus(vm *virtualMachine) []int64 {
202202

203203
}
204204

205-
func (client *client) getPVCSize(vm *virtualMachine) (int, int) {
205+
func (client *client) getPVCSize(vm VirtualMachine) (int, int) {
206206
sshRunner, err := vm.SSHRunner()
207207
if err != nil {
208208
logging.Debugf("Cannot get SSH runner: %v", err)

pkg/crc/machine/stop.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (client *client) Stop() (state.State, error) {
5454
// is fixed. We should also ignore the openshift specific errors because stop
5555
// operation shouldn't depend on the openshift side. Without this graceful shutdown
5656
// takes around 6-7 mins.
57-
func stopAllContainers(vm *virtualMachine) error {
57+
func stopAllContainers(vm VirtualMachine) error {
5858
logging.Info("Stopping kubelet and all containers...")
5959
sshRunner, err := vm.SSHRunner()
6060
if err != nil {

pkg/crc/machine/virtualmachine.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,28 @@ import (
99
"github.com/crc-org/crc/v2/pkg/crc/ssh"
1010
"github.com/crc-org/crc/v2/pkg/libmachine"
1111
libmachinehost "github.com/crc-org/crc/v2/pkg/libmachine/host"
12+
"github.com/crc-org/machine/libmachine/drivers"
1213
"github.com/pkg/errors"
1314
)
1415

16+
type VirtualMachine interface {
17+
Close() error
18+
Remove() error
19+
State() (state.State, error)
20+
IP() (string, error)
21+
SSHPort() int
22+
SSHRunner() (*ssh.Runner, error)
23+
Kill() error
24+
Stop() error
25+
Bundle() *bundle.CrcBundleInfo
26+
Driver() drivers.Driver
27+
API() libmachine.API
28+
Host() *libmachinehost.Host
29+
}
30+
1531
type virtualMachine struct {
16-
name string
17-
*libmachinehost.Host
32+
name string
33+
host *libmachinehost.Host
1834
bundle *bundle.CrcBundleInfo
1935
api libmachine.API
2036
vsock bool
@@ -34,7 +50,7 @@ func (err *MissingHostError) Error() string {
3450

3551
var errInvalidBundleMetadata = errors.New("Error loading bundle metadata")
3652

37-
func loadVirtualMachine(name string, useVSock bool) (*virtualMachine, error) {
53+
func loadVirtualMachine(name string, useVSock bool) (VirtualMachine, error) {
3854
apiClient := libmachine.NewClient(constants.MachineBaseDir)
3955
exists, err := apiClient.Exists(name)
4056
if err != nil {
@@ -56,7 +72,7 @@ func loadVirtualMachine(name string, useVSock bool) (*virtualMachine, error) {
5672

5773
return &virtualMachine{
5874
name: name,
59-
Host: libmachineHost,
75+
host: libmachineHost,
6076
bundle: crcBundleMetadata,
6177
api: apiClient,
6278
vsock: useVSock,
@@ -68,7 +84,7 @@ func (vm *virtualMachine) Close() error {
6884
}
6985

7086
func (vm *virtualMachine) Remove() error {
71-
if err := vm.Driver.Remove(); err != nil {
87+
if err := vm.Driver().Remove(); err != nil {
7288
return errors.Wrap(err, "Driver cannot remove machine")
7389
}
7490

@@ -80,7 +96,7 @@ func (vm *virtualMachine) Remove() error {
8096
}
8197

8298
func (vm *virtualMachine) State() (state.State, error) {
83-
vmStatus, err := vm.Driver.GetState()
99+
vmStatus, err := vm.Driver().GetState()
84100
if err != nil {
85101
return state.Error, err
86102
}
@@ -91,7 +107,7 @@ func (vm *virtualMachine) IP() (string, error) {
91107
if vm.vsock {
92108
return "127.0.0.1", nil
93109
}
94-
return vm.Driver.GetIP()
110+
return vm.Driver().GetIP()
95111
}
96112

97113
func (vm *virtualMachine) SSHPort() int {
@@ -108,3 +124,27 @@ func (vm *virtualMachine) SSHRunner() (*ssh.Runner, error) {
108124
}
109125
return ssh.CreateRunner(ip, vm.SSHPort(), constants.GetPrivateKeyPath(), constants.GetECDSAPrivateKeyPath(), vm.bundle.GetSSHKeyPath())
110126
}
127+
128+
func (vm *virtualMachine) Bundle() *bundle.CrcBundleInfo {
129+
return vm.bundle
130+
}
131+
132+
func (vm *virtualMachine) Driver() drivers.Driver {
133+
return vm.host.Driver
134+
}
135+
136+
func (vm *virtualMachine) API() libmachine.API {
137+
return vm.api
138+
}
139+
140+
func (vm *virtualMachine) Host() *libmachinehost.Host {
141+
return vm.host
142+
}
143+
144+
func (vm *virtualMachine) Kill() error {
145+
return vm.host.Kill()
146+
}
147+
148+
func (vm *virtualMachine) Stop() error {
149+
return vm.host.Stop()
150+
}

0 commit comments

Comments
 (0)