Skip to content

Commit

Permalink
add: create s3 bucket interface
Browse files Browse the repository at this point in the history
  • Loading branch information
nao1215 committed Dec 25, 2023
1 parent f1530c7 commit 2dd78c4
Show file tree
Hide file tree
Showing 21 changed files with 1,019 additions and 37 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VERSION = $(shell git describe --tags --abbrev=0)
GO = go
GO_BUILD = $(GO) build
GO_INSTALL = $(GO) install
GO_TEST = $(GO) test -v
GO_TEST = hottest -v
GO_TOOL = $(GO) tool
GO_DEP = $(GO) mod
GOOS = ""
Expand All @@ -29,6 +29,8 @@ changelog: ## Generate changelog

tools: ## Install dependency tools
$(GO_INSTALL) github.com/Songmu/ghch/cmd/ghch@latest
$(GO_INSTALL) github.com/nao1215/hottest@latest
$(GO_INSTALL) github.com/google/wire/cmd/wire@latest

.DEFAULT_GOAL := help
help:
Expand Down
39 changes: 39 additions & 0 deletions app/di/wire.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//go:build wireinject
// +build wireinject

// Package di Inject dependence by wire command.
package di

import (
"context"

"github.com/google/wire"
"github.com/nao1215/rainbow/app/domain/model"
"github.com/nao1215/rainbow/app/external"
"github.com/nao1215/rainbow/app/interactor"
"github.com/nao1215/rainbow/app/usecase"
)

// S3App is the application service for S3.
type S3App struct {
// S3BucketCreator is the usecase for creating a new S3 bucket.
s3bucketCreator usecase.S3BucketCreator
}

// NewS3App creates a new S3App.
func NewS3App(ctx context.Context, profile model.AWSProfile, region model.Region) (*S3App, error) {
wire.Build(
model.NewAWSConfig,
external.NewS3Client,
external.S3BucketCreatorSet,
interactor.S3bucketCreatorSet,
newS3App,
)
return nil, nil
}

func newS3App(s3bucketCreator usecase.S3BucketCreator) *S3App {
return &S3App{
s3bucketCreator: s3bucketCreator,
}
}
47 changes: 47 additions & 0 deletions app/di/wire_gen.go

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

62 changes: 62 additions & 0 deletions app/domain/model/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package model

import (
"context"
"os"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
)

// AWSProfile is the name of the AWS profile.
type AWSProfile string

// NewAWSProfile returns a new AWSProfile.
// If p is empty, read $AWS_PROFILE and return it.
func NewAWSProfile(p string) AWSProfile {
if p == "" {
profile := os.Getenv("AWS_PROFILE")
if profile == "" {
return AWSProfile("default")
}
return AWSProfile(profile)
}
return AWSProfile(p)
}

// String returns the string representation of the AWSProfile.
func (p AWSProfile) String() string {
return string(p)
}

// AWSConfig is the AWS config.
type AWSConfig struct {
*aws.Config
}

// NewAWSConfig creates a new AWS config.
func NewAWSConfig(ctx context.Context, profile AWSProfile, region Region) (*AWSConfig, error) {
opts := []func(*config.LoadOptions) error{}
if profile.String() != "" {
opts = append(opts, config.WithSharedConfigProfile(profile.String()))
}
if region.String() != "" {
opts = append(opts, config.WithRegion(string(region)))
}

cfg, err := config.LoadDefaultConfig(ctx, opts...)
if err != nil {
return nil, err
}
return &AWSConfig{
Config: &cfg,
}, nil
}

// Region returns the AWS region.
func (c *AWSConfig) Region() Region {
if Region(c.Config.Region) == "" {
return RegionUSEast1
}
return Region(c.Config.Region)
}
76 changes: 76 additions & 0 deletions app/domain/model/aws_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package model

import (
"testing"
)

func TestNewAWSProfile(t *testing.T) { //nolint
type args struct {
p string
}
tests := []struct {
name string
args args
want AWSProfile
}{
{
name: "success",
args: args{
p: "test",
},
want: AWSProfile("test"),
},
{
name: "success. p is empty",
args: args{
p: "",
},
want: AWSProfile("from env"),
},
{
name: "success. p is empty and $AWS_PROFILE is empty",
args: args{
p: "",
},
want: AWSProfile("default"),
},
}
for _, tt := range tests { //nolint
if tt.name == "success. p is empty" {
t.Setenv("AWS_PROFILE", "from env")
} else if tt.name == "success. p is empty and $AWS_PROFILE is empty" {
t.Setenv("AWS_PROFILE", "")
}

t.Run(tt.name, func(t *testing.T) {
if got := NewAWSProfile(tt.args.p); got != tt.want {
t.Errorf("NewAWSProfile() = %v, want %v", got, tt.want)
}
})
}
}

func TestAWSProfileString(t *testing.T) {
t.Parallel()

tests := []struct {
name string
p AWSProfile
want string
}{
{
name: "success",
p: AWSProfile("test"),
want: "test",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := tt.p.String(); got != tt.want {
t.Errorf("AWSProfile.String() = %v, want %v", got, tt.want)
}
})
}
}
12 changes: 12 additions & 0 deletions app/domain/model/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package model

import "errors"

var (
// ErrInvalidRegion is an error that occurs when the region is invalid.
ErrInvalidRegion = errors.New("invalid region")
// ErrEmptyRegion is an error that occurs when the region is empty.
ErrEmptyRegion = errors.New("region is empty")
// ErrInvalidBucketName is an error that occurs when the bucket name is invalid.
ErrInvalidBucketName = errors.New("bucket name is invalid")
)
10 changes: 10 additions & 0 deletions app/domain/model/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package model

// Validator is an interface that represents a validator.
type Validator interface {
// Validate validates the value.
Validate() error
}

// ValidationFunc is a type that represents a validation function.
type ValidationFunc func() error
Loading

0 comments on commit 2dd78c4

Please sign in to comment.