packer-cn/builder/vsphere/common/step_add_floppy_test.go

454 lines
13 KiB
Go

package common
import (
"context"
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer/builder/vsphere/driver"
)
func TestStepAddFloppy_Run(t *testing.T) {
tc := []struct {
name string
floppyPath string
uploadedPath string
step *StepAddFloppy
expectedAction multistep.StepAction
vmMock *driver.VirtualMachineMock
expectedVmMock *driver.VirtualMachineMock
driverMock *driver.DriverMock
expectedDriverMock *driver.DriverMock
dsMock *driver.DatastoreMock
expectedDsMock *driver.DatastoreMock
fail bool
errMessage string
}{
{
name: "Add floppy from state floppy path",
floppyPath: "floppy/path",
uploadedPath: "vm/dir/packer-tmp-created-floppy.flp",
step: &StepAddFloppy{
Config: new(FloppyConfig),
Datastore: "datastore",
Host: "host",
SetHostForDatastoreUploads: true,
},
expectedAction: multistep.ActionContinue,
vmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
},
expectedVmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
GetDirCalled: true,
AddFloppyCalled: true,
AddFloppyImagePath: "resolved/path",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
ResolvePathReturn: "resolved/path",
},
expectedDsMock: &driver.DatastoreMock{
UploadFileCalled: true,
UploadFileSrc: "floppy/path",
UploadFileDst: "vm/dir/packer-tmp-created-floppy.flp",
UploadFileHost: "host",
UploadFileSetHost: true,
ResolvePathCalled: true,
ResolvePathReturn: "resolved/path",
},
fail: false,
},
{
name: "State floppy path - find datastore fail",
floppyPath: "floppy/path",
step: &StepAddFloppy{
Config: new(FloppyConfig),
Datastore: "datastore",
Host: "host",
SetHostForDatastoreUploads: true,
},
expectedAction: multistep.ActionHalt,
vmMock: new(driver.VirtualMachineMock),
expectedVmMock: new(driver.VirtualMachineMock),
driverMock: &driver.DriverMock{
FindDatastoreErr: fmt.Errorf("error finding datastore"),
},
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: true,
errMessage: "error finding datastore",
},
{
name: "State floppy path - vm get dir fail",
floppyPath: "floppy/path",
step: &StepAddFloppy{
Config: new(FloppyConfig),
Datastore: "datastore",
Host: "host",
SetHostForDatastoreUploads: true,
},
expectedAction: multistep.ActionHalt,
vmMock: &driver.VirtualMachineMock{
GetDirErr: fmt.Errorf("fail to get vm dir"),
},
expectedVmMock: &driver.VirtualMachineMock{
GetDirCalled: true,
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: true,
errMessage: "fail to get vm dir",
},
{
name: "State floppy path - datastore upload file fail",
floppyPath: "floppy/path",
step: &StepAddFloppy{
Config: new(FloppyConfig),
Datastore: "datastore",
Host: "host",
SetHostForDatastoreUploads: true,
},
expectedAction: multistep.ActionHalt,
vmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
},
expectedVmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
GetDirCalled: true,
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
UploadFileErr: fmt.Errorf("failed to upload file"),
},
expectedDsMock: &driver.DatastoreMock{
UploadFileCalled: true,
UploadFileSrc: "floppy/path",
UploadFileDst: "vm/dir/packer-tmp-created-floppy.flp",
UploadFileHost: "host",
UploadFileSetHost: true,
},
fail: true,
errMessage: "failed to upload file",
},
{
name: "State floppy path - vm fail to add floppy",
floppyPath: "floppy/path",
uploadedPath: "vm/dir/packer-tmp-created-floppy.flp",
step: &StepAddFloppy{
Config: new(FloppyConfig),
Datastore: "datastore",
Host: "host",
SetHostForDatastoreUploads: true,
},
expectedAction: multistep.ActionHalt,
vmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
AddFloppyErr: fmt.Errorf("failed to add floppy"),
},
expectedVmMock: &driver.VirtualMachineMock{
GetDirResponse: "vm/dir",
GetDirCalled: true,
AddFloppyCalled: true,
AddFloppyImagePath: "resolved/path",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
ResolvePathReturn: "resolved/path",
},
expectedDsMock: &driver.DatastoreMock{
UploadFileCalled: true,
UploadFileSrc: "floppy/path",
UploadFileDst: "vm/dir/packer-tmp-created-floppy.flp",
UploadFileHost: "host",
UploadFileSetHost: true,
ResolvePathCalled: true,
ResolvePathReturn: "resolved/path",
},
fail: true,
errMessage: "failed to add floppy",
},
{
name: "Add floppy from FloppyIMGPath config",
step: &StepAddFloppy{
Config: &FloppyConfig{
FloppyIMGPath: "floppy/image/path",
},
},
expectedAction: multistep.ActionContinue,
vmMock: new(driver.VirtualMachineMock),
expectedVmMock: &driver.VirtualMachineMock{
AddFloppyCalled: true,
AddFloppyImagePath: "floppy/image/path",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: new(driver.DriverMock),
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: false,
},
{
name: "Fail to add floppy from FloppyIMGPath config",
step: &StepAddFloppy{
Config: &FloppyConfig{
FloppyIMGPath: "floppy/image/path",
},
},
expectedAction: multistep.ActionHalt,
vmMock: &driver.VirtualMachineMock{
AddFloppyErr: fmt.Errorf("fail to add floppy"),
},
expectedVmMock: &driver.VirtualMachineMock{
AddFloppyCalled: true,
AddFloppyImagePath: "floppy/image/path",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: new(driver.DriverMock),
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: true,
errMessage: "fail to add floppy",
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
state := basicStateBag(nil)
state.Put("vm", c.vmMock)
c.driverMock.DatastoreMock = c.dsMock
state.Put("driver", c.driverMock)
if c.floppyPath != "" {
state.Put("floppy_path", c.floppyPath)
}
if action := c.step.Run(context.TODO(), state); action != c.expectedAction {
t.Fatalf("unexpected action %v", action)
}
err, ok := state.Get("error").(error)
if ok {
if err.Error() != c.errMessage {
t.Fatalf("unexpected error %s", err.Error())
}
} else {
if c.fail {
t.Fatalf("expected to fail but it didn't")
}
}
uploadedPath, _ := state.Get("uploaded_floppy_path").(string)
if uploadedPath != c.uploadedPath {
t.Fatalf("Unexpected uploaded path state %s", uploadedPath)
}
if diff := cmp.Diff(c.vmMock, c.expectedVmMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected VirtualMachine calls: %s", diff)
}
c.expectedDriverMock.DatastoreMock = c.expectedDsMock
if diff := cmp.Diff(c.driverMock, c.expectedDriverMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected Driver calls: %s", diff)
}
if diff := cmp.Diff(c.dsMock, c.expectedDsMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected Datastore calls: %s", diff)
}
})
}
}
func TestStepAddFloppy_Cleanup(t *testing.T) {
tc := []struct {
name string
uploadedPath string
multistepState string
step *StepAddFloppy
driverMock *driver.DriverMock
expectedDriverMock *driver.DriverMock
dsMock *driver.DatastoreMock
expectedDsMock *driver.DatastoreMock
fail bool
errMessage string
}{
{
name: "State cancelled clean up",
uploadedPath: "uploaded/path",
multistepState: multistep.StateCancelled,
step: &StepAddFloppy{
Datastore: "datastore",
Host: "host",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
DeleteCalled: true,
},
expectedDsMock: &driver.DatastoreMock{
DeleteCalled: true,
DeletePath: "uploaded/path",
},
fail: false,
},
{
name: "State halted clean up",
uploadedPath: "uploaded/path",
multistepState: multistep.StateHalted,
step: &StepAddFloppy{
Datastore: "datastore",
Host: "host",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
DeleteCalled: true,
},
expectedDsMock: &driver.DatastoreMock{
DeleteCalled: true,
DeletePath: "uploaded/path",
},
fail: false,
},
{
name: "Don't clean up without uploaded path",
multistepState: multistep.StateHalted,
step: new(StepAddFloppy),
driverMock: new(driver.DriverMock),
expectedDriverMock: new(driver.DriverMock),
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: false,
},
{
name: "Don't clean up if state is not halted or canceled",
multistepState: "",
step: new(StepAddFloppy),
driverMock: new(driver.DriverMock),
expectedDriverMock: new(driver.DriverMock),
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: false,
},
{
name: "Fail because datastore is not found",
uploadedPath: "uploaded/path",
multistepState: multistep.StateHalted,
step: &StepAddFloppy{
Datastore: "datastore",
Host: "host",
},
driverMock: &driver.DriverMock{
FindDatastoreErr: fmt.Errorf("fail to find datastore"),
},
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: new(driver.DatastoreMock),
expectedDsMock: new(driver.DatastoreMock),
fail: true,
errMessage: "fail to find datastore",
},
{
name: "Fail to delete floppy",
uploadedPath: "uploaded/path",
multistepState: multistep.StateHalted,
step: &StepAddFloppy{
Datastore: "datastore",
Host: "host",
},
driverMock: new(driver.DriverMock),
expectedDriverMock: &driver.DriverMock{
FindDatastoreCalled: true,
FindDatastoreName: "datastore",
FindDatastoreHost: "host",
},
dsMock: &driver.DatastoreMock{
DeleteCalled: true,
DeleteErr: fmt.Errorf("failed to delete floppy"),
},
expectedDsMock: &driver.DatastoreMock{
DeleteCalled: true,
DeletePath: "uploaded/path",
},
fail: true,
errMessage: "failed to delete floppy",
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
state := basicStateBag(nil)
c.driverMock.DatastoreMock = c.dsMock
state.Put("driver", c.driverMock)
if c.uploadedPath != "" {
state.Put("uploaded_floppy_path", c.uploadedPath)
}
if c.multistepState != "" {
state.Put(c.multistepState, true)
}
c.step.Cleanup(state)
err, ok := state.Get("error").(error)
if ok {
if err.Error() != c.errMessage {
t.Fatalf("unexpected error %s", err.Error())
}
} else {
if c.fail {
t.Fatalf("expected to fail but it didn't")
}
}
c.expectedDriverMock.DatastoreMock = c.expectedDsMock
if diff := cmp.Diff(c.driverMock, c.expectedDriverMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected Driver calls: %s", diff)
}
if diff := cmp.Diff(c.dsMock, c.expectedDsMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected Datastore calls: %s", diff)
}
})
}
}