2019-07-12 09:10:03 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2021-03-04 19:08:03 +00:00
|
|
|
"io"
|
2019-07-12 09:10:03 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2021-03-04 19:08:03 +00:00
|
|
|
"os"
|
2019-07-12 09:10:03 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2023-02-03 14:24:05 +00:00
|
|
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/config/runtime"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/config/static"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/provider/docker"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/provider/file"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/ingress"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/provider/rest"
|
|
|
|
"github.com/traefik/traefik/v3/pkg/types"
|
2019-07-12 09:10:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestHandler_Overview(t *testing.T) {
|
|
|
|
type expected struct {
|
|
|
|
statusCode int
|
|
|
|
jsonFile string
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
path string
|
|
|
|
confStatic static.Configuration
|
2019-07-15 15:04:04 +00:00
|
|
|
confDyn runtime.Configuration
|
2019-07-12 09:10:03 +00:00
|
|
|
expected expected
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "without data in the dynamic configuration",
|
|
|
|
path: "/api/overview",
|
|
|
|
confStatic: static.Configuration{API: &static.API{}, Global: &static.Global{}},
|
2019-07-15 15:04:04 +00:00
|
|
|
confDyn: runtime.Configuration{},
|
2019-07-12 09:10:03 +00:00
|
|
|
expected: expected{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
jsonFile: "testdata/overview-empty.json",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "with data in the dynamic configuration",
|
|
|
|
path: "/api/overview",
|
|
|
|
confStatic: static.Configuration{API: &static.API{}, Global: &static.Global{}},
|
2019-07-15 15:04:04 +00:00
|
|
|
confDyn: runtime.Configuration{
|
|
|
|
Services: map[string]*runtime.ServiceInfo{
|
2019-07-12 09:10:03 +00:00
|
|
|
"foo-service@myprovider": {
|
|
|
|
Service: &dynamic.Service{
|
2019-08-26 08:30:05 +00:00
|
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
2019-07-15 15:04:04 +00:00
|
|
|
Servers: []dynamic.Server{{URL: "http://127.0.0.1"}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusEnabled,
|
|
|
|
},
|
|
|
|
"bar-service@myprovider": {
|
|
|
|
Service: &dynamic.Service{
|
2019-08-26 08:30:05 +00:00
|
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
2019-07-15 15:04:04 +00:00
|
|
|
Servers: []dynamic.Server{{URL: "http://127.0.0.1"}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusWarning,
|
|
|
|
},
|
|
|
|
"fii-service@myprovider": {
|
|
|
|
Service: &dynamic.Service{
|
2019-08-26 08:30:05 +00:00
|
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
2019-07-15 15:04:04 +00:00
|
|
|
Servers: []dynamic.Server{{URL: "http://127.0.0.1"}},
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
Status: runtime.StatusDisabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
Middlewares: map[string]*runtime.MiddlewareInfo{
|
2019-07-12 09:10:03 +00:00
|
|
|
"auth@myprovider": {
|
|
|
|
Middleware: &dynamic.Middleware{
|
|
|
|
BasicAuth: &dynamic.BasicAuth{
|
|
|
|
Users: []string{"admin:admin"},
|
|
|
|
},
|
|
|
|
},
|
2019-07-19 14:42:04 +00:00
|
|
|
Status: runtime.StatusEnabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
"addPrefixTest@myprovider": {
|
|
|
|
Middleware: &dynamic.Middleware{
|
|
|
|
AddPrefix: &dynamic.AddPrefix{
|
|
|
|
Prefix: "/titi",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"addPrefixTest@anotherprovider": {
|
|
|
|
Middleware: &dynamic.Middleware{
|
|
|
|
AddPrefix: &dynamic.AddPrefix{
|
|
|
|
Prefix: "/toto",
|
|
|
|
},
|
|
|
|
},
|
2019-07-19 14:42:04 +00:00
|
|
|
Err: []string{"error"},
|
|
|
|
Status: runtime.StatusDisabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
Routers: map[string]*runtime.RouterInfo{
|
2019-07-12 09:10:03 +00:00
|
|
|
"bar@myprovider": {
|
|
|
|
Router: &dynamic.Router{
|
|
|
|
EntryPoints: []string{"web"},
|
|
|
|
Service: "foo-service@myprovider",
|
|
|
|
Rule: "Host(`foo.bar`)",
|
|
|
|
Middlewares: []string{"auth", "addPrefixTest@anotherprovider"},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
Status: runtime.StatusEnabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
"test@myprovider": {
|
|
|
|
Router: &dynamic.Router{
|
|
|
|
EntryPoints: []string{"web"},
|
|
|
|
Service: "foo-service@myprovider",
|
|
|
|
Rule: "Host(`foo.bar.other`)",
|
|
|
|
Middlewares: []string{"addPrefixTest", "auth"},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
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,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
TCPServices: map[string]*runtime.TCPServiceInfo{
|
2019-07-12 09:10:03 +00:00
|
|
|
"tcpfoo-service@myprovider": {
|
|
|
|
TCPService: &dynamic.TCPService{
|
2019-09-13 18:00:06 +00:00
|
|
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
2019-07-12 09:10:03 +00:00
|
|
|
Servers: []dynamic.TCPServer{
|
|
|
|
{
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2019-07-18 13:56:04 +00:00
|
|
|
Status: runtime.StatusEnabled,
|
|
|
|
},
|
|
|
|
"tcpbar-service@myprovider": {
|
|
|
|
TCPService: &dynamic.TCPService{
|
2019-09-13 18:00:06 +00:00
|
|
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
2019-07-18 13:56:04 +00:00
|
|
|
Servers: []dynamic.TCPServer{
|
|
|
|
{
|
|
|
|
Address: "127.0.0.2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusWarning,
|
|
|
|
},
|
|
|
|
"tcpfii-service@myprovider": {
|
|
|
|
TCPService: &dynamic.TCPService{
|
2019-09-13 18:00:06 +00:00
|
|
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
2019-07-18 13:56:04 +00:00
|
|
|
Servers: []dynamic.TCPServer{
|
|
|
|
{
|
|
|
|
Address: "127.0.0.2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusDisabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2021-06-11 13:30:05 +00:00
|
|
|
TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{
|
2022-10-26 15:16:05 +00:00
|
|
|
"ipallowlist1@myprovider": {
|
2021-06-11 13:30:05 +00:00
|
|
|
TCPMiddleware: &dynamic.TCPMiddleware{
|
2022-10-26 15:16:05 +00:00
|
|
|
IPAllowList: &dynamic.TCPIPAllowList{
|
2021-06-11 13:30:05 +00:00
|
|
|
SourceRange: []string{"127.0.0.1/32"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusEnabled,
|
|
|
|
},
|
2022-10-26 15:16:05 +00:00
|
|
|
"ipallowlist2@myprovider": {
|
2021-06-11 13:30:05 +00:00
|
|
|
TCPMiddleware: &dynamic.TCPMiddleware{
|
2022-10-26 15:16:05 +00:00
|
|
|
IPAllowList: &dynamic.TCPIPAllowList{
|
2021-06-11 13:30:05 +00:00
|
|
|
SourceRange: []string{"127.0.0.1/32"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-10-26 15:16:05 +00:00
|
|
|
"ipallowlist3@myprovider": {
|
2021-06-11 13:30:05 +00:00
|
|
|
TCPMiddleware: &dynamic.TCPMiddleware{
|
2022-10-26 15:16:05 +00:00
|
|
|
IPAllowList: &dynamic.TCPIPAllowList{
|
2021-06-11 13:30:05 +00:00
|
|
|
SourceRange: []string{"127.0.0.1/32"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: runtime.StatusDisabled,
|
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
TCPRouters: map[string]*runtime.TCPRouterInfo{
|
2019-07-12 09:10:03 +00:00
|
|
|
"tcpbar@myprovider": {
|
|
|
|
TCPRouter: &dynamic.TCPRouter{
|
|
|
|
EntryPoints: []string{"web"},
|
|
|
|
Service: "tcpfoo-service@myprovider",
|
|
|
|
Rule: "HostSNI(`foo.bar`)",
|
|
|
|
},
|
2019-07-18 13:56:04 +00:00
|
|
|
Status: runtime.StatusEnabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
"tcptest@myprovider": {
|
|
|
|
TCPRouter: &dynamic.TCPRouter{
|
|
|
|
EntryPoints: []string{"web"},
|
|
|
|
Service: "tcpfoo-service@myprovider",
|
|
|
|
Rule: "HostSNI(`foo.bar.other`)",
|
|
|
|
},
|
2019-07-18 13:56:04 +00:00
|
|
|
Status: runtime.StatusWarning,
|
|
|
|
},
|
|
|
|
"tcpfoo@myprovider": {
|
|
|
|
TCPRouter: &dynamic.TCPRouter{
|
|
|
|
EntryPoints: []string{"web"},
|
|
|
|
Service: "tcpfoo-service@myprovider",
|
|
|
|
Rule: "HostSNI(`foo.bar.other`)",
|
|
|
|
},
|
|
|
|
Status: runtime.StatusDisabled,
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: expected{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
jsonFile: "testdata/overview-dynamic.json",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "with providers",
|
|
|
|
path: "/api/overview",
|
|
|
|
confStatic: static.Configuration{
|
|
|
|
Global: &static.Global{},
|
|
|
|
API: &static.API{},
|
|
|
|
Providers: &static.Providers{
|
|
|
|
Docker: &docker.Provider{},
|
2023-05-10 13:28:05 +00:00
|
|
|
Swarm: &docker.SwarmProvider{},
|
2019-07-12 09:10:03 +00:00
|
|
|
File: &file.Provider{},
|
|
|
|
KubernetesIngress: &ingress.Provider{},
|
|
|
|
KubernetesCRD: &crd.Provider{},
|
|
|
|
Rest: &rest.Provider{},
|
2021-05-11 14:14:10 +00:00
|
|
|
Plugin: map[string]static.PluginConf{
|
|
|
|
"test": map[string]interface{}{},
|
|
|
|
},
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
confDyn: runtime.Configuration{},
|
2019-07-12 09:10:03 +00:00
|
|
|
expected: expected{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
jsonFile: "testdata/overview-providers.json",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "with features",
|
|
|
|
path: "/api/overview",
|
|
|
|
confStatic: static.Configuration{
|
|
|
|
Global: &static.Global{},
|
|
|
|
API: &static.API{},
|
|
|
|
Metrics: &types.Metrics{
|
|
|
|
Prometheus: &types.Prometheus{},
|
|
|
|
},
|
2024-01-08 08:10:06 +00:00
|
|
|
Tracing: &static.Tracing{},
|
2019-07-12 09:10:03 +00:00
|
|
|
},
|
2019-07-15 15:04:04 +00:00
|
|
|
confDyn: runtime.Configuration{},
|
2019-07-12 09:10:03 +00:00
|
|
|
expected: expected{
|
|
|
|
statusCode: http.StatusOK,
|
|
|
|
jsonFile: "testdata/overview-features.json",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
handler := New(test.confStatic, &test.confDyn)
|
2019-11-14 15:40:05 +00:00
|
|
|
server := httptest.NewServer(handler.createRouter())
|
2019-07-12 09:10:03 +00:00
|
|
|
|
|
|
|
resp, err := http.DefaultClient.Get(server.URL + test.path)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
require.Equal(t, test.expected.statusCode, resp.StatusCode)
|
|
|
|
|
|
|
|
if test.expected.jsonFile == "" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-11-17 00:50:06 +00:00
|
|
|
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
|
2021-03-04 19:08:03 +00:00
|
|
|
contents, err := io.ReadAll(resp.Body)
|
2019-07-12 09:10:03 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = resp.Body.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
if *updateExpected {
|
|
|
|
var results interface{}
|
|
|
|
err := json.Unmarshal(contents, &results)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
newJSON, err := json.MarshalIndent(results, "", "\t")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-03-04 19:08:03 +00:00
|
|
|
err = os.WriteFile(test.expected.jsonFile, newJSON, 0o644)
|
2019-07-12 09:10:03 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2021-03-04 19:08:03 +00:00
|
|
|
data, err := os.ReadFile(test.expected.jsonFile)
|
2019-07-12 09:10:03 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.JSONEq(t, string(data), string(contents))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|