-
Notifications
You must be signed in to change notification settings - Fork 618
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
Rewrite cp #3323
base: main
Are you sure you want to change the base?
Rewrite cp #3323
Conversation
f1662be
to
a486b0a
Compare
options.SrcPath, | ||
options.GOptions.Snapshotter, | ||
options.FollowSymLink) | ||
options) |
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.
Simplifying signature
5ff18ff
to
7d17a10
Compare
err = errors.Join(errors.New("unable to retrieve containers with error"), err) | ||
} else { | ||
err = fmt.Errorf("no container found for: %s", options.ContainerReq) | ||
} |
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.
Make sure we report the right error message to the user.
if err := os.MkdirAll(dstFull, 0o755); err != nil { | ||
return err | ||
|
||
// XXX FIXME: this seems wrong. What about ownership? We could be doing that inside a container |
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 am not touching this right now.
This is previous code.
Am I mis-reading this, or is this a problem when doing that in a container target? (eg: shouldn't we do that as part of the nsenter/re-exec routine?)
resp, err := client.SnapshotService(snapshotter).Mounts(ctx, snapKey) | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
|
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 know you don't like these Akihiro, but would you reconsider? It does make code much easier to read for these old eyes here :-)
pkg/containerutil/cp_resolve.go
Outdated
@@ -0,0 +1,436 @@ | |||
/* |
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 is the gist of it, that provides (proper) symlink and path resolution.
@@ -0,0 +1,24 @@ | |||
/* |
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 one day we support this on Windows - we will need the win version of volumeNameLen
// FIXME: the following will break the test (anything that will evaluate on the shell, obviously): | ||
// - ` | ||
// - $a, ${a}, etc | ||
complexify = "" // = "-~a0-_.(){}[]*#! \"'∞" |
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.
Useful to stress test rig when modifying it. Deactivated by default as it makes things much harder to read.
CI is green. PTAL at your convenience. |
Rebased. |
Obviously, the move to sub-packages is further exposing problems in our tests (chiefly because the parallel pool is greatly reduced - split in 15 buckets - which significantly increase the risk of a negative interaction, and the chance of cross package leftovers (15x)). The introduction of a lot more / longer cp tests with this PR is likely tripping unrelated tests - and there seem to be something wrong with encrypt tests (starting with the fact that they are pruning), and even for the docker compat suite (with prune again). That doesn't change things for this PR fundamentally, as the problem is not the code in here (which is very limited in its impact) - but obviously I'll send a couple of other PRs first to fix some of our tests issues so this here gets green. |
Pending #3402 |
Reverting to draft until I figure out what's going on with testing. |
Will wait for new tooling framework to land to update tests and get some clarity on what's going on. |
As soon as #3492 is in, will rewrite tests with the new framework and get this in shape. |
a5aab67
to
f10b13a
Compare
ecf3af5
to
5c04821
Compare
@djdongjin I paused this (and other feature / refactor work) 3 months ago because the CI failed randomly, as testing became unmanageable at that point, and I embarked on the new test framework and tests clean-up overall instead. Rebasing this on top of all of that then, CI is now green. I will do another final proof-read of this PR before turning it to "ready for review" - but otherwise, I am still interested in getting this in as it will fix a number of issues with cp, so, would love your updated thoughts on this if/when you have bandwidth for that. |
@@ -115,16 +115,16 @@ func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptio | |||
} | |||
|
|||
container2host := srcSpec.Container != nil | |||
var container string | |||
var containerReq 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.
Do not shadow package name.
pkg/cmd/container/cp_linux.go
Outdated
err = errors.Join(errors.New("unable to copy"), err) | ||
} else if count == 0 { | ||
if err != nil { | ||
err = errors.Join(errors.New("unable to retrieve containers with error"), err) |
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.
same behavior you should panic if err != nil
with count == 0
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.
Reading into this now. Thanks.
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 don't think we should panic here.
if err != nil { | ||
return nil, errors.Join(errCannotResolvePathNoCwd, err) | ||
} | ||
path = cwd + string(os.PathSeparator) + path |
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(cwd, path)
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 do not fully remember the detailed reason of why in that case, but I am pretty sure it would not work. filepath.Join will clean the path, which we do not want in that 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.
Re-reading. We absolutely do not want filepath.Join here. That would defeat the whole purpose of resolving the final path properly.
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 will "clean" the path (eg: reduce relative path). The whole problem and point here is to perform proper resolution instead.
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.
IMO, we should reflect this intention in a comment.
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.
It is a common misunderstanding about lexical functions - they should not be used before resolving symlinks.
isn't safer to resolve the symlink before and then work with cleaned path ?
I am not completely sure what you mean - but here, the path may be relative, so in that case we do need to start resolving against cwd.
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 see that you evaluate the symlink at this line https://github.com/containerd/nerdctl/pull/3323/files#diff-f8d3022dbe81c88660be3b5c26107695a00ef30d103f67558a218780e5da1dbaR81 so may be resolving the relative path just after it ?
We need to account for the fact that the path may not exist - which is handled a few lines below.
Again not completely sure what you mean here, but see previous comment ^ - we need to handle relative path cases (which is the reason we resolve links against cwd + path).
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.
@fahedouch @djdongjin I wish this could be simpler.
Fact is, handling path resolution properly for files that may not exist (yet) is not a problem as simple as "let's lexical path join".
Case in point: docker config path resolution is hosed as well #3413 - and in their case, it is a much simpler problem.
There is some (moderately) useful reading over here, on the topic: https://9p.io/sys/doc/lexnames.html
So, point is: I am not interested in forcing anything here.
We all have better things to do.
If you folks are not comfortable with this PR, I would just accept that and close it.
This is fine. Not everything is meant to end-up accepted.
Anyhow, let me know your thoughts.
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.
Hi @apostasie, I will take another look when I get some time.
So, point is: I am not interested in forcing anything here.
We all have better things to do.
If you folks are not comfortable with this PR, I would just accept that and close it.
I don't think folks imply you're forcing anything or not comfortable with your change. I think mostly it's because people (including me) may be slow at responding recently due to holidays approaching.
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.
All fine @djdongjin
I want(ed) to make sure that people feel comfortable with a “no”
I am a simple and straightforward person 😁
Enjoy the holiday folks!
Signed-off-by: apostasie <[email protected]>
Signed-off-by: apostasie <[email protected]>
Rebased. Comments answered or addressed with latest push.
|
The motivation for this is to address all issues (and variants not listed as individual tickets) in:
--read-only
, and lets tar fail through in some cases #3315The fundamental problem with our current implementation of cp is that the logic to figure out if a destination is read-only is incomplete.
One of the key reason for it is that we do not follow symlinks, or relative paths, inside a container destination. For example, if we are copying to a path located into a readonly volume, we stop there, while the path may very well resolve to a completely different volume (or the rootfs).
Furthermore, there are other logic issues involving readonly rootfs, leading to situations where we DO copy while we should not, and conversely, where we do NOT copy while we should.
There is a also a fair amount of duplication, and finally, test isolation was problematic.
For this PR, the highlights are, for the testing part:
For the code part:
Also note this is superseding #3275
I appreciate this is a somewhat sizable PR (although a very large part of it (about 1500 lines) are just for tests).
If there is a different (simpler) approach to this problem - that would pass the test-suite - I am happy to re-evaluate of course.