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

many: modify snap run to understand component hooks #13976

Merged
merged 25 commits into from
Jun 26, 2024

Conversation

andrewphelpsj
Copy link
Member

@andrewphelpsj andrewphelpsj commented May 17, 2024

This PR enables the "snap run" command to run component hooks. It modifies the meaning of the "--hook" parameter a bit to allow snapd to run component hooks like so:

snap run --hook install snapname+compname

@github-actions github-actions bot added the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label May 17, 2024
@andrewphelpsj andrewphelpsj force-pushed the component-snap-run branch 3 times, most recently from b06f281 to 0523065 Compare May 23, 2024 16:24
@andrewphelpsj andrewphelpsj force-pushed the component-snap-run branch 2 times, most recently from 85f919d to 6878d5b Compare June 11, 2024 18:17
@github-actions github-actions bot removed the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Jun 11, 2024
@codecov-commenter
Copy link

Codecov Report

Attention: Patch coverage is 78.61915% with 96 lines in your changes missing coverage. Please review.

Project coverage is 78.71%. Comparing base (ab996a0) to head (4e1002a).
Report is 336 commits behind head on master.

Files Patch % Lines
interfaces/repo.go 50.00% 10 Missing and 6 partials ⚠️
snap/snaptest/snaptest.go 0.00% 15 Missing ⚠️
cmd/snap/cmd_run.go 85.56% 9 Missing and 5 partials ⚠️
interfaces/ifacetest/app_set.go 58.82% 12 Missing and 2 partials ⚠️
overlord/hookstate/hooks.go 7.69% 12 Missing ⚠️
snap/info.go 75.67% 6 Missing and 3 partials ⚠️
interfaces/connection.go 89.74% 2 Missing and 2 partials ⚠️
cmd/snap-exec/main.go 90.62% 2 Missing and 1 partial ⚠️
interfaces/snap_app_set.go 91.66% 2 Missing and 1 partial ⚠️
overlord/hookstate/hookmgr.go 86.36% 2 Missing and 1 partial ⚠️
... and 3 more

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #13976      +/-   ##
==========================================
- Coverage   78.86%   78.71%   -0.15%     
==========================================
  Files        1043     1050       +7     
  Lines      134595   137490    +2895     
==========================================
+ Hits       106144   108232    +2088     
- Misses      21837    22476     +639     
- Partials     6614     6782     +168     
Flag Coverage Δ
unittests 78.71% <78.61%> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@andrewphelpsj andrewphelpsj force-pushed the component-snap-run branch 2 times, most recently from fe158d1 to 02b71cf Compare June 14, 2024 16:44
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 first pass, bunch of questions


// TODO: fix this annoying import cycle issue
container := func(p string) (snap.Container, error) {
return snapdir.New(p), nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

you can use a hook from snapdir into snap I suppose to fix 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.

Addressed in 1e559b9, first timing adding one of those, so might be wrong.

snap/info.go Outdated

revision, err := ParseRevision(rev)
if err != nil {
return nil, fmt.Errorf("cannot read revision %s: %s", rev, err)
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/read/parse/ ? also this error message doesn't seem to contain a lot of context

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed in 4b1b48a.

snap/snaptest/snaptest.go Outdated Show resolved Hide resolved
Comment on lines 1155 to 1159
if hook != nil {
snapName, _ = snap.SplitSnapComponentInstanceName(snapTarget)
} else {
snapName, _ = snap.SplitSnapApp(snapTarget)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand the if here ? do we need to make the difference if snap.SplitSnapComponentInstanceName works in all cases?

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 think this was handled better by the refactor in the following commit.

snapConfine, err := snapdHelperPath("snap-confine")
if err != nil {
return err
}
if !osutil.FileExists(snapConfine) {
if hook != nil {
logger.Noticef("WARNING: skipping running hook %q of snap %q: missing snap-confine", hook.Name, info.InstanceName())
if runner.Hook() != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

have a IsHook predicate as well instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added in bfc4a0d.

}

return execApp(snapApp, revision, opts.Command, extraArgs)
return execApp(snapName, revision, opts.Command, extraArgs)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would have expected snapTarget here?? missing tests or am I confused?

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed in 79aad91. I moved the parsing of the target into the execHook and execApp functions themselves, to hopefully make things a bit easier to read.

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.

Couple of comments below

snap/info.go Outdated
@@ -1585,6 +1585,32 @@ func ReadCurrentInfo(snapName string) (*Info, error) {
return ReadInfo(snapName, &SideInfo{Revision: revision})
}

func ReadCurrentComponentInfo(component string, info *Info, container func(string) (Container, error)) (*ComponentInfo, error) {
link := filepath.Join(ComponentsBaseDir(info.InstanceName()), info.Revision.String(), component)

Choose a reason for hiding this comment

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

This could use snap.ComponentLinkPath() now that #14060 has been merged.

Copy link
Member Author

Choose a reason for hiding this comment

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

That function takes a ContainerPlaceInfo, which will be a componentPlaceInfo. That type's constructor expects a revision, which we don't have here.

snap.ComponentLinkPath() could just take a the component's name, which is the only thing that is used here:

func ComponentLinkPath(cpi ContainerPlaceInfo, snapRev Revision) string {
	instanceName, compName, _ := strings.Cut(cpi.ContainerName(), "+")
	compBase := ComponentsBaseDir(instanceName)
	return filepath.Join(compBase, snapRev.String(), compName)
}

You fine with me making that change, so that I can use the function here?

Choose a reason for hiding this comment

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

Sure, that is fine

Comment on lines 613 to 616
// TODO: we need to figure out how to get the component revision to set
// the environment variables that we provide to the hook
componentRevision := snap.Revision{}
_ = componentRevision

Choose a reason for hiding this comment

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

Maybe we need a --comprev argument as we are using -r for the snap revision for hooks, and use it in runHookAndWait. Not sure though why we do that instead of reading the snap information as in the non-hook case, probably @pedronis knows.

Copy link
Collaborator

Choose a reason for hiding this comment

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

there was the idea to run hooks for the non-current revisions but I'm not sure it can work in practice. maybe we should revisit 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.

Sorry, this TODO is old and I forgot to remove it. We are able to get the revision of the component ever since the change that @alfonsosanchezbeato made with the component symlinks. Although yes, I'm not sure what to do with running component hooks for revisions of a component that is not the current one. I'm not sure how that would work? What is the use case for that?

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, some questions

Comment on lines 613 to 616
// TODO: we need to figure out how to get the component revision to set
// the environment variables that we provide to the hook
componentRevision := snap.Revision{}
_ = componentRevision
Copy link
Collaborator

Choose a reason for hiding this comment

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

there was the idea to run hooks for the non-current revisions but I'm not sure it can work in practice. maybe we should revisit this

snap/info.go Outdated Show resolved Hide resolved
cmd/snap-exec/main.go Outdated Show resolved Hide resolved
cmd/snap/cmd_run.go Outdated Show resolved Hide resolved
@github-actions github-actions bot added the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Jun 20, 2024
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, couple small comments

func ComponentLinkPath(cpi ContainerPlaceInfo, snapRev Revision) string {
instanceName, compName, _ := strings.Cut(cpi.ContainerName(), "+")
func ComponentLinkPath(cref naming.ComponentRef, snapRev Revision) string {
instanceName, compName, _ := strings.Cut(cref.String(), "+")
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need the Cut? we could use cref.SnapName and cref.ComponentName, no?

Copy link
Member Author

Choose a reason for hiding this comment

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

Whoops, that was part of the motivation for 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.

Actually, I'm realizing now that this change might be wrong. I believe naming.ComponentRef shouldn't ever carry a snap's instance name, just the regular name? @alfonsosanchezbeato is that correct?

Choose a reason for hiding this comment

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

That's correct, it should carry the snap name, not the instance name in principle.

@@ -211,3 +211,11 @@ func (s *SnapDir) ListDir(path string) ([]string, error) {
func (s *SnapDir) Unpack(src, dstDir string) error {
return fmt.Errorf("unpack is not supported with snaps of type snapdir")
}

func NewContainerFromDir(path string) snap.Container {
Copy link
Collaborator

Choose a reason for hiding this comment

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

probably want a doc comment on this

@github-actions github-actions bot removed the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Jun 21, 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, thanks for the 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.

thanks, some small comments and a nitpick

snap/info.go Outdated
// able to set the revision of the component. we create it so that we can
// use ComponentLinkPath, which doesn't use the revision.
cpi := MinimalComponentContainerPlaceInfo(component, Revision{}, info.InstanceName())

Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick: I would leave this blank line

link := filepath.Join(ComponentsBaseDir(info.InstanceName()), info.Revision.String(), component)
// NOTE: creating this here is a bit of a hack, since we aren't actually
// able to set the revision of the component. we create it so that we can
// use ComponentLinkPath, which doesn't use the revision.
Copy link
Collaborator

Choose a reason for hiding this comment

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

does the ComponentLinkPath doc mention is not consuming the revision?

snap/info.go Outdated
@@ -1594,7 +1594,12 @@ var NewContainerFromDir func(snapName string) Container = func(snapName string)
// ReadCurrentComponentInfo reads the ComponentInfo for the currently linked
// revision of the given component associated with the given snap.
func ReadCurrentComponentInfo(component string, info *Info) (*ComponentInfo, error) {
link := filepath.Join(ComponentsBaseDir(info.InstanceName()), info.Revision.String(), component)
// NOTE: creating this here is a bit of a hack, since we aren't actually
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/NOTE/TODO, when we have a bit more time or other use cases we should reconsider this

…urrent revision of a component for a snap revision
…resent snap hooks, component hooks, and apps

This commit doesn't need to be here, and things will work without it.
But things were getting a bit complicated in runSnapConfine with
arguments that represented different things based on what we were
running.
…onentInstallDate param with naming.ComponentRef"

This reverts commit ca39dc1.
@alfonsosanchezbeato alfonsosanchezbeato merged commit 90c2e4c into canonical:master Jun 26, 2024
44 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.

4 participants