1866 lines
48 KiB
Go
1866 lines
48 KiB
Go
package marathon
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
"testing"
|
|
|
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
|
"github.com/gambol99/go-marathon"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func Int(v int) *int { return &v }
|
|
|
|
func TestGetConfigurationAPIErrors(t *testing.T) {
|
|
fakeClient := newFakeClient(true, marathon.Applications{})
|
|
|
|
p := &Provider{
|
|
marathonClient: fakeClient,
|
|
}
|
|
|
|
actualConfig := p.getConfigurations(context.Background())
|
|
fakeClient.AssertExpectations(t)
|
|
|
|
if actualConfig != nil {
|
|
t.Errorf("configuration should have been nil, got %v", actualConfig)
|
|
}
|
|
}
|
|
|
|
func TestBuildConfiguration(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
applications *marathon.Applications
|
|
constraints string
|
|
defaultRule string
|
|
expected *dynamic.Configuration
|
|
}{
|
|
{
|
|
desc: "simple application",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "filtered task",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80), taskState(taskStateStaging))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "multiple ports",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with basic auth",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"),
|
|
withLabel("traefik.http.routers.app.middlewares", "Middleware1"),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
Middlewares: []string{"Middleware1"},
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{
|
|
"Middleware1": {
|
|
BasicAuth: &dynamic.BasicAuth{
|
|
Users: []string{
|
|
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "2 applications in the same service",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/foo-v000"),
|
|
withTasks(localhostTask(taskPorts(8080))),
|
|
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"),
|
|
),
|
|
application(
|
|
appID("/foo-v001"),
|
|
withTasks(localhostTask(taskPorts(8081))),
|
|
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"),
|
|
),
|
|
),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:8080",
|
|
},
|
|
{
|
|
URL: "http://localhost:8081",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "2 applications with 2 tasks in the same service",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/foo-v000"),
|
|
withTasks(localhostTask(taskPorts(8080))),
|
|
withTasks(localhostTask(taskPorts(8081))),
|
|
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"),
|
|
),
|
|
application(
|
|
appID("/foo-v001"),
|
|
withTasks(localhostTask(taskPorts(8082))),
|
|
withTasks(localhostTask(taskPorts(8083))),
|
|
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "index:0"),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`app.marathon.localhost`)"),
|
|
),
|
|
),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:8080",
|
|
},
|
|
{
|
|
URL: "http://localhost:8081",
|
|
},
|
|
{
|
|
URL: "http://localhost:8082",
|
|
},
|
|
{
|
|
URL: "http://localhost:8083",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "2 applications",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/foo"),
|
|
withTasks(localhostTask(taskPorts(8080))),
|
|
),
|
|
application(
|
|
appID("/bar"),
|
|
withTasks(localhostTask(taskPorts(8081))),
|
|
),
|
|
),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"foo": {
|
|
Service: "foo",
|
|
Rule: "Host(`foo.marathon.localhost`)",
|
|
},
|
|
"bar": {
|
|
Service: "bar",
|
|
Rule: "Host(`bar.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"foo": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:8080",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
"bar": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:8081",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two tasks no labels",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80)), localhostTask(taskPorts(81))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
{
|
|
URL: "http://localhost:81",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "simple application with label on service",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with labels",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
withLabel("traefik.http.routers.Router1.service", "Service1"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "Service1",
|
|
Rule: "Host(`foo.com`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with rule label",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "app",
|
|
Rule: "Host(`foo.com`)",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with rule label and one service",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "Service1",
|
|
Rule: "Host(`foo.com`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with rule label and two services",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"),
|
|
withLabel("traefik.http.services.Service2.loadbalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"Service2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with same service name and different passhostheader",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "false"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.services.Service1.loadbalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
"app2": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app2.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with two identical middleware",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
"app2": {
|
|
Service: "app2",
|
|
Rule: "Host(`app2.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{
|
|
"Middleware1": {
|
|
InFlightReq: &dynamic.InFlightReq{
|
|
Amount: 42,
|
|
SourceCriterion: &dynamic.SourceCriterion{
|
|
RequestHost: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"app2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with two different middlewares",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "42"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.middlewares.Middleware1.inflightreq.amount", "41"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
"app2": {
|
|
Service: "app2",
|
|
Rule: "Host(`app2.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"app2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with two different routers with same name",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`bar.com`)"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"app2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with two identical routers with same name",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"Router1": {
|
|
Service: "Service1",
|
|
Rule: "Host(`foo.com`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "two apps with two identical routers with same name",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
),
|
|
application(
|
|
appID("/app2"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.routers.Router1.rule", "Host(`foo.com`)"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"app2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with wrong label",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.wrong.label", "tchouk"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with label port",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.scheme", "h2c"),
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", "90"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "Service1",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "h2c://localhost:90",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with label port on two services",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.http.services.Service1.LoadBalancer.server.port", ""),
|
|
withLabel("traefik.http.services.Service2.LoadBalancer.server.port", "8080"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"Service1": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
"Service2": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:8080",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app without port",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask()),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app without port with middleware",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask()),
|
|
withLabel("traefik.http.middlewares.Middleware1.basicauth.users", "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with traefik.enable=false",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask()),
|
|
withLabel("traefik.enable", "false"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with traefik.enable=false",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask()),
|
|
withLabel("traefik.enable", "false"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with non matching constraint",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tags", "foo"),
|
|
)),
|
|
constraints: `Label("traefik.tags", "bar")`,
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with non matching marathon constraint",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
constraint("rack_id:CLUSTER:rack-1"),
|
|
)),
|
|
constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`,
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with matching marathon constraint",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
constraint("rack_id:CLUSTER:rack-1"),
|
|
)),
|
|
constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`,
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with matching constraint",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tags", "bar"),
|
|
)),
|
|
constraints: `Label("traefik.tags", "bar")`,
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "app",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with group as subdomain rule",
|
|
defaultRule: `Host("{{ .Name | trimPrefix "/" | splitList "/" | strsToItfs | reverse | join "." }}.marathon.localhost")`,
|
|
applications: withApplications(
|
|
application(
|
|
appID("/a/b/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"a_b_app": {
|
|
Service: "a_b_app",
|
|
Rule: `Host("app.b.a.marathon.localhost")`,
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"a_b_app": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with tcp labels",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"),
|
|
withLabel("traefik.tcp.routers.foo.tls", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{
|
|
"foo": {
|
|
Service: "app",
|
|
Rule: "HostSNI(`foo.bar`)",
|
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.TCPService{
|
|
"app": {
|
|
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
Servers: []dynamic.TCPServer{
|
|
{
|
|
Address: "localhost:80",
|
|
},
|
|
},
|
|
TerminationDelay: Int(100),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with tcp labels without rule",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tcp.routers.foo.tls", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{},
|
|
Services: map[string]*dynamic.TCPService{
|
|
"app": {
|
|
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
Servers: []dynamic.TCPServer{
|
|
{
|
|
Address: "localhost:80",
|
|
},
|
|
},
|
|
TerminationDelay: Int(100),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with tcp labels with port",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"),
|
|
withLabel("traefik.tcp.routers.foo.tls", "true"),
|
|
withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{
|
|
"foo": {
|
|
Service: "foo",
|
|
Rule: "HostSNI(`foo.bar`)",
|
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.TCPService{
|
|
"foo": {
|
|
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
Servers: []dynamic.TCPServer{
|
|
{
|
|
Address: "localhost:8080",
|
|
},
|
|
},
|
|
TerminationDelay: Int(100),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with tcp labels with port, with termination delay",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"),
|
|
withLabel("traefik.tcp.routers.foo.tls", "true"),
|
|
withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"),
|
|
withLabel("traefik.tcp.services.foo.loadbalancer.terminationdelay", "200"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{
|
|
"foo": {
|
|
Service: "foo",
|
|
Rule: "HostSNI(`foo.bar`)",
|
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.TCPService{
|
|
"foo": {
|
|
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
Servers: []dynamic.TCPServer{
|
|
{
|
|
Address: "localhost:8080",
|
|
},
|
|
},
|
|
TerminationDelay: Int(200),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "one app with tcp labels with port and http service",
|
|
applications: withApplications(
|
|
application(
|
|
appID("/app"),
|
|
appPorts(80, 81),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
withLabel("traefik.tcp.routers.foo.rule", "HostSNI(`foo.bar`)"),
|
|
withLabel("traefik.tcp.routers.foo.tls", "true"),
|
|
withLabel("traefik.tcp.services.foo.loadbalancer.server.port", "8080"),
|
|
withLabel("traefik.http.services.bar.loadbalancer.passhostheader", "true"),
|
|
)),
|
|
expected: &dynamic.Configuration{
|
|
TCP: &dynamic.TCPConfiguration{
|
|
Routers: map[string]*dynamic.TCPRouter{
|
|
"foo": {
|
|
Service: "foo",
|
|
Rule: "HostSNI(`foo.bar`)",
|
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
|
},
|
|
},
|
|
Services: map[string]*dynamic.TCPService{
|
|
"foo": {
|
|
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
|
Servers: []dynamic.TCPServer{
|
|
{
|
|
Address: "localhost:8080",
|
|
},
|
|
},
|
|
TerminationDelay: Int(100),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
HTTP: &dynamic.HTTPConfiguration{
|
|
Routers: map[string]*dynamic.Router{
|
|
"app": {
|
|
Service: "bar",
|
|
Rule: "Host(`app.marathon.localhost`)",
|
|
},
|
|
},
|
|
Middlewares: map[string]*dynamic.Middleware{},
|
|
Services: map[string]*dynamic.Service{
|
|
"bar": {
|
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
|
Servers: []dynamic.Server{
|
|
{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
PassHostHeader: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
test := test
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
defaultRule := "Host(`{{ normalize .Name }}.marathon.localhost`)"
|
|
if len(test.defaultRule) > 0 {
|
|
defaultRule = test.defaultRule
|
|
}
|
|
|
|
p := &Provider{
|
|
DefaultRule: defaultRule,
|
|
ExposedByDefault: true,
|
|
}
|
|
p.Constraints = test.constraints
|
|
|
|
err := p.Init()
|
|
require.NoError(t, err)
|
|
|
|
actualConfig := p.buildConfiguration(context.Background(), test.applications)
|
|
|
|
assert.NotNil(t, actualConfig)
|
|
assert.Equal(t, test.expected, actualConfig)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestApplicationFilterEnabled(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
exposedByDefault bool
|
|
enabledLabel string
|
|
expected bool
|
|
}{
|
|
{
|
|
desc: "exposed and tolerated by valid label value",
|
|
exposedByDefault: true,
|
|
enabledLabel: "true",
|
|
expected: true,
|
|
},
|
|
{
|
|
desc: "exposed but overridden by label",
|
|
exposedByDefault: true,
|
|
enabledLabel: "false",
|
|
expected: false,
|
|
},
|
|
{
|
|
desc: "non-exposed but overridden by label",
|
|
exposedByDefault: false,
|
|
enabledLabel: "true",
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
test := test
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
provider := &Provider{ExposedByDefault: true}
|
|
|
|
app := application(withLabel("traefik.enable", test.enabledLabel))
|
|
|
|
extraConf, err := provider.getConfiguration(app)
|
|
require.NoError(t, err)
|
|
|
|
if provider.keepApplication(context.Background(), extraConf, stringValueMap(app.Labels)) != test.expected {
|
|
t.Errorf("got unexpected filtering = %t", !test.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetServer(t *testing.T) {
|
|
type expected struct {
|
|
server dynamic.Server
|
|
error string
|
|
}
|
|
|
|
testCases := []struct {
|
|
desc string
|
|
provider Provider
|
|
app marathon.Application
|
|
extraConf configuration
|
|
defaultServer dynamic.Server
|
|
expected expected
|
|
}{
|
|
{
|
|
desc: "undefined host",
|
|
provider: Provider{},
|
|
app: application(),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{},
|
|
expected: expected{
|
|
error: `host is undefined for task "taskID" app ""`,
|
|
},
|
|
},
|
|
{
|
|
desc: "with task port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "without task port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask()),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
error: "unable to process ports for /app taskID: no port found",
|
|
},
|
|
},
|
|
{
|
|
desc: "with default server port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "88",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://localhost:88",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with invalid default server port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "aaaa",
|
|
},
|
|
expected: expected{
|
|
error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaaa": invalid syntax`,
|
|
},
|
|
},
|
|
{
|
|
desc: "with negative default server port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "-6",
|
|
},
|
|
expected: expected{
|
|
error: `unable to process ports for /app taskID: explicitly specified port -6 must be greater than zero`,
|
|
},
|
|
},
|
|
{
|
|
desc: "with port index",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "index:1",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://localhost:81",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with out of range port index",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "index:2",
|
|
},
|
|
expected: expected{
|
|
error: "unable to process ports for /app taskID: index 2 must be within range (0, 1)",
|
|
},
|
|
},
|
|
{
|
|
desc: "with invalid port index",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
Port: "index:aaa",
|
|
},
|
|
expected: expected{
|
|
error: `unable to process ports for /app taskID: strconv.Atoi: parsing "aaa": invalid syntax`,
|
|
},
|
|
},
|
|
{
|
|
desc: "with application port and no task port",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
portDefinition(80),
|
|
withTasks(localhostTask()),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with IP per task",
|
|
provider: Provider{},
|
|
app: application(
|
|
appID("/app"),
|
|
appPorts(80),
|
|
ipAddrPerTask(88),
|
|
withTasks(localhostTask()),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://127.0.0.1:88",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with container network",
|
|
provider: Provider{},
|
|
app: application(
|
|
containerNetwork(),
|
|
appID("/app"),
|
|
appPorts(80),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://127.0.0.1:80",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with bridge network",
|
|
provider: Provider{},
|
|
app: application(
|
|
bridgeNetwork(),
|
|
appID("/app"),
|
|
appPorts(83),
|
|
withTasks(localhostTask(taskPorts(80, 81))),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://localhost:80",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with several IP addresses on task",
|
|
provider: Provider{},
|
|
app: application(
|
|
ipAddrPerTask(88),
|
|
appID("/app"),
|
|
appPorts(83),
|
|
withTasks(
|
|
task(
|
|
withTaskID("myTask"),
|
|
host("localhost"),
|
|
ipAddresses("127.0.0.1", "127.0.0.2"),
|
|
taskState(taskStateRunning),
|
|
)),
|
|
),
|
|
extraConf: configuration{
|
|
Marathon: specificConfiguration{
|
|
IPAddressIdx: 0,
|
|
},
|
|
},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
server: dynamic.Server{
|
|
URL: "http://127.0.0.1:88",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
desc: "with several IP addresses on task, undefined [MinInt32] IPAddressIdx",
|
|
provider: Provider{},
|
|
app: application(
|
|
ipAddrPerTask(88),
|
|
appID("/app"),
|
|
appPorts(83),
|
|
withTasks(
|
|
task(
|
|
host("localhost"),
|
|
ipAddresses("127.0.0.1", "127.0.0.2"),
|
|
taskState(taskStateRunning),
|
|
)),
|
|
),
|
|
extraConf: configuration{
|
|
Marathon: specificConfiguration{
|
|
IPAddressIdx: math.MinInt32,
|
|
},
|
|
},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
error: "found 2 task IP addresses but missing IP address index for Marathon application /app on task taskID",
|
|
},
|
|
},
|
|
{
|
|
desc: "with several IP addresses on task, IPAddressIdx out of range",
|
|
provider: Provider{},
|
|
app: application(
|
|
ipAddrPerTask(88),
|
|
appID("/app"),
|
|
appPorts(83),
|
|
withTasks(
|
|
task(
|
|
host("localhost"),
|
|
ipAddresses("127.0.0.1", "127.0.0.2"),
|
|
taskState(taskStateRunning),
|
|
)),
|
|
),
|
|
extraConf: configuration{
|
|
Marathon: specificConfiguration{
|
|
IPAddressIdx: 3,
|
|
},
|
|
},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
error: "cannot use IP address index to select from 2 task IP addresses for Marathon application /app on task taskID",
|
|
},
|
|
},
|
|
{
|
|
desc: "with task without IP address",
|
|
provider: Provider{},
|
|
app: application(
|
|
ipAddrPerTask(88),
|
|
appID("/app"),
|
|
appPorts(83),
|
|
withTasks(
|
|
task(
|
|
host("localhost"),
|
|
taskState(taskStateRunning),
|
|
)),
|
|
),
|
|
extraConf: configuration{},
|
|
defaultServer: dynamic.Server{
|
|
Scheme: "http",
|
|
},
|
|
expected: expected{
|
|
error: "missing IP address for Marathon application /app on task taskID",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
test := test
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
task := task()
|
|
if len(test.app.Tasks) > 0 {
|
|
task = *test.app.Tasks[0]
|
|
}
|
|
|
|
server, err := test.provider.getServer(test.app, task, test.extraConf, test.defaultServer)
|
|
if len(test.expected.error) > 0 {
|
|
require.EqualError(t, err, test.expected.error)
|
|
} else {
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.expected.server, server)
|
|
}
|
|
})
|
|
}
|
|
}
|