JCS-pub/common/pkgs/storage/s3/s3.go

122 lines
3.1 KiB
Go

package s3
import (
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/factory/reg"
"gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
)
func init() {
reg.RegisterBuilder[*cortypes.S3Type](newBuilder)
}
type builder struct {
types.EmptyBuilder
detail *clitypes.UserSpaceDetail
}
func newBuilder(detail *clitypes.UserSpaceDetail) types.StorageBuilder {
return &builder{
detail: detail,
}
}
func (b *builder) FeatureDesc() types.FeatureDesc {
return types.FeatureDesc{}
}
func (b *builder) CreateShardStore(typeOnly bool) (types.ShardStore, error) {
stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type)
s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred)
if !ok {
return nil, fmt.Errorf("invalid storage credential type %T for s3 storage", b.detail.UserSpace.Credential)
}
if typeOnly {
return (*ShardStore)(nil), nil
}
cli, bkt, err := createClient(stgType, s3Cred)
if err != nil {
return nil, err
}
return NewShardStore(b.detail, cli, bkt, ShardStoreOption{UseAWSSha256: true})
}
func (b *builder) CreateBaseStore(typeOnly bool) (types.BaseStore, error) {
stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type)
s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred)
if !ok {
return nil, fmt.Errorf("invalid storage credential type %T for s3 storage", b.detail.UserSpace.Credential)
}
if typeOnly {
return (*BaseStore)(nil), nil
}
cli, bkt, err := createClient(stgType, s3Cred)
if err != nil {
return nil, err
}
return NewBaseStore(b.detail, cli, bkt, BaseStoreOption{UseAWSSha256: false})
}
func createClient(stgType *cortypes.S3Type, cred *cortypes.S3Cred) (*s3.Client, string, error) {
awsConfig := aws.Config{}
if cred.AK != "" && cred.SK != "" {
cre := aws.Credentials{
AccessKeyID: cred.AK,
SecretAccessKey: cred.SK,
}
awsConfig.Credentials = &credentials.StaticCredentialsProvider{Value: cre}
}
awsConfig.Region = stgType.Region
options := []func(*s3.Options){}
options = append(options, func(s3Opt *s3.Options) {
s3Opt.BaseEndpoint = &stgType.Endpoint
})
cli := s3.NewFromConfig(awsConfig, options...)
return cli, stgType.Bucket, nil
}
func (b *builder) CreateMultiparter(typeOnly bool) (types.Multiparter, error) {
stgType := b.detail.UserSpace.Storage.(*cortypes.S3Type)
feat := types.FindFeature[*cortypes.MultipartUploadFeature](b.detail)
if feat == nil {
return nil, fmt.Errorf("feature %T not found", cortypes.MultipartUploadFeature{})
}
s3Cred, ok := b.detail.UserSpace.Credential.(*cortypes.S3Cred)
if !ok {
return nil, fmt.Errorf("invalid storage credential type %T for s3 base store", b.detail.UserSpace.Credential)
}
if typeOnly {
return (*Multiparter)(nil), nil
}
cli, bucket, err := createClient(stgType, s3Cred)
if err != nil {
return nil, err
}
return NewMultiparter(
b.detail,
feat,
bucket,
cli,
), nil
}