swappableMux is now public and Append() now updates Server.Handler
Co-authored-by: Roberto Abdelkader Martínez Pérez <robertomartinezp@gmail.com>
This commit is contained in:
@@ -8,34 +8,34 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
type swappableMux struct {
|
type SwappableMux struct {
|
||||||
m sync.RWMutex
|
m sync.RWMutex
|
||||||
root *mux.Router
|
root *mux.Router
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *swappableMux {
|
func New() *SwappableMux {
|
||||||
return &swappableMux{
|
return &SwappableMux{
|
||||||
root: mux.NewRouter(),
|
root: mux.NewRouter(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *swappableMux) get() *mux.Router {
|
func (sm *SwappableMux) get() *mux.Router {
|
||||||
sm.m.RLock()
|
sm.m.RLock()
|
||||||
defer sm.m.RUnlock()
|
defer sm.m.RUnlock()
|
||||||
|
|
||||||
return sm.root
|
return sm.root
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *swappableMux) set(mux *mux.Router) {
|
func (sm *SwappableMux) set(mux *mux.Router) {
|
||||||
sm.m.Lock()
|
sm.m.Lock()
|
||||||
sm.root = mux
|
sm.root = mux
|
||||||
sm.m.Unlock()
|
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)
|
sm.get().ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *swappableMux) Update(rs []model.Route) {
|
func (sm *SwappableMux) Update(rs []model.Route) {
|
||||||
sm.set(gorillize(rs, handlerBuilder))
|
sm.set(gorillize(rs, handlerBuilder))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func TestNewReturnsAProperlyInitializedMux(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxGetReturnsTheCurrentMux(t *testing.T) {
|
func TestSwappableMuxGetReturnsTheCurrentMux(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
mux := sm.get()
|
mux := sm.get()
|
||||||
if !reflect.DeepEqual(mux, sm.root) {
|
if !reflect.DeepEqual(mux, sm.root) {
|
||||||
t.Errorf("Returned mux is not the same %#v", mux)
|
t.Errorf("Returned mux is not the same %#v", mux)
|
||||||
@@ -38,7 +38,7 @@ func TestSwappableMuxGetReturnsTheCurrentMux(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxGetReturnsADifferentInstance(t *testing.T) {
|
func TestSwappableMuxGetReturnsADifferentInstance(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
mux := sm.get()
|
mux := sm.get()
|
||||||
if &mux == &sm.root {
|
if &mux == &sm.root {
|
||||||
t.Error("Returned mux is the same instance")
|
t.Error("Returned mux is the same instance")
|
||||||
@@ -46,7 +46,7 @@ func TestSwappableMuxGetReturnsADifferentInstance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxGetWaitsForTheMutexToBeReleased(t *testing.T) {
|
func TestSwappableMuxGetWaitsForTheMutexToBeReleased(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
|
|
||||||
sm.m.Lock()
|
sm.m.Lock()
|
||||||
defer sm.m.Unlock()
|
defer sm.m.Unlock()
|
||||||
@@ -64,7 +64,7 @@ func TestSwappableMuxGetWaitsForTheMutexToBeReleased(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxGetIsAbleToReadWhileOthersAreReading(t *testing.T) {
|
func TestSwappableMuxGetIsAbleToReadWhileOthersAreReading(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
|
|
||||||
sm.m.RLock()
|
sm.m.RLock()
|
||||||
defer sm.m.RUnlock()
|
defer sm.m.RUnlock()
|
||||||
@@ -82,7 +82,7 @@ func TestSwappableMuxGetIsAbleToReadWhileOthersAreReading(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxSetSetsTheGivenMux(t *testing.T) {
|
func TestSwappableMuxSetSetsTheGivenMux(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
// nolint
|
// nolint
|
||||||
m.KeepContext = true
|
m.KeepContext = true
|
||||||
@@ -96,7 +96,7 @@ func TestSwappableMuxSetSetsTheGivenMux(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxSetSetsTheSameInstance(t *testing.T) {
|
func TestSwappableMuxSetSetsTheSameInstance(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
|
|
||||||
sm.set(m)
|
sm.set(m)
|
||||||
@@ -107,7 +107,7 @@ func TestSwappableMuxSetSetsTheSameInstance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxSetWaitsForWriterToReleaseMutex(t *testing.T) {
|
func TestSwappableMuxSetWaitsForWriterToReleaseMutex(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
|
|
||||||
sm.m.Lock()
|
sm.m.Lock()
|
||||||
defer sm.m.Unlock()
|
defer sm.m.Unlock()
|
||||||
@@ -125,7 +125,7 @@ func TestSwappableMuxSetWaitsForWriterToReleaseMutex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwappableMuxSetWaitsForReadersToReleaseMutex(t *testing.T) {
|
func TestSwappableMuxSetWaitsForReadersToReleaseMutex(t *testing.T) {
|
||||||
sm := swappableMux{}
|
sm := SwappableMux{}
|
||||||
|
|
||||||
sm.m.RLock()
|
sm.m.RLock()
|
||||||
defer sm.m.RUnlock()
|
defer sm.m.RUnlock()
|
||||||
@@ -148,7 +148,7 @@ func TestServeHTTPCallsInnerMux(t *testing.T) {
|
|||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
||||||
|
|
||||||
sm := swappableMux{root: m}
|
sm := SwappableMux{root: m}
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@@ -166,7 +166,7 @@ func TestServeHTTPCanServeWhenMuxIsReadLocked(t *testing.T) {
|
|||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
||||||
|
|
||||||
sm := swappableMux{root: m}
|
sm := SwappableMux{root: m}
|
||||||
sm.m.RLock()
|
sm.m.RLock()
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
@@ -187,7 +187,7 @@ func TestServeHTTPCallsInnerMuxAfterAcquiringLock(t *testing.T) {
|
|||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { called = true })
|
||||||
|
|
||||||
sm := swappableMux{root: m}
|
sm := SwappableMux{root: m}
|
||||||
sm.m.Lock()
|
sm.m.Lock()
|
||||||
|
|
||||||
req := httptest.NewRequest("GET", "/", nil)
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/BBVA/kapow/internal/server/user/state"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Routes = state.New()
|
|
||||||
@@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,13 @@ package user
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/BBVA/kapow/internal/server/user/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Server http.Server
|
var Server = http.Server{
|
||||||
|
Handler: mux.New(),
|
||||||
|
}
|
||||||
|
|
||||||
func Run() {
|
func Run() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,41 @@
|
|||||||
package user
|
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) {}
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package state
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/BBVA/kapow/internal/server/model"
|
"github.com/BBVA/kapow/internal/server/model"
|
||||||
|
"github.com/BBVA/kapow/internal/server/user/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
type safeRouteList struct {
|
type safeRouteList struct {
|
||||||
@@ -12,6 +13,8 @@ type safeRouteList struct {
|
|||||||
m *sync.RWMutex
|
m *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Routes safeRouteList = New()
|
||||||
|
|
||||||
func New() safeRouteList {
|
func New() safeRouteList {
|
||||||
return safeRouteList{
|
return safeRouteList{
|
||||||
rs: []model.Route{},
|
rs: []model.Route{},
|
||||||
@@ -25,6 +28,8 @@ func (srl *safeRouteList) Append(r model.Route) model.Route {
|
|||||||
l := len(srl.rs)
|
l := len(srl.rs)
|
||||||
srl.m.Unlock()
|
srl.m.Unlock()
|
||||||
|
|
||||||
|
Server.Handler.(*mux.SwappableMux).Update(srl.Snapshot())
|
||||||
|
|
||||||
return model.Route{Index: l - 1}
|
return model.Route{Index: l - 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// +build !race
|
// +build !race
|
||||||
|
|
||||||
package state
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -271,3 +271,9 @@ func TestDeleteWaitsForReadersToFinishReading(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPackageHaveASingletonEmptyRouteList(t *testing.T) {
|
||||||
|
if !reflect.DeepEqual(Routes, New()) {
|
||||||
|
t.Error("Routes is not an empty safeRouteList")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user