Skip to content

Commit

Permalink
Merge pull request #4844 from bboozzoo/bboozzoo/system-config
Browse files Browse the repository at this point in the history
overlord/snapstate: allow core defaults configuration via 'system' key
  • Loading branch information
bboozzoo authored May 15, 2018
2 parents 7d95441 + 97b5857 commit 86c958c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 8 deletions.
24 changes: 20 additions & 4 deletions overlord/configstate/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,29 @@ type configureHandlerSuite struct {
var _ = Suite(&configureHandlerSuite{})

func (s *configureHandlerSuite) SetUpTest(c *C) {
dirs.SetRootDir(c.MkDir())

s.state = state.New(nil)
s.state.Lock()
defer s.state.Unlock()

coreSnapYaml := `name: core
version: 1.0
type: os
`
snaptest.MockSnap(c, coreSnapYaml, &snap.SideInfo{
RealName: "core",
Revision: snap.R(1),
})
snapstate.Set(s.state, "core", &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{
{RealName: "core", Revision: snap.R(1), SnapID: "core-snap-id"},
},
Current: snap.R(1),
SnapType: "os",
})

s.restore = snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})

task := s.state.NewTask("test-task", "my test task")
Expand All @@ -67,6 +86,7 @@ func (s *configureHandlerSuite) SetUpTest(c *C) {

func (s *configureHandlerSuite) TearDownTest(c *C) {
s.restore()
dirs.SetRootDir("/")
}

func (s *configureHandlerSuite) TestBeforeInitializesTransaction(c *C) {
Expand All @@ -91,8 +111,6 @@ func (s *configureHandlerSuite) TestBeforeInitializesTransaction(c *C) {
func (s *configureHandlerSuite) TestBeforeInitializesTransactionUseDefaults(c *C) {
r := release.MockOnClassic(false)
defer r()
dirs.SetRootDir(c.MkDir())
defer dirs.SetRootDir("/")

const mockGadgetSnapYaml = `
name: canonical-pc
Expand Down Expand Up @@ -162,8 +180,6 @@ hooks:
func (s *configureHandlerSuite) TestBeforeUseDefaultsMissingHook(c *C) {
r := release.MockOnClassic(false)
defer r()
dirs.SetRootDir(c.MkDir())
defer dirs.SetRootDir("/")

const mockGadgetSnapYaml = `
name: canonical-pc
Expand Down
26 changes: 24 additions & 2 deletions overlord/snapstate/snapstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,9 @@ func CoreInfo(st *state.State) (*snap.Info, error) {
return nil, fmt.Errorf("unexpected number of cores, got %d", len(res))
}

// ConfigDefaults returns the configuration defaults for the snap specified in the gadget. If gadget is absent or the snap has no snap-id it returns ErrNoState.
// ConfigDefaults returns the configuration defaults for the snap specified in
// the gadget. If gadget is absent or the snap has no snap-id it returns
// ErrNoState.
func ConfigDefaults(st *state.State, snapName string) (map[string]interface{}, error) {
gadget, err := GadgetInfo(st)
if err != nil {
Expand All @@ -1856,8 +1858,17 @@ func ConfigDefaults(st *state.State, snapName string) (map[string]interface{}, e
return nil, err
}

core, err := CoreInfo(st)
if err != nil {
return nil, err
}
isCoreDefaults := core.Name() == snapName

si := snapst.CurrentSideInfo()
if si.SnapID == "" {
// core snaps can be addressed even without a snap-id via the special
// "system" value in the config; first-boot always configures the core
// snap with UseConfigDefaults
if si.SnapID == "" && !isCoreDefaults {
return nil, state.ErrNoState
}

Expand All @@ -1866,6 +1877,17 @@ func ConfigDefaults(st *state.State, snapName string) (map[string]interface{}, e
return nil, err
}

// we support setting core defaults via "system"
if isCoreDefaults {
if defaults, ok := gadgetInfo.Defaults["system"]; ok {
if _, ok := gadgetInfo.Defaults[si.SnapID]; ok && si.SnapID != "" {
logger.Noticef("core snap configuration defaults found under both 'system' key and core-snap-id, preferring 'system'")
}

return defaults, nil
}
}

defaults, ok := gadgetInfo.Defaults[si.SnapID]
if !ok {
return nil, state.ErrNoState
Expand Down
66 changes: 64 additions & 2 deletions overlord/snapstate/snapstate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -7568,15 +7569,16 @@ volumes:
bootloader: grub
`

func (s *snapmgrTestSuite) prepareGadget(c *C) {
func (s *snapmgrTestSuite) prepareGadget(c *C, extraGadgetYaml ...string) {
gadgetSideInfo := &snap.SideInfo{RealName: "the-gadget", SnapID: "the-gadget-id", Revision: snap.R(1)}
gadgetInfo := snaptest.MockSnap(c, `
name: the-gadget
type: gadget
version: 1.0
`, gadgetSideInfo)

err := ioutil.WriteFile(filepath.Join(gadgetInfo.MountDir(), "meta/gadget.yaml"), []byte(gadgetYaml), 0600)
gadgetYamlWhole := strings.Join(append([]string{gadgetYaml}, extraGadgetYaml...), "")
err := ioutil.WriteFile(filepath.Join(gadgetInfo.MountDir(), "meta/gadget.yaml"), []byte(gadgetYamlWhole), 0600)
c.Assert(err, IsNil)

snapstate.Set(s.state, "the-gadget", &snapstate.SnapState{
Expand Down Expand Up @@ -7607,6 +7609,7 @@ func (s *snapmgrTestSuite) TestConfigDefaults(c *C) {
Current: snap.R(11),
SnapType: "app",
})
makeInstalledMockCoreSnap(c)

defls, err := snapstate.ConfigDefaults(s.state, "some-snap")
c.Assert(err, IsNil)
Expand All @@ -7624,6 +7627,65 @@ func (s *snapmgrTestSuite) TestConfigDefaults(c *C) {
c.Assert(err, Equals, state.ErrNoState)
}

func (s *snapmgrTestSuite) TestConfigDefaultsSystem(c *C) {
r := release.MockOnClassic(false)
defer r()

// using MockSnapReadInfo, we want to read the bits on disk
snapstate.MockSnapReadInfo(snap.ReadInfo)

s.state.Lock()
defer s.state.Unlock()

s.prepareGadget(c, `
defaults:
system:
foo: bar
`)

makeInstalledMockCoreSnap(c)

defls, err := snapstate.ConfigDefaults(s.state, "core")
c.Assert(err, IsNil)
c.Assert(defls, DeepEquals, map[string]interface{}{"foo": "bar"})
}

func (s *snapmgrTestSuite) TestConfigDefaultsSystemConflictsCoreSnapId(c *C) {
r := release.MockOnClassic(false)
defer r()

// using MockSnapReadInfo, we want to read the bits on disk
snapstate.MockSnapReadInfo(snap.ReadInfo)

s.state.Lock()
defer s.state.Unlock()

s.prepareGadget(c, `
defaults:
system:
foo: bar
the-core-snap:
foo: other-bar
other-key: other-key-default
`)

snapstate.Set(s.state, "core", &snapstate.SnapState{
Active: true,
Sequence: []*snap.SideInfo{
{RealName: "core", SnapID: "the-core-snap", Revision: snap.R(1)},
},
Current: snap.R(1),
SnapType: "os",
})

makeInstalledMockCoreSnap(c)

// 'system' key defaults take precedence over snap-id ones
defls, err := snapstate.ConfigDefaults(s.state, "core")
c.Assert(err, IsNil)
c.Assert(defls, DeepEquals, map[string]interface{}{"foo": "bar"})
}

func (s *snapmgrTestSuite) TestGadgetDefaultsAreNormalizedForConfigHook(c *C) {
var mockGadgetSnapYaml = `
name: canonical-pc
Expand Down
14 changes: 14 additions & 0 deletions tests/main/ubuntu-core-gadget-config-defaults/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ prepare: |
${TEST_SNAP_ID}:
a: A
b: B
system:
service:
rsyslog:
disable: true
EOF
mksquashfs squashfs-root pc_x1.snap -comp xz -no-fragments
rm -rf squashfs-root
Expand All @@ -47,6 +51,11 @@ restore: |
echo "This test needs test keys to be trusted"
exit
fi
echo "Undo the rsyslog disable"
systemctl unmask rsyslog.service || true
systemctl enable rsyslog.service || true
systemctl start rsyslog.service || true
. $TESTSLIB/systemd.sh
systemctl stop snapd.service snapd.socket
rm -rf /var/lib/snapd/assertions/*
Expand Down Expand Up @@ -100,3 +109,8 @@ execute: |
echo "The configuration defaults from the gadget where applied"
snap get test-snapd-with-configure a|MATCH "^A$"
snap get test-snapd-with-configure b|MATCH "^B$"
echo "The configuration for core is applied"
snap get core service.rsyslog.disable|MATCH true
echo "And the service is masked"
systemctl status rsyslog.service|MATCH masked

0 comments on commit 86c958c

Please sign in to comment.