Skip to content

Commit 01591da

Browse files
committed
change adds validation for lima config values on start or create command
Signed-off-by: olalekan odukoya <[email protected]>
1 parent 170824e commit 01591da

File tree

2 files changed

+208
-1
lines changed

2 files changed

+208
-1
lines changed

pkg/limayaml/validate.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,24 @@ func Validate(y *LimaYAML, warn bool) error {
410410
}
411411
}
412412

413-
return errs
413+
if y.Rosetta.Enabled != nil && *y.Rosetta.Enabled {
414+
if *y.VMType != VZ {
415+
return fmt.Errorf("field `rosetta.enabled` can only be enabled for VMType %q; got %q", VZ, *y.VMType)
416+
}
417+
if !IsNativeArch(AARCH64) {
418+
return fmt.Errorf("field `rosetta.enabled` can only be enabled on aarch64; got %q", *y.Arch)
419+
}
420+
}
421+
422+
if y.NestedVirtualization != nil && *y.NestedVirtualization && *y.VMType != VZ {
423+
return fmt.Errorf("field `nestedVirtualization` can only be enabled for VMType %q; got %q", VZ, *y.VMType)
424+
}
425+
426+
if err := validateMountType(y); err != nil {
427+
return err
428+
}
429+
430+
return nil
414431
}
415432

416433
func validateFileObject(f File, fieldName string) error {
@@ -432,6 +449,30 @@ func validateFileObject(f File, fieldName string) error {
432449
return errs
433450
}
434451

452+
func validateMountType(y *LimaYAML) error {
453+
validMountTypes := map[string]bool{
454+
REVSSHFS: true,
455+
NINEP: true,
456+
VIRTIOFS: true,
457+
WSLMount: true,
458+
}
459+
460+
if !validMountTypes[*y.MountType] {
461+
return fmt.Errorf("field `mountType` must be: %q, %q, %q, %q; got %q", REVSSHFS, NINEP, VIRTIOFS, WSLMount, *y.MountType)
462+
}
463+
464+
// On Windows, only WSL mount type is valid
465+
if runtime.GOOS == "windows" && *y.MountType != WSLMount {
466+
return fmt.Errorf("field `mountType` on Windows must be %q; got %q", WSLMount, *y.MountType)
467+
}
468+
469+
if *y.MountType == VIRTIOFS && runtime.GOOS == "darwin" && *y.VMType != VZ {
470+
return fmt.Errorf("field `mountType` %q on macOS requires vmType %q; got %q", *y.MountType, VZ, *y.VMType)
471+
}
472+
473+
return nil
474+
}
475+
435476
func validateNetwork(y *LimaYAML) error {
436477
var errs error
437478
interfaceName := make(map[string]int)
@@ -490,6 +531,9 @@ func validateNetwork(y *LimaYAML) error {
490531
errs = errors.Join(errs, fmt.Errorf("field `%s.macAddress` must be a 48 bit (6 bytes) MAC address; actual length of %q is %d bytes", field, nw.MACAddress, len(hw)))
491532
}
492533
}
534+
if nw.VZNAT != nil && *nw.VZNAT && *y.VMType != VZ {
535+
return fmt.Errorf("field `%s.vzNAT` requires vmType %q; got %q", field, VZ, *y.VMType)
536+
}
493537
// FillDefault() will make sure that nw.Interface is not the empty string
494538
if len(nw.Interface) >= 16 {
495539
errs = errors.Join(errs, fmt.Errorf("field `%s.interface` must be less than 16 bytes, but is %d bytes: %q", field, len(nw.Interface), nw.Interface))

pkg/limayaml/validate_test.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package limayaml
55

66
import (
77
"errors"
8+
"runtime"
89
"testing"
910

1011
"gotest.tools/v3/assert"
@@ -388,3 +389,165 @@ func TestValidateAgainstLatestConfig(t *testing.T) {
388389
})
389390
}
390391
}
392+
393+
func TestValidateRosetta(t *testing.T) {
394+
if runtime.GOOS != "darwin" {
395+
t.Skip("Skipping Rosetta validation test on non-macOS platform")
396+
}
397+
398+
images := `images: [{"location": "/"}]`
399+
400+
nilData := ``
401+
y, err := Load([]byte(nilData+"\n"+images), "lima.yaml")
402+
assert.NilError(t, err)
403+
404+
err = Validate(y, false)
405+
assert.NilError(t, err)
406+
407+
invalidRosetta := `rosetta:
408+
enabled: true
409+
vmType: "qemu"
410+
` + images
411+
y, err = Load([]byte(invalidRosetta), "lima.yaml")
412+
assert.NilError(t, err)
413+
414+
err = Validate(y, false)
415+
if IsNativeArch(AARCH64) {
416+
assert.Error(t, err, "field `rosetta.enabled` can only be enabled for VMType \"vz\"; got \"qemu\"")
417+
} else {
418+
assert.NilError(t, err)
419+
}
420+
421+
validRosetta := `rosetta:
422+
enabled: true
423+
vmType: "vz"
424+
` + images
425+
y, err = Load([]byte(validRosetta), "lima.yaml")
426+
assert.NilError(t, err)
427+
428+
err = Validate(y, false)
429+
assert.NilError(t, err)
430+
431+
rosettaDisabled := `rosetta:
432+
enabled: false
433+
vmType: "qemu"
434+
` + images
435+
y, err = Load([]byte(rosettaDisabled), "lima.yaml")
436+
assert.NilError(t, err)
437+
438+
err = Validate(y, false)
439+
assert.NilError(t, err)
440+
}
441+
442+
func TestValidateNestedVirtualization(t *testing.T) {
443+
if runtime.GOOS != "darwin" {
444+
t.Skip("Skipping nested virtualization validation test on non-macOS platform")
445+
}
446+
447+
images := `images: [{"location": "/"}]`
448+
449+
validYAML := `
450+
nestedVirtualization: true
451+
vmType: vz
452+
` + images
453+
454+
y, err := Load([]byte(validYAML), "lima.yaml")
455+
assert.NilError(t, err)
456+
457+
err = Validate(y, false)
458+
assert.NilError(t, err)
459+
460+
invalidYAML := `
461+
nestedVirtualization: true
462+
vmType: qemu
463+
` + images
464+
465+
y, err = Load([]byte(invalidYAML), "lima.yaml")
466+
assert.NilError(t, err)
467+
468+
err = Validate(y, false)
469+
assert.Error(t, err, "field `nestedVirtualization` can only be enabled for VMType \"vz\"; got \"qemu\"")
470+
}
471+
472+
func TestValidateMountTypeOS(t *testing.T) {
473+
images := `images: [{"location": "/"}]`
474+
475+
nilMountConf := ``
476+
y, err := Load([]byte(nilMountConf+"\n"+images), "lima.yaml")
477+
assert.NilError(t, err)
478+
479+
err = Validate(y, false)
480+
assert.NilError(t, err)
481+
482+
inValidMountTypeLinux := `
483+
mountType: "random"
484+
`
485+
y, err = Load([]byte(inValidMountTypeLinux+"\n"+images), "lima.yaml")
486+
assert.NilError(t, err)
487+
488+
err = Validate(y, true)
489+
assert.Error(t, err, "field `mountType` must be: \"reverse-sshfs\", \"9p\", \"virtiofs\", \"wsl2\"; got \"random\"")
490+
491+
// Skip macOS-specific tests on non-macOS platforms
492+
if runtime.GOOS != "darwin" {
493+
return
494+
}
495+
496+
validMountTypeLinux := `
497+
mountType: "virtiofs"
498+
`
499+
y, err = Load([]byte(validMountTypeLinux+"\n"+images), "lima.yaml")
500+
assert.NilError(t, err)
501+
502+
err = Validate(y, true)
503+
if IsNativeArch(AARCH64) {
504+
assert.Error(t, err, "field `mountType` \"virtiofs\" on macOS requires vmType \"vz\"; got \"qemu\"")
505+
} else {
506+
assert.NilError(t, err)
507+
}
508+
509+
validMountTypeMac := `
510+
mountType: "virtiofs"
511+
vmType: "vz"
512+
`
513+
y, err = Load([]byte(validMountTypeMac+"\n"+images), "lima.yaml")
514+
assert.NilError(t, err)
515+
516+
err = Validate(y, false)
517+
assert.NilError(t, err)
518+
519+
invalidMountTypeMac := `
520+
mountType: "virtiofs"
521+
vmType: "qemu"
522+
`
523+
y, err = Load([]byte(invalidMountTypeMac+"\n"+images), "lima.yaml")
524+
assert.NilError(t, err)
525+
526+
err = Validate(y, false)
527+
assert.Error(t, err, "field `mountType` \"virtiofs\" on macOS requires vmType \"vz\"; got \"qemu\"")
528+
}
529+
530+
func TestValidateWindowsMountType(t *testing.T) {
531+
if runtime.GOOS != "windows" {
532+
t.Skip("Skipping Windows-specific mount type validation test on non-Windows platform")
533+
}
534+
535+
images := `images: [{"location": "/"}]`
536+
537+
invalidMountTypes := []string{"reverse-sshfs", "9p", "virtiofs"}
538+
for _, mountType := range invalidMountTypes {
539+
invalidMountTypeWindows := `mountType: "` + mountType + `"`
540+
y, err := Load([]byte(invalidMountTypeWindows+"\n"+images), "lima.yaml")
541+
assert.NilError(t, err)
542+
543+
err = Validate(y, false)
544+
assert.Error(t, err, `field `+"`mountType`"+` on Windows must be "wsl2"; got "`+mountType+`"`)
545+
}
546+
547+
validMountTypeWindows := `mountType: "wsl2"`
548+
y, err := Load([]byte(validMountTypeWindows+"\n"+images), "lima.yaml")
549+
assert.NilError(t, err)
550+
551+
err = Validate(y, false)
552+
assert.NilError(t, err)
553+
}

0 commit comments

Comments
 (0)