Merge pull request #859 from versity/fix/object-lock-and-versioning-status-switch

fix: Added the implementation to automatically enable bucket versioni…
This commit is contained in:
Ben McClelland
2024-10-01 14:40:58 -07:00
committed by GitHub
4 changed files with 73 additions and 2 deletions

View File

@@ -325,6 +325,15 @@ func (p *Posix) CreateBucket(ctx context.Context, input *s3.CreateBucketInput, a
}
if input.ObjectLockEnabledForBucket != nil && *input.ObjectLockEnabledForBucket {
// First enable bucket versioning
// Bucket versioning is enabled automatically with object lock
if p.versioningEnabled() {
err = p.PutBucketVersioning(ctx, bucket, types.BucketVersioningStatusEnabled)
if err != nil {
return err
}
}
now := time.Now()
defaultLock := auth.BucketLockConfig{
Enabled: true,
@@ -437,7 +446,7 @@ func (p *Posix) DeleteBucketOwnershipControls(_ context.Context, bucket string)
return nil
}
func (p *Posix) PutBucketVersioning(_ context.Context, bucket string, status types.BucketVersioningStatus) error {
func (p *Posix) PutBucketVersioning(ctx context.Context, bucket string, status types.BucketVersioningStatus) error {
if !p.versioningEnabled() {
//TODO: Maybe we need to return our custom error here?
return nil
@@ -457,6 +466,18 @@ func (p *Posix) PutBucketVersioning(_ context.Context, bucket string, status typ
// '1' maps to 'Enabled'
versioning = []byte{1}
case types.BucketVersioningStatusSuspended:
lockRaw, err := p.GetObjectLockConfiguration(ctx, bucket)
if err != nil {
return err
}
lockStatus, err := auth.ParseBucketLockConfigurationOutput(lockRaw)
if err != nil {
return err
}
if lockStatus.ObjectLockEnabled == types.ObjectLockEnabledEnabled {
return s3err.GetAPIError(s3err.ErrSuspendedVersioningNotAllowed)
}
// '0' maps to 'Suspended'
versioning = []byte{0}
}
@@ -3409,7 +3430,7 @@ func (p *Posix) DeleteBucketPolicy(ctx context.Context, bucket string) error {
return p.PutBucketPolicy(ctx, bucket, nil)
}
func (p *Posix) PutObjectLockConfiguration(_ context.Context, bucket string, config []byte) error {
func (p *Posix) PutObjectLockConfiguration(ctx context.Context, bucket string, config []byte) error {
_, err := os.Stat(bucket)
if errors.Is(err, fs.ErrNotExist) {
return s3err.GetAPIError(s3err.ErrNoSuchBucket)

View File

@@ -134,6 +134,7 @@ const (
ErrKeyTooLong
ErrInvalidVersionId
ErrNoSuchVersion
ErrSuspendedVersioningNotAllowed
// Non-AWS errors
ErrExistingObjectIsDirectory
@@ -537,6 +538,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "The specified version does not exist.",
HTTPStatusCode: http.StatusNotFound,
},
ErrSuspendedVersioningNotAllowed: {
Code: "InvalidBucketState",
Description: "An Object Lock configuration is present on this bucket, so the versioning state cannot be changed.",
HTTPStatusCode: http.StatusBadRequest,
},
// non aws errors
ErrExistingObjectIsDirectory: {

View File

@@ -553,6 +553,9 @@ func TestVersioning(s *S3Conf) {
Versioning_Multipart_Upload_overwrite_an_object(s)
Versioning_UploadPartCopy_non_existing_versionId(s)
Versioning_UploadPartCopy_from_an_object_version(s)
// Object lock configuration
Versioning_Enable_object_lock(s)
Versioning_status_switch_to_suspended_with_object_lock(s)
// Object-Lock Retention
Versionsin_PutObjectRetention_invalid_versionId(s)
Versioning_GetObjectRetention_invalid_versionId(s)
@@ -912,6 +915,8 @@ func GetIntTests() IntTests {
"Versioning_Multipart_Upload_overwrite_an_object": Versioning_Multipart_Upload_overwrite_an_object,
"Versioning_UploadPartCopy_non_existing_versionId": Versioning_UploadPartCopy_non_existing_versionId,
"Versioning_UploadPartCopy_from_an_object_version": Versioning_UploadPartCopy_from_an_object_version,
"Versioning_Enable_object_lock": Versioning_Enable_object_lock,
"Versioning_status_switch_to_suspended_with_object_lock": Versioning_status_switch_to_suspended_with_object_lock,
"Versionsin_PutObjectRetention_invalid_versionId": Versionsin_PutObjectRetention_invalid_versionId,
"Versioning_GetObjectRetention_invalid_versionId": Versioning_GetObjectRetention_invalid_versionId,
"Versioning_Put_GetObjectRetention_success": Versioning_Put_GetObjectRetention_success,

View File

@@ -11746,6 +11746,45 @@ func Versioning_UploadPartCopy_from_an_object_version(s *S3Conf) error {
}, withVersioning())
}
func Versioning_Enable_object_lock(s *S3Conf) error {
testName := "Versioning_Enable_object_lock"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
res, err := s3client.GetBucketVersioning(ctx, &s3.GetBucketVersioningInput{
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
if res.Status != types.BucketVersioningStatusEnabled {
return fmt.Errorf("expected the bucket versioning status to be %v, instead got %v", types.BucketVersioningStatusEnabled, res.Status)
}
return nil
}, withLock())
}
func Versioning_status_switch_to_suspended_with_object_lock(s *S3Conf) error {
testName := "Versioning_status_switch_to_suspended_with_object_lock"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutBucketVersioning(ctx, &s3.PutBucketVersioningInput{
Bucket: &bucket,
VersioningConfiguration: &types.VersioningConfiguration{
Status: types.BucketVersioningStatusSuspended,
},
})
cancel()
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrSuspendedVersioningNotAllowed)); err != nil {
return err
}
return nil
}, withLock())
}
func Versionsin_PutObjectRetention_invalid_versionId(s *S3Conf) error {
testName := "Versionsin_PutObjectRetention_invalid_versionId"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {