Skip to content

Commit

Permalink
implement s3hub cp subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Jan 2, 2024
1 parent 1208623 commit 984513c
Show file tree
Hide file tree
Showing 10 changed files with 398 additions and 27 deletions.
6 changes: 6 additions & 0 deletions app/di/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type S3App struct {
usecase.S3ObjectDownloader
// FileUploader is the usecase for uploading a file.
usecase.FileUploader
// S3ObjectCopier is the usecase for copying a file in S3 bucket.
usecase.S3ObjectCopier
}

// NewS3App creates a new S3App.
Expand All @@ -45,13 +47,15 @@ func NewS3App(ctx context.Context, profile model.AWSProfile, region model.Region
external.S3ObjectsDeleterSet,
external.S3ObjectDownloaderSet,
external.S3ObjectUploaderSet,
external.S3ObjectCopierSet,
interactor.S3BucketCreatorSet,
interactor.S3BucketListerSet,
interactor.S3BucketDeleterSet,
interactor.S3ObjectsListerSet,
interactor.S3ObjectsDeleterSet,
interactor.S3ObjectDownloaderSet,
interactor.FileUploaderSet,
interactor.S3ObjectCopierSet,
newS3App,
)
return nil, nil
Expand All @@ -65,6 +69,7 @@ func newS3App(
S3ObjectsDeleter usecase.S3ObjectsDeleter,
s3ObjectDownloader usecase.S3ObjectDownloader,
fileUploader usecase.FileUploader,
s3ObjectCopier usecase.S3ObjectCopier,
) *S3App {
return &S3App{
S3BucketCreator: s3BucketCreator,
Expand All @@ -74,6 +79,7 @@ func newS3App(
S3ObjectsDeleter: S3ObjectsDeleter,
S3ObjectDownloader: s3ObjectDownloader,
FileUploader: fileUploader,
S3ObjectCopier: s3ObjectCopier,
}
}

Expand Down
9 changes: 8 additions & 1 deletion app/di/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions app/domain/model/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ func NewBucketWithoutProtocol(s string) Bucket {
return Bucket(strings.TrimPrefix(s, S3Protocol))
}

// WithProtocol returns the Bucket with the protocol.
func (b Bucket) WithProtocol() Bucket {
return Bucket(S3Protocol + b.String())
}

// Join returns the Bucket with the S3Key.
// e.g. "bucket" + "key" -> "bucket/key"
func (b Bucket) Join(key S3Key) Bucket {
return Bucket(fmt.Sprintf("%s/%s", b.String(), key.String()))
}

// String returns the string representation of the Bucket.
func (b Bucket) String() string {
return string(b)
Expand Down Expand Up @@ -377,6 +388,10 @@ func (k S3Key) IsAll() bool {
return k == "*"
}

func (k S3Key) Join(key S3Key) S3Key {
return S3Key(fmt.Sprintf("%s/%s", k.String(), key))
}

// VersionID is the version ID for the specific version of the object to delete.
// This functionality is not supported for directory buckets.
type VersionID string
Expand Down
20 changes: 20 additions & 0 deletions app/domain/service/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,23 @@ type S3ObjectUploaderOutput struct {
type S3ObjectUploader interface {
UploadS3Object(ctx context.Context, input *S3ObjectUploaderInput) (*S3ObjectUploaderOutput, error)
}

// S3ObjectCopierInput is the input of the CopyBucketObject method.
type S3ObjectCopierInput struct {
// SourceBucket is the name of the source bucket.
SourceBucket model.Bucket
// SourceKey is the key of the source object.
SourceKey model.S3Key
// DestinationBucket is the name of the destination bucket.
DestinationBucket model.Bucket
// DestinationKey is the key of the destination object.
DestinationKey model.S3Key
}

// S3ObjectCopierOutput is the output of the CopyBucketObject method.
type S3ObjectCopierOutput struct{}

// S3ObjectCopier is the interface that wraps the basic CopyBucketObject method.
type S3ObjectCopier interface {
CopyS3Object(ctx context.Context, input *S3ObjectCopierInput) (*S3ObjectCopierOutput, error)
}
39 changes: 28 additions & 11 deletions app/external/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,18 +357,35 @@ func (c *S3ObjectUploader) UploadS3Object(ctx context.Context, input *service.S3
}, nil
}

// BucketPublicAccessBlockerInput is an input struct for BucketAccessBlocker.
type BucketPublicAccessBlockerInput struct {
// Bucket is the name of the bucket.
Bucket model.Bucket
// Region is the name of the region.
Region model.Region
// S3ObjectCopier implements the S3ObjectCopier interface.
type S3ObjectCopier struct {
client *s3.Client
}

// BucketPublicAccessBlockerOutput is an output struct for BucketAccessBlocker.
type BucketPublicAccessBlockerOutput struct{}
// S3ObjectCopierSet is a provider set for S3ObjectCopier.
//
//nolint:gochecknoglobals
var S3ObjectCopierSet = wire.NewSet(
NewS3ObjectCopier,
wire.Bind(new(service.S3ObjectCopier), new(*S3ObjectCopier)),
)

var _ service.S3ObjectCopier = (*S3ObjectCopier)(nil)

// BucketPublicAccessBlocker is an interface for blocking access to a bucket.
type BucketPublicAccessBlocker interface {
BlockBucketPublicAccess(context.Context, *BucketPublicAccessBlockerInput) (*BucketPublicAccessBlockerOutput, error)
// NewS3ObjectCopier creates a new S3ObjectCopier.
func NewS3ObjectCopier(client *s3.Client) *S3ObjectCopier {
return &S3ObjectCopier{client: client}
}

// CopyS3Object copies the object in the bucket.
func (c *S3ObjectCopier) CopyS3Object(ctx context.Context, input *service.S3ObjectCopierInput) (*service.S3ObjectCopierOutput, error) {
_, err := c.client.CopyObject(ctx, &s3.CopyObjectInput{
Bucket: aws.String(input.DestinationBucket.String()),
CopySource: aws.String(input.SourceBucket.Join(input.SourceKey).String()),
Key: aws.String(input.DestinationKey.String()),
})
if err != nil {
return nil, err
}
return &service.S3ObjectCopierOutput{}, nil
}
43 changes: 43 additions & 0 deletions app/interactor/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,46 @@ func (s *S3ObjectDownloader) DownloadS3Object(ctx context.Context, input *usecas
S3Object: out.S3Object,
}, nil
}


// S3ObjectCopierSet is a provider set for S3ObjectCopier.
//
//nolint:gochecknoglobals
var S3ObjectCopierSet = wire.NewSet(
NewS3ObjectCopier,
wire.Bind(new(usecase.S3ObjectCopier), new(*S3ObjectCopier)),
)

// S3ObjectCopier is an implementation for S3ObjectCopier.
type S3ObjectCopier struct {
service.S3ObjectCopier
}

var _ usecase.S3ObjectCopier = (*S3ObjectCopier)(nil)

// NewS3ObjectCopier returns a new S3ObjectCopier struct.
func NewS3ObjectCopier(c service.S3ObjectCopier) *S3ObjectCopier {
return &S3ObjectCopier{
S3ObjectCopier: c,
}
}

// CopyS3Object copies an object from S3 to S3.
func (s *S3ObjectCopier) CopyS3Object(ctx context.Context, input *usecase.S3ObjectCopierInput) (*usecase.S3ObjectCopierOutput, error) {
if err := input.SourceBucket.Validate(); err != nil {
return nil, err
}
if err := input.DestinationBucket.Validate(); err != nil {
return nil, err
}

if _, err := s.S3ObjectCopier.CopyS3Object(ctx, &service.S3ObjectCopierInput{
SourceBucket: input.SourceBucket,
SourceKey: input.SourceKey,
DestinationBucket: input.DestinationBucket,
DestinationKey: input.DestinationKey,
}); err != nil {
return nil, err
}
return &usecase.S3ObjectCopierOutput{}, nil
}
21 changes: 21 additions & 0 deletions app/usecase/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,24 @@ type UploadFileOutput struct {
// ContentLength is the content length of the uploaded file.
ContentLength int64
}

// S3ObjectCopierInput is the input of the CopyObject method.
type S3ObjectCopierInput struct {
// SourceBucket is the name of the source bucket.
SourceBucket model.Bucket
// SourceKey is the key of the source object.
SourceKey model.S3Key
// DestinationBucket is the name of the destination bucket.
DestinationBucket model.Bucket
// DestinationKey is the key of the destination object.
DestinationKey model.S3Key
}

// S3ObjectCopierOutput is the output of the CopyObject method.
type S3ObjectCopierOutput struct{}

// S3ObjectCopier is the interface that wraps the basic CopyObject method.
type S3ObjectCopier interface {
CopyS3Object(ctx context.Context, input *S3ObjectCopierInput) (*S3ObjectCopierOutput, error)
}

Loading

0 comments on commit 984513c

Please sign in to comment.