diff --git a/modules/storage/minio.go b/modules/storage/minio.go index 3246993bb1..26f947fdfe 100644 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -71,6 +71,11 @@ func convertMinioErr(err error) error { return err } +var getBucketVersioning = func(ctx context.Context, minioClient *minio.Client, bucket string) error { + _, err := minioClient.GetBucketVersioning(ctx, bucket) + return err +} + // NewMinioStorage returns a minio storage func NewMinioStorage(ctx context.Context, cfg *setting.Storage) (ObjectStorage, error) { config := cfg.MinioConfig @@ -90,6 +95,19 @@ func NewMinioStorage(ctx context.Context, cfg *setting.Storage) (ObjectStorage, return nil, convertMinioErr(err) } + // Check if the connection works + err = getBucketVersioning(ctx, minioClient, config.Bucket) + if err != nil { + errResp, ok := err.(minio.ErrorResponse) + if !ok { + return nil, err + } + if errResp.StatusCode == http.StatusBadRequest { + log.Error("S3 storage connection failure at %s:%s with base path %s and region: %s", config.Endpoint, config.Bucket, config.Location, errResp.Message) + return nil, err + } + } + // Check to see if we already own this bucket exists, err := minioClient.BucketExists(ctx, config.Bucket) if err != nil { diff --git a/modules/storage/minio_test.go b/modules/storage/minio_test.go index 8fdf31e6cf..bb1d0e954a 100644 --- a/modules/storage/minio_test.go +++ b/modules/storage/minio_test.go @@ -4,10 +4,17 @@ package storage import ( + "context" + "net/http" "os" "testing" + "time" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + + "github.com/minio/minio-go/v7" + "github.com/stretchr/testify/assert" ) func TestMinioStorageIterator(t *testing.T) { @@ -25,3 +32,35 @@ func TestMinioStorageIterator(t *testing.T) { }, }) } + +func TestS3StorageBadRequest(t *testing.T) { + if os.Getenv("CI") == "" { + t.Skip("S3Storage not present outside of CI") + return + } + lc, cleanup := test.NewLogChecker("bad-request") + lc.StopMark("S3 storage connection failure") + defer cleanup() + cfg := &setting.Storage{ + MinioConfig: setting.MinioStorageConfig{ + Endpoint: "minio:9000", + AccessKeyID: "123456", + SecretAccessKey: "12345678", + Bucket: "bucket", + Location: "us-east-1", + }, + } + message := "ERROR" + defer test.MockVariableValue(&getBucketVersioning, func(ctx context.Context, minioClient *minio.Client, bucket string) error { + return minio.ErrorResponse{ + StatusCode: http.StatusBadRequest, + Code: "FixtureError", + Message: message, + } + })() + _, err := NewStorage(setting.MinioStorageType, cfg) + assert.ErrorContains(t, err, message) + + _, stopped := lc.Check(100 * time.Millisecond) + assert.False(t, stopped) +}