Skip to content

Commit

Permalink
o/devicestate/firstboot20_test.go: add dangerous seeding test with de…
Browse files Browse the repository at this point in the history
…vmode snap

This tests that with a grade dangerous model, we can seed devmode snaps and that
they are seeded with DevMode confinement activated.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
  • Loading branch information
anonymouse64 committed Dec 15, 2020
1 parent 453f461 commit a32324e
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 5 deletions.
99 changes: 94 additions & 5 deletions overlord/devicestate/firstboot20_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package devicestate_test
import (
"os"
"path/filepath"
"strings"
"time"

. "gopkg.in/check.v1"
Expand All @@ -38,6 +39,7 @@ import (
"github.com/snapcore/snapd/overlord/state"
"github.com/snapcore/snapd/seed/seedtest"
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/strutil"
"github.com/snapcore/snapd/systemd"
"github.com/snapcore/snapd/testutil"
)
Expand Down Expand Up @@ -76,7 +78,7 @@ func (s *firstBoot20Suite) SetUpTest(c *C) {
s.AddCleanup(ifacestate.MockSnapMapper(&ifacestate.CoreSnapdSystemMapper{}))
}

func (s *firstBoot20Suite) setupCore20Seed(c *C, sysLabel string, modelGrade asserts.ModelGrade) *asserts.Model {
func (s *firstBoot20Suite) setupCore20Seed(c *C, sysLabel string, modelGrade asserts.ModelGrade, extraDevModeSnaps ...string) *asserts.Model {
gadgetYaml := `
volumes:
volume-id:
Expand Down Expand Up @@ -104,8 +106,11 @@ volumes:
makeSnap("pc-kernel=20")
makeSnap("core20")
makeSnap("pc=20")
for _, sn := range extraDevModeSnaps {
makeSnap(sn)
}

return s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{
model := map[string]interface{}{
"display-name": "my model",
"architecture": "amd64",
"base": "core20",
Expand Down Expand Up @@ -134,9 +139,71 @@ volumes:
"type": "base",
},
},
}, nil)
}

for _, sn := range extraDevModeSnaps {
name, channel := splitSnapNameWithChannels(sn)
model["snaps"] = append(model["snaps"].([]interface{}), map[string]interface{}{
"name": name,
"type": "app",
"id": s.AssertedSnapID(name),
"default-channel": channel,
})
}

return s.MakeSeed(c, sysLabel, "my-brand", "my-model", model, nil)
}

func splitSnapNameWithChannels(sn string) (name, channel string) {
nameParts := strings.SplitN(sn, "=", 2)
name = nameParts[0]
channel = ""
if len(nameParts) == 2 {
channel = nameParts[1]
}
return name, channel
}

func stripSnapNamesWithChannels(snaps []string) []string {
names := []string{}
for _, sn := range snaps {
name, _ := splitSnapNameWithChannels(sn)
names = append(names, name)
}
return names
}

func checkSnapstateDevModeFlags(c *C, tsAll []*state.TaskSet, snapsWithDevModeFlag ...string) {
allDevModeSnaps := stripSnapNamesWithChannels(snapsWithDevModeFlag)

// XXX: mostly same code from checkOrder helper in firstboot_test.go, maybe
// combine someday?
matched := 0
var prevTask *state.Task
for i, ts := range tsAll {
task0 := ts.Tasks()[0]
waitTasks := task0.WaitTasks()
if i == 0 {
c.Check(waitTasks, HasLen, 0)
} else {
c.Check(waitTasks, testutil.Contains, prevTask)
}
prevTask = task0
if task0.Kind() != "prerequisites" {
continue
}
snapsup, err := snapstate.TaskSnapSetup(task0)
c.Assert(err, IsNil, Commentf("%#v", task0))
if strutil.ListContains(allDevModeSnaps, snapsup.InstanceName()) {
c.Assert(snapsup.DevMode, Equals, true)
matched++
} else {
// it should not have DevMode true
c.Assert(snapsup.DevMode, Equals, false)
}
}
c.Check(matched, Equals, len(snapsWithDevModeFlag))
}

func (s *firstBoot20Suite) testPopulateFromSeedCore20Happy(c *C, m *boot.Modeenv, modelGrade asserts.ModelGrade, extraDevModeSnaps ...string) {
c.Assert(m, NotNil, Commentf("missing modeenv test data"))
Expand All @@ -155,7 +222,7 @@ func (s *firstBoot20Suite) testPopulateFromSeedCore20Happy(c *C, m *boot.Modeenv
defer systemctlRestorer()

sysLabel := m.RecoverySystem
model := s.setupCore20Seed(c, sysLabel, modelGrade)
model := s.setupCore20Seed(c, sysLabel, modelGrade, extraDevModeSnaps...)
// sanity check that our returned model has the expected grade
c.Assert(model.Grade(), Equals, modelGrade)

Expand Down Expand Up @@ -183,7 +250,20 @@ func (s *firstBoot20Suite) testPopulateFromSeedCore20Happy(c *C, m *boot.Modeenv
tsAll, err := devicestate.PopulateStateFromSeedImpl(st, &opts, s.perfTimings)
c.Assert(err, IsNil)

checkOrder(c, tsAll, "snapd", "pc-kernel", "core20", "pc")
snaps := []string{"snapd", "pc-kernel", "core20", "pc"}
allDevModeSnaps := stripSnapNamesWithChannels(extraDevModeSnaps)
if len(extraDevModeSnaps) != 0 {
snaps = append(snaps, allDevModeSnaps...)
}
checkOrder(c, tsAll, snaps...)

// if the model is dangerous check that all snaps in the model have the flag
// set
// XXX: eventually we may need more complicated checks here and for
// non-dangerous models only specific snaps may have this flag set
if modelGrade == asserts.ModelDangerous {
checkSnapstateDevModeFlags(c, tsAll, allDevModeSnaps...)
}

// now run the change and check the result
// use the expected kind otherwise settle with start another one
Expand Down Expand Up @@ -326,6 +406,15 @@ func (s *firstBoot20Suite) testPopulateFromSeedCore20Happy(c *C, m *boot.Modeenv
}
}

func (s *firstBoot20Suite) TestPopulateFromSeedCore20RunModeDangerousWithDevmode(c *C) {
m := boot.Modeenv{
Mode: "run",
RecoverySystem: "20191018",
Base: "core20_1.snap",
}
s.testPopulateFromSeedCore20Happy(c, &m, asserts.ModelDangerous, "test-devmode=20")
}

func (s *firstBoot20Suite) TestPopulateFromSeedCore20RunMode(c *C) {
m := boot.Modeenv{
Mode: "run",
Expand Down
6 changes: 6 additions & 0 deletions seed/seedtest/sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ version: 1.0
"arm-kernel=20": `name: arm-kernel
type: kernel
version: 1.0
`,
"test-devmode=20": `name: test-devmode
type: app
base: core20
version: 1.0
confinement: devmode
`,
}

Expand Down

0 comments on commit a32324e

Please sign in to comment.