Skip to content

Commit 4ef46c4

Browse files
songponsswjandubois
andcommitted
reject shrinking disk during YAML validation
Signed-off-by: Songpon Srisawai <[email protected]> Co-authored-by: Jan Dubois <[email protected]>
1 parent dbf3cd9 commit 4ef46c4

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

cmd/limactl/edit.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,13 @@ func editAction(cmd *cobra.Command, args []string) error {
118118
return err
119119
}
120120
if err := limayaml.Validate(y, true); err != nil {
121-
rejectedYAML := "lima.REJECTED.yaml"
122-
if writeErr := os.WriteFile(rejectedYAML, yBytes, 0o644); writeErr != nil {
123-
return fmt.Errorf("the YAML is invalid, attempted to save the buffer as %q but failed: %w: %w", rejectedYAML, writeErr, err)
124-
}
125-
// TODO: may need to support editing the rejected YAML
126-
return fmt.Errorf("the YAML is invalid, saved the buffer as %q: %w", rejectedYAML, err)
121+
return saveRejectedYAML(yBytes, err)
122+
}
123+
124+
if err := limayaml.ValidateYAMLAgainstLatestConfig(yBytes, yContent); err != nil {
125+
return saveRejectedYAML(yBytes, err)
127126
}
127+
128128
if err := os.WriteFile(filePath, yBytes, 0o644); err != nil {
129129
return err
130130
}
@@ -171,3 +171,13 @@ func askWhetherToStart() (bool, error) {
171171
func editBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
172172
return bashCompleteInstanceNames(cmd)
173173
}
174+
175+
// saveRejectedYAML writes the rejected config and returns an error.
176+
func saveRejectedYAML(y []byte, origErr error) error {
177+
rejectedYAML := "lima.REJECTED.yaml"
178+
if writeErr := os.WriteFile(rejectedYAML, y, 0o644); writeErr != nil {
179+
return fmt.Errorf("the YAML is invalid, attempted to save the buffer as %q but failed: %w", rejectedYAML, errors.Join(writeErr, origErr))
180+
}
181+
// TODO: may need to support editing the rejected YAML
182+
return fmt.Errorf("the YAML is invalid, saved the buffer as %q: %w", rejectedYAML, origErr)
183+
}

pkg/limayaml/validate.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,38 @@ func warnExperimental(y *LimaYAML) {
610610
logrus.Warn("`mountInotify` is experimental")
611611
}
612612
}
613+
614+
// ValidateYAMLAgainstLatestConfig validates the values between the latest YAML and the updated(New) YAML.
615+
// This validates configuration rules that disallow certain changes, such as shrinking the disk.
616+
func ValidateYAMLAgainstLatestConfig(yNew, yLatest []byte) error {
617+
var l, n LimaYAML
618+
619+
if err := Unmarshal(yLatest, &l, "Unmarshal latest YAML bytes"); err != nil {
620+
return err
621+
}
622+
if err := Unmarshal(yNew, &n, "Unmarshal new YAML bytes"); err != nil {
623+
return err
624+
}
625+
626+
// Handle editing the template without a disk value
627+
if n.Disk == nil || l.Disk == nil {
628+
return nil
629+
}
630+
631+
// Disk value must be provided, as it is required when creating an instance.
632+
nDisk, err := units.RAMInBytes(*n.Disk)
633+
if err != nil {
634+
return err
635+
}
636+
lDisk, err := units.RAMInBytes(*l.Disk)
637+
if err != nil {
638+
return err
639+
}
640+
641+
// Reject shrinking disk
642+
if nDisk < lDisk {
643+
return fmt.Errorf("field `disk`: shrinking the disk (%v --> %v) is not supported", *l.Disk, *n.Disk)
644+
}
645+
646+
return nil
647+
}

pkg/limayaml/validate_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,28 @@ provision:
264264
"field `provision[0].mode` must one of \"system\", \"user\", \"boot\", \"data\", \"dependency\", or \"ansible\"\n"+
265265
"field `provision[1].path` must not be empty when mode is \"data\"")
266266
}
267+
268+
// TestValidateAgainstLatestConfig ensures the new config is correctly validated against the latest config.
269+
// (e.g., disk shrinking is disallowed).
270+
func TestValidateAgainstLatestConfig(t *testing.T) {
271+
validParam := [][]string{
272+
{`disk: 100G`, `disk: 100G`},
273+
{`disk: 200G`, `disk: 100G`},
274+
{``, ``},
275+
}
276+
for _, param := range validParam {
277+
n, l := param[0], param[1]
278+
err := ValidateYAMLAgainstLatestConfig([]byte(n), []byte(l))
279+
assert.NilError(t, err)
280+
}
281+
282+
invalidParam := [][]string{
283+
{`disk: 50G`, `disk: 100G`, `shrinking`},
284+
}
285+
286+
for _, param := range invalidParam {
287+
n, l := param[0], param[1]
288+
err := ValidateYAMLAgainstLatestConfig([]byte(n), []byte(l))
289+
assert.ErrorContains(t, err, param[2])
290+
}
291+
}

0 commit comments

Comments
 (0)