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: install components from the store #14092

Merged

Conversation

andrewphelpsj
Copy link
Member

This PR enables us to install components and a snap from the store at the same time. Note that installing components from the store for an already installed snap is not yet handled yet, as that interaction with the store is more complex, requiring the usage of both channel and revision.

First relevant commit is 97dad45, based on #14070.

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.

Some comments, see below.

Is it possible to have with these changes now a spread test using the store?

// if we are removing the snap, we can assume that we should remove
// the component too
RemoveComponentPath: snapsup.RemoveSnapPath,
SkipSecurity: true,

Choose a reason for hiding this comment

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

But we need the security profiles for component hooks generated, when is that happening? We need to know the hooks shipped in the component for that, is that considered? In any case, a comment regarding this here would be good to have.

Copy link
Member Author

Choose a reason for hiding this comment

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

The setup-profiles task that is created for the snap handles generating those profiles here: https://github.com/snapcore/snapd/blob/master/overlord/ifacestate/handlers.go?plain=1#L184. I'll add comment.

@@ -3901,7 +3934,7 @@ func RevertToRevision(st *state.State, name string, rev snap.Revision, flags Fla
PlugsOnly: len(info.Slots) == 0,
InstanceKey: snapst.InstanceKey,
}
return doInstall(st, &snapst, snapsup, 0, fromChange, nil)
return doInstall(st, &snapst, *snapsup, nil, 0, fromChange, nil)

Choose a reason for hiding this comment

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

Should this have a TODO as we will need components here as well?

@@ -2087,7 +2120,7 @@ func doUpdate(ctx context.Context, st *state.State, names []string, updates []mi

// Do not set any default restart boundaries, we do it when we have access to all
// the task-sets in preparation for single-reboot.
ts, err := doInstall(st, snapst, snapsup, noRestartBoundaries, fromChange, inUseFor(deviceCtx))
ts, err := doInstall(st, snapst, *snapsup, nil, noRestartBoundaries, fromChange, inUseFor(deviceCtx))

Choose a reason for hiding this comment

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

Should this have a TODO as we will need components here as well?

info *snap.ComponentInfo
}

func (c *componentTarget) compsup() ComponentSetup {

Choose a reason for hiding this comment

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

Why do you need to construct this instead of returning c.setup? Cannot it be fully filled in componentFromResource?

Copy link
Member Author

@andrewphelpsj andrewphelpsj Jun 18, 2024

Choose a reason for hiding this comment

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

It is shared here since there will be another implementation of UpdateGoal (the file one) which will also return a target.

Choose a reason for hiding this comment

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

But I do not see any mention to UpdateGoal in this PR (or am I missing something?), maybe it will become clear in the next PR, but atm I find this a bit confusing, maybe this part of the change could go in next one?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, I meant InstallGoal. Too many PRs in my head 🙂. I can move this to the next PR, which includes an InstallGoal implementation that installs from local files.

info: &snap.ComponentInfo{
Component: compName,
Type: comp.Type,
Version: sar.Version,

Choose a reason for hiding this comment

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

Should we sanity chech the version?

Copy link
Member Author

Choose a reason for hiding this comment

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

snap.Component doesn't carry a Version, is there something else you were thinking to compare it to?

Choose a reason for hiding this comment

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

It would need to be read from component.yaml, I guess we can skip. Not sure though if what we put in store.SnapActionResult is checked against snap.yaml or not.

@andrewphelpsj
Copy link
Member Author

@alfonsosanchezbeato as for the spread test, not yet without implementing some of the CLI aspects changes. Would you like that as a part of this PR?

@alfonsosanchezbeato
Copy link
Member

alfonsosanchezbeato commented Jun 18, 2024

@alfonsosanchezbeato as for the spread test, not yet without implementing some of the CLI aspects changes. Would you like that as a part of this PR?

Nope, we can do it in a follow-up, maybe as you say when we have api/cli changes.

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.

did a pass, some comments/questions, some might be for the store

overlord/snapstate/component.go Outdated Show resolved Hide resolved
overlord/snapstate/handlers_components.go Outdated Show resolved Hide resolved
@@ -438,7 +438,7 @@ func (s *snapmgrTestSuite) TestParallelInstanceRemoveRunThrough(c *C) {
{
op: "remove-snap-data-dir",
name: "some-snap_instance",
path: filepath.Join(dirs.SnapDataDir, "some-snap"),
path: filepath.Join(dirs.SnapDataDir, "some-snap_instance"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

why this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

It lines up with this change here: https://github.com/snapcore/snapd/pull/14092/files#r1647912200.

It doesn't have to happen, but I noticed that it was inconsistent when writing the new tests here.

overlord/snapstate/target.go Outdated Show resolved Hide resolved
func installActionForStoreTarget(t StoreSnap, opts Options, enforcedSets func() (*snapasserts.ValidationSets, error)) (*store.SnapAction, error) {
action := &store.SnapAction{
Action: "install",
InstanceName: t.InstanceName,
Channel: t.RevOpts.Channel,
Revision: t.RevOpts.Revision,
CohortKey: t.RevOpts.CohortKey,
Resources: t.Components,
Copy link
Collaborator

Choose a reason for hiding this comment

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

what's the reason we need to pass this along? for metrics?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is ultimately used to indicate in the store package that we should request resource info from the store. It could (and maybe should?) be a boolean value. It is a bit weird, since the option is a per-request toggle (just a query param), but right here I have it expressed as a per-action concept. But the StoreService.SnapAction API doesn't have any sort of flags right now.

overlord/snapstate/target.go Outdated Show resolved Hide resolved
@@ -1372,7 +1405,7 @@ func (f *fakeSnappyBackend) RemoveSnapDir(s snap.PlaceInfo, otherInstances bool)
f.appendOp(&fakeOp{
op: "remove-snap-dir",
name: s.InstanceName(),
path: snap.BaseDir(s.SnapName()),
path: snap.BaseDir(s.InstanceName()),
Copy link
Member Author

Choose a reason for hiding this comment

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

This change here I think is better representative of what actually happens in RemoveSnapDataDir (the real implementation).

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.

thanks for the changes, one question

prev = linkSnap

for _, t := range tasksAfterLinkSnap {
addTask(t)
Copy link
Collaborator

Choose a reason for hiding this comment

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

does this match where we specced after link hooks for components should run vs snap own hooks?

Copy link
Member Author

Choose a reason for hiding this comment

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

The component hook tasks aren't created yet. Should I add a TODO here for once #13775 gets merged?

Choose a reason for hiding this comment

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

As discussed, we are not adding hook tasks yet in doInstallComponent(), but that will eventually happen. In any case, if componentTasksForInstallWithSnap() keeps the tasks order things should be fine, maybe for the moment we could just add a comment there commenting that order needs to be kept.

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, couple of minor comments

return ComponentSetup{}, fmt.Errorf("inconsistent component type (%q in snap, %q in component)", typ, sar.Type)
}

compName := naming.NewComponentRef(info.SnapName(), name)

Choose a reason for hiding this comment

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

nitpick: maybe cref, there are too many *name variables here

prev = linkSnap

for _, t := range tasksAfterLinkSnap {
addTask(t)

Choose a reason for hiding this comment

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

As discussed, we are not adding hook tasks yet in doInstallComponent(), but that will eventually happen. In any case, if componentTasksForInstallWithSnap() keeps the tasks order things should be fine, maybe for the moment we could just add a comment there commenting that order needs to be kept.

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.

thanks

@alfonsosanchezbeato alfonsosanchezbeato merged commit 411ac6c into canonical:master Jun 26, 2024
45 of 51 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