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

OCI layout extensions #2633

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

vrothberg
Copy link
Member

@vrothberg vrothberg commented Nov 14, 2024

Taken over from #2567 but:

  • Added tests for the three commits
  • Use reflinks when adding a file

@vrothberg
Copy link
Member Author

In draft for now.

oci/layout/oci_dest.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Just a quick skim; I’m afraid I didn’t read the added tests yet.

oci/layout/oci_dest.go Outdated Show resolved Hide resolved
oci/layout/oci_dest.go Outdated Show resolved Hide resolved
oci/layout/oci_dest.go Outdated Show resolved Hide resolved
@vrothberg vrothberg force-pushed the layout-list branch 3 times, most recently from ae7457e to 234b45f Compare November 19, 2024 09:41
@vrothberg
Copy link
Member Author

I'd love to have some explicit test condition on Linux to make sure that the reflinking works. We're using the function from c/storage which is e2e tested. The unit tests run on tmp, so we have to create the test dirs in $HOME ... not sure we should though.

@vrothberg vrothberg marked this pull request as ready for review November 19, 2024 12:11
Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Actual detailed review still pending, I’m afraid.

oci/layout/oci_dest.go Outdated Show resolved Hide resolved
oci/layout/oci_dest.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

A full review now.

docs/containers-transports.5.md Outdated Show resolved Hide resolved
oci/layout/oci_dest_test.go Outdated Show resolved Hide resolved
oci/layout/oci_transport.go Outdated Show resolved Hide resolved
@@ -148,11 +148,17 @@ func testParseReference(t *testing.T, fn func(string) (types.ImageReference, err
"relativepath",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Holding the line at “all of *_transport.go should have test coverage”, please port the two test cases added to TestGetManifestDescriptor from #1677 (and then see if more need to be added).

Copy link
Member Author

Choose a reason for hiding this comment

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

Isn't that already being tested now with fixtures/two_images_manifest ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Tooling says that case ref.image != "" && ref.sourceIndex != -1: and case ref.sourceIndex != -1: is not covered by tests.

oci/layout/oci_transport_test.go Show resolved Hide resolved
oci/layout/reader.go Outdated Show resolved Hide resolved
oci/layout/reader_test.go Outdated Show resolved Hide resolved
oci/layout/reader_test.go Outdated Show resolved Hide resolved
require.Equal(t, test.names[i], ociRef.image)
if test.names[i] != "" {
require.True(t, strings.HasSuffix(res.Reference.StringWithinTransport(), test.names[i]))
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

else test that res.Reference is a sourceIndex reference with the right index?

Or, alternatively, use the returned reference to read a manifest and verify that it matches res.ManifestDescriptor.Digest.

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 we are doing that above, aren't we?

Copy link
Collaborator

@mtrmac mtrmac Dec 23, 2024

Choose a reason for hiding this comment

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

The test above verifies that res.ManifestDescriptor is valid, not that res.Reference is usable.

In particular, changing the index = manifestIndex line in reader.go to index = manifestIndex * 0, or … + 1, currently doesn’t fail tests.

oci/layout/oci_dest.go Outdated Show resolved Hide resolved
@mtrmac
Copy link
Collaborator

mtrmac commented Dec 3, 2024

I'd love to have some explicit test condition on Linux to make sure that the reflinking works.

The unit tests run on tmp, so we have to create the test dirs in $HOME ... not sure we should though.

Tests writing to non-test directories , and possibly leaving them around on aborts/failures, seems rather unexpected to me, some might consider it (or, at least, be worried that it is) hostile. So I’d prefer to leave this to e2e tests, maybe the future tests of the Podman artifact CLI.

(Just because I was looking it up, Google says reflinks don’t work on ext4. That’s not really a blocker, we could gate this behind a filesystem type check.)

vrothberg added a commit to vrothberg/libpod that referenced this pull request Dec 10, 2024
Vendor containers/image/pull/2633 and update the code so we can start
testing it.

Signed-off-by: Valentin Rothberg <[email protected]>
Images in the index can now be referenced via the @sourceIndex syntax.

Signed-off-by: Miloslav Trmač <[email protected]>
Signed-off-by: Valentin Rothberg <[email protected]>
The new API allows for listing all manifests in an OCI layout's index.

Signed-off-by: Miloslav Trmač <[email protected]>
Signed-off-by: Valentin Rothberg <[email protected]>
Try to reflink the file and restort to copying it in case of failure.
Also add an Options struct to be future proof.

Signed-off-by: Miloslav Trmač <[email protected]>
Signed-off-by: Valentin Rothberg <[email protected]>
#include <linux/fs.h>

#ifndef FICLONE
#define FICLONE _IOW(0x94, 9, int)
Copy link
Collaborator

Choose a reason for hiding this comment

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

x/sys/unix.FICLONE exists; if that works, we can avoid the CGo dependency.

oci/layout/oci_dest.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Thanks! ACK overall.

Ideally, I’d prefer sharing the reflink call with c/storage, but the logic (usage of c/storage/pkg/pools requires c/storage to explicitly special-case CopyFileRange, which is otherwise automatic) is just different enough to make that awkward, and anyway it’s ~10 lines, so not worth worrying about.

"io"
"os"

"golang.org/x/sys/unix"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please run go mod tidy to mark the package as a direct dependency.

blobFile.Close()
explicitClosed = true

*closed = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Nit: Move this one line above, please, to keep it immediately next to the actual .Close().)

@@ -300,6 +314,63 @@ func (d *ociImageDestination) CommitWithOptions(ctx context.Context, options pri
return os.WriteFile(d.ref.indexPath(), indexJSON, 0644)
}

// PutBlobFromLocalFileOptions is unused but may receive functionality in the future.
type PutBlobFromLocalFileOptions struct{}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
type PutBlobFromLocalFileOptions struct{}
type PutBlobFromLocalFileOption struct{}

please, multiple options can be independent items at the call site.

defer srcFile.Close()

// reflink.Copy will io.Copy() in case reflinking fails
err = reflink.Copy(srcFile, blobFile)
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Absolutely non-blocking, this is internal-only anyway, and it works just fine as is: Maybe the function could be named explicitly enough to make the comment unnecessary, something like ReflinkOrCopy. OTOH some linters gripe about reflink.Reflink….)

return "", -1, err
}

_, err = blobFile.Seek(0, 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
_, err = blobFile.Seek(0, 0)
_, err = blobFile.Seek(0, io.SeekStart)

please

defer func() {
if !blobFileClosed {
blobFile.Close()
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

blobFile remains on the filesystem on failure; I think this needs the succeeded logic from PutBlobWithOptions.

return private.UploadedBlob{Digest: blobDigest, Size: size}, nil
}

func (d *ociImageDestination) blobFileSyncAndRename(blobFile *os.File, blobDigest digest.Digest, closed *bool) error {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Documenting the interaction of blobFile and *closed would be nice.

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.

2 participants