Skip to content

Commit

Permalink
seedwriter: check if the optionSnap channel is same as model assert
Browse files Browse the repository at this point in the history
If we define `presence: optional` for an app snap in the model assertion, and the
default channel is `24/stable` for example, then when we pass `--snap=SNAP=24/stable`
to `snap prepare-image` with a model assertion that has model grade higher than
`dangerous`, I will get an error `error: cannot override channels, add devmode snaps,
local snaps, or extra snaps with a model of grade higher than dangerous`

However, I am expecting that snapd should check whether the channel for option snap
is same as the channel defined in model assertion, maybe snapd should only return
error if channel is not the same and the model grade is higher than dangerous

Signed-off-by: Aristo Chen <[email protected]>
  • Loading branch information
AristoChen committed Jul 3, 2024
1 parent 23f572b commit 633b7a2
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 1 deletion.
19 changes: 18 additions & 1 deletion seed/seedwriter/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,26 @@ func (w *Writer) SetOptionsSnaps(optSnaps []*OptionsSnap) error {
if err != nil {
return fmt.Errorf("cannot use option channel for snap %q: %v", whichSnap, err)
}
if err := w.policy.checkSnapChannel(ch, whichSnap); err != nil {

// Check whether the channel defined in the model assertion
// is same as the option snap(--snap=SNAP_NAME=CHANNEL)
modSnaps, err := w.modSnaps()
if err != nil {
return err
}
for _, modSnap := range modSnaps {
if sn.Name != modSnap.Name {
continue
}

if modSnap.Presence == "optional" && sn.Channel == modSnap.DefaultChannel {
continue
} else {
if err := w.policy.checkSnapChannel(ch, whichSnap); err != nil {
return err
}
}
}
}
if local {
if w.localSnaps == nil {
Expand Down
96 changes: 96 additions & 0 deletions seed/seedwriter/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3316,6 +3316,102 @@ func (s *writerSuite) TestSnapsToDownloadCore20OptionalSnaps(c *C) {
c.Check(snaps[5].SnapName(), Equals, "optional20-b")
}

func (s *writerSuite) TestSnapsToDownloadCore20OptionalSnapsWithSameChannel(c *C) {
model := s.Brands.Model("my-brand", "my-model", map[string]interface{}{
"display-name": "my model",
"architecture": "amd64",
"base": "core20",
"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": "optional20-a",
"id": s.AssertedSnapID("optional20-a"),
"presence": "optional",
"default-channel": "20",
},
},
})

// validity
c.Assert(model.Grade(), Equals, asserts.ModelSigned)

s.makeSnap(c, "snapd", "")
s.makeSnap(c, "core20", "")
s.makeSnap(c, "pc-kernel=20", "")
s.makeSnap(c, "pc=20", "")
s.makeSnap(c, "optional20-a", "developerid")

s.opts.Label = "20191122"
w, err := seedwriter.New(model, s.opts)
c.Assert(err, IsNil)

err = w.SetOptionsSnaps([]*seedwriter.OptionsSnap{{Name: "optional20-a", Channel: "20"}})
c.Assert(err, IsNil)

err = w.Start(s.db, s.rf)
c.Assert(err, IsNil)

snaps, err := w.SnapsToDownload()
c.Assert(err, IsNil)
c.Check(snaps, HasLen, 5)
c.Check(snaps[4].SnapName(), Equals, "optional20-a")
}

func (s *writerSuite) TestSnapsToDownloadCore20OptionalSnapsWithDifferentChannel(c *C) {
model := s.Brands.Model("my-brand", "my-model", map[string]interface{}{
"display-name": "my model",
"architecture": "amd64",
"base": "core20",
"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": "optional20-a",
"id": s.AssertedSnapID("optional20-a"),
"presence": "optional",
"default-channel": "20",
},
},
})

// validity
c.Assert(model.Grade(), Equals, asserts.ModelSigned)

s.makeSnap(c, "snapd", "")
s.makeSnap(c, "core20", "")
s.makeSnap(c, "pc-kernel=20", "")
s.makeSnap(c, "pc=20", "")
s.makeSnap(c, "optional20-a", "developerid")

s.opts.Label = "20191122"
w, err := seedwriter.New(model, s.opts)
c.Assert(err, IsNil)

err = w.SetOptionsSnaps([]*seedwriter.OptionsSnap{{Name: "optional20-a", Channel: "22"}})
c.Check(err, ErrorMatches, `cannot override channels, add devmode snaps, local snaps, or extra snaps with a model of grade higher than dangerous`)
}

func (s *writerSuite) TestSeedSnapsWriteMetaCore20ExtraSnaps(c *C) {
model := s.Brands.Model("my-brand", "my-model", map[string]interface{}{
"display-name": "my model",
Expand Down

0 comments on commit 633b7a2

Please sign in to comment.