Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deal with multiple errors and their criticality #5070

Merged
merged 6 commits into from Jul 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 45 additions & 0 deletions 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"
34 changes: 34 additions & 0 deletions 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"
45 changes: 45 additions & 0 deletions integration/simple_test.go
Expand Up @@ -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)
}
22 changes: 14 additions & 8 deletions integration/testdata/rawdata-crd.json
Expand Up @@ -9,7 +9,8 @@
"priority": 12,
"tls": {
"options": "default/mytlsoption"
}
},
"status": "enabled"
},
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
"entryPoints": [
Expand All @@ -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": {
Expand All @@ -39,39 +41,41 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.3:80"
"url": "http://10.42.0.4:80"
},
{
"url": "http://10.42.0.5:80"
}
],
"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"
}
},
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.3:80"
"url": "http://10.42.0.4:80"
},
{
"url": "http://10.42.0.5:80"
}
],
"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"
}
}
Expand All @@ -86,21 +90,23 @@
"tls": {
"passthrough": false,
"options": "default/mytlsoption"
}
},
"status": "enabled"
}
},
"tcpServices": {
"default/test3.crd-673acf455cb2dab0b43a@kubernetescrd": {
"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"
]
Expand Down
8 changes: 5 additions & 3 deletions integration/testdata/rawdata-ingress.json
Expand Up @@ -2,27 +2,29 @@
"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": {
"default/whoami/http@kubernetes": {
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.2:80"
"url": "http://10.42.0.4:80"
},
{
"url": "http://10.42.0.5:80"
}
],
"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"
}
}
Expand Down
18 changes: 9 additions & 9 deletions pkg/api/handler.go
Expand Up @@ -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"
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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{
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/handler_entrypoint_test.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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)

Expand Down
8 changes: 4 additions & 4 deletions pkg/api/handler_http.go
Expand Up @@ -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"`
}
Expand Down