Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

o/snapstate: properly handle components when refreshing to revision that has been on the system before #14498

Conversation

andrewphelpsj
Copy link
Member

This change properly handles components when refreshing to a snap revision that has already been on the system.

When doing something like: snap refresh --revision=n snapname, where n has already been installed on the system, we were previously just switching back to the components that were installed with that revision. This is more of a revert than a refresh.

To properly handle this, we should consider which components are currently installed, and remove any that are not available for the revision n, and check with the store for the most up-to-date revisions of components.

@andrewphelpsj
Copy link
Member Author

I forgot a commit here, will open again shortly.

@andrewphelpsj andrewphelpsj force-pushed the recheck-comp-revision-when-refreshing branch from 3118cf4 to a655bf5 Compare September 12, 2024 17:18
@andrewphelpsj andrewphelpsj marked this pull request as ready for review September 12, 2024 17:19
@andrewphelpsj andrewphelpsj force-pushed the recheck-comp-revision-when-refreshing branch 4 times, most recently from 8e7d528 to 0bfd630 Compare September 13, 2024 16:05
@andrewphelpsj andrewphelpsj force-pushed the recheck-comp-revision-when-refreshing branch 3 times, most recently from e1bab5e to 5a3180e Compare September 16, 2024 12:50
@andrewphelpsj andrewphelpsj force-pushed the recheck-comp-revision-when-refreshing branch from 5a3180e to 93b98c2 Compare September 16, 2024 13:19
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by the change in snapstate.go

@@ -13796,10 +13796,10 @@ func (s *snapmgrTestSuite) TestUpdateStateConflictRemoved(c *C) {

func (s *snapmgrTestSuite) TestUpdateWithComponentsBackToPrevRevision(c *C) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we have kept both a version with and without components of this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add the old version back if you like, but this is really just additive, the functionality of the original test is still there.

//
// This is mostly relevant when we're moving from one snap revision to another
// snap revision that has already been installed on the system. The target snap
// might have components that are installed that we don't want any more.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused by this comment, aren't the component linked to a given snap revision, why would we remove components when switch around by revision?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they are linked by snap revision. Consider this case:

snap revision 1, components a, b
snap revision 2, components b, c

When we move from snap revision 2 -> 1, we need to unlink component a (and discard it, if nothing else references it) and install component c.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused about the comment too, should "target snap might have components that are installed that we don't want any more" be "target revision might have components that were installed in the past but that we don't want any more"? Or maybe state more clearly that this is about checking a revision that was active in the past and still around but not currently. I always find misleading when we talk about installed revisions for non-active but present revisions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean, I'll update it to be explicit when I'm talking about something that was installed in the past.

@andrewphelpsj
Copy link
Member Author

Here is the set of tasks generated by the new test:

task prerequisites (1)
task prepare-snap (2)
task unlink-component (3), unlink "snap-with-components+test-component-extra" for snap revision 7, the target snap revision
task unlink-component (5), unlink "snap-with-components+test-component-present-in-sequence" for snap revision 7, the target snap revision
task download-component (6)
task validate-component (7)
task mount-component (8)
task run-hook (9), pre-refresh hook of "snap-with-components_key+kernel-modules-component"
task download-component (12)
task validate-component (13)
task mount-component (14)
task run-hook (15), pre-refresh hook of "snap-with-components_key+test-component"
task run-hook (18), pre-refresh hook of "snap-with-components_key"
task stop-snap-services (19)
task remove-aliases (20)
task unlink-current-snap (21)
task copy-snap-data (22)
task setup-profiles (23)
task link-snap (24)
task link-component (10)
task link-component (16)
task auto-connect (25)
task set-auto-aliases (26)
task setup-aliases (27)
task run-hook (28), post-refresh hook of "snap-with-components_key"
task run-hook (11), post-refresh hook of "snap-with-components_key+kernel-modules-component"
task run-hook (17), post-refresh hook of "snap-with-components_key+test-component"
task prepare-kernel-modules-components (29)
task start-snap-services (30)
task discard-component (4), discard "snap-with-components+test-component-extra" since it is not referenced by sequence
task cleanup (31)
task run-hook (32), configure hook of "snap-with-components_key"
task run-hook (33), health check of "snap-with-components_key"
task check-rerefresh (34)

…ponents

This test ensures that we don't hit the store when we have no components
to check on.
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of worries/questions

func installComponentAction(st *state.State, snapst SnapState, snapRev snap.Revision, channel string, opts Options) (*store.SnapAction, error) {
var si *snap.SideInfo
if snapRev.Unset() {
si = snapst.CurrentSideInfo()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmh, test don't seem to hit this case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code, we can't reach that case. Removed.

i18n.G("Unlink component %q for snap revision %s"), ci.Component, snapsup.Revision(),
))

unlink.Set("snap-setup", snapsup)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this confuse findSnapSetupTask ? that's one example but I fear we might have a few bits of logic that assume there is mainly one task in a snap lane with snap-setup attached to it vs id?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've change this in 6014886.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know why I didn't do that in the first place.

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you

@pedronis pedronis added this to the 2.66 milestone Sep 18, 2024
Copy link
Member

@alfonsosanchezbeato alfonsosanchezbeato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just some nitpicks about comments

//
// This is mostly relevant when we're moving from one snap revision to another
// snap revision that has already been installed on the system. The target snap
// might have components that are installed that we don't want any more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused about the comment too, should "target snap might have components that are installed that we don't want any more" be "target revision might have components that were installed in the past but that we don't want any more"? Or maybe state more clearly that this is about checking a revision that was active in the past and still around but not currently. I always find misleading when we talk about installed revisions for non-active but present revisions.


// note that we don't need to worry about kernel module components here,
// since the components that we are removing are not associated with the
// currently installed snap revision. unlink-component differs from

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here it says "currently installed", which contradicts how "install" is used in the function description

@@ -14127,8 +14475,8 @@ type updateWithComponentsOpts struct {
}

func componentNameToType(c *C, name string) snap.ComponentType {
typ := strings.TrimSuffix(name, "-component")
if typ == name {
typ, _, ok := strings.Cut(name, "-component")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking, but this is not doing the same as TrimSuffix (not that I expect a component to be called xx-componentblah-component, but still...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it this way because I wanted to be able to add some components like "test-component-extra", the difference was intentional.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see, sounds good

@andrewphelpsj andrewphelpsj merged commit 112e58d into canonical:master Sep 20, 2024
58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants