From f1483f4b93ae01f9a8888a724fbd8627267845c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 11:17:22 -0400 Subject: [PATCH 01/10] started moving prototype code away --- {clients => prototype/clients}/python/heketi.py | 0 {plugins => prototype/plugins}/glusterfs/bricks.go | 0 {plugins => prototype/plugins}/glusterfs/glusterfs.go | 0 {plugins => prototype/plugins}/glusterfs/glusterfsdb.go | 0 {plugins => prototype/plugins}/glusterfs/glusterfsdb_test.go | 0 {plugins => prototype/plugins}/glusterfs/handler_node.go | 0 {plugins => prototype/plugins}/glusterfs/handler_volume.go | 0 {plugins => prototype/plugins}/glusterfs/node.go | 0 {plugins => prototype/plugins}/glusterfs/ring.go | 0 {plugins => prototype/plugins}/glusterfs/scripts/ring.py | 0 {plugins => prototype/plugins}/glusterfs/volume.go | 0 {plugins => prototype/plugins}/mock/mock.go | 0 {plugins => prototype/plugins}/mock/node.go | 0 {plugins => prototype/plugins}/mock/volume.go | 0 {plugins => prototype/plugins}/plugins.go | 0 {handlers => rest}/asynchttp.go | 0 {handlers => rest}/asynchttp_test.go | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename {clients => prototype/clients}/python/heketi.py (100%) rename {plugins => prototype/plugins}/glusterfs/bricks.go (100%) rename {plugins => prototype/plugins}/glusterfs/glusterfs.go (100%) rename {plugins => prototype/plugins}/glusterfs/glusterfsdb.go (100%) rename {plugins => prototype/plugins}/glusterfs/glusterfsdb_test.go (100%) rename {plugins => prototype/plugins}/glusterfs/handler_node.go (100%) rename {plugins => prototype/plugins}/glusterfs/handler_volume.go (100%) rename {plugins => prototype/plugins}/glusterfs/node.go (100%) rename {plugins => prototype/plugins}/glusterfs/ring.go (100%) rename {plugins => prototype/plugins}/glusterfs/scripts/ring.py (100%) rename {plugins => prototype/plugins}/glusterfs/volume.go (100%) rename {plugins => prototype/plugins}/mock/mock.go (100%) rename {plugins => prototype/plugins}/mock/node.go (100%) rename {plugins => prototype/plugins}/mock/volume.go (100%) rename {plugins => prototype/plugins}/plugins.go (100%) rename {handlers => rest}/asynchttp.go (100%) rename {handlers => rest}/asynchttp_test.go (100%) diff --git a/clients/python/heketi.py b/prototype/clients/python/heketi.py similarity index 100% rename from clients/python/heketi.py rename to prototype/clients/python/heketi.py diff --git a/plugins/glusterfs/bricks.go b/prototype/plugins/glusterfs/bricks.go similarity index 100% rename from plugins/glusterfs/bricks.go rename to prototype/plugins/glusterfs/bricks.go diff --git a/plugins/glusterfs/glusterfs.go b/prototype/plugins/glusterfs/glusterfs.go similarity index 100% rename from plugins/glusterfs/glusterfs.go rename to prototype/plugins/glusterfs/glusterfs.go diff --git a/plugins/glusterfs/glusterfsdb.go b/prototype/plugins/glusterfs/glusterfsdb.go similarity index 100% rename from plugins/glusterfs/glusterfsdb.go rename to prototype/plugins/glusterfs/glusterfsdb.go diff --git a/plugins/glusterfs/glusterfsdb_test.go b/prototype/plugins/glusterfs/glusterfsdb_test.go similarity index 100% rename from plugins/glusterfs/glusterfsdb_test.go rename to prototype/plugins/glusterfs/glusterfsdb_test.go diff --git a/plugins/glusterfs/handler_node.go b/prototype/plugins/glusterfs/handler_node.go similarity index 100% rename from plugins/glusterfs/handler_node.go rename to prototype/plugins/glusterfs/handler_node.go diff --git a/plugins/glusterfs/handler_volume.go b/prototype/plugins/glusterfs/handler_volume.go similarity index 100% rename from plugins/glusterfs/handler_volume.go rename to prototype/plugins/glusterfs/handler_volume.go diff --git a/plugins/glusterfs/node.go b/prototype/plugins/glusterfs/node.go similarity index 100% rename from plugins/glusterfs/node.go rename to prototype/plugins/glusterfs/node.go diff --git a/plugins/glusterfs/ring.go b/prototype/plugins/glusterfs/ring.go similarity index 100% rename from plugins/glusterfs/ring.go rename to prototype/plugins/glusterfs/ring.go diff --git a/plugins/glusterfs/scripts/ring.py b/prototype/plugins/glusterfs/scripts/ring.py similarity index 100% rename from plugins/glusterfs/scripts/ring.py rename to prototype/plugins/glusterfs/scripts/ring.py diff --git a/plugins/glusterfs/volume.go b/prototype/plugins/glusterfs/volume.go similarity index 100% rename from plugins/glusterfs/volume.go rename to prototype/plugins/glusterfs/volume.go diff --git a/plugins/mock/mock.go b/prototype/plugins/mock/mock.go similarity index 100% rename from plugins/mock/mock.go rename to prototype/plugins/mock/mock.go diff --git a/plugins/mock/node.go b/prototype/plugins/mock/node.go similarity index 100% rename from plugins/mock/node.go rename to prototype/plugins/mock/node.go diff --git a/plugins/mock/volume.go b/prototype/plugins/mock/volume.go similarity index 100% rename from plugins/mock/volume.go rename to prototype/plugins/mock/volume.go diff --git a/plugins/plugins.go b/prototype/plugins/plugins.go similarity index 100% rename from plugins/plugins.go rename to prototype/plugins/plugins.go diff --git a/handlers/asynchttp.go b/rest/asynchttp.go similarity index 100% rename from handlers/asynchttp.go rename to rest/asynchttp.go diff --git a/handlers/asynchttp_test.go b/rest/asynchttp_test.go similarity index 100% rename from handlers/asynchttp_test.go rename to rest/asynchttp_test.go From b68ef7d1c4d0afca7d970b32fc21e3f682668dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 11:52:54 -0400 Subject: [PATCH 02/10] Added documentation to async api --- .travis-coverage | 2 +- rest/asynchttp.go | 104 ++++++++++++++++++++++++++++++++++++++++- rest/asynchttp_test.go | 4 +- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/.travis-coverage b/.travis-coverage index efaf7c1b9e..22e6bf2e8b 100755 --- a/.travis-coverage +++ b/.travis-coverage @@ -4,7 +4,7 @@ # the tool requires that it be used only on one package when # capturing the coverage # This is why we need this little script here. -packages="./handlers ./plugins" +packages="./rest" COVERFILE=packagecover.out coverage() diff --git a/rest/asynchttp.go b/rest/asynchttp.go index c9fbbedc6e..d94dbc5047 100644 --- a/rest/asynchttp.go +++ b/rest/asynchttp.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The heketi Authors +// Copyright (c) 2015 The heketi Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package handlers +package rest import ( "github.com/gorilla/mux" @@ -23,6 +23,7 @@ import ( "sync" ) +// Contains information about the asynchronous operation type AsyncHttpHandler struct { err error completed bool @@ -30,12 +31,14 @@ type AsyncHttpHandler struct { location, id string } +// Manager of asynchronous operations type AsyncHttpManager struct { lock sync.RWMutex route string handlers map[string]*AsyncHttpHandler } +// Creates a new manager func NewAsyncHttpManager(route string) *AsyncHttpManager { return &AsyncHttpManager{ route: route, @@ -43,6 +46,9 @@ func NewAsyncHttpManager(route string) *AsyncHttpManager { } } +// Use to create a new asynchronous operation handler. +// Only use this function if you need to do every step by hand. +// It is recommended to use AsyncHttpRedirectFunc() instead func (a *AsyncHttpManager) NewHandler() *AsyncHttpHandler { handler := &AsyncHttpHandler{ manager: a, @@ -57,6 +63,54 @@ func (a *AsyncHttpManager) NewHandler() *AsyncHttpHandler { return handler } +// Create an asynchronous operation handler and return the appropiate +// information the caller. +// This function will call handlerfunc() in a new go routine, then +// return to the caller a HTTP status 202 setting up the `Location` header +// to point to the new asynchronous handler. +// +// If handlerfunc() returns failure, the asynchronous handler will return +// an http status of 500 and save the error string in the body. +// If handlerfunc() is successful and returns a location url path in "string", +// the asynchronous handler will return 303 (See Other) with the Location +// header set to the value returned in the string. +// If handlerfunc() is successful and returns an empty string, then the +// asynchronous handler will return 204 to the caller. +// +// Example: +// package rest +// import ( +// "github.com/gorilla/mux" +// "github.com/heketi/heketi/rest" +// "net/http" +// "net/http/httptest" +// "time" +// ) +// +// // Setup asynchronous manager +// route := "/x" +// manager := rest.NewAsyncHttpManager(route) +// +// // Setup the route +// router := mux.NewRouter() +// router.HandleFunc(route+"/{id}", manager.HandlerStatus).Methods("GET") +// router.HandleFunc("/result", func(w http.ResponseWriter, r *http.Request) { +// w.Header().Set("Content-Type", "text/plain; charset=UTF-8") +// w.WriteHeader(http.StatusOK) +// fmt.Fprint(w, "HelloWorld") +// }).Methods("GET") +// +// router.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) { +// manager.AsyncHttpRedirectFunc(w, r, func() (string, error) { +// time.Sleep(100 * time.Millisecond) +// return "/result", nil +// }) +// }).Methods("GET") +// +// // Setup the server +// ts := httptest.NewServer(router) +// defer ts.Close() +// func (a *AsyncHttpManager) AsyncHttpRedirectFunc(w http.ResponseWriter, r *http.Request, handlerfunc func() (string, error)) { @@ -75,6 +129,39 @@ func (a *AsyncHttpManager) AsyncHttpRedirectFunc(w http.ResponseWriter, http.Redirect(w, r, handler.Url(), http.StatusAccepted) } +// Handler for asynchronous operation status +// Register this handler with a router like Gorilla Mux +// +// Returns the following HTTP status codes +// 200 Operation is still pending +// 404 Id requested does not exist +// 500 Operation finished and has failed. Body will be filled in with the +// error in plain text. +// 303 Operation finished and has setup a new location to retreive data. +// 204 Operation finished and has no data to return +// +// Example: +// package rest +// import ( +// "github.com/gorilla/mux" +// "github.com/heketi/heketi/rest" +// "net/http" +// "net/http/httptest" +// "time" +// ) +// +// // Setup asynchronous manager +// route := "/x" +// manager := rest.NewAsyncHttpManager(route) +// +// // Setup the route +// router := mux.NewRouter() +// router.HandleFunc(route+"/{id}", manager.HandlerStatus).Methods("GET") +// +// // Setup the server +// ts := httptest.NewServer(router) +// defer ts.Close() +// func (a *AsyncHttpManager) HandlerStatus(w http.ResponseWriter, r *http.Request) { // Get the id from the URL vars := mux.Vars(r) @@ -83,14 +170,22 @@ func (a *AsyncHttpManager) HandlerStatus(w http.ResponseWriter, r *http.Request) a.lock.Lock() defer a.lock.Unlock() + // Check the id is in the map if handler, ok := a.handlers[id]; ok { + if handler.completed { if handler.err != nil { + + // Return 500 status http.Error(w, handler.err.Error(), http.StatusInternalServerError) } else { if handler.location != "" { + + // Redirect to new location http.Redirect(w, r, handler.location, http.StatusSeeOther) } else { + + // Return 204 status w.WriteHeader(http.StatusNoContent) } } @@ -108,6 +203,7 @@ func (a *AsyncHttpManager) HandlerStatus(w http.ResponseWriter, r *http.Request) } } +// Returns the url for the specified asynchronous handler func (h *AsyncHttpHandler) Url() string { h.manager.lock.RLock() defer h.manager.lock.RUnlock() @@ -115,6 +211,7 @@ func (h *AsyncHttpHandler) Url() string { return h.manager.route + "/" + h.id } +// Registers that the handler has completed with an error func (h *AsyncHttpHandler) CompletedWithError(err error) { h.manager.lock.RLock() @@ -128,6 +225,8 @@ func (h *AsyncHttpHandler) CompletedWithError(err error) { godbc.Ensure(h.completed == true) } +// Registers that the handler has completed and has provided a location +// where information can be retreived func (h *AsyncHttpHandler) CompletedWithLocation(location string) { h.manager.lock.RLock() @@ -143,6 +242,7 @@ func (h *AsyncHttpHandler) CompletedWithLocation(location string) { godbc.Ensure(h.err == nil) } +// Registers that the handler has completed and no data needs to be returned func (h *AsyncHttpHandler) Completed() { h.manager.lock.RLock() diff --git a/rest/asynchttp_test.go b/rest/asynchttp_test.go index 737677eeeb..5fc44af45f 100644 --- a/rest/asynchttp_test.go +++ b/rest/asynchttp_test.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The heketi Authors +// Copyright (c) 2015 The heketi Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ // limitations under the License. // -package handlers +package rest import ( "errors" From 5b240435900e35bb0b57f8281337deadc6dff134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:01:11 -0400 Subject: [PATCH 03/10] Moving more code into prototype --- main.go | 38 +++++++++---------- {handlers => prototype/handlers}/nodes.go | 0 .../handlers}/nodes_test.go | 0 {handlers => prototype/handlers}/routes.go | 0 {handlers => prototype/handlers}/volumes.go | 0 5 files changed, 17 insertions(+), 21 deletions(-) rename {handlers => prototype/handlers}/nodes.go (100%) rename {handlers => prototype/handlers}/nodes_test.go (100%) rename {handlers => prototype/handlers}/routes.go (100%) rename {handlers => prototype/handlers}/volumes.go (100%) diff --git a/main.go b/main.go index f5af2855a8..700b57b42b 100644 --- a/main.go +++ b/main.go @@ -20,8 +20,6 @@ import ( "fmt" "github.com/codegangsta/negroni" "github.com/gorilla/mux" - "github.com/heketi/heketi/handlers" - "github.com/heketi/heketi/plugins" "log" "net/http" "os" @@ -30,29 +28,28 @@ import ( func main() { - // Get a mock node server - plugin := plugins.NewPlugin("glusterfs") - - // - nodeserver := handlers.NewNodeServer(plugin) - volumeserver := handlers.NewVolumeServer(plugin) - - r := volumeserver.VolumeRoutes() - r = append(r, nodeserver.NodeRoutes()...) - // Create a router and do not allow any routes // unless defined. router := mux.NewRouter().StrictSlash(true) - for _, route := range r { + /* - // Add routes from the table - router. - Methods(route.Method). - Path(route.Pattern). - Name(route.Name). - Handler(route.HandlerFunc) + for _, route := range r { + + // Add routes from the table + router. + Methods(route.Method). + Path(route.Pattern). + Name(route.Name). + Handler(route.HandlerFunc) + + } + */ - } + router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=UTF-8") + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, "HelloWorld") + }).Methods("GET") // Use negroni to add middleware. Here we add two // middlewares: Recovery and Logger, which come with @@ -68,7 +65,6 @@ func main() { select { case <-signalch: fmt.Printf("Shutting down...") - plugin.Close() os.Exit(0) } }() diff --git a/handlers/nodes.go b/prototype/handlers/nodes.go similarity index 100% rename from handlers/nodes.go rename to prototype/handlers/nodes.go diff --git a/handlers/nodes_test.go b/prototype/handlers/nodes_test.go similarity index 100% rename from handlers/nodes_test.go rename to prototype/handlers/nodes_test.go diff --git a/handlers/routes.go b/prototype/handlers/routes.go similarity index 100% rename from handlers/routes.go rename to prototype/handlers/routes.go diff --git a/handlers/volumes.go b/prototype/handlers/volumes.go similarity index 100% rename from handlers/volumes.go rename to prototype/handlers/volumes.go From 6f34908ff586d7fe4e669bb7ffb3b3730bcff02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:02:00 -0400 Subject: [PATCH 04/10] prefix prototype with _ to avoid unit tests --- {prototype => _prototype}/clients/python/heketi.py | 0 {prototype => _prototype}/handlers/nodes.go | 0 {prototype => _prototype}/handlers/nodes_test.go | 0 {prototype => _prototype}/handlers/routes.go | 0 {prototype => _prototype}/handlers/volumes.go | 0 {prototype => _prototype}/plugins/glusterfs/bricks.go | 0 {prototype => _prototype}/plugins/glusterfs/glusterfs.go | 0 {prototype => _prototype}/plugins/glusterfs/glusterfsdb.go | 0 {prototype => _prototype}/plugins/glusterfs/glusterfsdb_test.go | 0 {prototype => _prototype}/plugins/glusterfs/handler_node.go | 0 {prototype => _prototype}/plugins/glusterfs/handler_volume.go | 0 {prototype => _prototype}/plugins/glusterfs/node.go | 0 {prototype => _prototype}/plugins/glusterfs/ring.go | 0 {prototype => _prototype}/plugins/glusterfs/scripts/ring.py | 0 {prototype => _prototype}/plugins/glusterfs/volume.go | 0 {prototype => _prototype}/plugins/mock/mock.go | 0 {prototype => _prototype}/plugins/mock/node.go | 0 {prototype => _prototype}/plugins/mock/volume.go | 0 {prototype => _prototype}/plugins/plugins.go | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename {prototype => _prototype}/clients/python/heketi.py (100%) rename {prototype => _prototype}/handlers/nodes.go (100%) rename {prototype => _prototype}/handlers/nodes_test.go (100%) rename {prototype => _prototype}/handlers/routes.go (100%) rename {prototype => _prototype}/handlers/volumes.go (100%) rename {prototype => _prototype}/plugins/glusterfs/bricks.go (100%) rename {prototype => _prototype}/plugins/glusterfs/glusterfs.go (100%) rename {prototype => _prototype}/plugins/glusterfs/glusterfsdb.go (100%) rename {prototype => _prototype}/plugins/glusterfs/glusterfsdb_test.go (100%) rename {prototype => _prototype}/plugins/glusterfs/handler_node.go (100%) rename {prototype => _prototype}/plugins/glusterfs/handler_volume.go (100%) rename {prototype => _prototype}/plugins/glusterfs/node.go (100%) rename {prototype => _prototype}/plugins/glusterfs/ring.go (100%) rename {prototype => _prototype}/plugins/glusterfs/scripts/ring.py (100%) rename {prototype => _prototype}/plugins/glusterfs/volume.go (100%) rename {prototype => _prototype}/plugins/mock/mock.go (100%) rename {prototype => _prototype}/plugins/mock/node.go (100%) rename {prototype => _prototype}/plugins/mock/volume.go (100%) rename {prototype => _prototype}/plugins/plugins.go (100%) diff --git a/prototype/clients/python/heketi.py b/_prototype/clients/python/heketi.py similarity index 100% rename from prototype/clients/python/heketi.py rename to _prototype/clients/python/heketi.py diff --git a/prototype/handlers/nodes.go b/_prototype/handlers/nodes.go similarity index 100% rename from prototype/handlers/nodes.go rename to _prototype/handlers/nodes.go diff --git a/prototype/handlers/nodes_test.go b/_prototype/handlers/nodes_test.go similarity index 100% rename from prototype/handlers/nodes_test.go rename to _prototype/handlers/nodes_test.go diff --git a/prototype/handlers/routes.go b/_prototype/handlers/routes.go similarity index 100% rename from prototype/handlers/routes.go rename to _prototype/handlers/routes.go diff --git a/prototype/handlers/volumes.go b/_prototype/handlers/volumes.go similarity index 100% rename from prototype/handlers/volumes.go rename to _prototype/handlers/volumes.go diff --git a/prototype/plugins/glusterfs/bricks.go b/_prototype/plugins/glusterfs/bricks.go similarity index 100% rename from prototype/plugins/glusterfs/bricks.go rename to _prototype/plugins/glusterfs/bricks.go diff --git a/prototype/plugins/glusterfs/glusterfs.go b/_prototype/plugins/glusterfs/glusterfs.go similarity index 100% rename from prototype/plugins/glusterfs/glusterfs.go rename to _prototype/plugins/glusterfs/glusterfs.go diff --git a/prototype/plugins/glusterfs/glusterfsdb.go b/_prototype/plugins/glusterfs/glusterfsdb.go similarity index 100% rename from prototype/plugins/glusterfs/glusterfsdb.go rename to _prototype/plugins/glusterfs/glusterfsdb.go diff --git a/prototype/plugins/glusterfs/glusterfsdb_test.go b/_prototype/plugins/glusterfs/glusterfsdb_test.go similarity index 100% rename from prototype/plugins/glusterfs/glusterfsdb_test.go rename to _prototype/plugins/glusterfs/glusterfsdb_test.go diff --git a/prototype/plugins/glusterfs/handler_node.go b/_prototype/plugins/glusterfs/handler_node.go similarity index 100% rename from prototype/plugins/glusterfs/handler_node.go rename to _prototype/plugins/glusterfs/handler_node.go diff --git a/prototype/plugins/glusterfs/handler_volume.go b/_prototype/plugins/glusterfs/handler_volume.go similarity index 100% rename from prototype/plugins/glusterfs/handler_volume.go rename to _prototype/plugins/glusterfs/handler_volume.go diff --git a/prototype/plugins/glusterfs/node.go b/_prototype/plugins/glusterfs/node.go similarity index 100% rename from prototype/plugins/glusterfs/node.go rename to _prototype/plugins/glusterfs/node.go diff --git a/prototype/plugins/glusterfs/ring.go b/_prototype/plugins/glusterfs/ring.go similarity index 100% rename from prototype/plugins/glusterfs/ring.go rename to _prototype/plugins/glusterfs/ring.go diff --git a/prototype/plugins/glusterfs/scripts/ring.py b/_prototype/plugins/glusterfs/scripts/ring.py similarity index 100% rename from prototype/plugins/glusterfs/scripts/ring.py rename to _prototype/plugins/glusterfs/scripts/ring.py diff --git a/prototype/plugins/glusterfs/volume.go b/_prototype/plugins/glusterfs/volume.go similarity index 100% rename from prototype/plugins/glusterfs/volume.go rename to _prototype/plugins/glusterfs/volume.go diff --git a/prototype/plugins/mock/mock.go b/_prototype/plugins/mock/mock.go similarity index 100% rename from prototype/plugins/mock/mock.go rename to _prototype/plugins/mock/mock.go diff --git a/prototype/plugins/mock/node.go b/_prototype/plugins/mock/node.go similarity index 100% rename from prototype/plugins/mock/node.go rename to _prototype/plugins/mock/node.go diff --git a/prototype/plugins/mock/volume.go b/_prototype/plugins/mock/volume.go similarity index 100% rename from prototype/plugins/mock/volume.go rename to _prototype/plugins/mock/volume.go diff --git a/prototype/plugins/plugins.go b/_prototype/plugins/plugins.go similarity index 100% rename from prototype/plugins/plugins.go rename to _prototype/plugins/plugins.go From d1d1f389e3968b5dd109f560c826b3db06712cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:09:12 -0400 Subject: [PATCH 05/10] Created Rest Application interface --- rest/app.go | 21 +++++++++++++++++++++ {_prototype/handlers => rest}/routes.go | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 rest/app.go rename {_prototype/handlers => rest}/routes.go (93%) diff --git a/rest/app.go b/rest/app.go new file mode 100644 index 0000000000..5da2c7045f --- /dev/null +++ b/rest/app.go @@ -0,0 +1,21 @@ +// +// Copyright (c) 2015 The heketi Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package rest + +type Application interface { + GetRoutes() Routes +} diff --git a/_prototype/handlers/routes.go b/rest/routes.go similarity index 93% rename from _prototype/handlers/routes.go rename to rest/routes.go index 7b60a3797b..027025134a 100644 --- a/_prototype/handlers/routes.go +++ b/rest/routes.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The heketi Authors +// Copyright (c) 2015 The heketi Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ // limitations under the License. // -package handlers +package rest import ( "net/http" From 746fa8c1b30430ea3095c5aa485c18f5994eba69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:10:52 -0400 Subject: [PATCH 06/10] Added doc.go to rest --- rest/doc.go | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 rest/doc.go diff --git a/rest/doc.go b/rest/doc.go new file mode 100644 index 0000000000..639a2bf562 --- /dev/null +++ b/rest/doc.go @@ -0,0 +1,2 @@ +// Generic RESTful application functions +package rest From de706eb09fcaac2f6e087c4e2de29048f259949c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:29:42 -0400 Subject: [PATCH 07/10] Started glusterfs application --- apps/doc.go | 2 ++ apps/glusterfs/app.go | 61 +++++++++++++++++++++++++++++++++++++++++++ main.go | 28 ++++++++++++-------- 3 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 apps/doc.go create mode 100644 apps/glusterfs/app.go diff --git a/apps/doc.go b/apps/doc.go new file mode 100644 index 0000000000..830e2458a4 --- /dev/null +++ b/apps/doc.go @@ -0,0 +1,2 @@ +// Location for applications for Heketi +package apps diff --git a/apps/glusterfs/app.go b/apps/glusterfs/app.go new file mode 100644 index 0000000000..20af9cf30d --- /dev/null +++ b/apps/glusterfs/app.go @@ -0,0 +1,61 @@ +// +// Copyright (c) 2015 The heketi Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package glusterfs + +import ( + "fmt" + "github.com/heketi/heketi/rest" + "net/http" +) + +type App struct { + hello string +} + +func NewApp() *App { + return &App{} +} + +// Interface rest.App +func (a *App) GetRoutes() rest.Routes { + + return rest.Routes{ + + // HelloWorld + rest.Route{"Hello", "GET", "/hello", a.Hello}, + + // Cluster + + // Node + /* + Route{"NodeList", "GET", "/nodes", n.NodeListHandler}, + Route{"NodeAdd", "POST", "/nodes", n.NodeAddHandler}, + Route{"NodeInfo", "GET", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeInfoHandler}, + Route{"NodeDelete", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeDeleteHandler}, + Route{"NodeAddDevice", "POST", "/nodes/{id:[A-Fa-f0-9]+}/devices", n.NodeAddDeviceHandler}, + //Route{"NodeDeleteDevice", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}/devices/{devid:[A-Fa-f0-9]+}", n.NodeDeleteDeviceHandler}, + */ + + // Volume + } +} + +func (a *App) Hello(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=UTF-8") + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, "HelloWorld from GlusterFS Application") +} diff --git a/main.go b/main.go index 700b57b42b..143f494b71 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The heketi Authors +// Copyright (c) 2015 The heketi Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import ( "fmt" "github.com/codegangsta/negroni" "github.com/gorilla/mux" + "github.com/heketi/heketi/apps/glusterfs" + "github.com/heketi/heketi/rest" "log" "net/http" "os" @@ -28,22 +30,26 @@ import ( func main() { + var app rest.Application + + // Setup a new GlusterFS application + app = glusterfs.NewApp() + // Create a router and do not allow any routes // unless defined. router := mux.NewRouter().StrictSlash(true) - /* - for _, route := range r { + // Register all routes from the App + for _, route := range app.GetRoutes() { - // Add routes from the table - router. - Methods(route.Method). - Path(route.Pattern). - Name(route.Name). - Handler(route.HandlerFunc) + // Add routes from the table + router. + Methods(route.Method). + Path(route.Pattern). + Name(route.Name). + Handler(route.HandlerFunc) - } - */ + } router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain; charset=UTF-8") From df83b8542f849e99be2b7b4f68fe1f03812e0036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 12:38:33 -0400 Subject: [PATCH 08/10] Use glock to save project dependencies See https://github.com/robfig/glock --- GLOCKFILE | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 GLOCKFILE diff --git a/GLOCKFILE b/GLOCKFILE new file mode 100644 index 0000000000..989b8d3615 --- /dev/null +++ b/GLOCKFILE @@ -0,0 +1,5 @@ +github.com/codegangsta/negroni c7477ad8e330bef55bf1ebe300cf8aa67c492d1b +github.com/gorilla/context 215affda49addc4c8ef7e2534915df2c8c35c6cd +github.com/gorilla/mux 47e8f450ef38c857cdd922ec08862ca9d65a1c6d +github.com/lpabon/godbc 9577782540c1398b710ddae1b86268ba03a19b0c +golang.org/x/crypto 1e856cbfdf9bc25eefca75f83f25d55e35ae72e0 From e37fb5155beeab90b8e391c4f23d38d54137c5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 13:51:21 -0400 Subject: [PATCH 09/10] Added Close() to App --- apps/glusterfs/app.go | 4 ++++ main.go | 7 +------ rest/app.go | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/glusterfs/app.go b/apps/glusterfs/app.go index 20af9cf30d..65a76b6c2a 100644 --- a/apps/glusterfs/app.go +++ b/apps/glusterfs/app.go @@ -54,6 +54,10 @@ func (a *App) GetRoutes() rest.Routes { } } +func (a *App) Close() { + +} + func (a *App) Hello(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain; charset=UTF-8") w.WriteHeader(http.StatusOK) diff --git a/main.go b/main.go index 143f494b71..8f937c34a0 100644 --- a/main.go +++ b/main.go @@ -51,12 +51,6 @@ func main() { } - router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=UTF-8") - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, "HelloWorld") - }).Methods("GET") - // Use negroni to add middleware. Here we add two // middlewares: Recovery and Logger, which come with // Negroni @@ -71,6 +65,7 @@ func main() { select { case <-signalch: fmt.Printf("Shutting down...") + app.Close() os.Exit(0) } }() diff --git a/rest/app.go b/rest/app.go index 5da2c7045f..d1ab006d96 100644 --- a/rest/app.go +++ b/rest/app.go @@ -18,4 +18,5 @@ package rest type Application interface { GetRoutes() Routes + Close() } From 47611fe5d23b10330922947b55fcc0828c2e2197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Thu, 2 Jul 2015 14:11:33 -0400 Subject: [PATCH 10/10] Scaffolding for Heketi API --- apps/glusterfs/app.go | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/glusterfs/app.go b/apps/glusterfs/app.go index 65a76b6c2a..e01083deaf 100644 --- a/apps/glusterfs/app.go +++ b/apps/glusterfs/app.go @@ -39,18 +39,27 @@ func (a *App) GetRoutes() rest.Routes { rest.Route{"Hello", "GET", "/hello", a.Hello}, // Cluster + rest.Route{"ClusterCreate", "POST", "/clusters", a.NotImplemented}, + rest.Route{"ClusterInfo", "GET", "/clusters/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + rest.Route{"ClusterList", "GET", "/clusters", a.NotImplemented}, + rest.Route{"ClusterDelete", "DELETE", "/clusters/{id:[A-Fa-f0-9]+}", a.NotImplemented}, // Node - /* - Route{"NodeList", "GET", "/nodes", n.NodeListHandler}, - Route{"NodeAdd", "POST", "/nodes", n.NodeAddHandler}, - Route{"NodeInfo", "GET", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeInfoHandler}, - Route{"NodeDelete", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeDeleteHandler}, - Route{"NodeAddDevice", "POST", "/nodes/{id:[A-Fa-f0-9]+}/devices", n.NodeAddDeviceHandler}, - //Route{"NodeDeleteDevice", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}/devices/{devid:[A-Fa-f0-9]+}", n.NodeDeleteDeviceHandler}, - */ + rest.Route{"NodeAdd", "POST", "/nodes", a.NotImplemented}, + rest.Route{"NodeInfo", "GET", "/nodes/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + rest.Route{"NodeDelete", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + + // Devices + rest.Route{"DeviceAdd", "POST", "/devices", a.NotImplemented}, + rest.Route{"DeviceInfo", "GET", "/devices/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + rest.Route{"DeviceDelete", "DELETE", "/devices/{id:[A-Fa-f0-9]+}", a.NotImplemented}, // Volume + rest.Route{"VolumeCreate", "POST", "/volumes", a.NotImplemented}, + rest.Route{"VolumeInfo", "GET", "/volumes/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + rest.Route{"VolumeExpand", "POST", "/volumes/{id:[A-Fa-f0-9]+}/expand", a.NotImplemented}, + rest.Route{"VolumeDelete", "DELETE", "/volumes/{id:[A-Fa-f0-9]+}", a.NotImplemented}, + rest.Route{"VolumeList", "GET", "/volumes", a.NotImplemented}, } } @@ -63,3 +72,7 @@ func (a *App) Hello(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprint(w, "HelloWorld from GlusterFS Application") } + +func (a *App) NotImplemented(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Function not yet supported", http.StatusNotImplemented) +}