Skip to content

esti: test lakectl fs upload of files over 5GiB - #10478

Merged
itaigilo merged 4 commits into
treeverse:masterfrom
highlyavailable:esti-lakectl-large-upload
Nov 7, 2026
Merged

itaigilo merged 4 commits into
treeverse:masterfrom
highlyavailable:esti-lakectl-large-upload

Conversation

@highlyavailable

@highlyavailable highlyavailable commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #9284

Adds esti coverage for lakectl fs upload of a file over 5GiB, with and without --pre-sign, which is the multipart path fixed in #9283.

  • uses a sparse 5GiB+1 temp file so disk usage stays low
  • only runs on the S3 blockstore, where the 5GiB single-part limit applies
  • checks the uploaded size in lakectl's output and through the stat API
  • removes each uploaded object from the backing store on cleanup, since deleting the repo leaves its data behind (adds a Delete to the esti S3 adapter for this)

Covers the multipart path fixed in treeverse#9283 for both pre-signed and
regular uploads. Extends the output sanitizers to handle multipart
etags (md5-N) and relative physical addresses with part suffixes.

Closes treeverse#9284
@github-actions github-actions Bot added the area/testing Improvements or additions to tests label Jul 12, 2026
@highlyavailable

Copy link
Copy Markdown
Contributor Author

hi @itaiad200, just checking in on this one

@itaiad200

itaiad200 commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

hi @itaiad200, just checking in on this one

I think you meant to tag @itaigilo

@itaigilo itaigilo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @highlyavailable for your contribution!

These tests indeed add to the robustness of lakeFS, which is great.

However some changes are required, both to avoid unnecessary changes to the codebase, but mainly to make sure these large files are properly cleaned.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This golden serves no real purpose - you can just compare the size in the test itself.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed the golden file and the test now checks the size directly

Comment thread esti/lakectl_util.go Outdated
objectPrefix = strings.TrimPrefix(objectPrefix, "/")
for _, match := range rePhysicalAddress.FindAllString(output, -1) {
output = strings.Replace(output, objectPrefix+match, objectPrefix+"/<OBJECT_KEY>", 1)
if strings.Contains(output, objectPrefix+match) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These changes can hide future bugs in golden files.
Instead, I suggest to use RunCmdAndVerifySuccess in your tests, avoid using a golden file for these tests, and keep this file untouched.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I reverted these so lakectl_util.go is untouched now... I used RunCmdAndVerifyContainsText on the size line instead of RunCmdAndVerifySuccess

Comment thread esti/lakectl_test.go Outdated

t.Run("pre-sign", func(t *testing.T) {
vars["FILE_PATH"] = "large_file_presign"
RunCmdAndVerifySuccessWithFile(t, Lakectl()+" fs upload -s "+f.Name()+" lakefs://"+repoName+"/"+mainBranch+"/"+vars["FILE_PATH"]+" --pre-sign", false, "lakectl_fs_upload_large", vars)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This upload (and the following one) command uploads the large file to the storage.
While the repo is deleted as part of the ESTI tests cleanup, these files are not cleaned up from the storage itself. When running on a temp MinIO this is fine, but if it runs on S3, it will leave unused large files on the storage. Please make sure these are cleaned.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

each subtest now deletes its large object from S3 on cleanup, through a new Delete on the esti S3 adapter

Comment thread esti/lakectl_util.go Outdated
reTime = regexp.MustCompile(`\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} \w{1,4}`)
reCommitID = regexp.MustCompile(`[\d|a-f]{64}`)
reShortCommitID = regexp.MustCompile(`[\d|a-f]{16}`)
// multipart uploads report an etag with a part count suffix, e.g. <md5>-1025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please keep the same code style and avoid these extra comments.
Same for the next vars here.

@itaigilo
itaigilo requested review from N-o-Z and arielshaqed October 26, 2026 11:29

@arielshaqed arielshaqed left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this contribution, seems great!

Comment thread esti/lakectl_test.go Outdated
require.NoError(t, f.Close())

t.Run("pre-sign", func(t *testing.T) {
vars["FILE_PATH"] = "large_file_presign"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What does vars["FILE_PATH"] do here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it was only fed the Path line in the golden file, which is gone now, so I removed it

Comment thread esti/lakectl_test.go Outdated

t.Run("pre-sign", func(t *testing.T) {
vars["FILE_PATH"] = "large_file_presign"
RunCmdAndVerifySuccessWithFile(t, Lakectl()+" fs upload -s "+f.Name()+" lakefs://"+repoName+"/"+mainBranch+"/"+vars["FILE_PATH"]+" --pre-sign", false, "lakectl_fs_upload_large", vars)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we verify the contents, or the size? (ETag itself is hard, it is not really a function of contents because it also depends on the backend and on the split into parts.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed in 7e69d65, the test now verifies the size in lakectl's output and through the stat API. i think that's better than a full content check which would entails downloading 5db but I can add one if you'd recommend

Drop the golden file and the sanitizer changes it needed. The test now
checks the uploaded size through lakectl output and the stat API, and
deletes each large object from the backing store once the subtest ends,
since deleting the repository leaves its data in place.
@highlyavailable
highlyavailable force-pushed the esti-lakectl-large-upload branch from 7e69d65 to 92bda4e Compare October 31, 2026 04:43

@itaigilo itaigilo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the updates, @highlyavailable -
This looks much cleaner now.

Still a small fix is required,
plus a nit - the PR's description is stale now.

Comment thread esti/lakectl_test.go
// deleting the repository does not remove its data, so remove the large object from the storage
physicalAddress, err := url.Parse(statResp.JSON200.PhysicalAddress)
require.NoError(t, err)
t.Cleanup(func() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's a solid improvement.
However, the cleanup should be registered before the upload, in case one of the previous calls are failing.
It should be registered earlier.

Look up the object's physical address in the cleanup itself, so the
large object is removed from storage even if the upload or a later
check fails.
@itaigilo itaigilo added exclude-changelog PR description should not be included in next release changelog minor-change Used for PRs that don't require issue attached labels Nov 3, 2026
@itaigilo

itaigilo commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Great stuff @highlyavailable - almost there!

I ran the CI on a separate branch, and it seems that the only thing missing is adding AWS_REGION: us-east-1 to .github/workflows/lakectl-compatibility-tests.yaml, so the test knows from which region to delete the files:
Screenshot 2026-11-03 at 15 00 56

That's the only thing blocking the CI, other that that, LGTM.

The large upload test deletes its objects straight from S3, so the
default AWS config needs a region.

@itaigilo itaigilo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM -
Thanks @highlyavailable for your contribution!

@itaigilo
itaigilo merged commit 99ea350 into treeverse:master Nov 7, 2026
98 of 100 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci area/testing Improvements or additions to tests exclude-changelog PR description should not be included in next release changelog minor-change Used for PRs that don't require issue attached

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Esti: Add test for lakectl multipart upload with files > 5GB

4 participants