Skip to content

Commit 0f59a94

Browse files
committed
overlord: accept a SeedRefreshCandidate to check if both snaps and components can be removed
1 parent c037630 commit 0f59a94

9 files changed

Lines changed: 32 additions & 55 deletions

File tree

overlord/devicestate/devicestate.go

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ func delayedCrossMgrInit() {
298298
snapstate.SeedRefreshTasks = SeedRefreshTasks
299299
snapstate.UpdateSeedRefreshChange = UpdateSeedRefreshChange
300300
snapstate.CheckSeedRefreshRemove = CheckSeedRefreshRemove
301-
snapstate.CheckComponentSeedRefreshRemove = CheckComponentSeedRefreshRemove
302301
}
303302

304303
// proxyStore returns the store assertion for the proxy store if one is set.
@@ -1862,40 +1861,21 @@ func appendSeedRefreshCandidate(create *state.Task, snapSetupTasks []string, com
18621861
return setTaskRecoverySystemSetup(create, setup)
18631862
}
18641863

1865-
// CheckSeedRefreshRemove prevents removing optional snaps that are still
1866-
// present in the current seed while seed-refresh is enabled.
1864+
// CheckSeedRefreshRemove prevents removing optional snaps and components that
1865+
// are still present in the current seed while seed-refresh is enabled.
18671866
//
18681867
// TODO:SEEDREFRESH: remove this once we support seed-refresh seeds
18691868
// gaining/losing snaps
1870-
func CheckSeedRefreshRemove(st *state.State, si *snap.Info, dctx snapstate.DeviceContext) error {
1869+
func CheckSeedRefreshRemove(st *state.State, candidate snapstate.SeedRefreshCandidate, dctx snapstate.DeviceContext) error {
18711870
filter := seedRefreshFilter(st, dctx)
1872-
_, seedRefreshTriggered, err := filter(snapstate.SeedRefreshCandidate{
1873-
InstanceName: si.SnapName(),
1874-
})
1875-
if err != nil {
1876-
return err
1877-
}
1871+
_, seedRefreshTriggered, err := filter(candidate)
18781872

1879-
if seedRefreshTriggered {
1880-
return errors.New("cannot remove snap present in the current seed while seed-refresh is enabled")
1881-
}
1882-
return nil
1883-
}
1884-
1885-
// CheckComponentSeedRefreshRemove is set by devicestate to prevent removal of
1886-
// components that must remain present for seed-refresh.
1887-
var CheckComponentSeedRefreshRemove = func(st *state.State, si *snap.Info, componentName string, dctx snapstate.DeviceContext) error {
1888-
filter := seedRefreshFilter(st, dctx)
1889-
_, seedRefreshTriggered, err := filter(snapstate.SeedRefreshCandidate{
1890-
InstanceName: si.SnapName(),
1891-
ComponentSetupTaskIDs: map[string]string{componentName: ""},
1892-
})
18931873
if err != nil {
18941874
return err
18951875
}
18961876

18971877
if seedRefreshTriggered {
1898-
return errors.New("cannot remove component present in the current seed while seed-refresh is enabled")
1878+
return errors.New("cannot remove snap present in the current seed while seed-refresh is enabled")
18991879
}
19001880
return nil
19011881
}

overlord/devicestate/devicestate_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,9 +2855,10 @@ func (s *deviceMgrSuite) TestCheckSeedRefreshRemoveBlocksOptionalSnapInCurrentSe
28552855
{"name": "pc", "type": "gadget", "default-channel": "24"},
28562856
{"name": "snap-2", "presence": "optional"},
28572857
}, nil, "snap-2")
2858-
info := snaptest.MockInfo(c, "name: snap-2\nversion: 1", nil)
2859-
2860-
err := devicestate.CheckSeedRefreshRemove(s.state, info, dctx)
2858+
candidate := snapstate.SeedRefreshCandidate{
2859+
InstanceName: "snap-2",
2860+
}
2861+
err := devicestate.CheckSeedRefreshRemove(s.state, candidate, dctx)
28612862
c.Assert(err, ErrorMatches, `cannot remove snap present in the current seed while seed-refresh is enabled`)
28622863
}
28632864

@@ -2872,9 +2873,10 @@ func (s *deviceMgrSuite) TestCheckSeedRefreshRemoveAllowsOptionalSnapNotInCurren
28722873
{"name": "pc", "type": "gadget", "default-channel": "24"},
28732874
{"name": "snap-2", "presence": "optional"},
28742875
}, nil)
2875-
info := snaptest.MockInfo(c, "name: snap-2\nversion: 1", nil)
2876-
2877-
err := devicestate.CheckSeedRefreshRemove(s.state, info, dctx)
2876+
candidate := snapstate.SeedRefreshCandidate{
2877+
InstanceName: "snap-2",
2878+
}
2879+
err := devicestate.CheckSeedRefreshRemove(s.state, candidate, dctx)
28782880
c.Assert(err, IsNil)
28792881
}
28802882

overlord/snapstate/component.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,16 @@ func canRemoveComponent(st *state.State, compst *sequence.ComponentState, info *
827827
return err
828828
}
829829
if seedRefresh {
830-
if err := CheckComponentSeedRefreshRemove(st, info, compst.SideInfo.Component.ComponentName, deviceCtx); err != nil {
830+
// Construct a component exclusive candidate with the component
831+
// to test if the component would trigger a seed refresh.
832+
// The task id is not involved in the filtering when checking
833+
// if a component triggers a seed, so it is fine to leave
834+
// the value in the ComponentSetupTaskIDs field empty.
835+
candidate := SeedRefreshCandidate{
836+
InstanceName: info.InstanceName(),
837+
ComponentSetupTaskIDs: map[string]string{compst.SideInfo.Component.ComponentName: ""},
838+
}
839+
if err := CheckSeedRefreshRemove(st, candidate, deviceCtx); err != nil {
831840
return err
832841
}
833842
}

overlord/snapstate/component_remove_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,8 @@ func (s *snapmgrTestSuite) TestRemoveComponentInSeedRefresh(c *C) {
480480
c.Assert(tr.Set("core", "experimental.seed-refresh", true), IsNil)
481481
tr.Commit()
482482

483-
s.AddCleanup(snapstate.MockCheckComponentSeedRefreshRemove(func(st *state.State,
484-
si *snap.Info, componentName string, dctx snapstate.DeviceContext) error {
483+
s.AddCleanup(snapstate.MockCheckSeedRefreshRemove(func(*state.State,
484+
snapstate.SeedRefreshCandidate, snapstate.DeviceContext) error {
485485
return fmt.Errorf("blocked by seed refresh")
486486
}))
487487

overlord/snapstate/export_test.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,6 @@ func MockReadComponentInfo(mock func(compMntDir string, snapInfo *snap.Info, csi
8080
return func() { readComponentInfoAt = old }
8181
}
8282

83-
func MockCheckComponentSeedRefreshRemove(mock func(st *state.State, si *snap.Info, componentName string, dctx DeviceContext) error) (restore func()) {
84-
old := CheckComponentSeedRefreshRemove
85-
CheckComponentSeedRefreshRemove = mock
86-
return func() {
87-
CheckComponentSeedRefreshRemove = old
88-
}
89-
}
90-
9183
func MockMountPollInterval(intv time.Duration) (restore func()) {
9284
old := mountPollInterval
9385
mountPollInterval = intv
@@ -439,7 +431,7 @@ func MockRefreshAppsCheck(fn func(info *snap.Info) error) (restore func()) {
439431
return func() { refreshAppsCheck = old }
440432
}
441433

442-
func MockCheckSeedRefreshRemove(fn func(st *state.State, si *snap.Info, dctx DeviceContext) error) (restore func()) {
434+
func MockCheckSeedRefreshRemove(fn func(st *state.State, candidate SeedRefreshCandidate, dctx DeviceContext) error) (restore func()) {
443435
r := testutil.Backup(&CheckSeedRefreshRemove)
444436
CheckSeedRefreshRemove = fn
445437
return r

overlord/snapstate/seed.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626
"github.com/snapcore/snapd/features"
2727
"github.com/snapcore/snapd/overlord/configstate/config"
2828
"github.com/snapcore/snapd/overlord/state"
29-
"github.com/snapcore/snapd/snap"
3029
)
3130

3231
// SeedRefreshTaskSet carries the tasks needed to perform a seed refresh.
@@ -76,16 +75,10 @@ var UpdateSeedRefreshChange = func(chg *state.Change, dctx DeviceContext, candid
7675
//
7776
// TODO:SEEDREFRESH: remove this hook once seed-refresh supports seeds
7877
// gaining/losing snaps
79-
var CheckSeedRefreshRemove = func(st *state.State, si *snap.Info, dctx DeviceContext) error {
78+
var CheckSeedRefreshRemove = func(st *state.State, candidate SeedRefreshCandidate, dctx DeviceContext) error {
8079
panic("internal error: snapstate.CheckSeedRefreshRemove is unset")
8180
}
8281

83-
// CheckComponentSeedRefreshRemove is set by devicestate to prevent removal of
84-
// components that must remain present for seed-refresh.
85-
var CheckComponentSeedRefreshRemove = func(st *state.State, si *snap.Info, componentName string, dctx DeviceContext) error {
86-
panic("internal error: snapstate.CheckComponentSeedRefreshRemove is unset")
87-
}
88-
8982
func seedRefreshCandidateForTaskSet(ts *state.TaskSet) (SeedRefreshCandidate, error) {
9083
t, err := ts.Edge(SnapSetupEdge)
9184
if err != nil {

overlord/snapstate/snapstate.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,8 @@ func canRemove(st *state.State, si *snap.Info, snapst *SnapState, removeAll bool
30943094
return err
30953095
}
30963096
if seedRefresh && removeAll {
3097-
if err := CheckSeedRefreshRemove(st, si, deviceCtx); err != nil {
3097+
candidate := SeedRefreshCandidate{InstanceName: si.InstanceName()}
3098+
if err := CheckSeedRefreshRemove(st, candidate, deviceCtx); err != nil {
30983099
return err
30993100
}
31003101
}

overlord/snapstate/snapstate_remove_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,7 @@ func (s *snapmgrTestSuite) TestRemoveConsultsSeedRefreshRemoveHookOnlyWhenEnable
13611361
})
13621362

13631363
called := false
1364-
restore := snapstate.MockCheckSeedRefreshRemove(func(*state.State, *snap.Info, snapstate.DeviceContext) error {
1364+
restore := snapstate.MockCheckSeedRefreshRemove(func(*state.State, snapstate.SeedRefreshCandidate, snapstate.DeviceContext) error {
13651365
called = true
13661366
return errors.New("blocked by test hook")
13671367
})
@@ -1405,7 +1405,7 @@ func (s *snapmgrTestSuite) TestRemoveSpecificRevisionDoesNotConsultSeedRefreshRe
14051405
tr.Commit()
14061406

14071407
called := false
1408-
restore := snapstate.MockCheckSeedRefreshRemove(func(*state.State, *snap.Info, snapstate.DeviceContext) error {
1408+
restore := snapstate.MockCheckSeedRefreshRemove(func(*state.State, snapstate.SeedRefreshCandidate, snapstate.DeviceContext) error {
14091409
called = true
14101410
return errors.New("blocked by test hook")
14111411
})

overlord/snapstate/snapstate_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (s *snapmgrBaseTest) SetUpTest(c *C) {
303303
snapstate.SetupRemoveHook = hookstate.SetupRemoveHook
304304
snapstate.SnapServiceOptions = servicestate.SnapServiceOptions
305305
snapstate.EnsureSnapAbsentFromQuotaGroup = servicestate.EnsureSnapAbsentFromQuota
306-
s.AddCleanup(snapstate.MockCheckSeedRefreshRemove(func(*state.State, *snap.Info, snapstate.DeviceContext) error { return nil }))
306+
s.AddCleanup(snapstate.MockCheckSeedRefreshRemove(func(*state.State, snapstate.SeedRefreshCandidate, snapstate.DeviceContext) error { return nil }))
307307
_, restore := mockSeedRefreshHooks(nil)
308308
s.AddCleanup(restore)
309309

0 commit comments

Comments
 (0)