160 lines
5.1 KiB
Go
160 lines
5.1 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/tus/tusd/pkg/azurestore"
|
|
"github.com/tus/tusd/pkg/filelocker"
|
|
"github.com/tus/tusd/pkg/filestore"
|
|
"github.com/tus/tusd/pkg/gcsstore"
|
|
"github.com/tus/tusd/pkg/handler"
|
|
"github.com/tus/tusd/pkg/memorylocker"
|
|
"github.com/tus/tusd/pkg/s3store"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
)
|
|
|
|
var Composer *handler.StoreComposer
|
|
|
|
func CreateComposer() {
|
|
// Attempt to use S3 as a backend if the -s3-bucket option has been supplied.
|
|
// If not, we default to storing them locally on disk.
|
|
Composer = handler.NewStoreComposer()
|
|
if Flags.S3Bucket != "" {
|
|
s3Config := aws.NewConfig()
|
|
|
|
if Flags.S3TransferAcceleration {
|
|
s3Config = s3Config.WithS3UseAccelerate(true)
|
|
}
|
|
|
|
if Flags.S3DisableContentHashes {
|
|
// Prevent the S3 service client from automatically
|
|
// adding the Content-MD5 header to S3 Object Put and Upload API calls.
|
|
s3Config = s3Config.WithS3DisableContentMD5Validation(true)
|
|
}
|
|
|
|
if Flags.S3DisableSSL {
|
|
// Disable HTTPS and only use HTTP (helpful for debugging requests).
|
|
s3Config = s3Config.WithDisableSSL(true)
|
|
}
|
|
|
|
if Flags.S3Endpoint == "" {
|
|
|
|
if Flags.S3TransferAcceleration {
|
|
stdout.Printf("Using 's3://%s' as S3 bucket for storage with AWS S3 Transfer Acceleration enabled.\n", Flags.S3Bucket)
|
|
} else {
|
|
stdout.Printf("Using 's3://%s' as S3 bucket for storage.\n", Flags.S3Bucket)
|
|
}
|
|
|
|
} else {
|
|
stdout.Printf("Using '%s/%s' as S3 endpoint and bucket for storage.\n", Flags.S3Endpoint, Flags.S3Bucket)
|
|
|
|
s3Config = s3Config.WithEndpoint(Flags.S3Endpoint).WithS3ForcePathStyle(true)
|
|
}
|
|
|
|
// Derive credentials from default credential chain (env, shared, ec2 instance role)
|
|
// as per https://github.com/aws/aws-sdk-go#configuring-credentials
|
|
store := s3store.New(Flags.S3Bucket, s3.New(session.Must(session.NewSession()), s3Config))
|
|
store.ObjectPrefix = Flags.S3ObjectPrefix
|
|
store.PreferredPartSize = Flags.S3PartSize
|
|
store.DisableContentHashes = Flags.S3DisableContentHashes
|
|
store.UseIn(Composer)
|
|
|
|
locker := memorylocker.New()
|
|
locker.UseIn(Composer)
|
|
} else if Flags.GCSBucket != "" {
|
|
if Flags.GCSObjectPrefix != "" && strings.Contains(Flags.GCSObjectPrefix, "_") {
|
|
stderr.Fatalf("gcs-object-prefix value (%s) can't contain underscore. "+
|
|
"Please remove underscore from the value", Flags.GCSObjectPrefix)
|
|
}
|
|
|
|
// Derivce credentials from service account file path passed in
|
|
// GCS_SERVICE_ACCOUNT_FILE environment variable.
|
|
gcsSAF := os.Getenv("GCS_SERVICE_ACCOUNT_FILE")
|
|
if gcsSAF == "" {
|
|
stderr.Fatalf("No service account file provided for Google Cloud Storage using the GCS_SERVICE_ACCOUNT_FILE environment variable.\n")
|
|
}
|
|
|
|
service, err := gcsstore.NewGCSService(gcsSAF)
|
|
if err != nil {
|
|
stderr.Fatalf("Unable to create Google Cloud Storage service: %s\n", err)
|
|
}
|
|
|
|
stdout.Printf("Using 'gcs://%s' as GCS bucket for storage.\n", Flags.GCSBucket)
|
|
|
|
store := gcsstore.New(Flags.GCSBucket, service)
|
|
store.ObjectPrefix = Flags.GCSObjectPrefix
|
|
store.UseIn(Composer)
|
|
|
|
locker := memorylocker.New()
|
|
locker.UseIn(Composer)
|
|
} else if Flags.AzStorage != "" {
|
|
|
|
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT")
|
|
if accountName == "" {
|
|
stderr.Fatalf("No service account name for Azure BlockBlob Storage using the AZURE_STORAGE_ACCOUNT environment variable.\n")
|
|
}
|
|
|
|
accountKey := os.Getenv("AZURE_STORAGE_KEY")
|
|
if accountKey == "" {
|
|
stderr.Fatalf("No service account key for Azure BlockBlob Storage using the AZURE_STORAGE_KEY environment variable.\n")
|
|
}
|
|
|
|
azureEndpoint := Flags.AzEndpoint
|
|
// Enables support for using Azurite as a storage emulator without messing with proxies and stuff
|
|
// e.g. http://127.0.0.1:10000/devstoreaccount1
|
|
if azureEndpoint == "" {
|
|
azureEndpoint = fmt.Sprintf("https://%s.blob.core.windows.net", accountName)
|
|
stdout.Printf("Custom Azure Endpoint not specified in flag variable azure-endpoint.\n"+
|
|
"Using endpoint %s\n", azureEndpoint)
|
|
} else {
|
|
stdout.Printf("Using Azure endpoint %s\n", azureEndpoint)
|
|
}
|
|
|
|
azConfig := &azurestore.AzConfig{
|
|
AccountName: accountName,
|
|
AccountKey: accountKey,
|
|
ContainerName: Flags.AzStorage,
|
|
ContainerAccessType: Flags.AzContainerAccessType,
|
|
BlobAccessTier: Flags.AzBlobAccessTier,
|
|
Endpoint: azureEndpoint,
|
|
}
|
|
|
|
azService, err := azurestore.NewAzureService(azConfig)
|
|
if err != nil {
|
|
stderr.Fatalf(err.Error())
|
|
}
|
|
|
|
store := azurestore.New(azService)
|
|
store.ObjectPrefix = Flags.AzObjectPrefix
|
|
store.Container = Flags.AzStorage
|
|
store.UseIn(Composer)
|
|
|
|
locker := memorylocker.New()
|
|
locker.UseIn(Composer)
|
|
} else {
|
|
dir, err := filepath.Abs(Flags.UploadDir)
|
|
if err != nil {
|
|
stderr.Fatalf("Unable to make absolute path: %s", err)
|
|
}
|
|
|
|
stdout.Printf("Using '%s' as directory storage.\n", dir)
|
|
if err := os.MkdirAll(dir, os.FileMode(0774)); err != nil {
|
|
stderr.Fatalf("Unable to ensure directory exists: %s", err)
|
|
}
|
|
|
|
store := filestore.New(dir)
|
|
store.UseIn(Composer)
|
|
|
|
locker := filelocker.New(dir)
|
|
locker.UseIn(Composer)
|
|
}
|
|
|
|
stdout.Printf("Using %.2fMB as maximum size.\n", float64(Flags.MaxSize)/1024/1024)
|
|
}
|