-
Notifications
You must be signed in to change notification settings - Fork 18.7k
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
pkg/archive, pkg/tarsum: replace use of Xattrs with PAXRecords #46707
pkg/archive, pkg/tarsum: replace use of Xattrs with PAXRecords #46707
Conversation
The existing pkg/archive unit tests are primarily round-trip tests which assert that pkg/archive produces tarballs which pkg/archive can unpack. While these tests are effective at catching regressions in archiving or unarchiving, they have a blind spot for regressions in compatibility with the rest of the ecosystem. For example, a typo in the capabilities extended attribute constant would result in subtly broken image layer tarballs, but the existing tests would not catch the bug if both the archiving and unarchiving implementations have the same typo. Extend the test for archiving an overlay filesystem layer to assert that the overlayfs style whiteouts (extended attributes and device files) are transformed into AUFS-style whiteouts (magic file names). Extend the test for archiving files with extended attributes to assert that the extended attribute is encoded into the file's tar header in the standard, interoperable format compatible with the rest of the ecosystem. Signed-off-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
Fix a silly bug in the implementation which had the effect of len(h.Xattrs) blank entries being inserted in the middle of orderedHeaders. Luckily this is not a load-bearing bug: empty headers are ignored as the tarsum digest is computed by concatenating header keys and values without any intervening delimiter. Signed-off-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
Thanks for working on this! I recall I started working on this (just found an old branch where I started some bits thaJeztah@400be67), but wasn't sure what the best way was to verify compatibility, and looks like I never returned to continuing that 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.
LGTM
var xattrs [][2]string | ||
for k, v := range h.PAXRecords { | ||
if xattr, ok := strings.CutPrefix(k, paxSchilyXattr); ok { | ||
xattrs = append(xattrs, [2]string{xattr, v}) |
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.
Ah, smart to construct the key/value pair here instead of further down (I was looking here as to "what changed?" but now see this is to prevent the loop at line 134 👍
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.
Interesting; looks like BuildKit forked this code, and now I'm wondering if the implementation should be shared (the tarsum specification looks to be in this package);
moby/vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
Lines 38 to 76 in 452ca90
func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) { | |
pax := h.PAXRecords | |
if len(h.Xattrs) > 0 { //nolint:staticcheck // field deprecated in stdlib | |
if pax == nil { | |
pax = map[string]string{} | |
for k, v := range h.Xattrs { //nolint:staticcheck // field deprecated in stdlib | |
pax["SCHILY.xattr."+k] = v | |
} | |
} | |
} | |
// Get extended attributes. | |
xAttrKeys := make([]string, 0, len(h.PAXRecords)) | |
for k := range pax { | |
if strings.HasPrefix(k, "SCHILY.xattr.") { | |
k = strings.TrimPrefix(k, "SCHILY.xattr.") | |
if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") { | |
xAttrKeys = append(xAttrKeys, k) | |
} | |
} | |
} | |
sort.Strings(xAttrKeys) | |
// Make the slice with enough capacity to hold the 11 basic headers | |
// we want from the v0 selector plus however many xattrs we have. | |
orderedHeaders = make([][2]string, 0, 11+len(xAttrKeys)) | |
// Copy all headers from v0 excluding the 'mtime' header (the 5th element). | |
v0headers := v0TarHeaderSelect(h) | |
orderedHeaders = append(orderedHeaders, v0headers[0:5]...) | |
orderedHeaders = append(orderedHeaders, v0headers[6:]...) | |
// Finally, append the sorted xattrs. | |
for _, k := range xAttrKeys { | |
orderedHeaders = append(orderedHeaders, [2]string{k, h.PAXRecords["SCHILY.xattr."+k]}) | |
} | |
return | |
} |
@tonistiigi PTAL (also curious what we should do with the tarsum package; would it make sense to make it its own module (together with the specification?) |
Discussed this in the maintainers call, and current implementation looks good, but perhaps Cory will do a follow-up to merge instead of replace |
- What I did
Replaced use of Xattrs with PAXRecords.
- How I did it
Extended the pkg/archive unit tests to verify that these changes do not introduce any regressions in xattr handling. And I checked that the tests fail as expected when the handling of extended attributes is deliberately broken. (No changes to the pkg/tarsum tests were required.)
- How to verify it
CI is green.
- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)