diff --git a/seed/seedwriter/writer.go b/seed/seedwriter/writer.go index c84abd27c02..16810766354 100644 --- a/seed/seedwriter/writer.go +++ b/seed/seedwriter/writer.go @@ -55,6 +55,8 @@ type Options struct { // ManifestPath if set, specifies the file path where the // seed.manifest file should be written. ManifestPath string + + IgnoreOptionFileExtentions bool } // manifest returns either the manifest already provided by the @@ -417,7 +419,7 @@ func (w *Writer) warningf(format string, a ...interface{}) { w.warnings = append(w.warnings, fmt.Sprintf(format, a...)) } -func validateComponent(optComp *OptionsComponent) error { +func (w *Writer) validateComponent(optComp *OptionsComponent) error { if optComp.Name != "" { if optComp.Path != "" { return fmt.Errorf("cannot specify both name and path for component %q", @@ -427,7 +429,7 @@ func validateComponent(optComp *OptionsComponent) error { return err } } else { - if !strings.HasSuffix(optComp.Path, ".comp") { + if !strings.HasSuffix(optComp.Path, ".comp") && !w.opts.IgnoreOptionFileExtentions { return fmt.Errorf("local option component %q does not end in .comp", optComp.Path) } if !osutil.FileExists(optComp.Path) { @@ -469,7 +471,7 @@ func (w *Writer) SetOptionsSnaps(optSnaps []*OptionsSnap) error { } w.byNameOptSnaps.Add(sn) } else { - if !strings.HasSuffix(sn.Path, ".snap") { + if !strings.HasSuffix(sn.Path, ".snap") && !w.opts.IgnoreOptionFileExtentions { return fmt.Errorf("local option snap %q does not end in .snap", sn.Path) } if !osutil.FileExists(sn.Path) { @@ -489,7 +491,7 @@ func (w *Writer) SetOptionsSnaps(optSnaps []*OptionsSnap) error { } } for _, comp := range sn.Components { - if err := validateComponent(&comp); err != nil { + if err := w.validateComponent(&comp); err != nil { return err } } diff --git a/seed/seedwriter/writer_test.go b/seed/seedwriter/writer_test.go index b34443e4012..74389285a37 100644 --- a/seed/seedwriter/writer_test.go +++ b/seed/seedwriter/writer_test.go @@ -27,6 +27,7 @@ import ( "path" "path/filepath" "sort" + "strings" "testing" "time" @@ -330,6 +331,62 @@ func (s writerSuite) TestSetOptionsSnapsErrors(c *C) { } } +func (s writerSuite) TestSetOptionsSnapsIgnoreExtensions(c *C) { + model := s.Brands.Model("my-brand", "my-model", map[string]interface{}{ + "display-name": "my model", + "architecture": "amd64", + "store": "my-store", + "base": "core20", + "grade": "dangerous", + "snaps": []interface{}{ + map[string]interface{}{ + "name": "pc-kernel", + "id": s.AssertedSnapID("pc-kernel"), + "type": "kernel", + "default-channel": "20", + }, + map[string]interface{}{ + "name": "pc", + "id": s.AssertedSnapID("pc"), + "type": "gadget", + "default-channel": "20", + }, + map[string]interface{}{ + "name": "required20", + "id": s.AssertedSnapID("required20"), + }, + }, + }) + + s.opts.Label = "20240714" + s.opts.IgnoreOptionFileExtentions = true + w, err := seedwriter.New(model, s.opts) + c.Assert(err, IsNil) + + snapPath := s.makeLocalSnap(c, "required20") + compPath := s.makeLocalComponent(c, "required20+comp1") + + trimmed := strings.TrimSuffix(snapPath, ".snap") + os.Rename(snapPath, trimmed) + snapPath = trimmed + + trimmed = strings.TrimSuffix(compPath, ".comp") + os.Rename(compPath, trimmed) + compPath = trimmed + + err = w.SetOptionsSnaps([]*seedwriter.OptionsSnap{ + { + Path: snapPath, + Components: []seedwriter.OptionsComponent{ + { + Path: compPath, + }, + }, + }, + }) + c.Assert(err, IsNil) +} + func (s *writerSuite) TestSnapsToDownloadCore16(c *C) { model := s.Brands.Model("my-brand", "my-model", map[string]interface{}{ "display-name": "my model",