API: expose runtime representation

Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
This commit is contained in:
mpl 2019-05-16 10:58:06 +02:00 committed by Traefiker Bot
parent 5cd9396dae
commit f6df556eb0
50 changed files with 2250 additions and 1158 deletions

View file

@ -314,11 +314,17 @@ func TestRouterManager_Get(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
serviceManager := service.NewManager(test.serviceConfig, http.DefaultTransport)
middlewaresBuilder := middleware.NewBuilder(test.middlewaresConfig, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(test.middlewaresConfig)
routerManager := NewManager(test.routersConfig, serviceManager, middlewaresBuilder, responseModifierFactory)
rtConf := config.NewRuntimeConfig(config.Configuration{
HTTP: &config.HTTPConfiguration{
Services: test.serviceConfig,
Routers: test.routersConfig,
Middlewares: test.middlewaresConfig,
},
})
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport)
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
routerManager := NewManager(rtConf.Routers, serviceManager, middlewaresBuilder, responseModifierFactory)
handlers := routerManager.BuildHandlers(context.Background(), test.entryPoints, false)
@ -413,11 +419,17 @@ func TestAccessLog(t *testing.T) {
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
serviceManager := service.NewManager(test.serviceConfig, http.DefaultTransport)
middlewaresBuilder := middleware.NewBuilder(test.middlewaresConfig, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(test.middlewaresConfig)
routerManager := NewManager(test.routersConfig, serviceManager, middlewaresBuilder, responseModifierFactory)
rtConf := config.NewRuntimeConfig(config.Configuration{
HTTP: &config.HTTPConfiguration{
Services: test.serviceConfig,
Routers: test.routersConfig,
Middlewares: test.middlewaresConfig,
},
})
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport)
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
routerManager := NewManager(rtConf.Routers, serviceManager, middlewaresBuilder, responseModifierFactory)
handlers := routerManager.BuildHandlers(context.Background(), test.entryPoints, false)
@ -443,6 +455,310 @@ func TestAccessLog(t *testing.T) {
}
}
func TestRuntimeConfiguration(t *testing.T) {
testCases := []struct {
desc string
serviceConfig map[string]*config.Service
routerConfig map[string]*config.Router
middlewareConfig map[string]*config.Middleware
expectedError int
}{
{
desc: "No error",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1:8085",
Weight: 1,
},
{
URL: "http://127.0.0.1:8086",
Weight: 1,
},
},
Method: "wrr",
HealthCheck: &config.HealthCheck{
Interval: "500ms",
Path: "/health",
},
},
},
},
routerConfig: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
},
},
expectedError: 0,
},
{
desc: "One router with wrong rule",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
routerConfig: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "WrongRule(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
},
},
expectedError: 1,
},
{
desc: "All router with wrong rule",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
routerConfig: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "WrongRule(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "WrongRule(`foo.bar`)",
},
},
expectedError: 2,
},
{
desc: "Router with unknown service",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
routerConfig: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "wrong-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
},
},
expectedError: 1,
},
{
desc: "Router with broken service",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: nil,
},
},
routerConfig: map[string]*config.Router{
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
},
},
expectedError: 2,
},
{
desc: "Router with middleware",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
middlewareConfig: map[string]*config.Middleware{
"auth": {
BasicAuth: &config.BasicAuth{
Users: []string{"admin:admin"},
},
},
"addPrefixTest": {
AddPrefix: &config.AddPrefix{
Prefix: "/toto",
},
},
},
routerConfig: map[string]*config.Router{
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
Middlewares: []string{"auth", "addPrefixTest"},
},
"test": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar.other`)",
Middlewares: []string{"addPrefixTest", "auth"},
},
},
},
{
desc: "Router with unknown middleware",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
middlewareConfig: map[string]*config.Middleware{
"auth": {
BasicAuth: &config.BasicAuth{
Users: []string{"admin:admin"},
},
},
},
routerConfig: map[string]*config.Router{
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
Middlewares: []string{"unknown"},
},
},
expectedError: 1,
},
{
desc: "Router with broken middleware",
serviceConfig: map[string]*config.Service{
"foo-service": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://127.0.0.1",
Weight: 1,
},
},
Method: "wrr",
},
},
},
middlewareConfig: map[string]*config.Middleware{
"auth": {
BasicAuth: &config.BasicAuth{
Users: []string{"foo"},
},
},
},
routerConfig: map[string]*config.Router{
"bar": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host(`foo.bar`)",
Middlewares: []string{"auth"},
},
},
expectedError: 2,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
entryPoints := []string{"web"}
rtConf := config.NewRuntimeConfig(config.Configuration{
HTTP: &config.HTTPConfiguration{
Services: test.serviceConfig,
Routers: test.routerConfig,
Middlewares: test.middlewareConfig,
},
})
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport)
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*config.MiddlewareInfo{})
routerManager := NewManager(rtConf.Routers, serviceManager, middlewaresBuilder, responseModifierFactory)
_ = routerManager.BuildHandlers(context.Background(), entryPoints, false)
// even though rtConf was passed by argument to the manager builders above,
// it's ok to use it as the result we check, because everything worth checking
// can be accessed by pointers in it.
var allErrors int
for _, v := range rtConf.Services {
if v.Err != nil {
allErrors++
}
}
for _, v := range rtConf.Routers {
if v.Err != "" {
allErrors++
}
}
for _, v := range rtConf.Middlewares {
if v.Err != nil {
allErrors++
}
}
assert.Equal(t, test.expectedError, allErrors)
})
}
}
type staticTransport struct {
res *http.Response
}
@ -480,11 +796,17 @@ func BenchmarkRouterServe(b *testing.B) {
}
entryPoints := []string{"web"}
serviceManager := service.NewManager(serviceConfig, &staticTransport{res})
middlewaresBuilder := middleware.NewBuilder(map[string]*config.Middleware{}, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*config.Middleware{})
routerManager := NewManager(routersConfig, serviceManager, middlewaresBuilder, responseModifierFactory)
rtConf := config.NewRuntimeConfig(config.Configuration{
HTTP: &config.HTTPConfiguration{
Services: serviceConfig,
Routers: routersConfig,
Middlewares: map[string]*config.Middleware{},
},
})
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res})
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
routerManager := NewManager(rtConf.Routers, serviceManager, middlewaresBuilder, responseModifierFactory)
handlers := routerManager.BuildHandlers(context.Background(), entryPoints, false)
@ -498,6 +820,7 @@ func BenchmarkRouterServe(b *testing.B) {
}
}
func BenchmarkService(b *testing.B) {
res := &http.Response{
StatusCode: 200,
@ -518,7 +841,12 @@ func BenchmarkService(b *testing.B) {
},
}
serviceManager := service.NewManager(serviceConfig, &staticTransport{res})
rtConf := config.NewRuntimeConfig(config.Configuration{
HTTP: &config.HTTPConfiguration{
Services: serviceConfig,
},
})
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res})
w := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://foo.bar/", nil)