Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce spare command #13

Merged
merged 2 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ cover.*
data
localstack
/s3hub
/spare
3 changes: 2 additions & 1 deletion .gitleaksignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
389697647cbf4df63a2d2949f648216025355763:localstack/cache/server.test.pem.key:private-key:1
389697647cbf4df63a2d2949f648216025355763:localstack/cache/server.test.pem:private-key:1
389697647cbf4df63a2d2949f648216025355763:localstack/cache/server.test.pem:private-key:1
21b942e8aebe04827785fe961d4c97fb8323f7ba:doc/spare/README.md:generic-api-key:68
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.PHONY: build test clean changelog tools help docker generate gif

S3HUB = s3hub
SPARE = spare
VERSION = $(shell git describe --tags --abbrev=0)
GO = go
GO_BUILD = $(GO) build
Expand All @@ -16,9 +17,11 @@ GO_LDFLAGS = -ldflags '-X github.com/nao1215/rainbow/version.Version=${VERSION}

build: ## Build binary
env GO111MODULE=on GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO_BUILD) $(GO_LDFLAGS) -o $(S3HUB) cmd/s3hub/main.go
env GO111MODULE=on GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO_BUILD) $(GO_LDFLAGS) -o $(SPARE) cmd/spare/main.go


clean: ## Clean project
-rm -rf $(S3HUB) cover.out cover.html
-rm -rf $(S3HUB) $(SPARE) cover.out cover.html

test: ## Start unit test
env GOOS=$(GOOS) $(GO_TEST) -cover $(GO_PKGROOT) -coverprofile=cover.out
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ The rainbow project is a toolset for managing AWS resources. This project consis
[WIP]
|Name|README|implementation|Description|
|:--|:--|:--|:--|
|[s3hub](./doc/s3hub/README.md)|✅||user-friendly s3 management tool|
|[s3hub](./doc/s3hub/README.md)|✅||User-friendly s3 management tool|
|[spare](./doc/spare/README.md)|✅||Single Page Application Release Easily|

### s3hub example
#### Create a bucket(s)
Expand Down
53 changes: 53 additions & 0 deletions app/di/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,56 @@ func newS3App(
S3BucketObjectsDeleter: s3BucketObjectsDeleter,
}
}

// SpareApp is the application service for spare command.
type SpareApp struct {
// CloudFrontCreator is the usecase for creating CloudFront.
usecase.CloudFrontCreator
// FileUploader is the usecase for uploading a file.
usecase.FileUploader
// S3BucketCreator is the usecase for creating a new S3 bucket.
usecase.S3BucketCreator
// S3BucketPublicAccessBlocker is the usecase for blocking public access to a S3 bucket.
usecase.S3BucketPublicAccessBlocker
// BucketPolicySetter is the usecase for setting a bucket policy.
usecase.S3BucketPolicySetter
}

// NewSpareApp creates a new SpareApp.
func NewSpareApp(ctx context.Context, profile model.AWSProfile, region model.Region) (*SpareApp, error) {
wire.Build(
model.NewAWSConfig,
external.NewCloudFrontClient,
external.CloudFrontCreatorSet,
external.OAICreatorSet,
external.NewS3Client,
external.S3BucketCreatorSet,
external.S3BucketObjectUploaderSet,
external.S3BucketPublicAccessBlockerSet,
external.S3BucketPolicySetterSet,
interactor.CloudFrontCreatorSet,
interactor.FileUploaderSet,
interactor.S3BucketCreatorSet,
interactor.S3BucketPublicAccessBlockerSet,
interactor.S3BucketPolicySetterSet,
newSpareApp,
)
return nil, nil
}

// newSpareApp creates a new SpareApp.
func newSpareApp(
cloudFrontCreator usecase.CloudFrontCreator,
fileUploader usecase.FileUploader,
s3BucketCreator usecase.S3BucketCreator,
s3BucketPublicAccessBlocker usecase.S3BucketPublicAccessBlocker,
s3BucketPolicySetter usecase.S3BucketPolicySetter,
) *SpareApp {
return &SpareApp{
CloudFrontCreator: cloudFrontCreator,
FileUploader: fileUploader,
S3BucketCreator: s3BucketCreator,
S3BucketPublicAccessBlocker: s3BucketPublicAccessBlocker,
S3BucketPolicySetter: s3BucketPolicySetter,
}
}
72 changes: 72 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.

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

import (
"errors"
"fmt"
"net/url"
"strings"

"github.com/nao1215/rainbow/utils/errfmt"
)

// Domain is a type that represents a domain name.
type Domain string

// String returns the string representation of Domain.
func (d Domain) String() string {
return string(d)
}

// Validate validates Domain. If Domain is invalid, it returns an error.
// If domain is empty, it returns nil and the default CloudFront domain will be used.
func (d Domain) Validate() error {
for _, part := range strings.Split(d.String(), ".") {
if !isAlphaNumeric(part) {
return errfmt.Wrap(ErrInvalidDomain, fmt.Sprintf("domain %s is invalid", d))
}
}
return nil
}

// isAlphaNumeric returns true if s is alphanumeric.
func isAlphaNumeric(s string) bool {
for _, r := range s {
if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && (r < '0' || r > '9') {
return false
}
}
return true
}

// Empty is whether domain is empty
func (d Domain) Empty() bool {
return d == ""
}

// AllowOrigins is list of origins (domain names) that CloudFront can use as
// the value for the Access-Control-Allow-Origin HTTP response header.
type AllowOrigins []Domain

// Validate validates AllowOrigins. If AllowOrigins is invalid, it returns an error.
func (a AllowOrigins) Validate() (err error) {
for _, origin := range a {
if e := origin.Validate(); e != nil {
err = errors.Join(err, e)
}
}
return err
}

// String returns the string representation of AllowOrigins.
func (a AllowOrigins) String() string {
origins := make([]string, 0, len(a))
for _, origin := range a {
if origin.Empty() {
continue
}
origins = append(origins, origin.String())
}
return strings.Join(origins, ",")
}

// Endpoint is a type that represents an endpoint.
type Endpoint string

// String returns the string representation of Endpoint.
func (e Endpoint) String() string {
return string(e)
}

// Validate validates Endpoint. If Endpoint is invalid, it returns an error.
func (e Endpoint) Validate() error {
if e == "" {
return errfmt.Wrap(ErrInvalidEndpoint, "endpoint is empty")
}

parsedURL, err := url.Parse(e.String())
if err != nil {
return errfmt.Wrap(ErrInvalidDomain, err.Error())
}
host := parsedURL.Host
if host == "" || parsedURL.Scheme == "" {
return errfmt.Wrap(ErrInvalidDomain, host)
}
return nil
}

// DebugLocalstackEndpoint is the endpoint for localstack. It's used for testing.
const DebugLocalstackEndpoint = "http://localhost:4566"
Loading
Loading