diff --git a/storage/object_storage.go b/storage/object_storage.go index a0bb334..72f5811 100644 --- a/storage/object_storage.go +++ b/storage/object_storage.go @@ -2,18 +2,13 @@ package storage import ( "context" - "errors" "fmt" "github.com/aws/aws-sdk-go-v2/aws" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/aws/smithy-go" "net/url" - "os" "path" "strings" - "time" ) type ObjectStorageConfig struct { @@ -34,10 +29,6 @@ var supportedProvider = map[string]struct{}{ "s3c": {}, } -type BucketBasics struct { - S3Client *s3.Client -} - func (storageConfig *ObjectStorageConfig) UploadLocalFile(localDir, localFile, remotePath string) (string, error) { localFullPath := path.Join(localDir, localFile) s3Cfg, err := storageConfig.buildConfig() @@ -45,14 +36,14 @@ func (storageConfig *ObjectStorageConfig) UploadLocalFile(localDir, localFile, r return "", err } - bucketBasics := &BucketBasics{S3Client: s3.NewFromConfig(*s3Cfg)} - // Parse the bucket and key from the remote path bucket, key := parseBucketAndPath(remotePath) if strings.HasSuffix(key, "/") { key += localFile } + bucketBasics := NewBucketBasics(s3Cfg) + err = bucketBasics.UploadFile(context.TODO(), bucket, key, localFullPath) if err != nil { return "", err @@ -61,39 +52,6 @@ func (storageConfig *ObjectStorageConfig) UploadLocalFile(localDir, localFile, r return fmt.Sprintf("File %q successfully uploaded to %s://%s/%s\n", localFullPath, storageConfig.Provider, bucket, key), nil } -func (basics *BucketBasics) UploadFile(ctx context.Context, bucketName string, objectKey string, fileName string) error { - file, err := os.Open(fileName) - if err != nil { - return fmt.Errorf("Couldn't open file %v to upload. Here's why: %v\n", fileName, err) - } else { - defer file.Close() - - _, err = basics.S3Client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(objectKey), - Body: file, - }) - if err != nil { - var apiErr smithy.APIError - if errors.As(err, &apiErr) && apiErr.ErrorCode() == "EntityTooLarge" { - return fmt.Errorf("Error while uploading object to %s. The object is too large.\n"+ - "To upload objects larger than 5GB, use the S3 console (160GB max)\n"+ - "or the multipart upload API (5TB max).", bucketName) - } else { - return fmt.Errorf("Couldn't upload file %v to %v:%v. Here's why: %v\n", - fileName, bucketName, objectKey, err) - } - } else { - err = s3.NewObjectExistsWaiter(basics.S3Client).Wait( - ctx, &s3.HeadObjectInput{Bucket: aws.String(bucketName), Key: aws.String(objectKey)}, time.Minute) - if err != nil { - return fmt.Errorf("Failed attempt to wait for object %s to exist.\n", objectKey) - } - } - } - return err -} - func (storageConfig *ObjectStorageConfig) buildConfig() (cfg *aws.Config, err error) { var s3Cfg aws.Config if storageConfig.Provider == "s3c" { diff --git a/storage/object_storage_client.go b/storage/object_storage_client.go new file mode 100644 index 0000000..d19bafb --- /dev/null +++ b/storage/object_storage_client.go @@ -0,0 +1,54 @@ +package storage + +import ( + "context" + "errors" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/smithy-go" + "os" + "time" +) + +type BucketBasics struct { + S3Client *s3.Client +} + +func NewBucketBasics(config *aws.Config) *BucketBasics { + return &BucketBasics{S3Client: s3.NewFromConfig(*config)} +} + +func (basics *BucketBasics) UploadFile(ctx context.Context, bucketName string, objectKey string, fileName string) error { + file, err := os.Open(fileName) + if err != nil { + return fmt.Errorf("Couldn't open file %v to upload. Here's why: %v\n", fileName, err) + } else { + defer file.Close() + + _, err = basics.S3Client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Body: file, + }) + + if err != nil { + var apiErr smithy.APIError + if errors.As(err, &apiErr) && apiErr.ErrorCode() == "EntityTooLarge" { + return fmt.Errorf("Error while uploading object to %s. The object is too large.\n"+ + "To upload objects larger than 5GB, use the S3 console (160GB max)\n"+ + "or the multipart upload API (5TB max).", bucketName) + } else { + return fmt.Errorf("Couldn't upload file %v to %v:%v. Here's why: %v\n", + fileName, bucketName, objectKey, err) + } + } else { + err = s3.NewObjectExistsWaiter(basics.S3Client).Wait( + ctx, &s3.HeadObjectInput{Bucket: aws.String(bucketName), Key: aws.String(objectKey)}, time.Minute) + if err != nil { + return fmt.Errorf("Failed attempt to wait for object %s to exist.\n", objectKey) + } + } + } + return err +}