-
Notifications
You must be signed in to change notification settings - Fork 804
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
Add --parents option for COPY in Containerfiles #6008
Conversation
@nalind PTAL |
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 convinced we need two fields in the AddAndCopyOptions
, and I'm not a fan of having fields which can be nil
which, when left unset, will trigger a crash.
add.go
Outdated
@@ -94,6 +94,9 @@ type AddAndCopyOptions struct { | |||
// RetryDelay is how long to wait before retrying attempts to retrieve | |||
// remote contents. | |||
RetryDelay time.Duration | |||
// Parents preserve parent directories of source content | |||
Parents bool | |||
ParentsPatterns map[string]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.
When would a caller set ParentsPatterns
, and what should they put in it if they do? What happens if they leave the field set to its zero value of nil
? They're already passing in a list of sources, why are they required to supply more than that to get the desired effect?
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 tried to explain what the content should be in the comment. If ParentsPatterns
is a nil
value, it will be ignored. The sources
list is cleaned up with filepath.Join
, which removes /./
from the path so it can't be used. Therefore, I decided to use a map to connect the source path and the path (pattern) with /./
.
*/ | ||
}, "\n"), | ||
contextDir: "copy-parents", | ||
fsSkip: []string{"(dir):parents:mtime", "(dir):parents:(dir):y:mtime"}, |
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.
Does docker build
preserve the timestamp on y
, or its permissions if they're something other than 0o755
?
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 have made a rework and the current version preserves the timestamp of the copied directory.
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 Docker preserves the y
timestamp.
copier/copier.go
Outdated
ChmodDirs *os.FileMode // set permissions on directories. no effect on archives being extracted | ||
ChownFiles *idtools.IDPair // set ownership of files. no effect on archives being extracted | ||
ChmodFiles *os.FileMode // set permissions on files. no effect on archives being extracted | ||
Parents bool // maintain the sources parent directory in the destination |
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.
Are the parent directories of the items being read supposed to be emitted in the tarstream when this flag is set?
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 have made a rework and the current version copies the parent directories to the tarstream.
8c6ca1f
to
638f410
Compare
a37d19e
to
c3349de
Compare
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 think this really needs some unit tests in the copier
package to ensure that it produces exactly the right set of outputs for a given set of inputs, with no parent directories being implicit or being output multiple times.
copier/copier.go
Outdated
|
||
name := filepath.Base(queue[i]) | ||
if len(req.GetOptions.ParentsPrefixToRemove) > 0 { | ||
name = filepath.Clean(strings.TrimPrefix(item, filepath.Join(req.Directory, req.GetOptions.ParentsPrefixToRemove))) |
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.
Between this and https://github.com/containers/buildah/pull/6008/files#diff-cc55d39a0428ec028a6aefb86560d0e304d9618cfcfd5ead0130af486db41f24R1363, which are undoing what https://github.com/containers/buildah/pull/6008/files#diff-f2e4566c6b7e38384283187aba6d7fd91e5ba8da2ffd0f849277bb76bff27fb3R561 does, I'm wondering if we even need the field in AddAndCopyOptions
to be a map instead of a Parents
boolean.
copier/copier.go
Outdated
alreadyCopied[parentPath] = struct{}{} | ||
parentName = filepath.Dir(parentName) | ||
parentPath = filepath.Dir(parentPath) | ||
} |
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.
Is the order in which these are being emitted such that directories are being output before their parents?
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.
Oh, Yes, they are. That's probably wrong.
cmd/buildah/addcopy.go
Outdated
if iopts.parents { | ||
options.ParentsPatterns = map[string]string{} | ||
for _, pattern := range args { | ||
options.ParentsPatterns[pattern] = pattern |
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 doesn't appear to be doing anything different when contextdir
is set, while https://github.com/containers/buildah/pull/6008/files#diff-f2e4566c6b7e38384283187aba6d7fd91e5ba8da2ffd0f849277bb76bff27fb3R561-R562 does. If it's required, I'd expect it to be required in both places, and it's something that the integration tests should be verifying works correctly.
copier/copier.go
Outdated
parentName = filepath.Dir(parentName) | ||
parentPath = filepath.Dir(parentPath) | ||
} | ||
return alreadyCopied, nil |
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 kind of implies that alreadyCopied
wasn't already modified in the caller's scope, but this function was passed the map itself rather than a copy, so returning it here isn't really necessary.
copier/copier.go
Outdated
@@ -1400,6 +1428,31 @@ func copierHandlerGet(bulkWriter io.Writer, req request, pm *fileutils.PatternMa | |||
return &response{Stat: statResponse.Stat, Get: getResponse{}}, cb, nil | |||
} | |||
|
|||
func copyParentsDirs(name string, path string, alreadyCopied map[string]struct{}, copy func(string, string, os.FileInfo) error) (map[string]struct{}, error) { |
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.
Does this avoid outputting a directory that has already been output while walking the tree?
164e737
to
d467554
Compare
@nalind I removed the use of |
e1d2e20
to
da2d4c7
Compare
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.
Mostly nits, except that Get()
really shouldn't be outputting a given item more than once.
/packit rebuild-failed |
One thing I often forget when manipulating the When an entry with When an entry with I think that's the last part of this we need to be sure we've considered and have tests for. |
2f69989
to
23a49a8
Compare
@nalind I added tests for hardlinks and symlinks. |
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 have special logic for handling pivot points ("/./" in source paths), and for handling hard links, so both the conformance test and integration test should also include cases where they both come into play.
The tests don't automatically enforce that items that are hard linked to each other remain hard links when they're copied together, so the tests will need to check that directly by comparing the results of running something like stat -c %i
against the items that are expected to be hard links. We already have tests that ensure links show up in a committed image if they're in the working container's rootfs, so if it's easier, it would be sufficient to check on that during a RUN instruction right after the COPY instruction.
It also includes an implementation of the --parents flag for the buildah copy command. Fixes: https://issues.redhat.com/browse/RUN-2193 Fixes: containers#5557 Signed-off-by: Jan Rodák <[email protected]>
@nalind Oh, I forgot about that. Thank you. I found the mistake. It should be fine now. |
/packit rebuild-failed |
LGTM |
if err := copierHandlerGetOne(parentInfo, "", parentName, parent, req.GetOptions, tw, hardlinkChecker, idMappings); err != nil { | ||
if req.GetOptions.IgnoreUnreadable && errorIsPermission(err) { | ||
continue | ||
} else if errors.Is(err, os.ErrNotExist) { |
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.
Nit: No need for else here.
if err != nil { | ||
continue | ||
return fmt.Errorf("copier: get: lstat %q: %w", parent, 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.
Nit: this is kind of a stutter. Since parent path will be mentioned twice in error message.
logrus.Warningf("copier: file disappeared while reading: %q", parent) | ||
return nil | ||
} | ||
return fmt.Errorf("copier: get: %q: %w", queue[i].glob, 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.
Stutter?
Great job @Honny1. A couple of nits, and potential stutters but I will merge |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Honny1, rhatdan The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@rhatdan Thanks you. |
What type of PR is this?
/kind feature
What this PR does / why we need it:
This PR adds the
--parents
option for COPY in Containerfiles. It also includes an implementation of the--parents
option for thebuildah copy
command.How to verify it
Try using
--parents
as described in the docker documentation.Which issue(s) this PR fixes:
Fixes: https://issues.redhat.com/browse/RUN-2193
Fixes: #5557
Special notes for your reviewer:
Does this PR introduce a user-facing change?