From 088c33988a15213d6afbab59e28d6837c1d9994d Mon Sep 17 00:00:00 2001 From: reshke Date: Sat, 15 Aug 2026 07:03:17 +0000 Subject: [PATCH 1/4] Preserve yezzey storage class in two-stage delete // If the x-amz-storage-class header is not used, the copied object will be // stored in the STANDARD Storage Class by default. The STANDARD storage class // provides high durability and high availability. Depending on performance // needs, you can specify a different Storage Class. --- pkg/storage/s3storage.go | 18 ++++++++++++++---- ...12_delete_garbage_preserve_storage_class.sh | 9 +++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 test/regress/tests/12_delete_garbage_preserve_storage_class.sh diff --git a/pkg/storage/s3storage.go b/pkg/storage/s3storage.go index 4ca79ec..27d4c78 100644 --- a/pkg/storage/s3storage.go +++ b/pkg/storage/s3storage.go @@ -86,7 +86,7 @@ func (s *S3StorageInteractor) CatFileFromStorage(name string, offset int64, sett return nil, err } input := &s3.GetObjectInput{ - Bucket: &bucket, + Bucket: aws.String(bucket), Key: aws.String(objectPath), Range: aws.String(fmt.Sprintf("bytes=%d-", offset)), } @@ -350,10 +350,20 @@ func (s *S3StorageInteractor) SScopyObject(from, to, fromStoragePrefix, fromStor ylogger.Zero.Debug().Str("to", to).Str("from", from).Msg("requesting server-side copy") + sourceInput := &s3.GetObjectInput{ + Bucket: aws.String(fromStorageBucket), + Key: aws.String(from), + } + sourceObject, err := sess.GetObject(sourceInput) + if err != nil { + return err + } + inp := s3.CopyObjectInput{ - Bucket: &toStorageBucket, - CopySource: aws.String(from), - Key: aws.String(to), + Bucket: &toStorageBucket, + CopySource: aws.String(from), + Key: aws.String(to), + StorageClass: sourceObject.StorageClass, } _, err = sess.CopyObject(&inp) diff --git a/test/regress/tests/12_delete_garbage_preserve_storage_class.sh b/test/regress/tests/12_delete_garbage_preserve_storage_class.sh new file mode 100644 index 0000000..f0fa2d1 --- /dev/null +++ b/test/regress/tests/12_delete_garbage_preserve_storage_class.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -ex + +echo 'garbage data' | yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal put --storage-class GLACIER 'glacier_file' +yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal list '' +yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal delete --garbage --confirm --port 5432 --segnum 0 'glacier_file' +yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal list '' + +s3cmd --access_key some_key --secret_key some_key --host minio:9000 --host-bucket '' --no-ssl info s3://gpyezzey/trash/segments_005/seg0/basebackups_005/yezzey/glacier_file | grep Storage From c4aefc62556ffa01c23b6a233484aa3148301b76 Mon Sep 17 00:00:00 2001 From: Kirill Reshke Date: Mon, 17 Aug 2026 17:18:14 +0500 Subject: [PATCH 2/4] f --- .../expected/12_delete_garbage_preserve_storage_class.txt | 4 ++++ .../regress/tests/12_delete_garbage_preserve_storage_class.sh | 0 2 files changed, 4 insertions(+) create mode 100644 test/regress/expected/12_delete_garbage_preserve_storage_class.txt mode change 100644 => 100755 test/regress/tests/12_delete_garbage_preserve_storage_class.sh diff --git a/test/regress/expected/12_delete_garbage_preserve_storage_class.txt b/test/regress/expected/12_delete_garbage_preserve_storage_class.txt new file mode 100644 index 0000000..11d9ea7 --- /dev/null +++ b/test/regress/expected/12_delete_garbage_preserve_storage_class.txt @@ -0,0 +1,4 @@ +1 +Object: {Name: "/glacier_file", size: 13} +Object: {Name: "/trash/segments_005/seg0/basebackups_005/yezzey/glacier_file", size: 13} + Storage: GLACIER diff --git a/test/regress/tests/12_delete_garbage_preserve_storage_class.sh b/test/regress/tests/12_delete_garbage_preserve_storage_class.sh old mode 100644 new mode 100755 From 1acb101b79d368b23a4962ab8ffa384cb67014be Mon Sep 17 00:00:00 2001 From: reshke Date: Mon, 17 Aug 2026 12:32:34 +0000 Subject: [PATCH 3/4] f --- pkg/storage/s3storage.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/storage/s3storage.go b/pkg/storage/s3storage.go index 27d4c78..e7c72b4 100644 --- a/pkg/storage/s3storage.go +++ b/pkg/storage/s3storage.go @@ -350,11 +350,11 @@ func (s *S3StorageInteractor) SScopyObject(from, to, fromStoragePrefix, fromStor ylogger.Zero.Debug().Str("to", to).Str("from", from).Msg("requesting server-side copy") - sourceInput := &s3.GetObjectInput{ + sourceInput := &s3.HeadObjectInput{ Bucket: aws.String(fromStorageBucket), Key: aws.String(from), } - sourceObject, err := sess.GetObject(sourceInput) + sourceObject, err := sess.HeadObject(sourceInput) if err != nil { return err } From 2729153caa956949d34c058d246114736e483e1b Mon Sep 17 00:00:00 2001 From: reshke Date: Mon, 17 Aug 2026 12:54:45 +0000 Subject: [PATCH 4/4] f --- pkg/storage/s3storage.go | 7 ++++--- .../expected/12_delete_garbage_preserve_storage_class.txt | 6 +++--- .../tests/12_delete_garbage_preserve_storage_class.sh | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/storage/s3storage.go b/pkg/storage/s3storage.go index e7c72b4..a117a1b 100644 --- a/pkg/storage/s3storage.go +++ b/pkg/storage/s3storage.go @@ -346,9 +346,6 @@ func (s *S3StorageInteractor) SScopyObject(from, to, fromStoragePrefix, fromStor to = path.Join(s.cnf.StoragePrefix, to) } to = strings.TrimLeft(to, "/") - from = path.Join(fromStorageBucket, from) - - ylogger.Zero.Debug().Str("to", to).Str("from", from).Msg("requesting server-side copy") sourceInput := &s3.HeadObjectInput{ Bucket: aws.String(fromStorageBucket), @@ -359,6 +356,10 @@ func (s *S3StorageInteractor) SScopyObject(from, to, fromStoragePrefix, fromStor return err } + from = path.Join(fromStorageBucket, from) + + ylogger.Zero.Debug().Str("to", to).Str("from", from).Msg("requesting server-side copy") + inp := s3.CopyObjectInput{ Bucket: &toStorageBucket, CopySource: aws.String(from), diff --git a/test/regress/expected/12_delete_garbage_preserve_storage_class.txt b/test/regress/expected/12_delete_garbage_preserve_storage_class.txt index 11d9ea7..e974df5 100644 --- a/test/regress/expected/12_delete_garbage_preserve_storage_class.txt +++ b/test/regress/expected/12_delete_garbage_preserve_storage_class.txt @@ -1,4 +1,4 @@ 1 -Object: {Name: "/glacier_file", size: 13} -Object: {Name: "/trash/segments_005/seg0/basebackups_005/yezzey/glacier_file", size: 13} - Storage: GLACIER +Object: {Name: "/red_red_file", size: 13} +Object: {Name: "/trash/segments_005/seg0/basebackups_005/yezzey/red_red_file", size: 13} + Storage: REDUCED_REDUNDANCY diff --git a/test/regress/tests/12_delete_garbage_preserve_storage_class.sh b/test/regress/tests/12_delete_garbage_preserve_storage_class.sh index f0fa2d1..f2147ab 100755 --- a/test/regress/tests/12_delete_garbage_preserve_storage_class.sh +++ b/test/regress/tests/12_delete_garbage_preserve_storage_class.sh @@ -1,9 +1,9 @@ #!/bin/bash set -ex -echo 'garbage data' | yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal put --storage-class GLACIER 'glacier_file' +echo 'garbage data' | yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal put --storage-class REDUCED_REDUNDANCY 'red_red_file' yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal list '' -yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal delete --garbage --confirm --port 5432 --segnum 0 'glacier_file' +yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal delete --garbage --confirm --port 5432 --segnum 0 'red_red_file' yp-client --config test/regress/conf/yproxy_vacuum.yaml -l fatal list '' -s3cmd --access_key some_key --secret_key some_key --host minio:9000 --host-bucket '' --no-ssl info s3://gpyezzey/trash/segments_005/seg0/basebackups_005/yezzey/glacier_file | grep Storage +s3cmd --access_key some_key --secret_key some_key --host minio:9000 --host-bucket '' --no-ssl info s3://gpyezzey/trash/segments_005/seg0/basebackups_005/yezzey/red_red_file | grep Storage