diff --git a/cmd/limactl/edit.go b/cmd/limactl/edit.go index 33ee9581333..3e372826e3c 100644 --- a/cmd/limactl/edit.go +++ b/cmd/limactl/edit.go @@ -118,13 +118,13 @@ func editAction(cmd *cobra.Command, args []string) error { return err } if err := limayaml.Validate(y, true); err != nil { - rejectedYAML := "lima.REJECTED.yaml" - if writeErr := os.WriteFile(rejectedYAML, yBytes, 0o644); writeErr != nil { - return fmt.Errorf("the YAML is invalid, attempted to save the buffer as %q but failed: %w: %w", rejectedYAML, writeErr, err) - } - // TODO: may need to support editing the rejected YAML - return fmt.Errorf("the YAML is invalid, saved the buffer as %q: %w", rejectedYAML, err) + return saveRejectedYAML(yBytes, err) + } + + if err := limayaml.ValidateYAMLAgainstLatestConfig(yBytes, yContent); err != nil { + return saveRejectedYAML(yBytes, err) } + if err := os.WriteFile(filePath, yBytes, 0o644); err != nil { return err } @@ -171,3 +171,13 @@ func askWhetherToStart() (bool, error) { func editBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { return bashCompleteInstanceNames(cmd) } + +// saveRejectedYAML writes the rejected config and returns an error. +func saveRejectedYAML(y []byte, origErr error) error { + rejectedYAML := "lima.REJECTED.yaml" + if writeErr := os.WriteFile(rejectedYAML, y, 0o644); writeErr != nil { + return fmt.Errorf("the YAML is invalid, attempted to save the buffer as %q but failed: %w: %w", rejectedYAML, writeErr, origErr) + } + // TODO: may need to support editing the rejected YAML + return fmt.Errorf("the YAML is invalid, saved the buffer as %q: %w", rejectedYAML, origErr) +} diff --git a/pkg/limayaml/validate.go b/pkg/limayaml/validate.go index 750383e2c51..857ab962ae2 100644 --- a/pkg/limayaml/validate.go +++ b/pkg/limayaml/validate.go @@ -595,3 +595,37 @@ func warnExperimental(y *LimaYAML) { logrus.Warn("`mountInotify` is experimental") } } + +// ValidateYAMLAgainstLatestConfig validates the values between the latest YAML and the updated(New) YAML. +func ValidateYAMLAgainstLatestConfig(yNew, yLatest []byte) error { + var l, n LimaYAML + var err error + if err = Unmarshal(yLatest, &l, "Unmarshal latest YAML bytes"); err != nil { + return err + } + if err = Unmarshal(yNew, &n, "Unmarshal new YAML byte"); err != nil { + return err + } + + // Handle editing the template without a disk value + if n.Disk == nil && l.Disk == nil { + return nil + } + + // Disk value must be provided, as it is required when creating an instance. + nDisk, err := units.RAMInBytes(*n.Disk) + if err != nil { + return err + } + lDisk, err := units.RAMInBytes(*l.Disk) + if err != nil { + return err + } + + // Reject shrinking disk + if nDisk < lDisk { + return fmt.Errorf("field `disk`: shrinking the disk (%v --> %v) is not supported", *l.Disk, *n.Disk) + } + + return nil +}