From 8bb4bcba63d54db8ecde966d23d7d978ebdadd48 Mon Sep 17 00:00:00 2001 From: niksis02 Date: Mon, 10 Nov 2025 19:44:20 +0400 Subject: [PATCH] fix: fixes NoSuchVersion errors for some actions in posix Fixes #1616 Some object-level actions in the gateway that work with object versions used to return `InvalidVersionId` when the specified object version did not exist. The logic has now been fixed, and they correctly return `NoSuchVersion`. These actions include: `HeadObject`, `GetObject`, `PutObjectLegalHold`, `GetObjectLegalHold`, `PutObjectRetention`, and `GetObjectRetention`. --- backend/posix/posix.go | 10 +++---- tests/integration/group-tests.go | 24 ++++++++-------- tests/integration/versioning.go | 48 ++++++++++++++++---------------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/backend/posix/posix.go b/backend/posix/posix.go index cbf8971..d299a19 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -3656,7 +3656,7 @@ func (p *Posix) GetObject(_ context.Context, input *s3.GetObjectInput) (*s3.GetO fid, err := os.Stat(objPath) if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { if versionId != "" { - return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId) + return nil, s3err.GetAPIError(s3err.ErrNoSuchVersion) } return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } @@ -3912,7 +3912,7 @@ func (p *Posix) HeadObject(ctx context.Context, input *s3.HeadObjectInput) (*s3. fi, err := os.Stat(objPath) if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { if versionId != "" { - return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId) + return nil, s3err.GetAPIError(s3err.ErrNoSuchVersion) } return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } @@ -5151,7 +5151,7 @@ func (p *Posix) PutObjectLegalHold(_ context.Context, bucket, object, versionId err = p.meta.StoreAttribute(nil, bucket, object, objectLegalHoldKey, statusData) if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { if versionId != "" { - return s3err.GetAPIError(s3err.ErrInvalidVersionId) + return s3err.GetAPIError(s3err.ErrNoSuchVersion) } return s3err.GetAPIError(s3err.ErrNoSuchKey) } @@ -5197,7 +5197,7 @@ func (p *Posix) GetObjectLegalHold(_ context.Context, bucket, object, versionId data, err := p.meta.RetrieveAttribute(nil, bucket, object, objectLegalHoldKey) if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { if versionId != "" { - return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId) + return nil, s3err.GetAPIError(s3err.ErrNoSuchVersion) } return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } @@ -5288,7 +5288,7 @@ func (p *Posix) GetObjectRetention(_ context.Context, bucket, object, versionId data, err := p.meta.RetrieveAttribute(nil, bucket, object, objectRetentionKey) if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { if versionId != "" { - return nil, s3err.GetAPIError(s3err.ErrInvalidVersionId) + return nil, s3err.GetAPIError(s3err.ErrNoSuchVersion) } return nil, s3err.GetAPIError(s3err.ErrNoSuchKey) } diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 9944a29..d21002e 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -993,13 +993,13 @@ func TestVersioning(ts *TestState) { ts.Run(Versioning_CopyObject_from_an_object_version) ts.Run(Versioning_CopyObject_special_chars) // HeadObject action - ts.Run(Versioning_HeadObject_invalid_versionId) + ts.Run(Versioning_HeadObject_non_existing_object_version) ts.Run(Versioning_HeadObject_invalid_parent) ts.Run(Versioning_HeadObject_success) ts.Run(Versioning_HeadObject_without_versionId) ts.Run(Versioning_HeadObject_delete_marker) // GetObject action - ts.Run(Versioning_GetObject_invalid_versionId) + ts.Run(Versioning_GetObject_non_existing_object_version) ts.Run(Versioning_GetObject_success) ts.Run(Versioning_GetObject_delete_marker_without_versionId) ts.Run(Versioning_GetObject_delete_marker) @@ -1040,12 +1040,12 @@ func TestVersioning(ts *TestState) { ts.Run(Versioning_Enable_object_lock) ts.Run(Versioning_status_switch_to_suspended_with_object_lock) // Object-Lock Retention - ts.Run(Versioning_PutObjectRetention_invalid_versionId) - ts.Run(Versioning_GetObjectRetention_invalid_versionId) + ts.Run(Versioning_PutObjectRetention_non_existing_object_version) + ts.Run(Versioning_GetObjectRetention_non_existing_object_version) ts.Run(Versioning_Put_GetObjectRetention_success) // Object-Lock Legal hold - ts.Run(Versioning_PutObjectLegalHold_invalid_versionId) - ts.Run(Versioning_GetObjectLegalHold_invalid_versionId) + ts.Run(Versioning_PutObjectLegalHold_non_existing_object_version) + ts.Run(Versioning_GetObjectLegalHold_non_existing_object_version) ts.Run(Versioning_Put_GetObjectLegalHold_success) // WORM protection ts.Run(Versioning_WORM_obj_version_locked_with_legal_hold) @@ -1631,12 +1631,12 @@ func GetIntTests() IntTests { "Versioning_CopyObject_non_existing_version_id": Versioning_CopyObject_non_existing_version_id, "Versioning_CopyObject_from_an_object_version": Versioning_CopyObject_from_an_object_version, "Versioning_CopyObject_special_chars": Versioning_CopyObject_special_chars, - "Versioning_HeadObject_invalid_versionId": Versioning_HeadObject_invalid_versionId, + "Versioning_HeadObject_non_existing_object_version": Versioning_HeadObject_non_existing_object_version, "Versioning_HeadObject_invalid_parent": Versioning_HeadObject_invalid_parent, "Versioning_HeadObject_success": Versioning_HeadObject_success, "Versioning_HeadObject_without_versionId": Versioning_HeadObject_without_versionId, "Versioning_HeadObject_delete_marker": Versioning_HeadObject_delete_marker, - "Versioning_GetObject_invalid_versionId": Versioning_GetObject_invalid_versionId, + "Versioning_GetObject_non_existing_object_version": Versioning_GetObject_non_existing_object_version, "Versioning_GetObject_success": Versioning_GetObject_success, "Versioning_GetObject_delete_marker_without_versionId": Versioning_GetObject_delete_marker_without_versionId, "Versioning_GetObject_delete_marker": Versioning_GetObject_delete_marker, @@ -1670,11 +1670,11 @@ func GetIntTests() IntTests { "Versioning_object_lock_not_enabled_on_bucket_creation": Versioning_object_lock_not_enabled_on_bucket_creation, "Versioning_Enable_object_lock": Versioning_Enable_object_lock, "Versioning_status_switch_to_suspended_with_object_lock": Versioning_status_switch_to_suspended_with_object_lock, - "Versioning_PutObjectRetention_invalid_versionId": Versioning_PutObjectRetention_invalid_versionId, - "Versioning_GetObjectRetention_invalid_versionId": Versioning_GetObjectRetention_invalid_versionId, + "Versioning_PutObjectRetention_non_existing_object_version": Versioning_PutObjectRetention_non_existing_object_version, + "Versioning_GetObjectRetention_non_existing_object_version": Versioning_GetObjectRetention_non_existing_object_version, "Versioning_Put_GetObjectRetention_success": Versioning_Put_GetObjectRetention_success, - "Versioning_PutObjectLegalHold_invalid_versionId": Versioning_PutObjectLegalHold_invalid_versionId, - "Versioning_GetObjectLegalHold_invalid_versionId": Versioning_GetObjectLegalHold_invalid_versionId, + "Versioning_PutObjectLegalHold_non_existing_object_version": Versioning_PutObjectLegalHold_non_existing_object_version, + "Versioning_GetObjectLegalHold_non_existing_object_version": Versioning_GetObjectLegalHold_non_existing_object_version, "Versioning_Put_GetObjectLegalHold_success": Versioning_Put_GetObjectLegalHold_success, "Versioning_WORM_obj_version_locked_with_legal_hold": Versioning_WORM_obj_version_locked_with_legal_hold, "Versioning_WORM_obj_version_locked_with_governance_retention": Versioning_WORM_obj_version_locked_with_governance_retention, diff --git a/tests/integration/versioning.go b/tests/integration/versioning.go index c43e614..cf9b79a 100644 --- a/tests/integration/versioning.go +++ b/tests/integration/versioning.go @@ -463,8 +463,8 @@ func Versioning_CopyObject_special_chars(s *S3Conf) error { }, withVersioning(types.BucketVersioningStatusEnabled)) } -func Versioning_HeadObject_invalid_versionId(s *S3Conf) error { - testName := "Versioning_HeadObject_invalid_versionId" +func Versioning_HeadObject_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_HeadObject_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { dLen := int64(2000) obj := "my-obj" @@ -480,10 +480,10 @@ func Versioning_HeadObject_invalid_versionId(s *S3Conf) error { _, err = s3client.HeadObject(ctx, &s3.HeadObjectInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_version_id"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), }) cancel() - if err := checkSdkApiErr(err, "BadRequest"); err != nil { + if err := checkSdkApiErr(err, "NotFound"); err != nil { return err } return nil @@ -643,8 +643,8 @@ func Versioning_HeadObject_delete_marker(s *S3Conf) error { }, withVersioning(types.BucketVersioningStatusEnabled)) } -func Versioning_GetObject_invalid_versionId(s *S3Conf) error { - testName := "Versioning_GetObject_invalid_versionId" +func Versioning_GetObject_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_GetObject_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { dLen := int64(2000) obj := "my-obj" @@ -660,10 +660,10 @@ func Versioning_GetObject_invalid_versionId(s *S3Conf) error { _, err = s3client.GetObject(ctx, &s3.GetObjectInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_version_id"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), }) cancel() - if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidVersionId)); err != nil { + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchVersion)); err != nil { return err } @@ -1867,8 +1867,8 @@ func Versioning_status_switch_to_suspended_with_object_lock(s *S3Conf) error { }, withLock()) } -func Versioning_PutObjectRetention_invalid_versionId(s *S3Conf) error { - testName := "Versioning_PutObjectRetention_invalid_versionId" +func Versioning_PutObjectRetention_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_PutObjectRetention_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { obj := "my-obj" _, err := createObjVersions(s3client, bucket, obj, 3) @@ -1881,14 +1881,14 @@ func Versioning_PutObjectRetention_invalid_versionId(s *S3Conf) error { _, err = s3client.PutObjectRetention(ctx, &s3.PutObjectRetentionInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_versionId"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), Retention: &types.ObjectLockRetention{ Mode: types.ObjectLockRetentionModeGovernance, RetainUntilDate: &rDate, }, }) cancel() - if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidVersionId)); err != nil { + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchVersion)); err != nil { return err } @@ -1896,8 +1896,8 @@ func Versioning_PutObjectRetention_invalid_versionId(s *S3Conf) error { }, withLock(), withVersioning(types.BucketVersioningStatusEnabled)) } -func Versioning_GetObjectRetention_invalid_versionId(s *S3Conf) error { - testName := "Versioning_GetObjectRetention_invalid_versionId" +func Versioning_GetObjectRetention_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_GetObjectRetention_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { obj := "my-obj" _, err := createObjVersions(s3client, bucket, obj, 3) @@ -1909,10 +1909,10 @@ func Versioning_GetObjectRetention_invalid_versionId(s *S3Conf) error { _, err = s3client.GetObjectRetention(ctx, &s3.GetObjectRetentionInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_versionId"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), }) cancel() - if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidVersionId)); err != nil { + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchVersion)); err != nil { return err } @@ -1966,8 +1966,8 @@ func Versioning_Put_GetObjectRetention_success(s *S3Conf) error { }, withLock(), withVersioning(types.BucketVersioningStatusEnabled)) } -func Versioning_PutObjectLegalHold_invalid_versionId(s *S3Conf) error { - testName := "Versioning_PutObjectLegalHold_invalid_versionId" +func Versioning_PutObjectLegalHold_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_PutObjectLegalHold_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { obj := "my-obj" _, err := createObjVersions(s3client, bucket, obj, 3) @@ -1979,13 +1979,13 @@ func Versioning_PutObjectLegalHold_invalid_versionId(s *S3Conf) error { _, err = s3client.PutObjectLegalHold(ctx, &s3.PutObjectLegalHoldInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_versionId"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), LegalHold: &types.ObjectLockLegalHold{ Status: types.ObjectLockLegalHoldStatusOn, }, }) cancel() - if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidVersionId)); err != nil { + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchVersion)); err != nil { return err } @@ -1993,8 +1993,8 @@ func Versioning_PutObjectLegalHold_invalid_versionId(s *S3Conf) error { }, withLock(), withVersioning(types.BucketVersioningStatusEnabled)) } -func Versioning_GetObjectLegalHold_invalid_versionId(s *S3Conf) error { - testName := "Versioning_GetObjectLegalHold_invalid_versionId" +func Versioning_GetObjectLegalHold_non_existing_object_version(s *S3Conf) error { + testName := "Versioning_GetObjectLegalHold_non_existing_object_version" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { obj := "my-obj" _, err := createObjVersions(s3client, bucket, obj, 3) @@ -2006,10 +2006,10 @@ func Versioning_GetObjectLegalHold_invalid_versionId(s *S3Conf) error { _, err = s3client.GetObjectLegalHold(ctx, &s3.GetObjectLegalHoldInput{ Bucket: &bucket, Key: &obj, - VersionId: getPtr("invalid_versionId"), + VersionId: getPtr("01G65Z755AFWAKHE12NY0CQ9FH"), }) cancel() - if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidVersionId)); err != nil { + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchVersion)); err != nil { return err }