mirror of
https://github.com/versity/versitygw.git
synced 2026-09-23 08:24:17 +00:00
feat: add storage class to put object flows input
A new glaicer mode for the archiving backend needs the storage class supplied to the backend for put object, create multipart upload, and browser post object input.
This commit is contained in:
@@ -127,6 +127,7 @@ func (c S3ApiController) POSTObject(ctx fiber.Ctx) (*Response, error) {
|
||||
cacheControl := parsed.Fields["cache-control"]
|
||||
expires := parsed.Fields["expires"]
|
||||
websiteRedirectLocation := parsed.Fields["x-amz-website-redirect-location"]
|
||||
storageClass := parsed.Fields["x-amz-storage-class"]
|
||||
|
||||
key := parsed.Fields["key"]
|
||||
|
||||
@@ -233,6 +234,7 @@ func (c S3ApiController) POSTObject(ctx fiber.Ctx) (*Response, error) {
|
||||
ContentLength: &parsed.ContentLength,
|
||||
Tagging: &tagging,
|
||||
Metadata: metadata,
|
||||
StorageClass: types.StorageClass(storageClass),
|
||||
ChecksumCRC32: utils.GetStringPtr(checksums[types.ChecksumAlgorithmCrc32]),
|
||||
ChecksumCRC32C: utils.GetStringPtr(checksums[types.ChecksumAlgorithmCrc32c]),
|
||||
ChecksumSHA1: utils.GetStringPtr(checksums[types.ChecksumAlgorithmSha1]),
|
||||
|
||||
@@ -567,6 +567,7 @@ func TestS3ApiController_POSTObject(t *testing.T) {
|
||||
[]any{"eq", "$content-encoding", "gzip"},
|
||||
[]any{"eq", "$content-language", "en-US"},
|
||||
[]any{"eq", "$expires", "Fri, 21 Mar 2026 00:00:00 GMT"},
|
||||
[]any{"eq", "$x-amz-storage-class", string(types.StorageClassGlacier)},
|
||||
}),
|
||||
"file": "ignored",
|
||||
"x-amz-signature": "ignored",
|
||||
@@ -580,6 +581,7 @@ func TestS3ApiController_POSTObject(t *testing.T) {
|
||||
"content-encoding": "gzip",
|
||||
"content-language": "en-US",
|
||||
"expires": "Fri, 21 Mar 2026 00:00:00 GMT",
|
||||
"x-amz-storage-class": string(types.StorageClassGlacier),
|
||||
},
|
||||
FileRdr: newMockFileReader("payload"),
|
||||
ContentLength: int64(len("payload")),
|
||||
@@ -719,6 +721,7 @@ func TestS3ApiController_POSTObject(t *testing.T) {
|
||||
assert.Equal(t, "en-US", *putObjectInput.ContentLanguage)
|
||||
assert.Equal(t, "max-age=60", *putObjectInput.CacheControl)
|
||||
assert.Equal(t, "Fri, 21 Mar 2026 00:00:00 GMT", *putObjectInput.Expires)
|
||||
assert.Equal(t, types.StorageClassGlacier, putObjectInput.StorageClass)
|
||||
assert.Equal(t, int64(len("payload")), *putObjectInput.ContentLength)
|
||||
assert.Equal(t, "project=alpha+team", *putObjectInput.Tagging)
|
||||
assert.Equal(t, map[string]string{"owner": "alice"}, putObjectInput.Metadata)
|
||||
|
||||
@@ -151,6 +151,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx fiber.Ctx) (*Response, error)
|
||||
tagging := ctx.Get("X-Amz-Tagging")
|
||||
expires := ctx.Get("Expires")
|
||||
websiteRedirectLocation := ctx.Get("X-Amz-Website-Redirect-Location")
|
||||
storageClass := ctx.Get("X-Amz-Storage-Class")
|
||||
legalHoldHdr := ctx.Get("X-Amz-Object-Lock-Legal-Hold")
|
||||
lockModeHdr := ctx.Get("X-Amz-Object-Lock-Mode")
|
||||
objLockDate := ctx.Get("X-Amz-Object-Lock-Retain-Until-Date")
|
||||
@@ -241,6 +242,7 @@ func (c S3ApiController) CreateMultipartUpload(ctx fiber.Ctx) (*Response, error)
|
||||
ObjectLockMode: objLockState.ObjectLockMode,
|
||||
ObjectLockLegalHoldStatus: objLockState.LegalHoldStatus,
|
||||
Metadata: metadata,
|
||||
StorageClass: types.StorageClass(storageClass),
|
||||
ChecksumAlgorithm: checksumAlgorithm,
|
||||
ChecksumType: checksumType,
|
||||
})
|
||||
|
||||
@@ -312,6 +312,7 @@ func TestS3ApiController_CreateMultipartUpload(t *testing.T) {
|
||||
headers: map[string]string{
|
||||
"x-amz-checksum-algorithm": string(types.ChecksumAlgorithmCrc32),
|
||||
"x-amz-checksum-type": string(types.ChecksumTypeComposite),
|
||||
"X-Amz-Storage-Class": string(types.StorageClassGlacier),
|
||||
},
|
||||
},
|
||||
output: testOutput{
|
||||
@@ -332,6 +333,9 @@ func TestS3ApiController_CreateMultipartUpload(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
be := &BackendMock{
|
||||
CreateMultipartUploadFunc: func(contextMoqParam context.Context, createMultipartUploadInput s3response.CreateMultipartUploadInput) (s3response.InitiateMultipartUploadResult, error) {
|
||||
if tt.name == "successful response" && createMultipartUploadInput.StorageClass != types.StorageClassGlacier {
|
||||
t.Fatalf("expected storage class %q, got %q", types.StorageClassGlacier, createMultipartUploadInput.StorageClass)
|
||||
}
|
||||
return tt.input.beRes.(s3response.InitiateMultipartUploadResult), tt.input.beErr
|
||||
},
|
||||
GetBucketPolicyFunc: func(contextMoqParam context.Context, bucket string) ([]byte, error) {
|
||||
|
||||
@@ -668,6 +668,7 @@ func (c S3ApiController) PutObject(ctx fiber.Ctx) (*Response, error) {
|
||||
expires := ctx.Get("Expires")
|
||||
websiteRedirectLocation := ctx.Get("X-Amz-Website-Redirect-Location")
|
||||
tagging := ctx.Get("x-amz-tagging")
|
||||
storageClass := ctx.Get("X-Amz-Storage-Class")
|
||||
legalHoldHdr := ctx.Get("X-Amz-Object-Lock-Legal-Hold")
|
||||
lockModeHdr := ctx.Get("X-Amz-Object-Lock-Mode")
|
||||
objLockDate := ctx.Get("X-Amz-Object-Lock-Retain-Until-Date")
|
||||
@@ -803,6 +804,7 @@ func (c S3ApiController) PutObject(ctx fiber.Ctx) (*Response, error) {
|
||||
ObjectLockRetainUntilDate: &objLock.RetainUntilDate,
|
||||
ObjectLockMode: objLock.ObjectLockMode,
|
||||
ObjectLockLegalHoldStatus: objLock.LegalHoldStatus,
|
||||
StorageClass: types.StorageClass(storageClass),
|
||||
ChecksumAlgorithm: algorithm,
|
||||
ChecksumCRC32: utils.GetStringPtr(checksums[types.ChecksumAlgorithmCrc32]),
|
||||
ChecksumCRC32C: utils.GetStringPtr(checksums[types.ChecksumAlgorithmCrc32c]),
|
||||
|
||||
@@ -1169,6 +1169,58 @@ func TestS3ApiController_PutObject(t *testing.T) {
|
||||
emptyStringPtr := &str
|
||||
objSize := int64(120)
|
||||
|
||||
t.Run("forwards storage class", func(t *testing.T) {
|
||||
be := &BackendMock{
|
||||
PutObjectFunc: func(_ context.Context, input s3response.PutObjectInput) (s3response.PutObjectOutput, error) {
|
||||
if input.StorageClass != types.StorageClassGlacier {
|
||||
t.Fatalf("expected storage class %q, got %q", types.StorageClassGlacier, input.StorageClass)
|
||||
}
|
||||
return s3response.PutObjectOutput{ETag: "etag", VersionID: "version-id"}, nil
|
||||
},
|
||||
GetBucketPolicyFunc: func(_ context.Context, _ string) ([]byte, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrAccessDenied)
|
||||
},
|
||||
GetObjectLockConfigurationFunc: func(_ context.Context, _ string) ([]byte, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrObjectLockConfigurationNotFound)
|
||||
},
|
||||
GetBucketVersioningFunc: func(_ context.Context, _ string) (s3response.GetBucketVersioningOutput, error) {
|
||||
return s3response.GetBucketVersioningOutput{}, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := S3ApiController{be: be}
|
||||
testController(t, ctrl.PutObject, &Response{
|
||||
Headers: map[string]*string{
|
||||
"ETag": utils.GetStringPtr("etag"),
|
||||
"x-amz-checksum-crc32": nil,
|
||||
"x-amz-checksum-crc32c": nil,
|
||||
"x-amz-checksum-crc64nvme": nil,
|
||||
"x-amz-checksum-sha1": nil,
|
||||
"x-amz-checksum-sha256": nil,
|
||||
"x-amz-checksum-sha512": nil,
|
||||
"x-amz-checksum-md5": nil,
|
||||
"x-amz-checksum-xxhash64": nil,
|
||||
"x-amz-checksum-xxhash3": nil,
|
||||
"x-amz-checksum-xxhash128": nil,
|
||||
"x-amz-checksum-type": nil,
|
||||
"x-amz-version-id": utils.GetStringPtr("version-id"),
|
||||
"x-amz-object-size": nil,
|
||||
},
|
||||
MetaOpts: &MetaOptions{
|
||||
BucketOwner: "root",
|
||||
ObjectETag: utils.GetStringPtr("etag"),
|
||||
ContentLength: 0,
|
||||
ObjectSize: 0,
|
||||
EventName: s3event.EventObjectCreatedPut,
|
||||
},
|
||||
}, nil, ctxInputs{
|
||||
locals: defaultLocals,
|
||||
headers: map[string]string{
|
||||
"X-Amz-Storage-Class": string(types.StorageClassGlacier),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input testInput
|
||||
|
||||
@@ -608,6 +608,7 @@ type PutObjectInput struct {
|
||||
ObjectLockMode types.ObjectLockMode
|
||||
ObjectLockLegalHoldStatus types.ObjectLockLegalHoldStatus
|
||||
ChecksumAlgorithm types.ChecksumAlgorithm
|
||||
StorageClass types.StorageClass
|
||||
|
||||
Metadata map[string]string
|
||||
Body io.Reader
|
||||
|
||||
Reference in New Issue
Block a user