Skip to content

refactor: Limayaml validation functions #3660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
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
2 changes: 1 addition & 1 deletion cmd/limactl/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func editAction(cmd *cobra.Command, args []string) error {
return saveRejectedYAML(yBytes, err)
}

if err := limayaml.ValidateYAMLAgainstLatestConfig(yBytes, yContent); err != nil {
if err := limayaml.ValidateAgainstLatestConfig(yBytes, yContent); err != nil {
return saveRejectedYAML(yBytes, err)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/limayaml/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func load(b []byte, filePath string, warn bool) (*LimaYAML, error) {
}

// It should be called before the `y` parameter is passed to FillDefault() that execute template.
if err := ValidateParamIsUsed(&y); err != nil {
if err := validateParamIsUsed(&y); err != nil {
return nil, err
}

Expand Down
52 changes: 26 additions & 26 deletions pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,6 @@ import (
"github.com/lima-vm/lima/pkg/version/versionutil"
)

func validateFileObject(f File, fieldName string) error {
var errs error
if !strings.Contains(f.Location, "://") {
if _, err := localpathutil.Expand(f.Location); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `%s.location` refers to an invalid local file path: %q: %w", fieldName, f.Location, err))
}
// f.Location does NOT need to be accessible, so we do NOT check os.Stat(f.Location)
}
if !slices.Contains(ArchTypes, f.Arch) {
errs = errors.Join(errs, fmt.Errorf("field `arch` must be one of %v; got %q", ArchTypes, f.Arch))
}
if f.Digest != "" {
if !f.Digest.Algorithm().Available() {
errs = errors.Join(errs, fmt.Errorf("field `%s.digest` refers to an unavailable digest algorithm", fieldName))
}
if err := f.Digest.Validate(); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `%s.digest` is invalid: %s: %w", fieldName, f.Digest.String(), err))
}
}
return errs
}

func Validate(y *LimaYAML, warn bool) error {
var errs error

Expand Down Expand Up @@ -441,6 +419,28 @@ func Validate(y *LimaYAML, warn bool) error {
return errs
}

func validateFileObject(f File, fieldName string) error {
var errs error
if !strings.Contains(f.Location, "://") {
if _, err := localpathutil.Expand(f.Location); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `%s.location` refers to an invalid local file path: %q: %w", fieldName, f.Location, err))
}
// f.Location does NOT need to be accessible, so we do NOT check os.Stat(f.Location)
}
if !slices.Contains(ArchTypes, f.Arch) {
errs = errors.Join(errs, fmt.Errorf("field `arch` must be one of %v; got %q", ArchTypes, f.Arch))
}
if f.Digest != "" {
if !f.Digest.Algorithm().Available() {
errs = errors.Join(errs, fmt.Errorf("field `%s.digest` refers to an unavailable digest algorithm", fieldName))
}
if err := f.Digest.Validate(); err != nil {
errs = errors.Join(errs, fmt.Errorf("field `%s.digest` is invalid: %s: %w", fieldName, f.Digest.String(), err))
}
}
return errs
}

func validateNetwork(y *LimaYAML) error {
var errs error
interfaceName := make(map[string]int)
Expand Down Expand Up @@ -518,9 +518,9 @@ func validateNetwork(y *LimaYAML) error {
return errs
}

// ValidateParamIsUsed checks if the keys in the `param` field are used in any script, probe, copyToHost, or portForward.
// validateParamIsUsed checks if the keys in the `param` field are used in any script, probe, copyToHost, or portForward.
// It should be called before the `y` parameter is passed to FillDefault() that execute template.
func ValidateParamIsUsed(y *LimaYAML) error {
func validateParamIsUsed(y *LimaYAML) error {
for key := range y.Param {
re, err := regexp.Compile(`{{[^}]*\.Param\.` + key + `[^}]*}}|\bPARAM_` + key + `\b`)
if err != nil {
Expand Down Expand Up @@ -611,9 +611,9 @@ func warnExperimental(y *LimaYAML) {
}
}

// ValidateYAMLAgainstLatestConfig validates the values between the latest YAML and the updated(New) YAML.
// ValidateAgainstLatestConfig validates the values between the latest YAML and the updated(New) YAML.
// This validates configuration rules that disallow certain changes, such as shrinking the disk.
func ValidateYAMLAgainstLatestConfig(yNew, yLatest []byte) error {
func ValidateAgainstLatestConfig(yNew, yLatest []byte) error {
var n LimaYAML

// Load the latest YAML and fill in defaults
Expand Down
4 changes: 2 additions & 2 deletions pkg/limayaml/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ provision:
"field `provision[1].path` must not be empty when mode is \"data\"")
}

func TestValidateYAMLAgainstLatestConfig(t *testing.T) {
func TestValidateAgainstLatestConfig(t *testing.T) {
tests := []struct {
name string
yNew string
Expand Down Expand Up @@ -308,7 +308,7 @@ func TestValidateYAMLAgainstLatestConfig(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateYAMLAgainstLatestConfig([]byte(tt.yNew), []byte(tt.yLatest))
err := ValidateAgainstLatestConfig([]byte(tt.yNew), []byte(tt.yLatest))
if tt.wantErr == nil {
assert.NilError(t, err)
} else {
Expand Down