From f0b7e3c0996e0dbe9f8bde7aa0c9c811bc2c663d Mon Sep 17 00:00:00 2001 From: Jing Dong Date: Mon, 6 Apr 2015 14:03:10 +0100 Subject: [PATCH] - Refactor Websever to martini to handle unescaped app id in API - PUT allow creating missing app configuration --- api/service.go | 17 +++++----- main/bamboo/bamboo.go | 48 +++++++++++++++++++---------- services/event_bus/event_handler.go | 2 +- services/service/service.go | 7 ++++- 4 files changed, 48 insertions(+), 26 deletions(-) diff --git a/api/service.go b/api/service.go index 9e134d1..8fbef37 100644 --- a/api/service.go +++ b/api/service.go @@ -5,10 +5,9 @@ import ( "errors" "io/ioutil" "net/http" - "net/url" + "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/go-martini/martini" zk "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk" - "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/zenazn/goji/web" conf "github.com/QubitProducts/bamboo/configuration" "github.com/QubitProducts/bamboo/services/service" ) @@ -46,15 +45,18 @@ func (d *ServiceAPI) Create(w http.ResponseWriter, r *http.Request) { responseJSON(w, serviceModel) } -func (d *ServiceAPI) Put(c web.C, w http.ResponseWriter, r *http.Request) { - identifier, _ := url.QueryUnescape(c.URLParams["id"]) +func (d *ServiceAPI) Put(params martini.Params, w http.ResponseWriter, r *http.Request) { + + identity := params["_1"] + println(identity) + serviceModel, err := extractServiceModel(r) if err != nil { responseError(w, err.Error()) return } - _, err1 := service.Put(d.Zookeeper, d.Config.Bamboo.Zookeeper, identifier, serviceModel.Acl) + _, err1 := service.Put(d.Zookeeper, d.Config.Bamboo.Zookeeper, identity, serviceModel.Acl) if err1 != nil { responseError(w, err1.Error()) return @@ -63,9 +65,8 @@ func (d *ServiceAPI) Put(c web.C, w http.ResponseWriter, r *http.Request) { responseJSON(w, serviceModel) } -func (d *ServiceAPI) Delete(c web.C, w http.ResponseWriter, r *http.Request) { - identifier, _ := url.QueryUnescape(c.URLParams["id"]) - err := service.Delete(d.Zookeeper, d.Config.Bamboo.Zookeeper, identifier) +func (d *ServiceAPI) Delete(params martini.Params, w http.ResponseWriter, r *http.Request) { + err := service.Delete(d.Zookeeper, d.Config.Bamboo.Zookeeper, params["_1"]) if err != nil { responseError(w, err.Error()) return diff --git a/main/bamboo/bamboo.go b/main/bamboo/bamboo.go index a0853f6..a068492 100644 --- a/main/bamboo/bamboo.go +++ b/main/bamboo/bamboo.go @@ -13,10 +13,10 @@ import ( "syscall" "time" + "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/go-martini/martini" "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/kardianos/osext" "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/natefinch/lumberjack" "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk" - "github.com/QubitProducts/bamboo/Godeps/_workspace/src/github.com/zenazn/goji" "github.com/QubitProducts/bamboo/api" "github.com/QubitProducts/bamboo/configuration" "github.com/QubitProducts/bamboo/qzk" @@ -69,7 +69,10 @@ func main() { handlers := event_bus.Handlers{Conf: &conf, Zookeeper: zkConn} eventBus.Register(handlers.MarathonEventHandler) eventBus.Register(handlers.ServiceEventHandler) - eventBus.Publish(event_bus.MarathonEvent { EventType: "bamboo_startup", Timestamp: time.Now().Format(time.RFC3339) }) + eventBus.Publish(event_bus.MarathonEvent{EventType: "bamboo_startup", Timestamp: time.Now().Format(time.RFC3339)}) + + // Handle gracefully exit + registerOSSignals() // Start server initServer(&conf, zkConn, eventBus) @@ -82,24 +85,26 @@ func initServer(conf *configuration.Configuration, conn *zk.Conn, eventBus *even conf.StatsD.Increment(1.0, "restart", 1) // Status live information - goji.Get("/status", api.HandleStatus) - - // State API - goji.Get("/api/state", stateAPI.Get) - - // Service API - goji.Get("/api/services", serviceAPI.All) - goji.Post("/api/services", serviceAPI.Create) - goji.Put("/api/services/:id", serviceAPI.Put) - goji.Delete("/api/services/:id", serviceAPI.Delete) - goji.Post("/api/marathon/event_callback", eventSubAPI.Callback) + router := martini.Classic() + router.Get("/status", api.HandleStatus) + + // API + router.Group("/api", func(api martini.Router) { + // State API + api.Get("/state", stateAPI.Get) + // Service API + api.Get("/services", serviceAPI.All) + api.Post("/services", serviceAPI.Create) + api.Put("/services/**", serviceAPI.Put) + api.Delete("/services/**", serviceAPI.Delete) + api.Post("/marathon/event_callback", eventSubAPI.Callback) + }) // Static pages - goji.Get("/*", http.FileServer(http.Dir(path.Join(executableFolder(), "webapp")))) + router.Use(martini.Static(path.Join(executableFolder(), "webapp"))) registerMarathonEvent(conf) - - goji.Serve() + router.RunOnAddr(":8000") } // Get current executable folder path @@ -176,3 +181,14 @@ func configureLog() { }, os.Stdout)) } } + +func registerOSSignals() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go func() { + for _ = range c { + log.Println("Server Stopped") + os.Exit(0) + } + }() +} diff --git a/services/event_bus/event_handler.go b/services/event_bus/event_handler.go index 3b8c5f7..5e40118 100644 --- a/services/event_bus/event_handler.go +++ b/services/event_bus/event_handler.go @@ -95,7 +95,7 @@ func handleHAPUpdate(conf *configuration.Configuration, conn *zk.Conn) bool { err = execCommand(conf.HAProxy.ReloadCommand) if err != nil { - log.Fatalf("HAProxy: update failed\n") + log.Println("HAProxy: update failed\n") } else { conf.StatsD.Increment(1.0, "reload.marathon", 1) log.Println("HAProxy: Configuration updated") diff --git a/services/service/service.go b/services/service/service.go index e0a4e92..cc9aaa8 100644 --- a/services/service/service.go +++ b/services/service/service.go @@ -54,11 +54,16 @@ func Create(conn *zk.Conn, zkConf conf.Zookeeper, appId string, domainValue stri func Put(conn *zk.Conn, zkConf conf.Zookeeper, appId string, domainValue string) (*zk.Stat, error) { path := concatPath(zkConf.Path, appId) - stats, err := conn.Set(path, []byte(domainValue), -1) + err := ensurePathExists(conn, path) + if err != nil { + return nil, err + } + stats, err := conn.Set(path, []byte(domainValue), -1) if err != nil { return nil, err } + // Force triger an event on parent conn.Set(zkConf.Path, []byte{}, -1)