diff --git a/.cfignore b/.cfignore index 1f81a49..93d1107 100644 --- a/.cfignore +++ b/.cfignore @@ -1,5 +1,5 @@ /* -!/templates -!/entrypoint-cf.sh !/s3manager +!/web/ +!/deployments/cf/ diff --git a/.gitignore b/.gitignore index 4dc01c6..e84600e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -vendor/ /s3manager +/s3manager.exe +/vendor/ diff --git a/.travis.yml b/.travis.yml index 0da3238..4597b48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: go before_install: - - go get -t -v ./... +- curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + +install: +- dep ensure script: - - go test -race -coverprofile=coverage.txt -covermode=atomic - -after_success: - - bash <(curl -s https://codecov.io/bash) +- go test ./... -race diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 926a794..0000000 --- a/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM golang - -ADD . /go/src/github.com/mastertinner/s3manager -WORKDIR /go/src/github.com/mastertinner/s3manager - -RUN go build ./cmd/s3manager - -EXPOSE 8080 - -CMD ./s3manager -endpoint "${S3_ENDPOINT}" -access-key-id "${S3_ACCESS_KEY_ID}" -secret-access-key "${S3_SECRET_ACCESS_KEY}" diff --git a/Gopkg.lock b/Gopkg.lock index 61d19f1..5b4776b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -16,8 +16,8 @@ [[projects]] name = "github.com/go-ini/ini" packages = ["."] - revision = "6333e38ac20b8949a8dd68baa3650f4dee8f39f0" - version = "v1.33.0" + revision = "ace140f73450505f33e8b8418216792275ae82a7" + version = "v1.35.0" [[projects]] name = "github.com/gorilla/context" @@ -35,7 +35,7 @@ branch = "master" name = "github.com/mastertinner/adapters" packages = ["logging"] - revision = "368acae73d1569f0495b00991aaa85ec27d6ee8e" + revision = "9dd1b86beda61f4746be3a5ee267f1566ab032ce" [[projects]] name = "github.com/minio/minio-go" @@ -48,8 +48,8 @@ "pkg/s3utils", "pkg/set" ] - revision = "9e124ec59547551cb3f1324f73623bbb30650cf8" - version = "4.0.9" + revision = "66252c2a3c15f7b90cc8493d497a04ac3b6e3606" + version = "5.0.0" [[projects]] branch = "master" @@ -72,8 +72,8 @@ [[projects]] name = "github.com/sirupsen/logrus" packages = ["."] - revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" - version = "v1.0.4" + revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" + version = "v1.0.5" [[projects]] name = "github.com/stretchr/testify" @@ -84,8 +84,12 @@ [[projects]] branch = "master" name = "golang.org/x/crypto" - packages = ["ssh/terminal"] - revision = "c7dcf104e3a7a1417abc0230cb0d5240d764159d" + packages = [ + "argon2", + "blake2b", + "ssh/terminal" + ] + revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e" [[projects]] branch = "master" @@ -94,7 +98,7 @@ "idna", "lex/httplex" ] - revision = "d0aafc73d5cdc42264b0af071c261abac580695e" + revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41" [[projects]] branch = "master" @@ -103,7 +107,7 @@ "unix", "windows" ] - revision = "7dca6fe1f43775aa6d1334576870ff63f978f539" + revision = "f6f352972f061230a99fbf49d1eb8073ebdb36cb" [[projects]] name = "golang.org/x/text" @@ -129,6 +133,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "c70e9710ac0caf3a2f9041ebee7ea3804e6474256bb86e91795a5eb8788accc6" + inputs-digest = "2eb6d0e6d0142a6a38557c70a42069775e66ccbe7aea1620c03752808dcacb1a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 0c5b2fb..6e55710 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -35,7 +35,7 @@ [[constraint]] name = "github.com/minio/minio-go" - version = "4.0.9" + version = "5.0.0" [[constraint]] name = "github.com/pkg/errors" diff --git a/Makefile b/Makefile index 6ab0ed4..b56e77a 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,11 @@ all: go build ./cmd/s3manager test: - go test + go test ./... build-docker: - docker run --rm -v "${PWD}:/go/src/github.com/mastertinner/s3manager" -w /go/src/github.com/mastertinner/s3manager golang go build ./cmd/s3manager + docker build . -f build/docker/Dockerfile -t s3manager deploy-cf: GOOS=linux GOARCH=amd64 go build ./cmd/s3manager - cf push + cf push -f deployments/cf/manifest.yml diff --git a/README.md b/README.md index 87ac703..dc6fbb0 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,30 @@ # S3 Manager -[![Go Report Card](https://goreportcard.com/badge/github.com/mastertinner/s3manager)](https://goreportcard.com/report/github.com/mastertinner/s3manager) -[![Build Status](https://travis-ci.org/mastertinner/s3manager.svg?branch=master)](https://travis-ci.org/mastertinner/s3manager) -[![codecov](https://codecov.io/gh/mastertinner/s3manager/branch/master/graph/badge.svg)](https://codecov.io/gh/mastertinner/s3manager) +[![Go Report Card](https://goreportcard.com/badge/github.com/mastertinner/s3manager?style=flat-square)](https://goreportcard.com/report/github.com/mastertinner/s3manager) +[![Build Status](https://travis-ci.org/mastertinner/s3manager.svg?branch=master&style=flat-square)](https://travis-ci.org/mastertinner/s3manager) +[![Release](https://img.shields.io/github/release/mastertinner/s3manager.svg?style=flat-square)](https://github.com/mastertinner/s3manager/releases/latest) A Web GUI written in Go to manage S3 buckets from any provider. -## Run locally +## Install Dependencies -1. Run `make` -1. Execute the created binary and visit +1. Install [Dep](https://github.com/golang/dep) +1. Run `dep ensure` -## Run with Docker +## Build and Run Locally -1. Set environment variables in `docker-compose.yml` -1. Run `docker-compose up` -1. Visit +1. Run `make` +1. Execute the created binary and visit -## Build with Docker and run anywhere +## Run Tests -1. Run `make build-docker` +1. Run `make test` - To cross-compile for windows, add the `-e "GOOS=windows" -e "GOARCH=amd64"` flags to the `Makefile` (depending on your system, you might have to adjust `GOARCH`) +## Build Docker Image - To cross-compile for macOS, add the `-e "GOOS=darwin" -e "GOARCH=amd64"` flags to the `Makefile` (depending on your system, you might have to adjust `GOARCH`) +1. Run `make build-docker` ## Run on Cloud Foundry -1. Change the service in `manifest.yml` to represent your S3 service (if you are using an external S3 provider, you'll have to switch the service type in `entrypoint-cf.sh` from `dynstrg` to `user-provided` and create the respective user-provided service with `cf create-user-provided-service`) -1. Add a route in `manifest.yml` that isn't taken yet -1. Run `make deploy-cf` +1. Modify `deployments/cf/*` to your liking +1. Run `make deploy-cf` diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile new file mode 100644 index 0000000..b517a2d --- /dev/null +++ b/build/docker/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:latest + +WORKDIR /go/src/github.com/mastertinner/s3manager +COPY . . + +RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh +RUN dep ensure +RUN go build ./cmd/s3manager + +EXPOSE 8080 + +ENTRYPOINT ["./s3manager"] diff --git a/cmd/s3manager/main.go b/cmd/s3manager/main.go index 3360e0a..c6f548b 100644 --- a/cmd/s3manager/main.go +++ b/cmd/s3manager/main.go @@ -5,10 +5,11 @@ import ( "log" "net/http" "os" + "path/filepath" "github.com/gorilla/mux" "github.com/mastertinner/adapters/logging" - "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" minio "github.com/minio/minio-go" "github.com/pkg/errors" ) @@ -40,6 +41,8 @@ func main() { log.Fatalln(errors.Wrap(err, "error creating s3 client")) } + tmplDir := filepath.Join("web", "template") + // Set up router r := mux.NewRouter().StrictSlash(true) r.Use(logging.Handler(os.Stdout)) @@ -51,11 +54,11 @@ func main() { r. Methods(http.MethodGet). Path("/buckets"). - Handler(s3manager.BucketsViewHandler(s3)) + Handler(s3manager.BucketsViewHandler(s3, tmplDir)) r. Methods(http.MethodGet). Path("/buckets/{bucketName}"). - Handler(s3manager.BucketViewHandler(s3)) + Handler(s3manager.BucketViewHandler(s3, tmplDir)) r. Methods(http.MethodPost). Path("/api/buckets"). diff --git a/entrypoint-cf.sh b/deployments/cf/entrypoint.sh similarity index 100% rename from entrypoint-cf.sh rename to deployments/cf/entrypoint.sh diff --git a/deployments/cf/manifest.yml b/deployments/cf/manifest.yml new file mode 100644 index 0000000..7582104 --- /dev/null +++ b/deployments/cf/manifest.yml @@ -0,0 +1,9 @@ +--- +applications: +- name: s3-manager + memory: 64M + buildpack: https://github.com/cloudfoundry/binary-buildpack.git + command: ./deployments/cf/entrypoint-cf.sh + + services: + - my-storage diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 176bd80..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: '2' -services: - - s3manager: - build: . - ports: - - "8080:8080" - environment: - - S3_ENDPOINT=s3.amazonaws.com - - S3_ACCESS_KEY_ID=xxx - - S3_SECRET_ACCESS_KEY=xxx diff --git a/bucket_view.go b/internal/app/s3manager/bucket_view.go similarity index 89% rename from bucket_view.go rename to internal/app/s3manager/bucket_view.go index 454af56..728bb33 100644 --- a/bucket_view.go +++ b/internal/app/s3manager/bucket_view.go @@ -4,6 +4,7 @@ import ( "html/template" "net/http" "path" + "path/filepath" "github.com/gorilla/mux" minio "github.com/minio/minio-go" @@ -23,20 +24,11 @@ type bucketPage struct { } // BucketViewHandler shows the details page of a bucket. -func BucketViewHandler(s3 S3) http.Handler { +func BucketViewHandler(s3 S3, tmplDir string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { bucketName := mux.Vars(r)["bucketName"] + var objs []objectWithIcon - - l := path.Join(tmplDirectory, "layout.html.tmpl") - p := path.Join(tmplDirectory, "bucket.html.tmpl") - - t, err := template.ParseFiles(l, p) - if err != nil { - handleHTTPError(w, errors.Wrap(err, errParsingTemplates)) - return - } - doneCh := make(chan struct{}) defer close(doneCh) objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh) @@ -48,12 +40,18 @@ func BucketViewHandler(s3 S3) http.Handler { obj := objectWithIcon{object, icon(object.Key)} objs = append(objs, obj) } - page := bucketPage{ BucketName: bucketName, Objects: objs, } + l := filepath.Join(tmplDir, "layout.html.tmpl") + p := filepath.Join(tmplDir, "bucket.html.tmpl") + t, err := template.ParseFiles(l, p) + if err != nil { + handleHTTPError(w, errors.Wrap(err, errParsingTemplates)) + return + } err = t.ExecuteTemplate(w, "layout", page) if err != nil { handleHTTPError(w, errors.Wrap(err, errExecutingTemplate)) diff --git a/bucket_view_test.go b/internal/app/s3manager/bucket_view_test.go similarity index 92% rename from bucket_view_test.go rename to internal/app/s3manager/bucket_view_test.go index 5e98f45..0a42277 100644 --- a/bucket_view_test.go +++ b/internal/app/s3manager/bucket_view_test.go @@ -6,17 +6,18 @@ import ( "io/ioutil" "net/http" "net/http/httptest" + "path/filepath" "testing" "github.com/gorilla/mux" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" minio "github.com/minio/minio-go" "github.com/stretchr/testify/assert" ) func TestBucketViewHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 bucketName string expectedStatusCode int expectedBodyContains string @@ -103,11 +104,12 @@ func TestBucketViewHandler(t *testing.T) { t.Run(tcID, func(t *testing.T) { assert := assert.New(t) + tmplDir := filepath.Join("..", "..", "..", "web", "template") r := mux.NewRouter() r. Methods(http.MethodGet). Path("/buckets/{bucketName}"). - Handler(BucketViewHandler(tc.s3)) + Handler(s3manager.BucketViewHandler(tc.s3, tmplDir)) ts := httptest.NewServer(r) defer ts.Close() diff --git a/buckets_view.go b/internal/app/s3manager/buckets_view.go similarity index 77% rename from buckets_view.go rename to internal/app/s3manager/buckets_view.go index f03a969..6a6dd89 100644 --- a/buckets_view.go +++ b/internal/app/s3manager/buckets_view.go @@ -3,29 +3,27 @@ package s3manager import ( "html/template" "net/http" - "path" + "path/filepath" "github.com/pkg/errors" ) // BucketsViewHandler renders all buckets on an HTML page. -func BucketsViewHandler(s3 S3) http.Handler { +func BucketsViewHandler(s3 S3, tmplDir string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - l := path.Join(tmplDirectory, "layout.html.tmpl") - p := path.Join(tmplDirectory, "buckets.html.tmpl") - - t, err := template.ParseFiles(l, p) - if err != nil { - handleHTTPError(w, errors.Wrap(err, errParsingTemplates)) - return - } - buckets, err := s3.ListBuckets() if err != nil { handleHTTPError(w, errors.Wrap(err, "error listing buckets")) return } + l := filepath.Join(tmplDir, "layout.html.tmpl") + p := filepath.Join(tmplDir, "buckets.html.tmpl") + t, err := template.ParseFiles(l, p) + if err != nil { + handleHTTPError(w, errors.Wrap(err, errParsingTemplates)) + return + } err = t.ExecuteTemplate(w, "layout", buckets) if err != nil { handleHTTPError(w, errors.Wrap(err, errExecutingTemplate)) diff --git a/buckets_view_test.go b/internal/app/s3manager/buckets_view_test.go similarity index 76% rename from buckets_view_test.go rename to internal/app/s3manager/buckets_view_test.go index d5c84d2..9c79b41 100644 --- a/buckets_view_test.go +++ b/internal/app/s3manager/buckets_view_test.go @@ -4,16 +4,18 @@ import ( "errors" "net/http" "net/http/httptest" + "path/filepath" "testing" - . "github.com/mastertinner/s3manager" + "github.com/gorilla/mux" + "github.com/mastertinner/s3manager/internal/app/s3manager" minio "github.com/minio/minio-go" "github.com/stretchr/testify/assert" ) func TestBucketsViewHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 expectedStatusCode int expectedBodyContains string }{ @@ -44,11 +46,18 @@ func TestBucketsViewHandler(t *testing.T) { t.Run(tcID, func(t *testing.T) { assert := assert.New(t) + tmplDir := filepath.Join("..", "..", "..", "web", "template") + r := mux.NewRouter() + r. + Methods(http.MethodGet). + Path("/buckets/{bucketName}"). + Handler(s3manager.BucketViewHandler(tc.s3, tmplDir)) + req, err := http.NewRequest(http.MethodGet, "/buckets", nil) assert.NoError(err, tcID) rr := httptest.NewRecorder() - handler := BucketsViewHandler(tc.s3) + handler := s3manager.BucketsViewHandler(tc.s3, tmplDir) handler.ServeHTTP(rr, req) resp := rr.Result() diff --git a/copy_object.go b/internal/app/s3manager/copy_object.go similarity index 99% rename from copy_object.go rename to internal/app/s3manager/copy_object.go index 70aef2e..31e1df5 100644 --- a/copy_object.go +++ b/internal/app/s3manager/copy_object.go @@ -21,7 +21,6 @@ type copyObjectInfo struct { func CopyObjectHandler(s3 S3) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var copy copyObjectInfo - err := json.NewDecoder(r.Body).Decode(©) if err != nil { handleHTTPError(w, errors.Wrap(err, errDecodingBody)) @@ -42,7 +41,6 @@ func CopyObjectHandler(s3 S3) http.Handler { w.Header().Set(HeaderContentType, ContentTypeJSON) w.WriteHeader(http.StatusCreated) - err = json.NewEncoder(w).Encode(copy) if err != nil { handleHTTPError(w, errors.Wrap(err, errEncodingJSON)) diff --git a/create_bucket.go b/internal/app/s3manager/create_bucket.go similarity index 99% rename from create_bucket.go rename to internal/app/s3manager/create_bucket.go index 8825df0..7951027 100644 --- a/create_bucket.go +++ b/internal/app/s3manager/create_bucket.go @@ -12,7 +12,6 @@ import ( func CreateBucketHandler(s3 S3) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var bucket minio.BucketInfo - err := json.NewDecoder(r.Body).Decode(&bucket) if err != nil { handleHTTPError(w, errors.Wrap(err, errDecodingBody)) @@ -27,7 +26,6 @@ func CreateBucketHandler(s3 S3) http.Handler { w.Header().Set(HeaderContentType, ContentTypeJSON) w.WriteHeader(http.StatusCreated) - err = json.NewEncoder(w).Encode(bucket) if err != nil { handleHTTPError(w, errors.Wrap(err, errEncodingJSON)) diff --git a/create_bucket_test.go b/internal/app/s3manager/create_bucket_test.go similarity index 92% rename from create_bucket_test.go rename to internal/app/s3manager/create_bucket_test.go index b2309d3..5896475 100644 --- a/create_bucket_test.go +++ b/internal/app/s3manager/create_bucket_test.go @@ -7,13 +7,13 @@ import ( "net/http/httptest" "testing" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/stretchr/testify/assert" ) func TestCreateBucketHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 body string expectedStatusCode int expectedBodyContains string @@ -54,7 +54,7 @@ func TestCreateBucketHandler(t *testing.T) { assert.NoError(err, tcID) rr := httptest.NewRecorder() - handler := CreateBucketHandler(tc.s3) + handler := s3manager.CreateBucketHandler(tc.s3) handler.ServeHTTP(rr, req) resp := rr.Result() diff --git a/create_object.go b/internal/app/s3manager/create_object.go similarity index 99% rename from create_object.go rename to internal/app/s3manager/create_object.go index cae5483..2b208c6 100644 --- a/create_object.go +++ b/internal/app/s3manager/create_object.go @@ -12,12 +12,12 @@ import ( // CreateObjectHandler uploads a new object. func CreateObjectHandler(s3 S3) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + bucketName := mux.Vars(r)["bucketName"] err := r.ParseMultipartForm(32 << 20) if err != nil { handleHTTPError(w, errors.Wrap(err, errParsingForm)) return } - file, handler, err := r.FormFile("file") if err != nil { handleHTTPError(w, errors.Wrap(err, "error getting file from form")) @@ -30,7 +30,6 @@ func CreateObjectHandler(s3 S3) http.Handler { } }() - bucketName := mux.Vars(r)["bucketName"] _, err = s3.PutObject(bucketName, handler.Filename, file, 1, minio.PutObjectOptions{ContentType: contentTypeOctetStream}) if err != nil { handleHTTPError(w, errors.Wrap(err, "error putting object")) diff --git a/delete_bucket.go b/internal/app/s3manager/delete_bucket.go similarity index 99% rename from delete_bucket.go rename to internal/app/s3manager/delete_bucket.go index 6050034..2f0180e 100644 --- a/delete_bucket.go +++ b/internal/app/s3manager/delete_bucket.go @@ -11,6 +11,7 @@ import ( func DeleteBucketHandler(s3 S3) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { bucketName := mux.Vars(r)["bucketName"] + err := s3.RemoveBucket(bucketName) if err != nil { handleHTTPError(w, errors.Wrap(err, "error removing bucket")) diff --git a/delete_bucket_test.go b/internal/app/s3manager/delete_bucket_test.go similarity index 88% rename from delete_bucket_test.go rename to internal/app/s3manager/delete_bucket_test.go index 6c27943..c8c9983 100644 --- a/delete_bucket_test.go +++ b/internal/app/s3manager/delete_bucket_test.go @@ -6,13 +6,13 @@ import ( "net/http/httptest" "testing" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/stretchr/testify/assert" ) func TestDeleteBucketHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 expectedStatusCode int expectedBodyContains string }{ @@ -38,7 +38,7 @@ func TestDeleteBucketHandler(t *testing.T) { assert.NoError(err, tcID) rr := httptest.NewRecorder() - handler := DeleteBucketHandler(tc.s3) + handler := s3manager.DeleteBucketHandler(tc.s3) handler.ServeHTTP(rr, req) resp := rr.Result() diff --git a/delete_object.go b/internal/app/s3manager/delete_object.go similarity index 99% rename from delete_object.go rename to internal/app/s3manager/delete_object.go index d85fb46..eb947c6 100644 --- a/delete_object.go +++ b/internal/app/s3manager/delete_object.go @@ -13,6 +13,7 @@ func DeleteObjectHandler(s3 S3) http.Handler { vars := mux.Vars(r) bucketName := vars["bucketName"] objectName := vars["objectName"] + err := s3.RemoveObject(bucketName, objectName) if err != nil { handleHTTPError(w, errors.Wrap(err, "error removing object")) diff --git a/delete_object_test.go b/internal/app/s3manager/delete_object_test.go similarity index 88% rename from delete_object_test.go rename to internal/app/s3manager/delete_object_test.go index 3cded07..988d355 100644 --- a/delete_object_test.go +++ b/internal/app/s3manager/delete_object_test.go @@ -6,13 +6,13 @@ import ( "net/http/httptest" "testing" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/stretchr/testify/assert" ) func TestDeleteObjectHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 expectedStatusCode int expectedBodyContains string }{ @@ -38,7 +38,7 @@ func TestDeleteObjectHandler(t *testing.T) { assert.NoError(err, tcID) rr := httptest.NewRecorder() - handler := DeleteObjectHandler(tc.s3) + handler := s3manager.DeleteObjectHandler(tc.s3) handler.ServeHTTP(rr, req) diff --git a/errors.go b/internal/app/s3manager/errors.go similarity index 95% rename from errors.go rename to internal/app/s3manager/errors.go index 165da1c..552200c 100644 --- a/errors.go +++ b/internal/app/s3manager/errors.go @@ -14,6 +14,7 @@ const ( errDecodingBody = "error decoding body JSON" errEncodingJSON = "error encoding JSON" errExecutingTemplate = "error executing template" + errGettingWD = "error getting working directory" errParsingForm = "error parsing form" errParsingTemplates = "error parsing template files" ) diff --git a/get_object.go b/internal/app/s3manager/get_object.go similarity index 99% rename from get_object.go rename to internal/app/s3manager/get_object.go index d59f346..adbd317 100644 --- a/get_object.go +++ b/internal/app/s3manager/get_object.go @@ -25,7 +25,6 @@ func GetObjectHandler(s3 S3) http.Handler { w.Header().Set(headerContentDisposition, fmt.Sprintf("attachment; filename=\"%s\"", objectName)) w.Header().Set(HeaderContentType, contentTypeOctetStream) - _, err = io.Copy(w, object) if err != nil { handleHTTPError(w, errors.Wrap(err, "error copying object to response writer")) diff --git a/get_object_test.go b/internal/app/s3manager/get_object_test.go similarity index 90% rename from get_object_test.go rename to internal/app/s3manager/get_object_test.go index 70e8d54..0c61e84 100644 --- a/get_object_test.go +++ b/internal/app/s3manager/get_object_test.go @@ -9,13 +9,13 @@ import ( "testing" "github.com/gorilla/mux" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" "github.com/stretchr/testify/assert" ) func TestGetObjectHandler(t *testing.T) { cases := map[string]struct { - s3 S3 + s3 s3manager.S3 bucketName string objectName string expectedStatusCode int @@ -40,7 +40,7 @@ func TestGetObjectHandler(t *testing.T) { r. Methods(http.MethodGet). Path("/buckets/{bucketName}/objects/{objectName}"). - Handler(GetObjectHandler(tc.s3)) + Handler(s3manager.GetObjectHandler(tc.s3)) ts := httptest.NewServer(r) defer ts.Close() diff --git a/s3.go b/internal/app/s3manager/s3.go similarity index 100% rename from s3.go rename to internal/app/s3manager/s3.go diff --git a/s3_test.go b/internal/app/s3manager/s3_test.go similarity index 94% rename from s3_test.go rename to internal/app/s3manager/s3_test.go index 442a09a..2b8131c 100644 --- a/s3_test.go +++ b/internal/app/s3manager/s3_test.go @@ -3,7 +3,7 @@ package s3manager_test import ( "io" - . "github.com/mastertinner/s3manager" + "github.com/mastertinner/s3manager/internal/app/s3manager" minio "github.com/minio/minio-go" ) @@ -52,7 +52,7 @@ func (s *s3Mock) ListObjectsV2(name string, p string, r bool, d <-chan struct{}) } if !found { s.Objects = append(s.Objects, minio.ObjectInfo{ - Err: ErrBucketDoesNotExist, + Err: s3manager.ErrBucketDoesNotExist, }) } diff --git a/s3manager.go b/internal/app/s3manager/s3manager.go similarity index 78% rename from s3manager.go rename to internal/app/s3manager/s3manager.go index 9aae21e..de9da22 100644 --- a/s3manager.go +++ b/internal/app/s3manager/s3manager.go @@ -1,12 +1,11 @@ // Package s3manager allows to interact with an S3 compatible storage. package s3manager -// Constants commonly used throughout the application. +// These are constants commonly used throughout the application. const ( HeaderContentType = "Content-Type" ContentTypeJSON = "application/json" ContentTypeMultipartForm = "multipart/form-data" headerContentDisposition = "Content-Disposition" contentTypeOctetStream = "application/octet-stream" - tmplDirectory = "templates" ) diff --git a/manifest.yml b/manifest.yml deleted file mode 100644 index 728c324..0000000 --- a/manifest.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -applications: - - name: s3-manager - memory: 64M - buildpack: https://github.com/cloudfoundry/binary-buildpack.git - command: ./entrypoint-cf.sh - - services: - - my-storage diff --git a/templates/bucket.html.tmpl b/web/template/bucket.html.tmpl similarity index 100% rename from templates/bucket.html.tmpl rename to web/template/bucket.html.tmpl diff --git a/templates/buckets.html.tmpl b/web/template/buckets.html.tmpl similarity index 100% rename from templates/buckets.html.tmpl rename to web/template/buckets.html.tmpl diff --git a/templates/layout.html.tmpl b/web/template/layout.html.tmpl similarity index 100% rename from templates/layout.html.tmpl rename to web/template/layout.html.tmpl