From 4672fc2e1c37af899cdc7978941120a26b259a92 Mon Sep 17 00:00:00 2001 From: Lena Fuhrimann <6780471+cloudlena@users.noreply.github.com> Date: Mon, 3 Apr 2017 14:08:01 +0200 Subject: [PATCH] Remove unneeded packages --- bucket-view.go | 80 +++++++++++++++++++ buckets-view.go | 36 +++++++++ buckets/create-handler.go => create-bucket.go | 14 ++-- ...e-handler_test.go => create-bucket_test.go | 37 ++++----- objects/create-handler.go => create-object.go | 20 +++-- buckets/delete-handler.go => delete-bucket.go | 10 +-- ...e-handler_test.go => delete-bucket_test.go | 27 +++---- objects/delete-handler.go => delete-object.go | 10 +-- ...e-handler_test.go => delete-object_test.go | 27 +++---- objects/get-handler.go => get-object.go | 12 ++- ...ndle-http-error.go => handle-http-error.go | 6 +- views/index-handler.go => index-view.go | 4 +- main.go | 41 +++++----- datasources/minio.go => minio.go | 2 +- mock/s3-client.go | 46 ----------- objects/with-icon.go | 9 --- s3-client-mock.go | 47 +++++++++++ datasources/s3-client.go => s3-client.go | 2 +- .../bucket.html => templates/bucket.html.tmpl | 0 .../buckets.html.tmpl | 0 .../layout.html => templates/layout.html.tmpl | 0 views/bucket-handler.go | 60 -------------- views/buckets-handler.go | 39 --------- views/icon.go | 19 ----- 24 files changed, 254 insertions(+), 294 deletions(-) create mode 100644 bucket-view.go create mode 100644 buckets-view.go rename buckets/create-handler.go => create-bucket.go (59%) rename buckets/create-handler_test.go => create-bucket_test.go (60%) rename objects/create-handler.go => create-object.go (72%) rename buckets/delete-handler.go => delete-bucket.go (52%) rename buckets/delete-handler_test.go => delete-bucket_test.go (52%) rename objects/delete-handler.go => delete-object.go (54%) rename objects/delete-handler_test.go => delete-object_test.go (53%) rename objects/get-handler.go => get-object.go (62%) rename utils/handle-http-error.go => handle-http-error.go (59%) rename views/index-handler.go => index-view.go (79%) rename datasources/minio.go => minio.go (97%) delete mode 100644 mock/s3-client.go delete mode 100644 objects/with-icon.go create mode 100644 s3-client-mock.go rename datasources/s3-client.go => s3-client.go (96%) rename views/bucket.html => templates/bucket.html.tmpl (100%) rename views/buckets.html => templates/buckets.html.tmpl (100%) rename views/layout.html => templates/layout.html.tmpl (100%) delete mode 100644 views/bucket-handler.go delete mode 100644 views/buckets-handler.go delete mode 100644 views/icon.go diff --git a/bucket-view.go b/bucket-view.go new file mode 100644 index 0000000..f9523d8 --- /dev/null +++ b/bucket-view.go @@ -0,0 +1,80 @@ +package main + +import ( + "html/template" + "net/http" + "path" + + "github.com/gorilla/mux" + minio "github.com/minio/minio-go" +) + +// ObjectWithIcon is a minio object with an added icon +type ObjectWithIcon struct { + minio.ObjectInfo + Icon string +} + +// BucketPage defines the details page of a bucket +type BucketPage struct { + BucketName string + Objects []ObjectWithIcon +} + +// BucketViewHandler shows the details page of a bucket +func BucketViewHandler(s3 S3Client) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + bucketName := mux.Vars(r)["bucketName"] + var objs []ObjectWithIcon + + l := path.Join("templates", "layout.html.tmpl") + p := path.Join("templates", "bucket.html.tmpl") + + t, err := template.ParseFiles(l, p) + if err != nil { + msg := "error parsing templates" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + + doneCh := make(chan struct{}) + objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh) + for object := range objectCh { + if object.Err != nil { + msg := "error listing objects" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + objectWithIcon := ObjectWithIcon{object, icon(object.Key)} + objs = append(objs, objectWithIcon) + } + + bucketPage := BucketPage{ + BucketName: bucketName, + Objects: objs, + } + + err = t.ExecuteTemplate(w, "layout", bucketPage) + if err != nil { + msg := "error executing template" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + }) +} + +// icon returns an icon for a file type +func icon(fileName string) string { + e := path.Ext(fileName) + + switch e { + case ".tgz": + return "archive" + case ".png", ".jpg", ".gif", ".svg": + return "photo" + case ".mp3": + return "music_note" + } + + return "insert_drive_file" +} diff --git a/buckets-view.go b/buckets-view.go new file mode 100644 index 0000000..205f6ab --- /dev/null +++ b/buckets-view.go @@ -0,0 +1,36 @@ +package main + +import ( + "html/template" + "net/http" + "path" +) + +// BucketsViewHandler shows all buckets +func BucketsViewHandler(s3 S3Client) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + l := path.Join("templates", "layout.html.tmpl") + p := path.Join("templates", "buckets.html.tmpl") + + t, err := template.ParseFiles(l, p) + if err != nil { + msg := "error parsing templates" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + + buckets, err := s3.ListBuckets() + if err != nil { + msg := "error listing buckets" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + + err = t.ExecuteTemplate(w, "layout", buckets) + if err != nil { + msg := "error executing template" + handleHTTPError(w, msg, err, http.StatusInternalServerError) + return + } + }) +} diff --git a/buckets/create-handler.go b/create-bucket.go similarity index 59% rename from buckets/create-handler.go rename to create-bucket.go index 286810b..2fadbf7 100644 --- a/buckets/create-handler.go +++ b/create-bucket.go @@ -1,30 +1,28 @@ -package buckets +package main import ( "encoding/json" "net/http" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/utils" minio "github.com/minio/minio-go" ) -// CreateHandler creates a new bucket -func CreateHandler(s3 datasources.S3Client) http.Handler { +// CreateBucketHandler creates a new bucket +func CreateBucketHandler(s3 S3Client) 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 { msg := "error decoding json" - utils.HandleHTTPError(w, msg, err, http.StatusUnprocessableEntity) + handleHTTPError(w, msg, err, http.StatusUnprocessableEntity) return } err = s3.MakeBucket(bucket.Name, "") if err != nil { msg := "error making bucket" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } @@ -34,7 +32,7 @@ func CreateHandler(s3 datasources.S3Client) http.Handler { err = json.NewEncoder(w).Encode(bucket) if err != nil { msg := "error encoding json" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } }) diff --git a/buckets/create-handler_test.go b/create-bucket_test.go similarity index 60% rename from buckets/create-handler_test.go rename to create-bucket_test.go index 8f17a21..50ceeaf 100644 --- a/buckets/create-handler_test.go +++ b/create-bucket_test.go @@ -1,4 +1,4 @@ -package buckets_test +package main import ( "bytes" @@ -7,45 +7,38 @@ import ( "net/http/httptest" "testing" - "github.com/mastertinner/s3-manager/buckets" - "github.com/mastertinner/s3-manager/mock" "github.com/stretchr/testify/assert" ) -func TestCreateHandler(t *testing.T) { +func TestCreateBucketHandler(t *testing.T) { assert := assert.New(t) - tests := []struct { - description string - s3Client *mock.S3Client + tests := map[string]struct { + s3Client S3Client body string expectedStatusCode int expectedBody string }{ - { - description: "success", - s3Client: &mock.S3Client{}, + "success": { + s3Client: &S3ClientMock{}, body: "{\"name\":\"myBucket\"}", expectedStatusCode: http.StatusCreated, expectedBody: "{\"name\":\"myBucket\",\"creationDate\":\"0001-01-01T00:00:00Z\"}\n", }, - { - description: "empty request", - s3Client: &mock.S3Client{}, + "empty request": { + s3Client: &S3ClientMock{}, body: "", expectedStatusCode: http.StatusUnprocessableEntity, expectedBody: "error decoding json\n", }, - { - description: "malformed request", - s3Client: &mock.S3Client{}, + "malformed request": { + s3Client: &S3ClientMock{}, body: "}", expectedStatusCode: http.StatusUnprocessableEntity, expectedBody: "error decoding json\n", }, - { - description: "s3 error", - s3Client: &mock.S3Client{ + "s3 error": { + s3Client: &S3ClientMock{ Err: errors.New("internal S3 error"), }, body: "{\"name\":\"myBucket\"}", @@ -59,11 +52,11 @@ func TestCreateHandler(t *testing.T) { assert.NoError(err) rr := httptest.NewRecorder() - handler := buckets.CreateHandler(tc.s3Client) + handler := CreateBucketHandler(tc.s3Client) handler.ServeHTTP(rr, req) - assert.Equal(tc.expectedStatusCode, rr.Code, tc.description) - assert.Equal(tc.expectedBody, rr.Body.String(), tc.description) + assert.Equal(tc.expectedStatusCode, rr.Code) + assert.Equal(tc.expectedBody, rr.Body.String()) } } diff --git a/objects/create-handler.go b/create-object.go similarity index 72% rename from objects/create-handler.go rename to create-object.go index 3caa5f3..7b90465 100644 --- a/objects/create-handler.go +++ b/create-object.go @@ -1,4 +1,4 @@ -package objects +package main import ( "encoding/json" @@ -6,8 +6,6 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/utils" minio "github.com/minio/minio-go" ) @@ -19,8 +17,8 @@ type CopyObjectInfo struct { SourceObjectName string `json:"sourceObjectName"` } -// CreateHandler allows to upload a new object -func CreateHandler(s3 datasources.S3Client) http.Handler { +// CreateObjectHandler allows to upload a new object +func CreateObjectHandler(s3 S3Client) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -30,7 +28,7 @@ func CreateHandler(s3 datasources.S3Client) http.Handler { err := json.NewDecoder(r.Body).Decode(©) if err != nil { msg := "error decoding json" - utils.HandleHTTPError(w, msg, err, http.StatusUnprocessableEntity) + handleHTTPError(w, msg, err, http.StatusUnprocessableEntity) return } @@ -39,7 +37,7 @@ func CreateHandler(s3 datasources.S3Client) http.Handler { err = s3.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds) if err != nil { msg := "error copying object" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } @@ -49,21 +47,21 @@ func CreateHandler(s3 datasources.S3Client) http.Handler { err = json.NewEncoder(w).Encode(copy) if err != nil { msg := "error encoding json" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } } else { err := r.ParseMultipartForm(32 << 20) if err != nil { msg := "error parsing form" - utils.HandleHTTPError(w, msg, err, http.StatusUnprocessableEntity) + handleHTTPError(w, msg, err, http.StatusUnprocessableEntity) return } file, handler, err := r.FormFile("file") if err != nil { msg := "error getting form file" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } defer file.Close() @@ -71,7 +69,7 @@ func CreateHandler(s3 datasources.S3Client) http.Handler { _, err = s3.PutObject(vars["bucketName"], handler.Filename, file, "application/octet-stream") if err != nil { msg := "error putting object" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } diff --git a/buckets/delete-handler.go b/delete-bucket.go similarity index 52% rename from buckets/delete-handler.go rename to delete-bucket.go index 8976228..09929aa 100644 --- a/buckets/delete-handler.go +++ b/delete-bucket.go @@ -1,22 +1,20 @@ -package buckets +package main import ( "net/http" "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/utils" ) -// DeleteHandler deletes a bucket -func DeleteHandler(s3 datasources.S3Client) http.Handler { +// DeleteBucketHandler deletes a bucket +func DeleteBucketHandler(s3 S3Client) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) err := s3.RemoveBucket(vars["bucketName"]) if err != nil { msg := "error removing bucket" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } diff --git a/buckets/delete-handler_test.go b/delete-bucket_test.go similarity index 52% rename from buckets/delete-handler_test.go rename to delete-bucket_test.go index a9fe64e..3af387f 100644 --- a/buckets/delete-handler_test.go +++ b/delete-bucket_test.go @@ -1,4 +1,4 @@ -package buckets_test +package main import ( "errors" @@ -6,29 +6,24 @@ import ( "net/http/httptest" "testing" - "github.com/mastertinner/s3-manager/buckets" - "github.com/mastertinner/s3-manager/mock" "github.com/stretchr/testify/assert" ) -func TestDeleteHandler(t *testing.T) { +func TestDeleteBucketHandler(t *testing.T) { assert := assert.New(t) - tests := []struct { - description string - s3Client *mock.S3Client + tests := map[string]struct { + s3Client S3Client expectedStatusCode int expectedBody string }{ - { - description: "success", - s3Client: &mock.S3Client{}, + "success": { + s3Client: &S3ClientMock{}, expectedStatusCode: http.StatusNoContent, expectedBody: "", }, - { - description: "s3 error", - s3Client: &mock.S3Client{ + "s3 error": { + s3Client: &S3ClientMock{ Err: errors.New("internal S3 error"), }, expectedStatusCode: http.StatusInternalServerError, @@ -41,11 +36,11 @@ func TestDeleteHandler(t *testing.T) { assert.NoError(err) rr := httptest.NewRecorder() - handler := buckets.DeleteHandler(tc.s3Client) + handler := DeleteBucketHandler(tc.s3Client) handler.ServeHTTP(rr, req) - assert.Equal(tc.expectedStatusCode, rr.Code, tc.description) - assert.Equal(tc.expectedBody, rr.Body.String(), tc.description) + assert.Equal(tc.expectedStatusCode, rr.Code) + assert.Equal(tc.expectedBody, rr.Body.String()) } } diff --git a/objects/delete-handler.go b/delete-object.go similarity index 54% rename from objects/delete-handler.go rename to delete-object.go index df5f964..4d0f329 100644 --- a/objects/delete-handler.go +++ b/delete-object.go @@ -1,22 +1,20 @@ -package objects +package main import ( "net/http" "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/utils" ) -// DeleteHandler deletes an object -func DeleteHandler(s3 datasources.S3Client) http.Handler { +// DeleteObjectHandler deletes an object +func DeleteObjectHandler(s3 S3Client) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) err := s3.RemoveObject(vars["bucketName"], vars["objectName"]) if err != nil { msg := "error removing object" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } diff --git a/objects/delete-handler_test.go b/delete-object_test.go similarity index 53% rename from objects/delete-handler_test.go rename to delete-object_test.go index ada6bdc..508a797 100644 --- a/objects/delete-handler_test.go +++ b/delete-object_test.go @@ -1,4 +1,4 @@ -package objects_test +package main import ( "errors" @@ -6,29 +6,24 @@ import ( "net/http/httptest" "testing" - "github.com/mastertinner/s3-manager/mock" - "github.com/mastertinner/s3-manager/objects" "github.com/stretchr/testify/assert" ) -func TestDeleteHandler(t *testing.T) { +func TestDeleteObjectHandler(t *testing.T) { assert := assert.New(t) - tests := []struct { - description string - s3Client *mock.S3Client + tests := map[string]struct { + s3Client S3Client expectedStatusCode int expectedBody string }{ - { - description: "success", - s3Client: &mock.S3Client{}, + "success": { + s3Client: &S3ClientMock{}, expectedStatusCode: http.StatusNoContent, expectedBody: "", }, - { - description: "s3 error", - s3Client: &mock.S3Client{ + "s3 error": { + s3Client: &S3ClientMock{ Err: errors.New("internal S3 error"), }, expectedStatusCode: http.StatusInternalServerError, @@ -41,11 +36,11 @@ func TestDeleteHandler(t *testing.T) { assert.NoError(err) rr := httptest.NewRecorder() - handler := objects.DeleteHandler(tc.s3Client) + handler := DeleteObjectHandler(tc.s3Client) handler.ServeHTTP(rr, req) - assert.Equal(tc.expectedStatusCode, rr.Code, tc.description) - assert.Equal(tc.expectedBody, rr.Body.String(), tc.description) + assert.Equal(tc.expectedStatusCode, rr.Code) + assert.Equal(tc.expectedBody, rr.Body.String()) } } diff --git a/objects/get-handler.go b/get-object.go similarity index 62% rename from objects/get-handler.go rename to get-object.go index 7458844..77865a3 100644 --- a/objects/get-handler.go +++ b/get-object.go @@ -1,4 +1,4 @@ -package objects +package main import ( "fmt" @@ -6,12 +6,10 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/utils" ) -// GetHandler downloads an object to the client -func GetHandler(s3 datasources.S3Client) http.Handler { +// GetObjectHandler downloads an object to the client +func GetObjectHandler(s3 S3Client) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) objectName := vars["objectName"] @@ -19,7 +17,7 @@ func GetHandler(s3 datasources.S3Client) http.Handler { object, err := s3.GetObject(vars["bucketName"], objectName) if err != nil { msg := "error getting object" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } @@ -29,7 +27,7 @@ func GetHandler(s3 datasources.S3Client) http.Handler { _, err = io.Copy(w, object) if err != nil { msg := "error copying object" - utils.HandleHTTPError(w, msg, err, http.StatusInternalServerError) + handleHTTPError(w, msg, err, http.StatusInternalServerError) return } }) diff --git a/utils/handle-http-error.go b/handle-http-error.go similarity index 59% rename from utils/handle-http-error.go rename to handle-http-error.go index e8f95c6..aa12832 100644 --- a/utils/handle-http-error.go +++ b/handle-http-error.go @@ -1,12 +1,12 @@ -package utils +package main import ( "log" "net/http" ) -// HandleHTTPError handles HTTP errors -func HandleHTTPError(w http.ResponseWriter, msg string, err error, statusCode int) { +// handleHTTPError handles HTTP errors +func handleHTTPError(w http.ResponseWriter, msg string, err error, statusCode int) { http.Error(w, msg, statusCode) if err != nil { log.Println(msg+":", err.Error()) diff --git a/views/index-handler.go b/index-view.go similarity index 79% rename from views/index-handler.go rename to index-view.go index c1313b8..8dfadbb 100644 --- a/views/index-handler.go +++ b/index-view.go @@ -1,9 +1,9 @@ -package views +package main import "net/http" // IndexHandler forwards to "/buckets" -func IndexHandler() http.Handler { +func IndexViewHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/buckets", http.StatusPermanentRedirect) }) diff --git a/main.go b/main.go index 8a3bd30..26ba595 100644 --- a/main.go +++ b/main.go @@ -6,15 +6,12 @@ import ( "os" "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/adapters" - "github.com/mastertinner/s3-manager/buckets" - "github.com/mastertinner/s3-manager/datasources" - "github.com/mastertinner/s3-manager/objects" - "github.com/mastertinner/s3-manager/views" + "github.com/mastertinner/adapters" + "github.com/mastertinner/adapters/logging" ) func main() { - s3 := datasources.NewMinioClient() + s3 := NewMinioClient() logger := log.New(os.Stdout, "", log.Ldate|log.Ltime) router := mux.NewRouter() @@ -22,22 +19,22 @@ func main() { Methods("GET"). Path("/"). Handler(adapters.Adapt( - views.IndexHandler(), - adapters.Logging(logger), + IndexViewHandler(), + logging.Handler(logger), )) router. Methods("GET"). Path("/buckets"). Handler(adapters.Adapt( - views.BucketsHandler(s3), - adapters.Logging(logger), + BucketsViewHandler(s3), + logging.Handler(logger), )) router. Methods("GET"). Path("/buckets/{bucketName}"). Handler(adapters.Adapt( - views.BucketHandler(s3), - adapters.Logging(logger), + BucketViewHandler(s3), + logging.Handler(logger), )) api := router.PathPrefix("/api").Subrouter() @@ -47,36 +44,36 @@ func main() { Methods("POST"). Path(""). Handler(adapters.Adapt( - buckets.CreateHandler(s3), - adapters.Logging(logger), + CreateBucketHandler(s3), + logging.Handler(logger), )) br. Methods("DELETE"). Path("/{bucketName}"). Handler(adapters.Adapt( - buckets.DeleteHandler(s3), - adapters.Logging(logger), + DeleteBucketHandler(s3), + logging.Handler(logger), )) br. Methods("POST"). Path("/{bucketName}/objects"). Handler(adapters.Adapt( - objects.CreateHandler(s3), - adapters.Logging(logger), + CreateObjectHandler(s3), + logging.Handler(logger), )) br. Methods("GET"). Path("/{bucketName}/objects/{objectName}"). Handler(adapters.Adapt( - objects.GetHandler(s3), - adapters.Logging(logger), + GetObjectHandler(s3), + logging.Handler(logger), )) br. Methods("DELETE"). Path("/{bucketName}/objects/{objectName}"). Handler(adapters.Adapt( - objects.DeleteHandler(s3), - adapters.Logging(logger), + DeleteObjectHandler(s3), + logging.Handler(logger), )) port := os.Getenv("PORT") diff --git a/datasources/minio.go b/minio.go similarity index 97% rename from datasources/minio.go rename to minio.go index a6e139d..cbd1b27 100644 --- a/datasources/minio.go +++ b/minio.go @@ -1,4 +1,4 @@ -package datasources +package main import ( "log" diff --git a/mock/s3-client.go b/mock/s3-client.go deleted file mode 100644 index 8f6af4c..0000000 --- a/mock/s3-client.go +++ /dev/null @@ -1,46 +0,0 @@ -package mock - -import ( - "io" - - minio "github.com/minio/minio-go" -) - -type S3Client struct { - Buckets []minio.BucketInfo - ObjectInfos []minio.ObjectInfo - Objects []minio.Object - Err error -} - -func (s S3Client) CopyObject(string, string, string, minio.CopyConditions) error { - return s.Err -} - -func (s S3Client) GetObject(string, string) (*minio.Object, error) { - return &s.Objects[0], s.Err -} - -func (s S3Client) ListBuckets() ([]minio.BucketInfo, error) { - return s.Buckets, s.Err -} - -func (s S3Client) ListObjectsV2(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { - return make(<-chan minio.ObjectInfo) -} - -func (s S3Client) MakeBucket(string, string) error { - return s.Err -} - -func (s S3Client) PutObject(string, string, io.Reader, string) (int64, error) { - return 0, s.Err -} - -func (s S3Client) RemoveBucket(string) error { - return s.Err -} - -func (s S3Client) RemoveObject(string, string) error { - return s.Err -} diff --git a/objects/with-icon.go b/objects/with-icon.go deleted file mode 100644 index 8e68f6d..0000000 --- a/objects/with-icon.go +++ /dev/null @@ -1,9 +0,0 @@ -package objects - -import minio "github.com/minio/minio-go" - -// WithIcon is a minio object with an added icon -type WithIcon struct { - minio.ObjectInfo - Icon string -} diff --git a/s3-client-mock.go b/s3-client-mock.go new file mode 100644 index 0000000..9ea72e5 --- /dev/null +++ b/s3-client-mock.go @@ -0,0 +1,47 @@ +package main + +import ( + "io" + + minio "github.com/minio/minio-go" +) + +// S3ClientMock is a mocked S3 client +type S3ClientMock struct { + Buckets []minio.BucketInfo + ObjectInfos []minio.ObjectInfo + Objects []minio.Object + Err error +} + +func (s S3ClientMock) CopyObject(string, string, string, minio.CopyConditions) error { + return s.Err +} + +func (s S3ClientMock) GetObject(string, string) (*minio.Object, error) { + return &s.Objects[0], s.Err +} + +func (s S3ClientMock) ListBuckets() ([]minio.BucketInfo, error) { + return s.Buckets, s.Err +} + +func (s S3ClientMock) ListObjectsV2(string, string, bool, <-chan struct{}) <-chan minio.ObjectInfo { + return make(<-chan minio.ObjectInfo) +} + +func (s S3ClientMock) MakeBucket(string, string) error { + return s.Err +} + +func (s S3ClientMock) PutObject(string, string, io.Reader, string) (int64, error) { + return 0, s.Err +} + +func (s S3ClientMock) RemoveBucket(string) error { + return s.Err +} + +func (s S3ClientMock) RemoveObject(string, string) error { + return s.Err +} diff --git a/datasources/s3-client.go b/s3-client.go similarity index 96% rename from datasources/s3-client.go rename to s3-client.go index b99d084..1d4cf3a 100644 --- a/datasources/s3-client.go +++ b/s3-client.go @@ -1,4 +1,4 @@ -package datasources +package main import ( "io" diff --git a/views/bucket.html b/templates/bucket.html.tmpl similarity index 100% rename from views/bucket.html rename to templates/bucket.html.tmpl diff --git a/views/buckets.html b/templates/buckets.html.tmpl similarity index 100% rename from views/buckets.html rename to templates/buckets.html.tmpl diff --git a/views/layout.html b/templates/layout.html.tmpl similarity index 100% rename from views/layout.html rename to templates/layout.html.tmpl diff --git a/views/bucket-handler.go b/views/bucket-handler.go deleted file mode 100644 index 3598471..0000000 --- a/views/bucket-handler.go +++ /dev/null @@ -1,60 +0,0 @@ -package views - -import ( - "html/template" - "net/http" - "path" - - "github.com/gorilla/mux" - "github.com/mastertinner/s3-manager/objects" - "github.com/mastertinner/s3-manager/web" - minio "github.com/minio/minio-go" -) - -// BucketPage defines the details page of a bucket -type BucketPage struct { - BucketName string - Objects []objects.WithIcon -} - -// BucketHandler shows the details page of a bucket -func BucketHandler(s3 *minio.Client) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - bucketName := mux.Vars(r)["bucketName"] - var objs []objects.WithIcon - - l := path.Join("views", "layout.html") - p := path.Join("views", "bucket.html") - - t, err := template.ParseFiles(l, p) - if err != nil { - msg := "error parsing templates" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - - doneCh := make(chan struct{}) - objectCh := s3.ListObjectsV2(bucketName, "", true, doneCh) - for object := range objectCh { - if object.Err != nil { - msg := "error listing objects" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - objectWithIcon := objects.WithIcon{object, icon(object.Key)} - objs = append(objs, objectWithIcon) - } - - bucketPage := BucketPage{ - BucketName: bucketName, - Objects: objs, - } - - err = t.ExecuteTemplate(w, "layout", bucketPage) - if err != nil { - msg := "error executing template" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - }) -} diff --git a/views/buckets-handler.go b/views/buckets-handler.go deleted file mode 100644 index 0e86ade..0000000 --- a/views/buckets-handler.go +++ /dev/null @@ -1,39 +0,0 @@ -package views - -import ( - "html/template" - "net/http" - "path" - - "github.com/mastertinner/s3-manager/web" - minio "github.com/minio/minio-go" -) - -// BucketsHandler shows all buckets -func BucketsHandler(s3 *minio.Client) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - l := path.Join("views", "layout.html") - p := path.Join("views", "buckets.html") - - t, err := template.ParseFiles(l, p) - if err != nil { - msg := "error parsing templates" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - - buckets, err := s3.ListBuckets() - if err != nil { - msg := "error listing buckets" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - - err = t.ExecuteTemplate(w, "layout", buckets) - if err != nil { - msg := "error executing template" - web.HandleHTTPError(w, msg, err, http.StatusInternalServerError) - return - } - }) -} diff --git a/views/icon.go b/views/icon.go deleted file mode 100644 index 9922c37..0000000 --- a/views/icon.go +++ /dev/null @@ -1,19 +0,0 @@ -package views - -import "path" - -// icon returns an icon for a file type -func icon(fileName string) string { - e := path.Ext(fileName) - - switch e { - case ".tgz": - return "archive" - case ".png", ".jpg", ".gif", ".svg": - return "photo" - case ".mp3": - return "music_note" - } - - return "insert_drive_file" -}