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: fix test cases to work with different DistroLibExecDir #3222
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just quick comments. I'll read more soon
cmd/cmd.go
Outdated
@@ -90,7 +91,7 @@ func ExecInCoreSnap() { | |||
// ensure we do not re-exec into an older version of snapd, look | |||
// for info file and ignore version of core that do not yet have | |||
// it | |||
fullInfo := filepath.Join(corePath, "/usr/lib/snapd/info") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, this feels wrong. If core path is the path where core is mounted the rest of the string can be a constant because it's not depending on the distribution anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into this again. However all tests except refresh-delta-from-core on Ubuntu 14.04 seem to pass. However for Fedora/SUSE/Arch/... this might fail. We really need CI for all of these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, this is not what I expected (the diff looked different before). So on Fedora the core path is /var/lib/snapd/snap/core/current/
but then the dirs.DistroLibExecDir
will contain /usr/libexec/snapd
, I don't understand how this is supposed to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zyga Please note that the code now uses dirs.CoreLibExecDir which will expand to /usr/lib/snapd even on Fedora. A previous version of the code was using dirs.DistroLibExecDir which is, as you pointed out, wrong.
In summary: The new code filepath.Join(corePath, dirs.CoreLibExecDir, "info")
will take the corePath
as determined before through /proc/self/exe
and append dirs.CoreLibExecDir so that we end up with /snap/core/current/usr/libexec/snapd/info
on Ubuntu and /var/lib/snapd/snap/core/current/usr/libexec/snapd/info
cmd/snap/cmd_run_test.go
Outdated
@@ -449,8 +450,8 @@ func (s *SnapSuite) TestSnapRunIsReexeced(c *check.C) { | |||
readlink string | |||
expected bool | |||
}{ | |||
{filepath.Join(dirs.SnapMountDir, "/usr/lib/snapd/snapd"), true}, | |||
{"/usr/lib/snapd/snapd", false}, | |||
{filepath.Join(dirs.SnapMountDir, dirs.DistroLibExecDir, "snapd"), true}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, isn't this constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now yes, but when we have switch to different core/base snaps it may not. Using dirs.CoreLibExecDir here now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using CoreLibExecDir
is fine. For core/base split I don't know how it will work yet so it's hard to say.
5f64f6c
to
417b113
Compare
cmd/cmd.go
Outdated
@@ -90,7 +91,7 @@ func ExecInCoreSnap() { | |||
// ensure we do not re-exec into an older version of snapd, look | |||
// for info file and ignore version of core that do not yet have | |||
// it | |||
fullInfo := filepath.Join(corePath, "/usr/lib/snapd/info") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct now.
cmd/snap/main_test.go
Outdated
func mockSnapConfine() func() { | ||
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine") | ||
if err := os.MkdirAll(dirs.DistroLibExecDir, 0755); err != nil { | ||
func mockSnapConfine(reexec bool) func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just nitpick. I'd prefer a flag like ReExecEnabled or something similar. The false/true that is in tests above is hard to grok just by looking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even simpler, pass libExecDir as a parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using libExecDir now.
cmd/snap/cmd_run.go
Outdated
@@ -228,7 +228,11 @@ func isReexeced() bool { | |||
} | |||
|
|||
func runSnapConfine(info *snap.Info, securityTag, snapApp, command, hook string, args []string) error { | |||
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine") | |||
libExecDir := dirs.DistroLibExecDir | |||
if isReexeced() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done only once in this function. Right now it's being done twice, and it's also bogus because code right below will test for a path that does not exist. Proper way is likely to bring the code currently at the bottom here, and make sure snapConfine points to the proper thing upfront.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked the logic a bit.
cmd/snap/main_test.go
Outdated
func mockSnapConfine() func() { | ||
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine") | ||
if err := os.MkdirAll(dirs.DistroLibExecDir, 0755); err != nil { | ||
func mockSnapConfine(reexec bool) func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even simpler, pass libExecDir as a parameter.
I'm confused... Why are so many things changing from DistroLibExecDir to CoreLibExecDir? That seems to indicate it'd be running/testing a completely different/wrong thing... |
@Conan-Kudo Many of the changes are for paths are in the code path for the re-execution feature which never worked on Fedora/Suse. So you never saw anything going wrong. This PR fixes those cases and brings us a bit closer to working re-execution too. |
Looks good, but some review comments (like #3222 (comment) are not addressed yet) |
417b113
to
8c30864
Compare
Fixed all review comments and rebased on latest master |
Some unit test failures, e.g. https://travis-ci.org/snapcore/snapd/builds/226369117#L2580 |
1d1612e
to
76d7ec3
Compare
@mvo5 Pushed a change to fix the failing unit tests. |
@@ -195,11 +199,11 @@ apps: | |||
|
|||
func (s *ContentSuite) TestResolveSpecialVariable(c *C) { | |||
info := snaptest.MockInfo(c, "name: name", &snap.SideInfo{Revision: snap.R(42)}) | |||
c.Check(builtin.ResolveSpecialVariable("foo", info), Equals, "/snap/name/42/foo") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking so long to verify this. This part is incorrect. The generated mount profile is only processed after pivot_root has happened so it must use the internal layout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How that? On Debian & Ubuntu we have /snap and on Fedora we have /var/lib/snapd/snap in and outside of the snap or do I miss anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are missing one thing. After pivot_root whatever the snap mount directory is it ends up being /snap. Only then do we process those mount directives so the hard-coded paths are actually always correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running the following
$ snap run --shell hello-world
bash-4.3$ echo $SNAP
/var/lib/snapd/snap/hello-world/27
Please also note that I didn't change builting.ResolveSpecialVariable. It is using dirs.BaseSnapMountDir already without this PR. See https://github.com/snapcore/snapd/blob/master/interfaces/builtin/content.go#L123
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on IRC there are a host of bugs here:
- snap execution environment should look the same everywhere
- $SNAP is always /snap/$SNAP_NAME/$SNAP_REVISION when seen from inside snap execution environment
- various other things are wrong but we'll discuss and fix them in separate PRs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is now changed to use /snap as static prefix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Silly question - if the code got changed to use /snap as static prefix, do we still need to change:
- "/snap/foo"
+ filepath.Join(dirs.CoreSnapMountDir, "foo")
I guess the answer is yes to make it more obvious when we mean "context-is-inside-core" and "context-is-outside"(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say, we should do it this way, With that we always have a clear bind to the context and know what we're dealing with.
tests/unit/go/task.yaml
Outdated
|
||
execute: | | ||
mkdir -p /tmp/unit-tests/src/github.com/snapcore | ||
cp -ar $PROJECT_PATH /tmp/unit-tests/src/github.com/snapcore | ||
chown -R test:12345 /tmp/unit-tests | ||
su -l -c "cd /tmp/unit-tests/src/github.com/snapcore/snapd && GOPATH=/tmp/unit-tests ./run-checks --unit" test | ||
|
||
mv /etc/os-release /etc/os-release.orig |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a prepare:
stage to me but the actual section looks curious. Is this intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and reworked the test case a bit more.
448507e
to
fe8cb4f
Compare
dirs/dirs.go
Outdated
@@ -126,9 +128,11 @@ func SetRootDir(rootdir string) { | |||
|
|||
switch release.ReleaseInfo.ID { | |||
case "fedora", "centos", "rhel", "arch": | |||
SnapMountDir = filepath.Join(rootdir, "/var/lib/snapd/snap") | |||
BaseSnapMountDir = "/var/lib/snapd/snap" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use the "BaseSnap" term here, even more when we have a matching variable with "CoreSnap". Base snaps are around the block and this is unrelated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HostSnapMountDir
would make more sense, ne?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HostSnapMountDir
still has a notion of not saying that it is absolute or not. BaseSnapMountDir
was my attempt to word that. What about RawSnapMountDir
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes it Raw, except other things raw are not Raw. Still pretty misleading and error prone. Not to mention "raw" doesn't really say much in this context.
See the suggestion in the other point.
dirs/dirs.go
Outdated
@@ -179,7 +183,8 @@ func SetRootDir(rootdir string) { | |||
DistroLibExecDir = filepath.Join(rootdir, "/usr/lib/snapd") | |||
} | |||
|
|||
CoreLibExecDir = filepath.Join(rootdir, "/usr/lib/snapd") | |||
CoreLibExecDir = "/usr/lib/snapd" | |||
CoreSnapMountDir = "/snap" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the line for deciding what has a prefix or not? Why do we have BaseSnapMountDir with rootdir, but the ones above not? Hard to guess on call sites, which makes it quite error prone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a variable which has just the clean mount dir without the root prefix as otherwise we end up with something $prefix/$prefix/$snapmountdir
in the unit tests. See https://github.com/snapcore/snapd/pull/3222/files#diff-76f691a17e89c1330742e51bb468ef76R203 as an example. The only place where it is ever being used are unit tests. I can move these variables into test code and keep it away from dirs/dirs.go but actually it would be nice to keep these things in a central place.
Also CoreLibExecDir/CoreSnapMountDir are needed as these describe where in the core snap those directories are located. These are different on Fedora than the outside SnapMountDir/LibExecDir so we have to keep them distinct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if a unit test tries to write to those Core* dirs missing the rootdir will creates errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unit test doesn't try to write into those dirs. They are used for example in the content interface where we check if the mount entries generated are ok. @zyga told me that those should never use SnapMountDir (which might be prefixed) but the mount dir without any prefix so /snap on Ubuntu and /var/lib/snapd/snap on Fedora.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest keeping the rootdir as originally, and stripping GlobalRootDir out of it when really needed. That makes it consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@niemeyer Doing that now. Please have another look.
9d17651
to
b22a99f
Compare
dirs/dirs.go
Outdated
// CoreLibExecDir is similar to CoreSnapMountDir but for the | ||
// LibExecDir used by snapd. | ||
CoreLibExecDir string | ||
DistroLibExecDir string | ||
SnapBlobDir string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we probably want a newline to separate things here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add one.
dc66df4
to
003c870
Compare
003c870
to
9b771dd
Compare
Codecov Report
@@ Coverage Diff @@
## master #3222 +/- ##
==========================================
- Coverage 77.16% 77.15% -0.01%
==========================================
Files 373 373
Lines 25793 25792 -1
==========================================
- Hits 19902 19900 -2
Misses 4134 4134
- Partials 1757 1758 +1
Continue to review full report at Codecov.
|
dirs/dirs.go
Outdated
SnapMountDir string | ||
|
||
// CoreSnapMountDir is the path of the snap mount dir inside | ||
// the snap confinement environment. Give this nature it will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given its nature
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My head hurts with all the new snap
variables everywhere. LGTM
dirs/dirs.go
Outdated
// These are directories which are static inside the core snap and | ||
// can never be prefixed as they will be always absolute once we | ||
// are in the snap confinement environment. | ||
CoreLibExecDir = "/usr/lib/snapd" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we const
those?
interfaces/builtin/content.go
Outdated
@@ -116,13 +117,23 @@ func (iface *contentInterface) path(slot *interfaces.Slot, name string) []string | |||
return out | |||
} | |||
|
|||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would feel better with a dedicated type.
interfaces/builtin/content.go
Outdated
const ( | ||
SnapMountDir = iota | ||
SnapDataDir | ||
SnapCommonDir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, are those even used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, they aren't. Seems to be a leftover. Good spot!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop these now.
@pedronis @zyga @Conan-Kudo @niemeyer Can you have another look so we get this reviewed and merged soon? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, some comments inline. I am in favour of merging even if imperfect and do a followup to ease the burden of fixing this branch, it has a lot of conflicts potential.
@@ -98,7 +98,7 @@ func (s *SnapSuite) TestSnapRunAppIntegration(c *check.C) { | |||
// mock installed snap | |||
dirs.SetRootDir(c.MkDir()) | |||
defer func() { dirs.SetRootDir("/") }() | |||
defer mockSnapConfine()() | |||
defer mockSnapConfine(dirs.DistroLibExecDir)() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pardon my ignorance, but it looks like the argument for mockSnapConfine()
is always dirs.DistroLibExecDir - do we really need this new argument in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is exactly one case where it isn't. See https://github.com/snapcore/snapd/pull/3222/files/f78d7918f26f71239000599fd11db988cd605cc0#diff-78f744cbc3eb83652f8ed773dceac016R466
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, silly me. I even found this in subsequent reading but then forgot to delete the comment. Sorry for the noise.
cmd/snap/cmd_run_test.go
Outdated
{filepath.Join(dirs.SnapMountDir, "/usr/lib/snapd/snapd"), true}, | ||
{"/usr/lib/snapd/snapd", false}, | ||
{filepath.Join(dirs.SnapMountDir, dirs.CoreLibExecDir, "snapd"), true}, | ||
{fmt.Sprintf("%s/snapd", dirs.DistroLibExecDir), false}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filepath.Join() is probably more natural here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -195,11 +199,11 @@ apps: | |||
|
|||
func (s *ContentSuite) TestResolveSpecialVariable(c *C) { | |||
info := snaptest.MockInfo(c, "name: name", &snap.SideInfo{Revision: snap.R(42)}) | |||
c.Check(builtin.ResolveSpecialVariable("foo", info), Equals, "/snap/name/42/foo") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Silly question - if the code got changed to use /snap as static prefix, do we still need to change:
- "/snap/foo"
+ filepath.Join(dirs.CoreSnapMountDir, "foo")
I guess the answer is yes to make it more obvious when we mean "context-is-inside-core" and "context-is-outside"(?)
@@ -2689,7 +2719,7 @@ version: 1.0`) | |||
{ | |||
// ensure only local install was run, i.e. first action is pseudo-action current | |||
op: "current", | |||
old: "/snap/mock/100001", | |||
old: filepath.Join(dirs.StripRootDir(dirs.SnapMountDir), "mock/100001"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels a bit repetitive and relatively long, I wonder if we could compute the dirs only once at the beginning of the test. OTOH it was repetitive before so maybe that is something for a later branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 (change + later branch)
@@ -4987,6 +5017,9 @@ func (s *snapmgrTestSuite) TestTrySetsTryModeJailMode(c *C) { | |||
s.testTrySetsTryMode(snapstate.Flags{JailMode: true}, c) | |||
} | |||
func (s *snapmgrTestSuite) TestTrySetsTryModeClassic(c *C) { | |||
if !dirs.SupportsClassicConfinement() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to move everything that needs classic confinement into a single snapmgrWithClassicConfinementTestSuite and simply skip the entire suite on the above condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, something I would have to look into but would prefer to do it with a follow up PR to not put more burden on this one.
@@ -5046,6 +5082,9 @@ func (s *snapmgrTestSuite) TestTryUndoRemovesTryFlagLeavesJailMode(c *C) { | |||
s.testTrySetsTryMode(snapstate.Flags{JailMode: true}, c) | |||
} | |||
func (s *snapmgrTestSuite) TestTryUndoRemovesTryFlagLeavesClassic(c *C) { | |||
if !dirs.SupportsClassicConfinement() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly strange that SupportsClassicConfinement()
is a member of dirs
- I understand why but still feels wrong. Anyway, not something to be concerned about for this branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM assuming it drops the function mentioned below.
snap/info.go
Outdated
} | ||
|
||
// MountDirWithBasePath returns the base directory where it gets mounted of the snap with the given name and revision. | ||
func MountDirWithBasePath(basePath, name string, revision Revision) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's please drop this function. We don't need a special (and long) name for filepath.Join. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
1f78b74
to
999789f
Compare
This is needed to allow execution of our unit tests within the package build on other distributions like Fedora.