diff --git a/integration/fixtures/router_errors.toml b/integration/fixtures/router_errors.toml new file mode 100644 index 000000000..335339e2b --- /dev/null +++ b/integration/fixtures/router_errors.toml @@ -0,0 +1,45 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.web-secure] + address = ":4443" + +[api] + +[providers.file] + filename = "{{ .SelfFilename }}" + +## dynamic configuration ## + +[http.routers] + [http.routers.router4] + service = "service1" + rule = "Host(`snitest.net`)" + [http.routers.router4.tls] + options = "foo" + + [http.routers.router5] + service = "service1" + rule = "Host(`snitest.net`)" + middlewares = [ "unknown" ] + [http.routers.router5.tls] + options = "baz" + +[http.services] + [http.services.service1] + [http.services.service1.loadBalancer] + [[http.services.service1.loadBalancer.servers]] + url = "http://127.0.0.1:9010" + +[tls.options] + + [tls.options.foo] + minversion = "VersionTLS11" + + [tls.options.baz] + minversion = "VersionTLS11" diff --git a/integration/fixtures/service_errors.toml b/integration/fixtures/service_errors.toml new file mode 100644 index 000000000..3bdc495bb --- /dev/null +++ b/integration/fixtures/service_errors.toml @@ -0,0 +1,34 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.web-secure] + address = ":4443" + +[api] + +[providers.file] + filename = "{{ .SelfFilename }}" + +## dynamic configuration ## + +[http.routers] + [http.routers.router4] + service = "service1" + rule = "Host(`snitest.net`)" + + [http.routers.router5] + service = "service2" + rule = "Host(`snitest.com`)" + +[http.services] + [http.services.service1] + + [http.services.service2] + [http.services.service2.loadBalancer] + [[http.services.service2.loadBalancer.servers]] + url = "http://127.0.0.1:9010" diff --git a/integration/simple_test.go b/integration/simple_test.go index ef4baa451..b7309d809 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -524,3 +524,48 @@ func (s *SimpleSuite) TestSimpleConfigurationHostRequestTrailingPeriod(c *check. } } } + +func (s *SimpleSuite) TestRouterConfigErrors(c *check.C) { + file := s.adaptFile(c, "fixtures/router_errors.toml", struct{}{}) + defer os.Remove(file) + + cmd, output := s.traefikCmd(withConfigFile(file)) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + // All errors + err = try.GetRequest("http://127.0.0.1:8080/api/http/routers", 1000*time.Millisecond, try.BodyContains(`["middleware \"unknown@file\" does not exist","found different TLS options for routers on the same host snitest.net, so using the default TLS option instead"]`)) + c.Assert(err, checker.IsNil) + + // router4 is enabled, but in warning state because its tls options conf was messed up + err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router4@file", 1000*time.Millisecond, try.BodyContains(`"status":"warning"`)) + c.Assert(err, checker.IsNil) + + // router5 is disabled because its middleware conf is broken + err = try.GetRequest("http://127.0.0.1:8080/api/http/routers/router5@file", 1000*time.Millisecond, try.BodyContains()) + c.Assert(err, checker.IsNil) +} + +func (s *SimpleSuite) TestServiceConfigErrors(c *check.C) { + file := s.adaptFile(c, "fixtures/service_errors.toml", struct{}{}) + defer os.Remove(file) + + cmd, output := s.traefikCmd(withConfigFile(file)) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://127.0.0.1:8080/api/http/services", 1000*time.Millisecond, try.BodyContains(`["the service \"service1@file\" doesn't have any load balancer"]`)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/http/services/service1@file", 1000*time.Millisecond, try.BodyContains(`"status":"disabled"`)) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/http/services/service2@file", 1000*time.Millisecond, try.BodyContains(`"status":"enabled"`)) + c.Assert(err, checker.IsNil) +} diff --git a/integration/testdata/rawdata-crd.json b/integration/testdata/rawdata-crd.json index 1851ddd5e..8b2dadbbb 100644 --- a/integration/testdata/rawdata-crd.json +++ b/integration/testdata/rawdata-crd.json @@ -9,7 +9,8 @@ "priority": 12, "tls": { "options": "default/mytlsoption" - } + }, + "status": "enabled" }, "default/test2.route-23c7f4c450289ee29016@kubernetescrd": { "entryPoints": [ @@ -19,7 +20,8 @@ "default/stripprefix" ], "service": "default/test2.route-23c7f4c450289ee29016", - "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)" + "rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)", + "status": "enabled" } }, "middlewares": { @@ -39,7 +41,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.3:80" + "url": "http://10.42.0.4:80" }, { "url": "http://10.42.0.5:80" @@ -47,11 +49,12 @@ ], "passHostHeader": true }, + "status": "enabled", "usedBy": [ "default/test.route-6b204d94623b3df4370c@kubernetescrd" ], "serverStatus": { - "http://10.42.0.3:80": "UP", + "http://10.42.0.4:80": "UP", "http://10.42.0.5:80": "UP" } }, @@ -59,7 +62,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.3:80" + "url": "http://10.42.0.4:80" }, { "url": "http://10.42.0.5:80" @@ -67,11 +70,12 @@ ], "passHostHeader": true }, + "status": "enabled", "usedBy": [ "default/test2.route-23c7f4c450289ee29016@kubernetescrd" ], "serverStatus": { - "http://10.42.0.3:80": "UP", + "http://10.42.0.4:80": "UP", "http://10.42.0.5:80": "UP" } } @@ -86,7 +90,8 @@ "tls": { "passthrough": false, "options": "default/mytlsoption" - } + }, + "status": "enabled" } }, "tcpServices": { @@ -94,13 +99,14 @@ "loadBalancer": { "servers": [ { - "address": "10.42.0.4:8080" + "address": "10.42.0.3:8080" }, { "address": "10.42.0.6:8080" } ] }, + "status": "enabled", "usedBy": [ "default/test3.crd-673acf455cb2dab0b43a@kubernetescrd" ] diff --git a/integration/testdata/rawdata-ingress.json b/integration/testdata/rawdata-ingress.json index c22fdf46e..79692c664 100644 --- a/integration/testdata/rawdata-ingress.json +++ b/integration/testdata/rawdata-ingress.json @@ -2,7 +2,8 @@ "routers": { "whoami-test/whoami@kubernetes": { "service": "default/whoami/http", - "rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)" + "rule": "Host(`whoami.test`) \u0026\u0026 PathPrefix(`/whoami`)", + "status": "enabled" } }, "services": { @@ -10,7 +11,7 @@ "loadBalancer": { "servers": [ { - "url": "http://10.42.0.2:80" + "url": "http://10.42.0.4:80" }, { "url": "http://10.42.0.5:80" @@ -18,11 +19,12 @@ ], "passHostHeader": true }, + "status": "enabled", "usedBy": [ "whoami-test/whoami@kubernetes" ], "serverStatus": { - "http://10.42.0.2:80": "UP", + "http://10.42.0.4:80": "UP", "http://10.42.0.5:80": "UP" } } diff --git a/pkg/api/handler.go b/pkg/api/handler.go index 79e0540d7..75fa1f7ff 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/containous/mux" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/types" @@ -24,17 +24,17 @@ const ( const nextPageHeader = "X-Next-Page" type serviceInfoRepresentation struct { - *dynamic.ServiceInfo + *runtime.ServiceInfo ServerStatus map[string]string `json:"serverStatus,omitempty"` } // RunTimeRepresentation is the configuration information exposed by the API handler. type RunTimeRepresentation struct { - Routers map[string]*dynamic.RouterInfo `json:"routers,omitempty"` - Middlewares map[string]*dynamic.MiddlewareInfo `json:"middlewares,omitempty"` + Routers map[string]*runtime.RouterInfo `json:"routers,omitempty"` + Middlewares map[string]*runtime.MiddlewareInfo `json:"middlewares,omitempty"` Services map[string]*serviceInfoRepresentation `json:"services,omitempty"` - TCPRouters map[string]*dynamic.TCPRouterInfo `json:"tcpRouters,omitempty"` - TCPServices map[string]*dynamic.TCPServiceInfo `json:"tcpServices,omitempty"` + TCPRouters map[string]*runtime.TCPRouterInfo `json:"tcpRouters,omitempty"` + TCPServices map[string]*runtime.TCPServiceInfo `json:"tcpServices,omitempty"` } type pageInfo struct { @@ -48,7 +48,7 @@ type Handler struct { dashboard bool debug bool // runtimeConfiguration is the data set used to create all the data representations exposed by the API. - runtimeConfiguration *dynamic.RuntimeConfiguration + runtimeConfiguration *runtime.Configuration staticConfig static.Configuration statistics *types.Statistics // stats *thoasstats.Stats // FIXME stats @@ -58,10 +58,10 @@ type Handler struct { // New returns a Handler defined by staticConfig, and if provided, by runtimeConfig. // It finishes populating the information provided in the runtimeConfig. -func New(staticConfig static.Configuration, runtimeConfig *dynamic.RuntimeConfiguration) *Handler { +func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration) *Handler { rConfig := runtimeConfig if rConfig == nil { - rConfig = &dynamic.RuntimeConfiguration{} + rConfig = &runtime.Configuration{} } return &Handler{ diff --git a/pkg/api/handler_entrypoint_test.go b/pkg/api/handler_entrypoint_test.go index 162e655a2..333fd6c4c 100644 --- a/pkg/api/handler_entrypoint_test.go +++ b/pkg/api/handler_entrypoint_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/containous/mux" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -198,7 +198,7 @@ func TestHandler_EntryPoints(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - handler := New(test.conf, &dynamic.RuntimeConfiguration{}) + handler := New(test.conf, &runtime.Configuration{}) router := mux.NewRouter() handler.Append(router) diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index 02b8165f9..d13d92f7a 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -7,25 +7,25 @@ import ( "strconv" "github.com/containous/mux" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" ) type routerRepresentation struct { - *dynamic.RouterInfo + *runtime.RouterInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` } type serviceRepresentation struct { - *dynamic.ServiceInfo + *runtime.ServiceInfo ServerStatus map[string]string `json:"serverStatus,omitempty"` Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` } type middlewareRepresentation struct { - *dynamic.MiddlewareInfo + *runtime.MiddlewareInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` } diff --git a/pkg/api/handler_http_test.go b/pkg/api/handler_http_test.go index 2d9a2235a..2d04091c7 100644 --- a/pkg/api/handler_http_test.go +++ b/pkg/api/handler_http_test.go @@ -11,6 +11,7 @@ import ( "github.com/containous/mux" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -26,13 +27,13 @@ func TestHandler_HTTP(t *testing.T) { testCases := []struct { desc string path string - conf dynamic.RuntimeConfiguration + conf runtime.Configuration expected expected }{ { desc: "all routers, but no config", path: "/api/http/routers", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, nextPage: "1", @@ -42,8 +43,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all routers", path: "/api/http/routers", - conf: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "test@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -71,8 +72,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all routers, pagination, 1 res per page, want page 2", path: "/api/http/routers?page=2&per_page=1", - conf: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -107,7 +108,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all routers, pagination, 19 results overall, 7 res per page, want page 3", path: "/api/http/routers?page=3&per_page=7", - conf: dynamic.RuntimeConfiguration{ + conf: runtime.Configuration{ Routers: generateHTTPRouters(19), }, expected: expected{ @@ -119,7 +120,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all routers, pagination, 5 results overall, 10 res per page, want page 2", path: "/api/http/routers?page=2&per_page=10", - conf: dynamic.RuntimeConfiguration{ + conf: runtime.Configuration{ Routers: generateHTTPRouters(5), }, expected: expected{ @@ -129,7 +130,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all routers, pagination, 10 results overall, 10 res per page, want page 2", path: "/api/http/routers?page=2&per_page=10", - conf: dynamic.RuntimeConfiguration{ + conf: runtime.Configuration{ Routers: generateHTTPRouters(10), }, expected: expected{ @@ -139,8 +140,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one router by id", path: "/api/http/routers/bar@myprovider", - conf: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -148,6 +149,7 @@ func TestHandler_HTTP(t *testing.T) { Rule: "Host(`foo.bar`)", Middlewares: []string{"auth", "addPrefixTest@anotherprovider"}, }, + Status: "enabled", }, }, }, @@ -159,8 +161,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one router by id, that does not exist", path: "/api/http/routers/foo@myprovider", - conf: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + conf: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -178,7 +180,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one router by id, but no config", path: "/api/http/routers/foo@myprovider", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusNotFound, }, @@ -186,7 +188,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all services, but no config", path: "/api/http/services", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, nextPage: "1", @@ -196,10 +198,10 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all services", path: "/api/http/services", - conf: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ - "bar@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -211,11 +213,11 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider", "test@myprovider"}, } - si.UpdateStatus("http://127.0.0.1", "UP") + si.UpdateServerStatus("http://127.0.0.1", "UP") return si }(), - "baz@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + "baz@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -227,7 +229,7 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider"}, } - si.UpdateStatus("http://127.0.0.2", "UP") + si.UpdateServerStatus("http://127.0.0.2", "UP") return si }(), }, @@ -241,10 +243,10 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all services, 1 res per page, want page 2", path: "/api/http/services?page=2&per_page=1", - conf: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ - "bar@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -256,11 +258,11 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider", "test@myprovider"}, } - si.UpdateStatus("http://127.0.0.1", "UP") + si.UpdateServerStatus("http://127.0.0.1", "UP") return si }(), - "baz@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + "baz@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -272,11 +274,11 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider"}, } - si.UpdateStatus("http://127.0.0.2", "UP") + si.UpdateServerStatus("http://127.0.0.2", "UP") return si }(), - "test@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + "test@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -288,7 +290,7 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider", "test@myprovider"}, } - si.UpdateStatus("http://127.0.0.4", "UP") + si.UpdateServerStatus("http://127.0.0.4", "UP") return si }(), }, @@ -302,10 +304,10 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one service by id", path: "/api/http/services/bar@myprovider", - conf: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ - "bar@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -317,7 +319,7 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider", "test@myprovider"}, } - si.UpdateStatus("http://127.0.0.1", "UP") + si.UpdateServerStatus("http://127.0.0.1", "UP") return si }(), }, @@ -330,10 +332,10 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one service by id, that does not exist", path: "/api/http/services/nono@myprovider", - conf: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ - "bar@myprovider": func() *dynamic.ServiceInfo { - si := &dynamic.ServiceInfo{ + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ + "bar@myprovider": func() *runtime.ServiceInfo { + si := &runtime.ServiceInfo{ Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ Servers: []dynamic.Server{ @@ -345,7 +347,7 @@ func TestHandler_HTTP(t *testing.T) { }, UsedBy: []string{"foo@myprovider", "test@myprovider"}, } - si.UpdateStatus("http://127.0.0.1", "UP") + si.UpdateServerStatus("http://127.0.0.1", "UP") return si }(), }, @@ -357,7 +359,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one service by id, but no config", path: "/api/http/services/foo@myprovider", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusNotFound, }, @@ -365,7 +367,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all middlewares, but no config", path: "/api/http/middlewares", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, nextPage: "1", @@ -375,8 +377,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all middlewares", path: "/api/http/middlewares", - conf: dynamic.RuntimeConfiguration{ - Middlewares: map[string]*dynamic.MiddlewareInfo{ + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -412,8 +414,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "all middlewares, 1 res per page, want page 2", path: "/api/http/middlewares?page=2&per_page=1", - conf: dynamic.RuntimeConfiguration{ - Middlewares: map[string]*dynamic.MiddlewareInfo{ + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -449,8 +451,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one middleware by id", path: "/api/http/middlewares/auth@myprovider", - conf: dynamic.RuntimeConfiguration{ - Middlewares: map[string]*dynamic.MiddlewareInfo{ + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -485,8 +487,8 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one middleware by id, that does not exist", path: "/api/http/middlewares/foo@myprovider", - conf: dynamic.RuntimeConfiguration{ - Middlewares: map[string]*dynamic.MiddlewareInfo{ + conf: runtime.Configuration{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -504,7 +506,7 @@ func TestHandler_HTTP(t *testing.T) { { desc: "one middleware by id, but no config", path: "/api/http/middlewares/foo@myprovider", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusNotFound, }, @@ -517,6 +519,8 @@ func TestHandler_HTTP(t *testing.T) { t.Parallel() rtConf := &test.conf + // To lazily initialize the Statuses. + rtConf.PopulateUsedBy() handler := New(static.Configuration{API: &static.API{}, Global: &static.Global{}}, rtConf) router := mux.NewRouter() handler.Append(router) @@ -560,10 +564,10 @@ func TestHandler_HTTP(t *testing.T) { } } -func generateHTTPRouters(nbRouters int) map[string]*dynamic.RouterInfo { - routers := make(map[string]*dynamic.RouterInfo, nbRouters) +func generateHTTPRouters(nbRouters int) map[string]*runtime.RouterInfo { + routers := make(map[string]*runtime.RouterInfo, nbRouters) for i := 0; i < nbRouters; i++ { - routers[fmt.Sprintf("bar%2d@myprovider", i)] = &dynamic.RouterInfo{ + routers[fmt.Sprintf("bar%2d@myprovider", i)] = &runtime.RouterInfo{ Router: &dynamic.Router{ EntryPoints: []string{"web"}, Service: "foo-service@myprovider", diff --git a/pkg/api/handler_overview.go b/pkg/api/handler_overview.go index 01c15f2b5..6d6c51751 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -5,7 +5,7 @@ import ( "net/http" "reflect" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/log" ) @@ -60,37 +60,45 @@ func (h Handler) getOverview(rw http.ResponseWriter, request *http.Request) { } } -func getHTTPRouterSection(routers map[string]*dynamic.RouterInfo) *section { +func getHTTPRouterSection(routers map[string]*runtime.RouterInfo) *section { var countErrors int + var countWarnings int for _, rt := range routers { - if rt.Err != "" { + switch rt.Status { + case runtime.StatusDisabled: countErrors++ + case runtime.StatusWarning: + countWarnings++ } } return §ion{ Total: len(routers), - Warnings: 0, // TODO + Warnings: countWarnings, Errors: countErrors, } } -func getHTTPServiceSection(services map[string]*dynamic.ServiceInfo) *section { +func getHTTPServiceSection(services map[string]*runtime.ServiceInfo) *section { var countErrors int + var countWarnings int for _, svc := range services { - if svc.Err != nil { + switch svc.Status { + case runtime.StatusDisabled: countErrors++ + case runtime.StatusWarning: + countWarnings++ } } return §ion{ Total: len(services), - Warnings: 0, // TODO + Warnings: countWarnings, Errors: countErrors, } } -func getHTTPMiddlewareSection(middlewares map[string]*dynamic.MiddlewareInfo) *section { +func getHTTPMiddlewareSection(middlewares map[string]*runtime.MiddlewareInfo) *section { var countErrors int for _, md := range middlewares { if md.Err != nil { @@ -100,12 +108,12 @@ func getHTTPMiddlewareSection(middlewares map[string]*dynamic.MiddlewareInfo) *s return §ion{ Total: len(middlewares), - Warnings: 0, // TODO + Warnings: 0, Errors: countErrors, } } -func getTCPRouterSection(routers map[string]*dynamic.TCPRouterInfo) *section { +func getTCPRouterSection(routers map[string]*runtime.TCPRouterInfo) *section { var countErrors int for _, rt := range routers { if rt.Err != "" { @@ -120,7 +128,7 @@ func getTCPRouterSection(routers map[string]*dynamic.TCPRouterInfo) *section { } } -func getTCPServiceSection(services map[string]*dynamic.TCPServiceInfo) *section { +func getTCPServiceSection(services map[string]*runtime.TCPServiceInfo) *section { var countErrors int for _, svc := range services { if svc.Err != nil { diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index bfdaf0b42..418335c40 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -9,6 +9,7 @@ import ( "github.com/containous/mux" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/provider/docker" "github.com/containous/traefik/pkg/provider/file" @@ -33,14 +34,14 @@ func TestHandler_Overview(t *testing.T) { desc string path string confStatic static.Configuration - confDyn dynamic.RuntimeConfiguration + confDyn runtime.Configuration expected expected }{ { desc: "without data in the dynamic configuration", path: "/api/overview", confStatic: static.Configuration{API: &static.API{}, Global: &static.Global{}}, - confDyn: dynamic.RuntimeConfiguration{}, + confDyn: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, jsonFile: "testdata/overview-empty.json", @@ -50,21 +51,34 @@ func TestHandler_Overview(t *testing.T) { desc: "with data in the dynamic configuration", path: "/api/overview", confStatic: static.Configuration{API: &static.API{}, Global: &static.Global{}}, - confDyn: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + confDyn: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ - Servers: []dynamic.Server{ - { - URL: "http://127.0.0.1", - }, - }, + Servers: []dynamic.Server{{URL: "http://127.0.0.1"}}, }, }, + Status: runtime.StatusEnabled, + }, + "bar-service@myprovider": { + Service: &dynamic.Service{ + LoadBalancer: &dynamic.LoadBalancerService{ + Servers: []dynamic.Server{{URL: "http://127.0.0.1"}}, + }, + }, + Status: runtime.StatusWarning, + }, + "fii-service@myprovider": { + Service: &dynamic.Service{ + LoadBalancer: &dynamic.LoadBalancerService{ + Servers: []dynamic.Server{{URL: "http://127.0.0.1"}}, + }, + }, + Status: runtime.StatusDisabled, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -85,9 +99,10 @@ func TestHandler_Overview(t *testing.T) { Prefix: "/toto", }, }, + Err: []string{"error"}, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -95,6 +110,7 @@ func TestHandler_Overview(t *testing.T) { Rule: "Host(`foo.bar`)", Middlewares: []string{"auth", "addPrefixTest@anotherprovider"}, }, + Status: runtime.StatusEnabled, }, "test@myprovider": { Router: &dynamic.Router{ @@ -103,9 +119,19 @@ func TestHandler_Overview(t *testing.T) { Rule: "Host(`foo.bar.other`)", Middlewares: []string{"addPrefixTest", "auth"}, }, + Status: runtime.StatusWarning, + }, + "foo@myprovider": { + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "foo-service@myprovider", + Rule: "Host(`foo.bar.other`)", + Middlewares: []string{"addPrefixTest", "auth"}, + }, + Status: runtime.StatusDisabled, }, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "tcpfoo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -118,7 +144,7 @@ func TestHandler_Overview(t *testing.T) { }, }, }, - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "tcpbar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -156,7 +182,7 @@ func TestHandler_Overview(t *testing.T) { Rancher: &rancher.Provider{}, }, }, - confDyn: dynamic.RuntimeConfiguration{}, + confDyn: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, jsonFile: "testdata/overview-providers.json", @@ -175,7 +201,7 @@ func TestHandler_Overview(t *testing.T) { Jaeger: &jaeger.Config{}, }, }, - confDyn: dynamic.RuntimeConfiguration{}, + confDyn: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, jsonFile: "testdata/overview-features.json", diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 81217f240..6dcb0915a 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -7,18 +7,18 @@ import ( "strconv" "github.com/containous/mux" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" ) type tcpRouterRepresentation struct { - *dynamic.TCPRouterInfo + *runtime.TCPRouterInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` } type tcpServiceRepresentation struct { - *dynamic.TCPServiceInfo + *runtime.TCPServiceInfo Name string `json:"name,omitempty"` Provider string `json:"provider,omitempty"` } diff --git a/pkg/api/handler_tcp_test.go b/pkg/api/handler_tcp_test.go index 20f7cbeb8..9c68b0f2b 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -9,6 +9,7 @@ import ( "github.com/containous/mux" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,13 +25,13 @@ func TestHandler_TCP(t *testing.T) { testCases := []struct { desc string path string - conf dynamic.RuntimeConfiguration + conf runtime.Configuration expected expected }{ { desc: "all TCP routers, but no config", path: "/api/tcp/routers", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, nextPage: "1", @@ -40,8 +41,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "all TCP routers", path: "/api/tcp/routers", - conf: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "test@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -70,8 +71,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "all TCP routers, pagination, 1 res per page, want page 2", path: "/api/tcp/routers?page=2&per_page=1", - conf: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -104,8 +105,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "one TCP router by id", path: "/api/tcp/routers/bar@myprovider", - conf: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -123,8 +124,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "one TCP router by id, that does not exist", path: "/api/tcp/routers/foo@myprovider", - conf: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + conf: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -141,7 +142,7 @@ func TestHandler_TCP(t *testing.T) { { desc: "one TCP router by id, but no config", path: "/api/tcp/routers/bar@myprovider", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusNotFound, }, @@ -149,7 +150,7 @@ func TestHandler_TCP(t *testing.T) { { desc: "all tcp services, but no config", path: "/api/tcp/services", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusOK, nextPage: "1", @@ -159,8 +160,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "all tcp services", path: "/api/tcp/services", - conf: dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "bar@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -196,8 +197,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "all tcp services, 1 res per page, want page 2", path: "/api/tcp/services?page=2&per_page=1", - conf: dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "bar@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -244,8 +245,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "one tcp service by id", path: "/api/tcp/services/bar@myprovider", - conf: dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "bar@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -268,8 +269,8 @@ func TestHandler_TCP(t *testing.T) { { desc: "one tcp service by id, that does not exist", path: "/api/tcp/services/nono@myprovider", - conf: dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "bar@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -291,7 +292,7 @@ func TestHandler_TCP(t *testing.T) { { desc: "one tcp service by id, but no config", path: "/api/tcp/services/foo@myprovider", - conf: dynamic.RuntimeConfiguration{}, + conf: runtime.Configuration{}, expected: expected{ statusCode: http.StatusNotFound, }, diff --git a/pkg/api/handler_test.go b/pkg/api/handler_test.go index 59f0d5edc..1055eead0 100644 --- a/pkg/api/handler_test.go +++ b/pkg/api/handler_test.go @@ -10,6 +10,7 @@ import ( "github.com/containous/mux" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -26,14 +27,14 @@ func TestHandler_RawData(t *testing.T) { testCases := []struct { desc string path string - conf dynamic.RuntimeConfiguration + conf runtime.Configuration expected expected }{ { desc: "Get rawdata", path: "/api/rawdata", - conf: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -46,7 +47,7 @@ func TestHandler_RawData(t *testing.T) { }, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -69,7 +70,7 @@ func TestHandler_RawData(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -87,7 +88,7 @@ func TestHandler_RawData(t *testing.T) { }, }, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "tcpfoo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -100,7 +101,7 @@ func TestHandler_RawData(t *testing.T) { }, }, }, - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "tcpbar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, diff --git a/pkg/api/testdata/getrawdata.json b/pkg/api/testdata/getrawdata.json index 7e238245b..9ef1b9111 100644 --- a/pkg/api/testdata/getrawdata.json +++ b/pkg/api/testdata/getrawdata.json @@ -9,7 +9,8 @@ "addPrefixTest@anotherprovider" ], "service": "foo-service@myprovider", - "rule": "Host(`foo.bar`)" + "rule": "Host(`foo.bar`)", + "status": "enabled" }, "test@myprovider": { "entryPoints": [ @@ -20,7 +21,8 @@ "auth" ], "service": "foo-service@myprovider", - "rule": "Host(`foo.bar.other`)" + "rule": "Host(`foo.bar.other`)", + "status": "enabled" } }, "middlewares": { @@ -62,6 +64,7 @@ ], "passHostHeader": false }, + "status": "enabled", "usedBy": [ "bar@myprovider", "test@myprovider" @@ -74,14 +77,16 @@ "web" ], "service": "tcpfoo-service@myprovider", - "rule": "HostSNI(`foo.bar`)" + "rule": "HostSNI(`foo.bar`)", + "status": "enabled" }, "tcptest@myprovider": { "entryPoints": [ "web" ], "service": "tcpfoo-service@myprovider", - "rule": "HostSNI(`foo.bar.other`)" + "rule": "HostSNI(`foo.bar.other`)", + "status": "enabled" } }, "tcpServices": { @@ -93,6 +98,7 @@ } ] }, + "status": "enabled", "usedBy": [ "tcpbar@myprovider", "tcptest@myprovider" diff --git a/pkg/api/testdata/overview-dynamic.json b/pkg/api/testdata/overview-dynamic.json index 346f47433..c2c864386 100644 --- a/pkg/api/testdata/overview-dynamic.json +++ b/pkg/api/testdata/overview-dynamic.json @@ -6,19 +6,19 @@ }, "http": { "middlewares": { - "errors": 0, + "errors": 1, "total": 3, "warnings": 0 }, "routers": { - "errors": 0, - "total": 2, - "warnings": 0 + "errors": 1, + "total": 3, + "warnings": 1 }, "services": { - "errors": 0, - "total": 1, - "warnings": 0 + "errors": 1, + "total": 3, + "warnings": 1 } }, "tcp": { diff --git a/pkg/api/testdata/router-bar.json b/pkg/api/testdata/router-bar.json index ea407a3a3..267a9628b 100644 --- a/pkg/api/testdata/router-bar.json +++ b/pkg/api/testdata/router-bar.json @@ -9,5 +9,6 @@ "name": "bar@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" } \ No newline at end of file diff --git a/pkg/api/testdata/routers-many-lastpage.json b/pkg/api/testdata/routers-many-lastpage.json index c13b87a55..290672375 100644 --- a/pkg/api/testdata/routers-many-lastpage.json +++ b/pkg/api/testdata/routers-many-lastpage.json @@ -6,7 +6,8 @@ "name": "bar14@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar14`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" }, { "entryPoints": [ @@ -15,7 +16,8 @@ "name": "bar15@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar15`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" }, { "entryPoints": [ @@ -24,7 +26,8 @@ "name": "bar16@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar16`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" }, { "entryPoints": [ @@ -33,7 +36,8 @@ "name": "bar17@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar17`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" }, { "entryPoints": [ @@ -42,6 +46,7 @@ "name": "bar18@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar18`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" } ] \ No newline at end of file diff --git a/pkg/api/testdata/routers-page2.json b/pkg/api/testdata/routers-page2.json index 73d97c6d6..8c7f65d1b 100644 --- a/pkg/api/testdata/routers-page2.json +++ b/pkg/api/testdata/routers-page2.json @@ -6,6 +6,7 @@ "name": "baz@myprovider", "provider": "myprovider", "rule": "Host(`toto.bar`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" } ] \ No newline at end of file diff --git a/pkg/api/testdata/routers.json b/pkg/api/testdata/routers.json index f0e4c37b8..664aedc51 100644 --- a/pkg/api/testdata/routers.json +++ b/pkg/api/testdata/routers.json @@ -10,7 +10,8 @@ "name": "bar@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" }, { "entryPoints": [ @@ -23,6 +24,7 @@ "name": "test@myprovider", "provider": "myprovider", "rule": "Host(`foo.bar.other`)", - "service": "foo-service@myprovider" + "service": "foo-service@myprovider", + "status": "enabled" } ] \ No newline at end of file diff --git a/pkg/api/testdata/service-bar.json b/pkg/api/testdata/service-bar.json index 529e3382a..e26b65a72 100644 --- a/pkg/api/testdata/service-bar.json +++ b/pkg/api/testdata/service-bar.json @@ -12,6 +12,7 @@ "serverStatus": { "http://127.0.0.1": "UP" }, + "status": "enabled", "usedBy": [ "foo@myprovider", "test@myprovider" diff --git a/pkg/api/testdata/services-page2.json b/pkg/api/testdata/services-page2.json index 2f5dce034..66b8390d1 100644 --- a/pkg/api/testdata/services-page2.json +++ b/pkg/api/testdata/services-page2.json @@ -13,6 +13,7 @@ "serverStatus": { "http://127.0.0.2": "UP" }, + "status": "enabled", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/api/testdata/services.json b/pkg/api/testdata/services.json index 9abd426f8..bd54b536c 100644 --- a/pkg/api/testdata/services.json +++ b/pkg/api/testdata/services.json @@ -13,6 +13,7 @@ "serverStatus": { "http://127.0.0.1": "UP" }, + "status": "enabled", "usedBy": [ "foo@myprovider", "test@myprovider" @@ -32,6 +33,7 @@ "serverStatus": { "http://127.0.0.2": "UP" }, + "status": "enabled", "usedBy": [ "foo@myprovider" ] diff --git a/pkg/config/dynamic/runtime.go b/pkg/config/runtime/runtime.go similarity index 50% rename from pkg/config/dynamic/runtime.go rename to pkg/config/runtime/runtime.go index 94dfe2c94..4c6221af3 100644 --- a/pkg/config/dynamic/runtime.go +++ b/pkg/config/runtime/runtime.go @@ -1,4 +1,4 @@ -package dynamic +package runtime import ( "context" @@ -6,11 +6,19 @@ import ( "strings" "sync" + "github.com/containous/traefik/pkg/config/dynamic" "github.com/containous/traefik/pkg/log" ) -// RuntimeConfiguration holds the information about the currently running traefik instance. -type RuntimeConfiguration struct { +// Status of the router/service +const ( + StatusEnabled = "enabled" + StatusDisabled = "disabled" + StatusWarning = "warning" +) + +// Configuration holds the information about the currently running traefik instance. +type Configuration struct { Routers map[string]*RouterInfo `json:"routers,omitempty"` Middlewares map[string]*MiddlewareInfo `json:"middlewares,omitempty"` Services map[string]*ServiceInfo `json:"services,omitempty"` @@ -18,20 +26,20 @@ type RuntimeConfiguration struct { TCPServices map[string]*TCPServiceInfo `json:"tcpServices,omitempty"` } -// NewRuntimeConfig returns a RuntimeConfiguration initialized with the given conf. It never returns nil. -func NewRuntimeConfig(conf Configuration) *RuntimeConfiguration { +// NewConfig returns a Configuration initialized with the given conf. It never returns nil. +func NewConfig(conf dynamic.Configuration) *Configuration { if conf.HTTP == nil && conf.TCP == nil { - return &RuntimeConfiguration{} + return &Configuration{} } - runtimeConfig := &RuntimeConfiguration{} + runtimeConfig := &Configuration{} if conf.HTTP != nil { routers := conf.HTTP.Routers if len(routers) > 0 { runtimeConfig.Routers = make(map[string]*RouterInfo, len(routers)) for k, v := range routers { - runtimeConfig.Routers[k] = &RouterInfo{Router: v} + runtimeConfig.Routers[k] = &RouterInfo{Router: v, Status: StatusEnabled} } } @@ -39,7 +47,7 @@ func NewRuntimeConfig(conf Configuration) *RuntimeConfiguration { if len(services) > 0 { runtimeConfig.Services = make(map[string]*ServiceInfo, len(services)) for k, v := range services { - runtimeConfig.Services[k] = &ServiceInfo{Service: v} + runtimeConfig.Services[k] = &ServiceInfo{Service: v, Status: StatusEnabled} } } @@ -56,14 +64,14 @@ func NewRuntimeConfig(conf Configuration) *RuntimeConfiguration { if len(conf.TCP.Routers) > 0 { runtimeConfig.TCPRouters = make(map[string]*TCPRouterInfo, len(conf.TCP.Routers)) for k, v := range conf.TCP.Routers { - runtimeConfig.TCPRouters[k] = &TCPRouterInfo{TCPRouter: v} + runtimeConfig.TCPRouters[k] = &TCPRouterInfo{TCPRouter: v, Status: StatusEnabled} } } if len(conf.TCP.Services) > 0 { runtimeConfig.TCPServices = make(map[string]*TCPServiceInfo, len(conf.TCP.Services)) for k, v := range conf.TCP.Services { - runtimeConfig.TCPServices[k] = &TCPServiceInfo{TCPService: v} + runtimeConfig.TCPServices[k] = &TCPServiceInfo{TCPService: v, Status: StatusEnabled} } } } @@ -73,7 +81,7 @@ func NewRuntimeConfig(conf Configuration) *RuntimeConfiguration { // PopulateUsedBy populates all the UsedBy lists of the underlying fields of r, // based on the relations between the included services, routers, and middlewares. -func (r *RuntimeConfiguration) PopulateUsedBy() { +func (r *Configuration) PopulateUsedBy() { if r == nil { return } @@ -81,6 +89,11 @@ func (r *RuntimeConfiguration) PopulateUsedBy() { logger := log.WithoutContext() for routerName, routerInfo := range r.Routers { + // lazily initialize Status in case caller forgot to do it + if routerInfo.Status == "" { + routerInfo.Status = StatusEnabled + } + providerName := getProviderName(routerName) if providerName == "" { logger.WithField(log.RouterName, routerName).Error("router name is not fully qualified") @@ -102,7 +115,12 @@ func (r *RuntimeConfiguration) PopulateUsedBy() { r.Services[serviceName].UsedBy = append(r.Services[serviceName].UsedBy, routerName) } - for k := range r.Services { + for k, serviceInfo := range r.Services { + // lazily initialize Status in case caller forgot to do it + if serviceInfo.Status == "" { + serviceInfo.Status = StatusEnabled + } + sort.Strings(r.Services[k].UsedBy) } @@ -111,6 +129,11 @@ func (r *RuntimeConfiguration) PopulateUsedBy() { } for routerName, routerInfo := range r.TCPRouters { + // lazily initialize Status in case caller forgot to do it + if routerInfo.Status == "" { + routerInfo.Status = StatusEnabled + } + providerName := getProviderName(routerName) if providerName == "" { logger.WithField(log.RouterName, routerName).Error("tcp router name is not fully qualified") @@ -124,7 +147,12 @@ func (r *RuntimeConfiguration) PopulateUsedBy() { r.TCPServices[serviceName].UsedBy = append(r.TCPServices[serviceName].UsedBy, routerName) } - for k := range r.TCPServices { + for k, serviceInfo := range r.TCPServices { + // lazily initialize Status in case caller forgot to do it + if serviceInfo.Status == "" { + serviceInfo.Status = StatusEnabled + } + sort.Strings(r.TCPServices[k].UsedBy) } } @@ -138,8 +166,8 @@ func contains(entryPoints []string, entryPointName string) bool { return false } -// GetRoutersByEntrypoints returns all the http routers by entrypoints name and routers name -func (r *RuntimeConfiguration) GetRoutersByEntrypoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo { +// GetRoutersByEntryPoints returns all the http routers by entry points name and routers name +func (r *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo { entryPointsRouters := make(map[string]map[string]*RouterInfo) for rtName, rt := range r.Routers { @@ -169,8 +197,8 @@ func (r *RuntimeConfiguration) GetRoutersByEntrypoints(ctx context.Context, entr return entryPointsRouters } -// GetTCPRoutersByEntrypoints returns all the tcp routers by entrypoints name and routers name -func (r *RuntimeConfiguration) GetTCPRoutersByEntrypoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo { +// GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name +func (r *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo { entryPointsRouters := make(map[string]map[string]*TCPRouterInfo) for rtName, rt := range r.TCPRouters { @@ -199,57 +227,126 @@ func (r *RuntimeConfiguration) GetTCPRoutersByEntrypoints(ctx context.Context, e // RouterInfo holds information about a currently running HTTP router type RouterInfo struct { - *Router // dynamic configuration - Err string `json:"error,omitempty"` // initialization error + *dynamic.Router // dynamic configuration + // Err contains all the errors that occurred during router's creation. + Err []string `json:"error,omitempty"` + // Status reports whether the router is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` +} + +// AddError adds err to r.Err, if it does not already exist. +// If critical is set, r is marked as disabled. +func (r *RouterInfo) AddError(err error, critical bool) { + for _, value := range r.Err { + if value == err.Error() { + return + } + } + + r.Err = append(r.Err, err.Error()) + if critical { + r.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if r.Status != StatusDisabled { + r.Status = StatusWarning + } } // TCPRouterInfo holds information about a currently running TCP router type TCPRouterInfo struct { - *TCPRouter // dynamic configuration - Err string `json:"error,omitempty"` // initialization error + *dynamic.TCPRouter // dynamic configuration + Err string `json:"error,omitempty"` // initialization error + // Status reports whether the router is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` } // MiddlewareInfo holds information about a currently running middleware type MiddlewareInfo struct { - *Middleware // dynamic configuration - Err error `json:"error,omitempty"` // initialization error - UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware + *dynamic.Middleware // dynamic configuration + // Err contains all the errors that occurred during service creation. + Err []string `json:"error,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware +} + +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, m is marked as disabled. +func (m *MiddlewareInfo) AddError(err error) { + for _, value := range m.Err { + if value == err.Error() { + return + } + } + + m.Err = append(m.Err, err.Error()) } // ServiceInfo holds information about a currently running service type ServiceInfo struct { - *Service // dynamic configuration - Err error `json:"error,omitempty"` // initialization error - UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service + *dynamic.Service // dynamic configuration + // Err contains all the errors that occurred during service creation. + Err []string `json:"error,omitempty"` + // Status reports whether the service is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service - statusMu sync.RWMutex - status map[string]string // keyed by server URL + serverStatusMu sync.RWMutex + serverStatus map[string]string // keyed by server URL } -// UpdateStatus sets the status of the server in the ServiceInfo. -// It is the responsibility of the caller to check that s is not nil. -func (s *ServiceInfo) UpdateStatus(server string, status string) { - s.statusMu.Lock() - defer s.statusMu.Unlock() - - if s.status == nil { - s.status = make(map[string]string) +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, s is marked as disabled. +func (s *ServiceInfo) AddError(err error, critical bool) { + for _, value := range s.Err { + if value == err.Error() { + return + } } - s.status[server] = status + + s.Err = append(s.Err, err.Error()) + if critical { + s.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if s.Status != StatusDisabled { + s.Status = StatusWarning + } +} + +// UpdateServerStatus sets the status of the server in the ServiceInfo. +// It is the responsibility of the caller to check that s is not nil. +func (s *ServiceInfo) UpdateServerStatus(server string, status string) { + s.serverStatusMu.Lock() + defer s.serverStatusMu.Unlock() + + if s.serverStatus == nil { + s.serverStatus = make(map[string]string) + } + s.serverStatus[server] = status } // GetAllStatus returns all the statuses of all the servers in ServiceInfo. // It is the responsibility of the caller to check that s is not nil func (s *ServiceInfo) GetAllStatus() map[string]string { - s.statusMu.RLock() - defer s.statusMu.RUnlock() + s.serverStatusMu.RLock() + defer s.serverStatusMu.RUnlock() - if len(s.status) == 0 { + if len(s.serverStatus) == 0 { return nil } - allStatus := make(map[string]string, len(s.status)) - for k, v := range s.status { + allStatus := make(map[string]string, len(s.serverStatus)) + for k, v := range s.serverStatus { allStatus[k] = v } return allStatus @@ -257,9 +354,13 @@ func (s *ServiceInfo) GetAllStatus() map[string]string { // TCPServiceInfo holds information about a currently running TCP service type TCPServiceInfo struct { - *TCPService // dynamic configuration - Err error `json:"error,omitempty"` // initialization error - UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service + *dynamic.TCPService // dynamic configuration + Err error `json:"error,omitempty"` // initialization error + // Status reports whether the service is disabled, in a warning state, or all good (enabled). + // If not in "enabled" state, the reason for it should be in the list of Err. + // It is the caller's responsibility to set the initial status. + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service } func getProviderName(elementName string) string { diff --git a/pkg/config/dynamic/runtime_test.go b/pkg/config/runtime/runtime_test.go similarity index 82% rename from pkg/config/dynamic/runtime_test.go rename to pkg/config/runtime/runtime_test.go index 4cd1be4e1..0d5885f22 100644 --- a/pkg/config/dynamic/runtime_test.go +++ b/pkg/config/runtime/runtime_test.go @@ -1,30 +1,31 @@ -package dynamic_test +package runtime_test import ( "context" "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // all the Routers/Middlewares/Services are considered fully qualified -func TestPopulateUsedby(t *testing.T) { +func TestPopulateUsedBy(t *testing.T) { testCases := []struct { desc string - conf *dynamic.RuntimeConfiguration - expected dynamic.RuntimeConfiguration + conf *runtime.Configuration + expected runtime.Configuration }{ { desc: "nil config", conf: nil, - expected: dynamic.RuntimeConfiguration{}, + expected: runtime.Configuration{}, }, { desc: "One service used by two routers", - conf: &dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + conf: &runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "foo@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -40,7 +41,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -57,12 +58,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "foo@myprovider": {}, "bar@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "foo@myprovider"}, }, @@ -71,8 +72,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "One service used by two routers, but one router with wrong rule", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -83,7 +84,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "foo@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -100,12 +101,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "foo@myprovider": {}, "bar@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "foo@myprovider"}, }, @@ -114,15 +115,15 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "Broken Service used by one Router", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: nil, }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -132,11 +133,11 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider"}, }, @@ -145,8 +146,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "2 different Services each used by a disctinct router.", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -184,7 +185,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "foo@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -201,12 +202,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": {}, "foo@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"foo@myprovider"}, }, @@ -218,8 +219,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "2 middlewares both used by 2 Routers", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -232,7 +233,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -248,7 +249,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -267,17 +268,17 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": {}, "test@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "test@myprovider"}, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { UsedBy: []string{"bar@myprovider", "test@myprovider"}, }, @@ -289,8 +290,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "Unknown middleware is not used by the Router", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -303,7 +304,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -312,7 +313,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -323,8 +324,8 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + expected: runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider"}, }, @@ -333,8 +334,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "Broken middleware is used by Router", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -347,7 +348,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -356,7 +357,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -367,16 +368,16 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider"}, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { UsedBy: []string{"bar@myprovider"}, }, @@ -385,8 +386,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "2 middlewares from 2 disctinct providers both used by 2 Routers", - conf: &dynamic.RuntimeConfiguration{ - Services: map[string]*dynamic.ServiceInfo{ + conf: &runtime.Configuration{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{ @@ -399,7 +400,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { Middleware: &dynamic.Middleware{ BasicAuth: &dynamic.BasicAuth{ @@ -422,7 +423,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - Routers: map[string]*dynamic.RouterInfo{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": { Router: &dynamic.Router{ EntryPoints: []string{"web"}, @@ -441,17 +442,17 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - Routers: map[string]*dynamic.RouterInfo{ + expected: runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{ "bar@myprovider": {}, "test@myprovider": {}, }, - Services: map[string]*dynamic.ServiceInfo{ + Services: map[string]*runtime.ServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "test@myprovider"}, }, }, - Middlewares: map[string]*dynamic.MiddlewareInfo{ + Middlewares: map[string]*runtime.MiddlewareInfo{ "auth@myprovider": { UsedBy: []string{"bar@myprovider", "test@myprovider"}, }, @@ -468,8 +469,8 @@ func TestPopulateUsedby(t *testing.T) { // TCP tests from hereon { desc: "TCP, One service used by two routers", - conf: &dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + conf: &runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "foo@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -485,7 +486,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -504,12 +505,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + expected: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "foo@myprovider": {}, "bar@myprovider": {}, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "foo@myprovider"}, }, @@ -518,8 +519,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "TCP, One service used by two routers, but one router with wrong rule", - conf: &dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: &runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -532,7 +533,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "foo@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -549,12 +550,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + expected: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "foo@myprovider": {}, "bar@myprovider": {}, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider", "foo@myprovider"}, }, @@ -563,15 +564,15 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "TCP, Broken Service used by one Router", - conf: &dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: &runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: nil, }, }, }, - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -581,11 +582,11 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + expected: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": {}, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"bar@myprovider"}, }, @@ -594,8 +595,8 @@ func TestPopulateUsedby(t *testing.T) { }, { desc: "TCP, 2 different Services each used by a disctinct router.", - conf: &dynamic.RuntimeConfiguration{ - TCPServices: map[string]*dynamic.TCPServiceInfo{ + conf: &runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -629,7 +630,7 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "foo@myprovider": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -646,12 +647,12 @@ func TestPopulateUsedby(t *testing.T) { }, }, }, - expected: dynamic.RuntimeConfiguration{ - TCPRouters: map[string]*dynamic.TCPRouterInfo{ + expected: runtime.Configuration{ + TCPRouters: map[string]*runtime.TCPRouterInfo{ "bar@myprovider": {}, "foo@myprovider": {}, }, - TCPServices: map[string]*dynamic.TCPServiceInfo{ + TCPServices: map[string]*runtime.TCPServiceInfo{ "foo-service@myprovider": { UsedBy: []string{"foo@myprovider"}, }, @@ -690,24 +691,24 @@ func TestPopulateUsedby(t *testing.T) { } -func TestGetTCPRoutersByEntrypoints(t *testing.T) { +func TestGetTCPRoutersByEntryPoints(t *testing.T) { testCases := []struct { desc string conf dynamic.Configuration entryPoints []string - expected map[string]map[string]*dynamic.TCPRouterInfo + expected map[string]map[string]*runtime.TCPRouterInfo }{ { desc: "Empty Configuration without entrypoint", conf: dynamic.Configuration{}, entryPoints: []string{""}, - expected: map[string]map[string]*dynamic.TCPRouterInfo{}, + expected: map[string]map[string]*runtime.TCPRouterInfo{}, }, { desc: "Empty Configuration with unknown entrypoints", conf: dynamic.Configuration{}, entryPoints: []string{"foo"}, - expected: map[string]map[string]*dynamic.TCPRouterInfo{}, + expected: map[string]map[string]*runtime.TCPRouterInfo{}, }, { desc: "Valid configuration with an unknown entrypoint", @@ -732,7 +733,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"foo"}, - expected: map[string]map[string]*dynamic.TCPRouterInfo{}, + expected: map[string]map[string]*runtime.TCPRouterInfo{}, }, { desc: "Valid configuration with a known entrypoint", @@ -777,7 +778,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"web"}, - expected: map[string]map[string]*dynamic.TCPRouterInfo{ + expected: map[string]map[string]*runtime.TCPRouterInfo{ "web": { "foo": { TCPRouter: &dynamic.TCPRouter{ @@ -785,6 +786,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "foo-service@myprovider", Rule: "HostSNI(`bar.foo`)", }, + Status: "enabled", }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -792,6 +794,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "HostSNI(`bar.foobar`)", }, + Status: "enabled", }, }, }, @@ -839,7 +842,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"web", "webs"}, - expected: map[string]map[string]*dynamic.TCPRouterInfo{ + expected: map[string]map[string]*runtime.TCPRouterInfo{ "web": { "foo": { TCPRouter: &dynamic.TCPRouter{ @@ -847,6 +850,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "foo-service@myprovider", Rule: "HostSNI(`bar.foo`)", }, + Status: "enabled", }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -854,6 +858,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "HostSNI(`bar.foobar`)", }, + Status: "enabled", }, }, "webs": { @@ -864,6 +869,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "bar-service@myprovider", Rule: "HostSNI(`foo.bar`)", }, + Status: "enabled", }, "foobar": { TCPRouter: &dynamic.TCPRouter{ @@ -871,6 +877,7 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "HostSNI(`bar.foobar`)", }, + Status: "enabled", }, }, }, @@ -881,31 +888,31 @@ func TestGetTCPRoutersByEntrypoints(t *testing.T) { test := test t.Run(test.desc, func(t *testing.T) { t.Parallel() - runtimeConfig := dynamic.NewRuntimeConfig(test.conf) - actual := runtimeConfig.GetTCPRoutersByEntrypoints(context.Background(), test.entryPoints) + runtimeConfig := runtime.NewConfig(test.conf) + actual := runtimeConfig.GetTCPRoutersByEntryPoints(context.Background(), test.entryPoints) assert.Equal(t, test.expected, actual) }) } } -func TestGetRoutersByEntrypoints(t *testing.T) { +func TestGetRoutersByEntryPoints(t *testing.T) { testCases := []struct { desc string conf dynamic.Configuration entryPoints []string - expected map[string]map[string]*dynamic.RouterInfo + expected map[string]map[string]*runtime.RouterInfo }{ { desc: "Empty Configuration without entrypoint", conf: dynamic.Configuration{}, entryPoints: []string{""}, - expected: map[string]map[string]*dynamic.RouterInfo{}, + expected: map[string]map[string]*runtime.RouterInfo{}, }, { desc: "Empty Configuration with unknown entrypoints", conf: dynamic.Configuration{}, entryPoints: []string{"foo"}, - expected: map[string]map[string]*dynamic.RouterInfo{}, + expected: map[string]map[string]*runtime.RouterInfo{}, }, { desc: "Valid configuration with an unknown entrypoint", @@ -930,7 +937,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"foo"}, - expected: map[string]map[string]*dynamic.RouterInfo{}, + expected: map[string]map[string]*runtime.RouterInfo{}, }, { desc: "Valid configuration with a known entrypoint", @@ -975,7 +982,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"web"}, - expected: map[string]map[string]*dynamic.RouterInfo{ + expected: map[string]map[string]*runtime.RouterInfo{ "web": { "foo": { Router: &dynamic.Router{ @@ -983,6 +990,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "foo-service@myprovider", Rule: "Host(`bar.foo`)", }, + Status: "enabled", }, "foobar": { Router: &dynamic.Router{ @@ -990,6 +998,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "Host(`bar.foobar`)", }, + Status: "enabled", }, }, }, @@ -1037,7 +1046,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { }, }, entryPoints: []string{"web", "webs"}, - expected: map[string]map[string]*dynamic.RouterInfo{ + expected: map[string]map[string]*runtime.RouterInfo{ "web": { "foo": { Router: &dynamic.Router{ @@ -1045,6 +1054,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "foo-service@myprovider", Rule: "Host(`bar.foo`)", }, + Status: "enabled", }, "foobar": { Router: &dynamic.Router{ @@ -1052,6 +1062,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "Host(`bar.foobar`)", }, + Status: "enabled", }, }, "webs": { @@ -1062,6 +1073,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "bar-service@myprovider", Rule: "Host(`foo.bar`)", }, + Status: "enabled", }, "foobar": { Router: &dynamic.Router{ @@ -1069,6 +1081,7 @@ func TestGetRoutersByEntrypoints(t *testing.T) { Service: "foobar-service@myprovider", Rule: "Host(`bar.foobar`)", }, + Status: "enabled", }, }, }, @@ -1079,8 +1092,8 @@ func TestGetRoutersByEntrypoints(t *testing.T) { test := test t.Run(test.desc, func(t *testing.T) { t.Parallel() - runtimeConfig := dynamic.NewRuntimeConfig(test.conf) - actual := runtimeConfig.GetRoutersByEntrypoints(context.Background(), test.entryPoints, false) + runtimeConfig := runtime.NewConfig(test.conf) + actual := runtimeConfig.GetRoutersByEntryPoints(context.Background(), test.entryPoints, false) assert.Equal(t, test.expected, actual) }) } diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go index f36a2b039..1da028d27 100644 --- a/pkg/healthcheck/healthcheck.go +++ b/pkg/healthcheck/healthcheck.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/safe" "github.com/go-kit/kit/metrics" @@ -229,7 +229,7 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error { } // NewLBStatusUpdater returns a new LbStatusUpdater -func NewLBStatusUpdater(bh BalancerHandler, svinfo *dynamic.ServiceInfo) *LbStatusUpdater { +func NewLBStatusUpdater(bh BalancerHandler, svinfo *runtime.ServiceInfo) *LbStatusUpdater { return &LbStatusUpdater{ BalancerHandler: bh, serviceInfo: svinfo, @@ -240,7 +240,7 @@ func NewLBStatusUpdater(bh BalancerHandler, svinfo *dynamic.ServiceInfo) *LbStat // so it can keep track of the status of a server in the ServiceInfo. type LbStatusUpdater struct { BalancerHandler - serviceInfo *dynamic.ServiceInfo // can be nil + serviceInfo *runtime.ServiceInfo // can be nil } // RemoveServer removes the given server from the BalancerHandler, @@ -248,7 +248,7 @@ type LbStatusUpdater struct { func (lb *LbStatusUpdater) RemoveServer(u *url.URL) error { err := lb.BalancerHandler.RemoveServer(u) if err == nil && lb.serviceInfo != nil { - lb.serviceInfo.UpdateStatus(u.String(), serverDown) + lb.serviceInfo.UpdateServerStatus(u.String(), serverDown) } return err } @@ -258,7 +258,7 @@ func (lb *LbStatusUpdater) RemoveServer(u *url.URL) error { func (lb *LbStatusUpdater) UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error { err := lb.BalancerHandler.UpsertServer(u, options...) if err == nil && lb.serviceInfo != nil { - lb.serviceInfo.UpdateStatus(u.String(), serverUp) + lb.serviceInfo.UpdateServerStatus(u.String(), serverUp) } return err } diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go index 9dc9ef406..59fbe8f43 100644 --- a/pkg/healthcheck/healthcheck_test.go +++ b/pkg/healthcheck/healthcheck_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/testhelpers" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -443,7 +443,7 @@ func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func TestLBStatusUpdater(t *testing.T) { lb := &testLoadBalancer{RWMutex: &sync.RWMutex{}} - svInfo := &dynamic.ServiceInfo{} + svInfo := &runtime.ServiceInfo{} lbsu := NewLBStatusUpdater(lb, svInfo) newServer, err := url.Parse("http://foo.com") assert.Nil(t, err) diff --git a/pkg/responsemodifiers/response_modifier.go b/pkg/responsemodifiers/response_modifier.go index cf30f42cf..e12bddf9c 100644 --- a/pkg/responsemodifiers/response_modifier.go +++ b/pkg/responsemodifiers/response_modifier.go @@ -4,17 +4,17 @@ import ( "context" "net/http" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" ) // NewBuilder creates a builder. -func NewBuilder(configs map[string]*dynamic.MiddlewareInfo) *Builder { +func NewBuilder(configs map[string]*runtime.MiddlewareInfo) *Builder { return &Builder{configs: configs} } // Builder holds builder configuration. type Builder struct { - configs map[string]*dynamic.MiddlewareInfo + configs map[string]*runtime.MiddlewareInfo } // Build Builds the response modifier. diff --git a/pkg/responsemodifiers/response_modifier_test.go b/pkg/responsemodifiers/response_modifier_test.go index f407c124c..de48fc4b3 100644 --- a/pkg/responsemodifiers/response_modifier_test.go +++ b/pkg/responsemodifiers/response_modifier_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/middlewares/headers" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -166,7 +167,7 @@ func TestBuilderBuild(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Middlewares: test.conf, }, diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 7d2609623..8333247bc 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -8,7 +8,7 @@ import ( "strings" "github.com/containous/alice" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/middlewares/addprefix" "github.com/containous/traefik/pkg/middlewares/auth" "github.com/containous/traefik/pkg/middlewares/buffering" @@ -39,7 +39,7 @@ const ( // Builder the middleware builder type Builder struct { - configs map[string]*dynamic.MiddlewareInfo + configs map[string]*runtime.MiddlewareInfo serviceBuilder serviceBuilder } @@ -48,7 +48,7 @@ type serviceBuilder interface { } // NewBuilder creates a new Builder -func NewBuilder(configs map[string]*dynamic.MiddlewareInfo, serviceBuilder serviceBuilder) *Builder { +func NewBuilder(configs map[string]*runtime.MiddlewareInfo, serviceBuilder serviceBuilder) *Builder { return &Builder{configs: configs, serviceBuilder: serviceBuilder} } @@ -66,19 +66,19 @@ func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *alice.C var err error if constructorContext, err = checkRecursion(constructorContext, middlewareName); err != nil { - b.configs[middlewareName].Err = err + b.configs[middlewareName].AddError(err) return nil, err } constructor, err := b.buildConstructor(constructorContext, middlewareName) if err != nil { - b.configs[middlewareName].Err = err + b.configs[middlewareName].AddError(err) return nil, err } handler, err := constructor(next) if err != nil { - b.configs[middlewareName].Err = err + b.configs[middlewareName].AddError(err) return nil, err } diff --git a/pkg/server/middleware/middlewares_test.go b/pkg/server/middleware/middlewares_test.go index ead213a69..5da03c335 100644 --- a/pkg/server/middleware/middlewares_test.go +++ b/pkg/server/middleware/middlewares_test.go @@ -8,13 +8,14 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/server/internal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestBuilder_BuildChainNilConfig(t *testing.T) { - testConfig := map[string]*dynamic.MiddlewareInfo{ + testConfig := map[string]*runtime.MiddlewareInfo{ "empty": {}, } middlewaresBuilder := NewBuilder(testConfig, nil) @@ -25,7 +26,7 @@ func TestBuilder_BuildChainNilConfig(t *testing.T) { } func TestBuilder_BuildChainNonExistentChain(t *testing.T) { - testConfig := map[string]*dynamic.MiddlewareInfo{ + testConfig := map[string]*runtime.MiddlewareInfo{ "foobar": {}, } middlewaresBuilder := NewBuilder(testConfig, nil) @@ -264,7 +265,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) { ctx = internal.AddProviderInContext(ctx, "foobar@"+test.contextProvider) } - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Middlewares: test.configuration, }, @@ -315,7 +316,7 @@ func TestBuilder_buildConstructor(t *testing.T) { }, } - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Middlewares: testConfig, }, diff --git a/pkg/server/router/route_appender_aggregator.go b/pkg/server/router/route_appender_aggregator.go index 5f1423546..271498a23 100644 --- a/pkg/server/router/route_appender_aggregator.go +++ b/pkg/server/router/route_appender_aggregator.go @@ -6,7 +6,7 @@ import ( "github.com/containous/alice" "github.com/containous/mux" "github.com/containous/traefik/pkg/api" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/metrics" @@ -20,7 +20,7 @@ type chainBuilder interface { // NewRouteAppenderAggregator Creates a new RouteAppenderAggregator func NewRouteAppenderAggregator(ctx context.Context, chainBuilder chainBuilder, conf static.Configuration, - entryPointName string, runtimeConfiguration *dynamic.RuntimeConfiguration) *RouteAppenderAggregator { + entryPointName string, runtimeConfiguration *runtime.Configuration) *RouteAppenderAggregator { aggregator := &RouteAppenderAggregator{} if conf.Providers != nil && conf.Providers.Rest != nil { diff --git a/pkg/server/router/route_appender_factory.go b/pkg/server/router/route_appender_factory.go index ea44a4e21..5565aa616 100644 --- a/pkg/server/router/route_appender_factory.go +++ b/pkg/server/router/route_appender_factory.go @@ -3,7 +3,7 @@ package router import ( "context" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/provider/acme" "github.com/containous/traefik/pkg/server/middleware" @@ -27,7 +27,7 @@ type RouteAppenderFactory struct { } // NewAppender Creates a new RouteAppender -func (r *RouteAppenderFactory) NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *dynamic.RuntimeConfiguration) types.RouteAppender { +func (r *RouteAppenderFactory) NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender { aggregator := NewRouteAppenderAggregator(ctx, middlewaresBuilder, r.staticConfiguration, r.entryPointName, runtimeConfiguration) if r.acmeProvider != nil && r.acmeProvider.HTTPChallenge != nil && r.acmeProvider.HTTPChallenge.EntryPoint == r.entryPointName { diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index 104e9b42f..79a7aec15 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/containous/alice" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/middlewares/accesslog" "github.com/containous/traefik/pkg/middlewares/recovery" @@ -22,7 +22,7 @@ const ( ) // NewManager Creates a new Manager -func NewManager(conf *dynamic.RuntimeConfiguration, +func NewManager(conf *runtime.Configuration, serviceManager *service.Manager, middlewaresBuilder *middleware.Builder, modifierBuilder *responsemodifiers.Builder, @@ -42,15 +42,15 @@ type Manager struct { serviceManager *service.Manager middlewaresBuilder *middleware.Builder modifierBuilder *responsemodifiers.Builder - conf *dynamic.RuntimeConfiguration + conf *runtime.Configuration } -func (m *Manager) getHTTPRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*dynamic.RouterInfo { +func (m *Manager) getHTTPRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*runtime.RouterInfo { if m.conf != nil { - return m.conf.GetRoutersByEntrypoints(ctx, entryPoints, tls) + return m.conf.GetRoutersByEntryPoints(ctx, entryPoints, tls) } - return make(map[string]map[string]*dynamic.RouterInfo) + return make(map[string]map[string]*runtime.RouterInfo) } // BuildHandlers Builds handler for all entry points @@ -83,7 +83,7 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t return entryPointHandlers } -func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*dynamic.RouterInfo) (http.Handler, error) { +func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*runtime.RouterInfo) (http.Handler, error) { router, err := rules.NewRouter() if err != nil { return nil, err @@ -95,14 +95,14 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig) if err != nil { - routerConfig.Err = err.Error() + routerConfig.AddError(err, true) logger.Error(err) continue } err = router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler) if err != nil { - routerConfig.Err = err.Error() + routerConfig.AddError(err, true) logger.Error(err) continue } @@ -118,7 +118,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string return chain.Then(router) } -func (m *Manager) buildRouterHandler(ctx context.Context, routerName string, routerConfig *dynamic.RouterInfo) (http.Handler, error) { +func (m *Manager) buildRouterHandler(ctx context.Context, routerName string, routerConfig *runtime.RouterInfo) (http.Handler, error) { if handler, ok := m.routerHandlers[routerName]; ok { return handler, nil } @@ -141,7 +141,7 @@ func (m *Manager) buildRouterHandler(ctx context.Context, routerName string, rou return m.routerHandlers[routerName], nil } -func (m *Manager) buildHTTPHandler(ctx context.Context, router *dynamic.RouterInfo, routerName string) (http.Handler, error) { +func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterInfo, routerName string) (http.Handler, error) { qualifiedNames := make([]string, len(router.Middlewares)) for i, name := range router.Middlewares { qualifiedNames[i] = internal.GetQualifiedName(ctx, name) diff --git a/pkg/server/router/router_test.go b/pkg/server/router/router_test.go index 8e110008f..387dcbcc2 100644 --- a/pkg/server/router/router_test.go +++ b/pkg/server/router/router_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/middlewares/accesslog" "github.com/containous/traefik/pkg/middlewares/requestdecorator" "github.com/containous/traefik/pkg/responsemodifiers" @@ -298,7 +299,7 @@ func TestRouterManager_Get(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Services: test.serviceConfig, Routers: test.routersConfig, @@ -399,7 +400,7 @@ func TestAccessLog(t *testing.T) { for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Services: test.serviceConfig, Routers: test.routersConfig, @@ -685,7 +686,7 @@ func TestRuntimeConfiguration(t *testing.T) { entryPoints := []string{"web"} - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Services: test.serviceConfig, Routers: test.routerConfig, @@ -694,7 +695,7 @@ func TestRuntimeConfiguration(t *testing.T) { }) serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport) middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager) - responseModifierFactory := responsemodifiers.NewBuilder(map[string]*dynamic.MiddlewareInfo{}) + responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{}) routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory) _ = routerManager.BuildHandlers(context.Background(), entryPoints, false) @@ -709,7 +710,7 @@ func TestRuntimeConfiguration(t *testing.T) { } } for _, v := range rtConf.Routers { - if v.Err != "" { + if len(v.Err) > 0 { allErrors++ } } @@ -759,7 +760,7 @@ func BenchmarkRouterServe(b *testing.B) { } entryPoints := []string{"web"} - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Services: serviceConfig, Routers: routersConfig, @@ -802,7 +803,7 @@ func BenchmarkService(b *testing.B) { }, } - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{ + rtConf := runtime.NewConfig(dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Services: serviceConfig, }, diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index fba89d2c6..3111f3838 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -6,7 +6,7 @@ import ( "fmt" "net/http" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/rules" "github.com/containous/traefik/pkg/server/internal" @@ -16,7 +16,7 @@ import ( ) // NewManager Creates a new Manager -func NewManager(conf *dynamic.RuntimeConfiguration, +func NewManager(conf *runtime.Configuration, serviceManager *tcpservice.Manager, httpHandlers map[string]http.Handler, httpsHandlers map[string]http.Handler, @@ -37,23 +37,23 @@ type Manager struct { httpHandlers map[string]http.Handler httpsHandlers map[string]http.Handler tlsManager *traefiktls.Manager - conf *dynamic.RuntimeConfiguration + conf *runtime.Configuration } -func (m *Manager) getTCPRouters(ctx context.Context, entryPoints []string) map[string]map[string]*dynamic.TCPRouterInfo { +func (m *Manager) getTCPRouters(ctx context.Context, entryPoints []string) map[string]map[string]*runtime.TCPRouterInfo { if m.conf != nil { - return m.conf.GetTCPRoutersByEntrypoints(ctx, entryPoints) + return m.conf.GetTCPRoutersByEntryPoints(ctx, entryPoints) } - return make(map[string]map[string]*dynamic.TCPRouterInfo) + return make(map[string]map[string]*runtime.TCPRouterInfo) } -func (m *Manager) getHTTPRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*dynamic.RouterInfo { +func (m *Manager) getHTTPRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*runtime.RouterInfo { if m.conf != nil { - return m.conf.GetRoutersByEntrypoints(ctx, entryPoints, tls) + return m.conf.GetRoutersByEntryPoints(ctx, entryPoints, tls) } - return make(map[string]map[string]*dynamic.RouterInfo) + return make(map[string]map[string]*runtime.RouterInfo) } // BuildHandlers builds the handlers for the given entrypoints @@ -79,7 +79,7 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string) m return entryPointHandlers } -func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*dynamic.TCPRouterInfo, configsHTTP map[string]*dynamic.RouterInfo, handlerHTTP http.Handler, handlerHTTPS http.Handler) (*tcp.Router, error) { +func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*runtime.TCPRouterInfo, configsHTTP map[string]*runtime.RouterInfo, handlerHTTP http.Handler, handlerHTTPS http.Handler) (*tcp.Router, error) { router := &tcp.Router{} router.HTTPHandler(handlerHTTP) const defaultTLSConfigName = "default" @@ -108,7 +108,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string domains, err := rules.ParseDomains(routerHTTPConfig.Rule) if err != nil { routerErr := fmt.Errorf("invalid rule %s, error: %v", routerHTTPConfig.Rule, err) - routerHTTPConfig.Err = routerErr.Error() + routerHTTPConfig.AddError(routerErr, true) logger.Debug(routerErr) continue } @@ -126,7 +126,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string tlsConf, err := m.tlsManager.Get("default", tlsOptionsName) if err != nil { - routerHTTPConfig.Err = err.Error() + routerHTTPConfig.AddError(err, true) logger.Debug(err) continue } @@ -156,11 +156,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string } else { routers := make([]string, 0, len(tlsConfigs)) for _, v := range tlsConfigs { - // TODO: properly deal with critical errors VS non-critical errors - if configsHTTP[v.routerName].Err != "" { - configsHTTP[v.routerName].Err += "\n" - } - configsHTTP[v.routerName].Err += fmt.Sprintf("found different TLS options for routers on the same host %v, so using the default TLS option instead", hostSNI) + configsHTTP[v.routerName].AddError(fmt.Errorf("found different TLS options for routers on the same host %v, so using the default TLS option instead", hostSNI), false) routers = append(routers, v.routerName) } logger.Warnf("Found different TLS options for routers on the same host %v, so using the default TLS options instead for these routers: %#v", hostSNI, routers) diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index b2320f9e0..a3fda9d7a 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/server/service/tcp" "github.com/containous/traefik/pkg/tls" "github.com/stretchr/testify/assert" @@ -13,13 +14,13 @@ import ( func TestRuntimeConfiguration(t *testing.T) { testCases := []struct { desc string - serviceConfig map[string]*dynamic.TCPServiceInfo - routerConfig map[string]*dynamic.TCPRouterInfo + serviceConfig map[string]*runtime.TCPServiceInfo + routerConfig map[string]*runtime.TCPRouterInfo expectedError int }{ { desc: "No error", - serviceConfig: map[string]*dynamic.TCPServiceInfo{ + serviceConfig: map[string]*runtime.TCPServiceInfo{ "foo-service": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -37,7 +38,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, }, }, - routerConfig: map[string]*dynamic.TCPRouterInfo{ + routerConfig: map[string]*runtime.TCPRouterInfo{ "foo": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -66,7 +67,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, { desc: "One router with wrong rule", - serviceConfig: map[string]*dynamic.TCPServiceInfo{ + serviceConfig: map[string]*runtime.TCPServiceInfo{ "foo-service": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -79,7 +80,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, }, }, - routerConfig: map[string]*dynamic.TCPRouterInfo{ + routerConfig: map[string]*runtime.TCPRouterInfo{ "foo": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -100,7 +101,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, { desc: "All router with wrong rule", - serviceConfig: map[string]*dynamic.TCPServiceInfo{ + serviceConfig: map[string]*runtime.TCPServiceInfo{ "foo-service": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -113,7 +114,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, }, }, - routerConfig: map[string]*dynamic.TCPRouterInfo{ + routerConfig: map[string]*runtime.TCPRouterInfo{ "foo": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -133,7 +134,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, { desc: "Router with unknown service", - serviceConfig: map[string]*dynamic.TCPServiceInfo{ + serviceConfig: map[string]*runtime.TCPServiceInfo{ "foo-service": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -146,7 +147,7 @@ func TestRuntimeConfiguration(t *testing.T) { }, }, }, - routerConfig: map[string]*dynamic.TCPRouterInfo{ + routerConfig: map[string]*runtime.TCPRouterInfo{ "foo": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -167,14 +168,14 @@ func TestRuntimeConfiguration(t *testing.T) { }, { desc: "Router with broken service", - serviceConfig: map[string]*dynamic.TCPServiceInfo{ + serviceConfig: map[string]*runtime.TCPServiceInfo{ "foo-service": { TCPService: &dynamic.TCPService{ LoadBalancer: nil, }, }, }, - routerConfig: map[string]*dynamic.TCPRouterInfo{ + routerConfig: map[string]*runtime.TCPRouterInfo{ "bar": { TCPRouter: &dynamic.TCPRouter{ EntryPoints: []string{"web"}, @@ -195,7 +196,7 @@ func TestRuntimeConfiguration(t *testing.T) { entryPoints := []string{"web"} - conf := &dynamic.RuntimeConfiguration{ + conf := &runtime.Configuration{ TCPServices: test.serviceConfig, TCPRouters: test.routerConfig, } diff --git a/pkg/server/server.go b/pkg/server/server.go index 0feadb30f..99e925e07 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -10,6 +10,7 @@ import ( "time" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/metrics" @@ -47,7 +48,7 @@ type Server struct { // RouteAppenderFactory the route appender factory interface type RouteAppenderFactory interface { - NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *dynamic.RuntimeConfiguration) types.RouteAppender + NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender } func setupTracing(conf *static.Tracing) tracing.Backend { diff --git a/pkg/server/server_configuration.go b/pkg/server/server_configuration.go index 1a184274e..d159e4c85 100644 --- a/pkg/server/server_configuration.go +++ b/pkg/server/server_configuration.go @@ -10,6 +10,7 @@ import ( "github.com/containous/alice" "github.com/containous/mux" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/middlewares/accesslog" "github.com/containous/traefik/pkg/middlewares/requestdecorator" @@ -65,7 +66,7 @@ func (s *Server) loadConfigurationTCP(configurations dynamic.Configurations) map s.tlsManager.UpdateConfigs(conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates) - rtConf := dynamic.NewRuntimeConfig(conf) + rtConf := runtime.NewConfig(conf) handlersNonTLS, handlersTLS := s.createHTTPHandlers(ctx, rtConf, entryPoints) routersTCP := s.createTCPRouters(ctx, rtConf, entryPoints, handlersNonTLS, handlersTLS) rtConf.PopulateUsedBy() @@ -74,7 +75,7 @@ func (s *Server) loadConfigurationTCP(configurations dynamic.Configurations) map } // the given configuration must not be nil. its fields will get mutated. -func (s *Server) createTCPRouters(ctx context.Context, configuration *dynamic.RuntimeConfiguration, entryPoints []string, handlers map[string]http.Handler, handlersTLS map[string]http.Handler) map[string]*tcpCore.Router { +func (s *Server) createTCPRouters(ctx context.Context, configuration *runtime.Configuration, entryPoints []string, handlers map[string]http.Handler, handlersTLS map[string]http.Handler) map[string]*tcpCore.Router { if configuration == nil { return make(map[string]*tcpCore.Router) } @@ -87,7 +88,7 @@ func (s *Server) createTCPRouters(ctx context.Context, configuration *dynamic.Ru } // createHTTPHandlers returns, for the given configuration and entryPoints, the HTTP handlers for non-TLS connections, and for the TLS ones. the given configuration must not be nil. its fields will get mutated. -func (s *Server) createHTTPHandlers(ctx context.Context, configuration *dynamic.RuntimeConfiguration, entryPoints []string) (map[string]http.Handler, map[string]http.Handler) { +func (s *Server) createHTTPHandlers(ctx context.Context, configuration *runtime.Configuration, entryPoints []string) (map[string]http.Handler, map[string]http.Handler) { serviceManager := service.NewManager(configuration.Services, s.defaultRoundTripper) middlewaresBuilder := middleware.NewBuilder(configuration.Middlewares, serviceManager) responseModifierFactory := responsemodifiers.NewBuilder(configuration.Middlewares) diff --git a/pkg/server/server_configuration_test.go b/pkg/server/server_configuration_test.go index 6bdcc706d..9d12b725c 100644 --- a/pkg/server/server_configuration_test.go +++ b/pkg/server/server_configuration_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" th "github.com/containous/traefik/pkg/testhelpers" "github.com/stretchr/testify/assert" @@ -46,7 +47,7 @@ func TestReuseService(t *testing.T) { srv := NewServer(staticConfig, nil, entryPoints, nil) - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{HTTP: dynamicConfigs}) + rtConf := runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs}) entrypointsHandlers, _ := srv.createHTTPHandlers(context.Background(), rtConf, []string{"http"}) // Test that the /ok path returns a status 200. diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index e2b2219f9..4756a197e 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/config/static" th "github.com/containous/traefik/pkg/testhelpers" "github.com/containous/traefik/pkg/types" @@ -253,7 +254,7 @@ func TestServerResponseEmptyBackend(t *testing.T) { } srv := NewServer(globalConfig, nil, entryPointsConfig, nil) - rtConf := dynamic.NewRuntimeConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)}) + rtConf := runtime.NewConfig(dynamic.Configuration{HTTP: test.config(testServer.URL)}) entryPoints, _ := srv.createHTTPHandlers(context.Background(), rtConf, []string{"http"}) responseRecorder := &httptest.ResponseRecorder{} diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index 03ec8e138..3e9974ff7 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -10,6 +10,7 @@ import ( "github.com/containous/alice" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/healthcheck" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/middlewares/accesslog" @@ -26,7 +27,7 @@ const ( ) // NewManager creates a new Manager -func NewManager(configs map[string]*dynamic.ServiceInfo, defaultRoundTripper http.RoundTripper) *Manager { +func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper http.RoundTripper) *Manager { return &Manager{ bufferPool: newBufferPool(), defaultRoundTripper: defaultRoundTripper, @@ -40,7 +41,7 @@ type Manager struct { bufferPool httputil.BufferPool defaultRoundTripper http.RoundTripper balancers map[string][]healthcheck.BalancerHandler - configs map[string]*dynamic.ServiceInfo + configs map[string]*runtime.ServiceInfo } // BuildHTTP Creates a http.Handler for a service configuration. @@ -58,13 +59,14 @@ func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string, respons // TODO Should handle multiple service types // FIXME Check if the service is declared multiple times with different types if conf.LoadBalancer == nil { - conf.Err = fmt.Errorf("the service %q doesn't have any load balancer", serviceName) - return nil, conf.Err + sErr := fmt.Errorf("the service %q doesn't have any load balancer", serviceName) + conf.AddError(sErr, true) + return nil, sErr } lb, err := m.getLoadBalancerServiceHandler(ctx, serviceName, conf.LoadBalancer, responseModifier) if err != nil { - conf.Err = err + conf.AddError(err, true) return nil, err } diff --git a/pkg/server/service/service_test.go b/pkg/server/service/service_test.go index 963d67b25..6d96ea0db 100644 --- a/pkg/server/service/service_test.go +++ b/pkg/server/service/service_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/server/internal" "github.com/containous/traefik/pkg/testhelpers" "github.com/stretchr/testify/assert" @@ -287,13 +288,13 @@ func TestManager_Build(t *testing.T) { testCases := []struct { desc string serviceName string - configs map[string]*dynamic.ServiceInfo + configs map[string]*runtime.ServiceInfo providerName string }{ { desc: "Simple service name", serviceName: "serviceName", - configs: map[string]*dynamic.ServiceInfo{ + configs: map[string]*runtime.ServiceInfo{ "serviceName": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{}, @@ -304,7 +305,7 @@ func TestManager_Build(t *testing.T) { { desc: "Service name with provider", serviceName: "serviceName@provider-1", - configs: map[string]*dynamic.ServiceInfo{ + configs: map[string]*runtime.ServiceInfo{ "serviceName@provider-1": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{}, @@ -315,7 +316,7 @@ func TestManager_Build(t *testing.T) { { desc: "Service name with provider in context", serviceName: "serviceName", - configs: map[string]*dynamic.ServiceInfo{ + configs: map[string]*runtime.ServiceInfo{ "serviceName@provider-1": { Service: &dynamic.Service{ LoadBalancer: &dynamic.LoadBalancerService{}, diff --git a/pkg/server/service/tcp/service.go b/pkg/server/service/tcp/service.go index 704ba9fc2..6abc92d04 100644 --- a/pkg/server/service/tcp/service.go +++ b/pkg/server/service/tcp/service.go @@ -5,7 +5,7 @@ import ( "fmt" "net" - "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/log" "github.com/containous/traefik/pkg/server/internal" "github.com/containous/traefik/pkg/tcp" @@ -13,11 +13,11 @@ import ( // Manager is the TCPHandlers factory type Manager struct { - configs map[string]*dynamic.TCPServiceInfo + configs map[string]*runtime.TCPServiceInfo } // NewManager creates a new manager -func NewManager(conf *dynamic.RuntimeConfiguration) *Manager { +func NewManager(conf *runtime.Configuration) *Manager { return &Manager{ configs: conf.TCPServices, } diff --git a/pkg/server/service/tcp/service_test.go b/pkg/server/service/tcp/service_test.go index 15550eb63..a4ec678d6 100644 --- a/pkg/server/service/tcp/service_test.go +++ b/pkg/server/service/tcp/service_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/containous/traefik/pkg/config/dynamic" + "github.com/containous/traefik/pkg/config/runtime" "github.com/containous/traefik/pkg/server/internal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,7 +15,7 @@ func TestManager_BuildTCP(t *testing.T) { testCases := []struct { desc string serviceName string - configs map[string]*dynamic.TCPServiceInfo + configs map[string]*runtime.TCPServiceInfo providerName string expectedError string }{ @@ -27,7 +28,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "missing lb configuration", serviceName: "test", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "test": { TCPService: &dynamic.TCPService{}, }, @@ -37,7 +38,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "no such host, server is skipped, error is logged", serviceName: "test", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "test": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -52,7 +53,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "invalid IP address, server is skipped, error is logged", serviceName: "test", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "test": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -67,7 +68,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Simple service name", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{}, @@ -78,7 +79,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Service name with provider", serviceName: "serviceName@provider-1", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{}, @@ -89,7 +90,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Service name with provider in context", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{}, @@ -101,7 +102,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Server with correct host:port as address", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -119,7 +120,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "Server with correct ip:port as address", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -137,7 +138,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "missing port in address with hostname, server is skipped, error is logged", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -155,7 +156,7 @@ func TestManager_BuildTCP(t *testing.T) { { desc: "missing port in address with ip, server is skipped, error is logged", serviceName: "serviceName", - configs: map[string]*dynamic.TCPServiceInfo{ + configs: map[string]*runtime.TCPServiceInfo{ "serviceName@provider-1": { TCPService: &dynamic.TCPService{ LoadBalancer: &dynamic.TCPLoadBalancerService{ @@ -177,7 +178,7 @@ func TestManager_BuildTCP(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - manager := NewManager(&dynamic.RuntimeConfiguration{ + manager := NewManager(&runtime.Configuration{ TCPServices: test.configs, })