Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

br: skip automatically get bucket region with other s3 compatible provider. #41889

Merged
merged 10 commits into from
Mar 30, 2023
37 changes: 23 additions & 14 deletions br/pkg/storage/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ func (options *S3BackendOptions) Apply(s3 *backuppb.S3) error {
s3.ForcePathStyle = options.ForcePathStyle
s3.RoleArn = options.RoleARN
s3.ExternalId = options.ExternalID
s3.Provider = options.Provider
return nil
}

Expand Down Expand Up @@ -358,22 +359,30 @@ func NewS3Storage(ctx context.Context, backend *backuppb.S3, opts *ExternalStora
)
}
c := s3.New(ses, s3CliConfigs...)
confCred := ses.Config.Credentials
setCredOpt := func(req *request.Request) {
// s3manager.GetBucketRegionWithClient will set credential anonymous, which works with s3.
// we need reassign credential to be compatible with minio authentication.
if confCred != nil {
req.Config.Credentials = confCred

var region string
if len(qs.Provider) == 0 || qs.Provider == "aws" {
confCred := ses.Config.Credentials
setCredOpt := func(req *request.Request) {
// s3manager.GetBucketRegionWithClient will set credential anonymous, which works with s3.
// we need reassign credential to be compatible with minio authentication.
if confCred != nil {
req.Config.Credentials = confCred
}
// s3manager.GetBucketRegionWithClient use path style addressing default.
// we need set S3ForcePathStyle by our config if we set endpoint.
if qs.Endpoint != "" {
req.Config.S3ForcePathStyle = ses.Config.S3ForcePathStyle
}
}
// s3manager.GetBucketRegionWithClient use path style addressing default.
// we need set S3ForcePathStyle by our config if we set endpoint.
if qs.Endpoint != "" {
req.Config.S3ForcePathStyle = ses.Config.S3ForcePathStyle
region, err = s3manager.GetBucketRegionWithClient(ctx, c, qs.Bucket, setCredOpt)
if err != nil {
return nil, errors.Annotatef(err, "failed to get region of bucket %s", qs.Bucket)
}
}
region, err := s3manager.GetBucketRegionWithClient(ctx, c, qs.Bucket, setCredOpt)
if err != nil {
return nil, errors.Annotatef(err, "failed to get region of bucket %s", qs.Bucket)
} else {
// for other s3 compatible provider like ovh storage didn't return the region correctlly
// so we cannot automatically get the bucket region. just fallback to manually region setting.
region = qs.Region
}

if qs.Region != region {
Expand Down
73 changes: 73 additions & 0 deletions br/pkg/storage/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1217,3 +1217,76 @@ func TestObjectLock(t *testing.T) {
)
require.Equal(t, true, s.storage.IsObjectLockEnabled())
}

func TestS3StorageBucketRegion(t *testing.T) {
type testcase struct {
name string
expectRegion string
s3 *backuppb.S3
}

require.NoError(t, os.Setenv("AWS_ACCESS_KEY_ID", "ab"))
require.NoError(t, os.Setenv("AWS_SECRET_ACCESS_KEY", "cd"))
require.NoError(t, os.Setenv("AWS_SESSION_TOKEN", "ef"))

cases := []testcase{
{
"empty region from aws",
"us-east-1",
&backuppb.S3{
Region: "",
Bucket: "bucket",
Prefix: "prefix",
Provider: "aws",
},
},
{
"region from different provider",
"sdg",
&backuppb.S3{
Region: "sdg",
Bucket: "bucket",
Prefix: "prefix",
Provider: "ovh",
},
},
{
"empty region from different provider",
"",
&backuppb.S3{
Region: "",
Bucket: "bucket",
Prefix: "prefix",
Provider: "ovh",
},
},
{
"region from aws",
"us-west-2",
&backuppb.S3{
Region: "us-west-2",
Bucket: "bucket",
Prefix: "prefix",
Provider: "aws",
},
},
}
for _, ca := range cases {
func(name string, region string, s3 *backuppb.S3) {
s := createGetBucketRegionServer(region, 200, true)
defer s.Close()
s3.ForcePathStyle = true
s3.Endpoint = s.URL

t.Log(name)
es, err := New(context.Background(),
&backuppb.StorageBackend{Backend: &backuppb.StorageBackend_S3{S3: s3}},
&ExternalStorageOptions{})
require.NoError(t, err)
ss, ok := es.(*S3Storage)
require.True(t, ok)
require.Equal(t, region, ss.GetOptions().Region)

}(ca.name, ca.expectRegion, ca.s3)
}
}