From df5d38e94fefabbe25d3c4b1ae54b0ed8e00f089 Mon Sep 17 00:00:00 2001 From: pancho horrillo Date: Thu, 10 Oct 2019 20:06:05 +0200 Subject: [PATCH] swappableMux is now public and Append() now updates Server.Handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Roberto Abdelkader Martínez Pérez --- internal/server/user/mux/mux.go | 14 +++---- internal/server/user/mux/mux_test.go | 22 +++++------ internal/server/user/routes.go | 7 ---- internal/server/user/routes_test.go | 14 ------- internal/server/user/server.go | 6 ++- internal/server/user/server_test.go | 38 +++++++++++++++++++ internal/server/user/{state => }/state.go | 7 +++- .../server/user/{state => }/state_test.go | 8 +++- 8 files changed, 74 insertions(+), 42 deletions(-) delete mode 100644 internal/server/user/routes.go delete mode 100644 internal/server/user/routes_test.go rename internal/server/user/{state => }/state.go (86%) rename internal/server/user/{state => }/state_test.go (96%) diff --git a/internal/server/user/mux/mux.go b/internal/server/user/mux/mux.go index ec814d1..b5acb08 100644 --- a/internal/server/user/mux/mux.go +++ b/internal/server/user/mux/mux.go @@ -8,34 +8,34 @@ import ( "github.com/gorilla/mux" ) -type swappableMux struct { +type SwappableMux struct { m sync.RWMutex root *mux.Router } -func New() *swappableMux { - return &swappableMux{ +func New() *SwappableMux { + return &SwappableMux{ root: mux.NewRouter(), } } -func (sm *swappableMux) get() *mux.Router { +func (sm *SwappableMux) get() *mux.Router { sm.m.RLock() defer sm.m.RUnlock() return sm.root } -func (sm *swappableMux) set(mux *mux.Router) { +func (sm *SwappableMux) set(mux *mux.Router) { sm.m.Lock() sm.root = mux sm.m.Unlock() } -func (sm *swappableMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (sm *SwappableMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { sm.get().ServeHTTP(w, r) } -func (sm *swappableMux) Update(rs []model.Route) { +func (sm *SwappableMux) Update(rs []model.Route) { sm.set(gorillize(rs, handlerBuilder)) } diff --git a/internal/server/user/mux/mux_test.go b/internal/server/user/mux/mux_test.go index 7d770cb..48938ed 100644 --- a/internal/server/user/mux/mux_test.go +++ b/internal/server/user/mux/mux_test.go @@ -30,7 +30,7 @@ func TestNewReturnsAProperlyInitializedMux(t *testing.T) { } func TestSwappableMuxGetReturnsTheCurrentMux(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} mux := sm.get() if !reflect.DeepEqual(mux, sm.root) { t.Errorf("Returned mux is not the same %#v", mux) @@ -38,7 +38,7 @@ func TestSwappableMuxGetReturnsTheCurrentMux(t *testing.T) { } func TestSwappableMuxGetReturnsADifferentInstance(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} mux := sm.get() if &mux == &sm.root { t.Error("Returned mux is the same instance") @@ -46,7 +46,7 @@ func TestSwappableMuxGetReturnsADifferentInstance(t *testing.T) { } func TestSwappableMuxGetWaitsForTheMutexToBeReleased(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} sm.m.Lock() defer sm.m.Unlock() @@ -64,7 +64,7 @@ func TestSwappableMuxGetWaitsForTheMutexToBeReleased(t *testing.T) { } func TestSwappableMuxGetIsAbleToReadWhileOthersAreReading(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} sm.m.RLock() defer sm.m.RUnlock() @@ -82,7 +82,7 @@ func TestSwappableMuxGetIsAbleToReadWhileOthersAreReading(t *testing.T) { } func TestSwappableMuxSetSetsTheGivenMux(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} m := mux.NewRouter() // nolint m.KeepContext = true @@ -96,7 +96,7 @@ func TestSwappableMuxSetSetsTheGivenMux(t *testing.T) { } func TestSwappableMuxSetSetsTheSameInstance(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} m := mux.NewRouter() sm.set(m) @@ -107,7 +107,7 @@ func TestSwappableMuxSetSetsTheSameInstance(t *testing.T) { } func TestSwappableMuxSetWaitsForWriterToReleaseMutex(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} sm.m.Lock() defer sm.m.Unlock() @@ -125,7 +125,7 @@ func TestSwappableMuxSetWaitsForWriterToReleaseMutex(t *testing.T) { } func TestSwappableMuxSetWaitsForReadersToReleaseMutex(t *testing.T) { - sm := swappableMux{} + sm := SwappableMux{} sm.m.RLock() defer sm.m.RUnlock() @@ -148,7 +148,7 @@ func TestServeHTTPCallsInnerMux(t *testing.T) { m := mux.NewRouter() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true }) - sm := swappableMux{root: m} + sm := SwappableMux{root: m} req := httptest.NewRequest("GET", "/", nil) w := httptest.NewRecorder() @@ -166,7 +166,7 @@ func TestServeHTTPCanServeWhenMuxIsReadLocked(t *testing.T) { m := mux.NewRouter() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true }) - sm := swappableMux{root: m} + sm := SwappableMux{root: m} sm.m.RLock() req := httptest.NewRequest("GET", "/", nil) @@ -187,7 +187,7 @@ func TestServeHTTPCallsInnerMuxAfterAcquiringLock(t *testing.T) { m := mux.NewRouter() m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true }) - sm := swappableMux{root: m} + sm := SwappableMux{root: m} sm.m.Lock() req := httptest.NewRequest("GET", "/", nil) diff --git a/internal/server/user/routes.go b/internal/server/user/routes.go deleted file mode 100644 index e53211e..0000000 --- a/internal/server/user/routes.go +++ /dev/null @@ -1,7 +0,0 @@ -package user - -import ( - "github.com/BBVA/kapow/internal/server/user/state" -) - -var Routes = state.New() diff --git a/internal/server/user/routes_test.go b/internal/server/user/routes_test.go deleted file mode 100644 index e9133cd..0000000 --- a/internal/server/user/routes_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package user - -import ( - "reflect" - "testing" - - "github.com/BBVA/kapow/internal/server/user/state" -) - -func TestPackageHaveASingletonEmptyRouteList(t *testing.T) { - if !reflect.DeepEqual(Routes, state.New()) { - t.Error("Routes is not an empty safeRouteList") - } -} diff --git a/internal/server/user/server.go b/internal/server/user/server.go index ff8b332..ee2c122 100644 --- a/internal/server/user/server.go +++ b/internal/server/user/server.go @@ -2,9 +2,13 @@ package user import ( "net/http" + + "github.com/BBVA/kapow/internal/server/user/mux" ) -var Server http.Server +var Server = http.Server{ + Handler: mux.New(), +} func Run() { } diff --git a/internal/server/user/server_test.go b/internal/server/user/server_test.go index d5eed30..c1fc42b 100644 --- a/internal/server/user/server_test.go +++ b/internal/server/user/server_test.go @@ -1,3 +1,41 @@ package user +import ( + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/BBVA/kapow/internal/server/model" + "github.com/BBVA/kapow/internal/server/user/mux" +) + // TODO TestRunRunsAnHTTPServer(t *testing.T) {} + +func TestAppendUpdatesMuxWithProvideRoute(t *testing.T) { + Server = http.Server{ + Handler: mux.New(), + } + srl := New() + route := model.Route{ + Method: "GET", + Pattern: "/", + Entrypoint: "/bin/sh -c", + Command: "jaillover > /tmp/kapow-test-append-updates-mux", + } + os.Remove("/tmp/kapow-test-append-updates-mux") + defer os.Remove("/tmp/kapow-test-append-updates-mux") + + srl.Append(route) + + req := httptest.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + + Server.Handler.ServeHTTP(w, req) + + if _, err := os.Stat("/tmp/kapow-test-append-updates-mux"); os.IsNotExist(err) { + t.Error("Routes not updated") + } else if err != nil { + t.Fatalf("Unexpected error: %v", err) + } +} diff --git a/internal/server/user/state/state.go b/internal/server/user/state.go similarity index 86% rename from internal/server/user/state/state.go rename to internal/server/user/state.go index eac0fe9..5f98186 100644 --- a/internal/server/user/state/state.go +++ b/internal/server/user/state.go @@ -1,10 +1,11 @@ -package state +package user import ( "errors" "sync" "github.com/BBVA/kapow/internal/server/model" + "github.com/BBVA/kapow/internal/server/user/mux" ) type safeRouteList struct { @@ -12,6 +13,8 @@ type safeRouteList struct { m *sync.RWMutex } +var Routes safeRouteList = New() + func New() safeRouteList { return safeRouteList{ rs: []model.Route{}, @@ -25,6 +28,8 @@ func (srl *safeRouteList) Append(r model.Route) model.Route { l := len(srl.rs) srl.m.Unlock() + Server.Handler.(*mux.SwappableMux).Update(srl.Snapshot()) + return model.Route{Index: l - 1} } diff --git a/internal/server/user/state/state_test.go b/internal/server/user/state_test.go similarity index 96% rename from internal/server/user/state/state_test.go rename to internal/server/user/state_test.go index 672d35e..3981f3f 100644 --- a/internal/server/user/state/state_test.go +++ b/internal/server/user/state_test.go @@ -1,6 +1,6 @@ // +build !race -package state +package user import ( "reflect" @@ -271,3 +271,9 @@ func TestDeleteWaitsForReadersToFinishReading(t *testing.T) { default: } } + +func TestPackageHaveASingletonEmptyRouteList(t *testing.T) { + if !reflect.DeepEqual(Routes, New()) { + t.Error("Routes is not an empty safeRouteList") + } +}