mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 16:07:33 +08:00
support minio as object storage
This commit is contained in:
@@ -60,6 +60,7 @@ const (
|
||||
// Object Storage types
|
||||
const (
|
||||
LocalFileSystemObjectStorageType string = "local_filesystem"
|
||||
MinIOStorageType string = "minio"
|
||||
)
|
||||
|
||||
// Uuid generator types
|
||||
@@ -165,6 +166,17 @@ type SMTPConfig struct {
|
||||
FromAddress string
|
||||
}
|
||||
|
||||
type MinIOConfig struct {
|
||||
Endpoint string
|
||||
Location string
|
||||
AccessKeyID string
|
||||
SecretAccessKey string
|
||||
UseSSL bool
|
||||
SkipTLSVerify bool
|
||||
Bucket string
|
||||
RootPath string
|
||||
}
|
||||
|
||||
// Config represents the global setting config
|
||||
type Config struct {
|
||||
// Global
|
||||
@@ -210,6 +222,7 @@ type Config struct {
|
||||
// Storage
|
||||
StorageType string
|
||||
LocalFileSystemPath string
|
||||
MinIOConfig *MinIOConfig
|
||||
|
||||
// Uuid
|
||||
UuidGeneratorType string
|
||||
@@ -542,6 +555,8 @@ func loadLogConfiguration(config *Config, configFile *ini.File, sectionName stri
|
||||
func loadStorageConfiguration(config *Config, configFile *ini.File, sectionName string) error {
|
||||
if getConfigItemStringValue(configFile, sectionName, "storage_type") == LocalFileSystemObjectStorageType {
|
||||
config.StorageType = LocalFileSystemObjectStorageType
|
||||
} else if getConfigItemStringValue(configFile, sectionName, "storage_type") == MinIOStorageType {
|
||||
config.StorageType = MinIOStorageType
|
||||
} else {
|
||||
return errs.ErrInvalidStorageType
|
||||
}
|
||||
@@ -554,6 +569,18 @@ func loadStorageConfiguration(config *Config, configFile *ini.File, sectionName
|
||||
return errs.ErrInvalidLocalFileSystemStoragePath
|
||||
}
|
||||
|
||||
minIOConfig := &MinIOConfig{}
|
||||
minIOConfig.Endpoint = getConfigItemStringValue(configFile, sectionName, "minio_endpoint")
|
||||
minIOConfig.Location = getConfigItemStringValue(configFile, sectionName, "minio_location")
|
||||
minIOConfig.AccessKeyID = getConfigItemStringValue(configFile, sectionName, "minio_access_key_id")
|
||||
minIOConfig.SecretAccessKey = getConfigItemStringValue(configFile, sectionName, "minio_secret_access_key")
|
||||
minIOConfig.UseSSL = getConfigItemBoolValue(configFile, sectionName, "minio_use_ssl", false)
|
||||
minIOConfig.SkipTLSVerify = getConfigItemBoolValue(configFile, sectionName, "minio_skip_tls_verify", false)
|
||||
minIOConfig.Bucket = getConfigItemStringValue(configFile, sectionName, "minio_bucket")
|
||||
minIOConfig.RootPath = getConfigItemStringValue(configFile, sectionName, "minio_root_path")
|
||||
|
||||
config.MinIOConfig = minIOConfig
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
||||
)
|
||||
|
||||
// MinIOObjectStorage represents MinIO object storage
|
||||
type MinIOObjectStorage struct {
|
||||
minIOClient *minio.Client
|
||||
minIOConfig *settings.MinIOConfig
|
||||
rootPath string
|
||||
}
|
||||
|
||||
// NewMinIOObjectStorage returns a MinIO object storage
|
||||
func NewMinIOObjectStorage(config *settings.Config, pathPrefix string) (*MinIOObjectStorage, error) {
|
||||
minIOConfig := config.MinIOConfig
|
||||
|
||||
minIOClient, err := minio.New(minIOConfig.Endpoint, &minio.Options{
|
||||
Region: minIOConfig.Location,
|
||||
Creds: credentials.NewStaticV4(minIOConfig.AccessKeyID, minIOConfig.SecretAccessKey, ""),
|
||||
Secure: minIOConfig.UseSSL,
|
||||
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: minIOConfig.SkipTLSVerify}},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storage := &MinIOObjectStorage{
|
||||
minIOClient: minIOClient,
|
||||
minIOConfig: minIOConfig,
|
||||
rootPath: minIOConfig.RootPath,
|
||||
}
|
||||
|
||||
storage.rootPath = storage.getFinalPath(pathPrefix)
|
||||
|
||||
ctx := context.Background()
|
||||
exists, err := minIOClient.BucketExists(ctx, minIOConfig.Bucket)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
err := minIOClient.MakeBucket(ctx, minIOConfig.Bucket, minio.MakeBucketOptions{
|
||||
Region: minIOConfig.Location,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
// Exists returns whether the file exists
|
||||
func (s *MinIOObjectStorage) Exists(path string) (bool, error) {
|
||||
ctx := context.Background()
|
||||
objectInfo, err := s.minIOClient.StatObject(ctx, s.minIOConfig.Bucket, s.getFinalPath(path), minio.StatObjectOptions{})
|
||||
|
||||
if err == nil && !objectInfo.IsDeleteMarker {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Read returns the object instance according to specified the file path
|
||||
func (s *MinIOObjectStorage) Read(path string) (ObjectInStorage, error) {
|
||||
ctx := context.Background()
|
||||
return s.minIOClient.GetObject(ctx, s.minIOConfig.Bucket, s.getFinalPath(path), minio.GetObjectOptions{})
|
||||
}
|
||||
|
||||
// Save returns whether save the object instance successfully
|
||||
func (s *MinIOObjectStorage) Save(path string, object ObjectInStorage) error {
|
||||
ctx := context.Background()
|
||||
_, err := s.minIOClient.PutObject(ctx, s.minIOConfig.Bucket, s.getFinalPath(path), object, -1, minio.PutObjectOptions{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete returns whether delete the object according to specified the file path successfully
|
||||
func (s *MinIOObjectStorage) Delete(path string) error {
|
||||
ctx := context.Background()
|
||||
return s.minIOClient.RemoveObject(ctx, s.minIOConfig.Bucket, s.getFinalPath(path), minio.RemoveObjectOptions{})
|
||||
}
|
||||
|
||||
func (s *MinIOObjectStorage) getFinalPath(path string) string {
|
||||
rootPath := s.rootPath
|
||||
|
||||
if len(rootPath) < 1 || rootPath[len(rootPath)-1] != '/' {
|
||||
rootPath = rootPath + "/"
|
||||
}
|
||||
|
||||
if len(path) > 0 && path[0] == '/' {
|
||||
path = path[1:]
|
||||
}
|
||||
|
||||
return rootPath + path
|
||||
}
|
||||
@@ -22,8 +22,13 @@ var (
|
||||
// InitializeStorageContainer initializes the current object storage according to the config
|
||||
func InitializeStorageContainer(config *settings.Config) error {
|
||||
if config.StorageType == settings.LocalFileSystemObjectStorageType {
|
||||
storage, err := NewLocalFileSystemObjectStorage(config, avatarPathPrefix)
|
||||
Container.AvatarCurrentStorage = storage
|
||||
avatarStorage, err := NewLocalFileSystemObjectStorage(config, avatarPathPrefix)
|
||||
Container.AvatarCurrentStorage = avatarStorage
|
||||
|
||||
return err
|
||||
} else if config.StorageType == settings.MinIOStorageType {
|
||||
avatarStorage, err := NewMinIOObjectStorage(config, avatarPathPrefix)
|
||||
Container.AvatarCurrentStorage = avatarStorage
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user