2015-11-13 10:50:32 +00:00
|
|
|
package provider
|
|
|
|
|
|
|
|
import (
|
2016-12-30 08:21:13 +00:00
|
|
|
"errors"
|
2015-11-13 10:50:32 +00:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
2016-02-24 15:43:39 +00:00
|
|
|
"github.com/containous/traefik/mocks"
|
|
|
|
"github.com/containous/traefik/types"
|
2015-11-13 10:50:32 +00:00
|
|
|
"github.com/gambol99/go-marathon"
|
2016-02-09 22:10:24 +00:00
|
|
|
"github.com/stretchr/testify/mock"
|
2015-11-13 10:50:32 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type fakeClient struct {
|
2016-02-09 22:10:24 +00:00
|
|
|
mocks.Marathon
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
|
2016-02-09 22:10:24 +00:00
|
|
|
func newFakeClient(applicationsError bool, applications *marathon.Applications, tasksError bool, tasks *marathon.Tasks) *fakeClient {
|
|
|
|
// create an instance of our test object
|
|
|
|
fakeClient := new(fakeClient)
|
|
|
|
if applicationsError {
|
2016-06-20 15:11:07 +00:00
|
|
|
fakeClient.On("Applications", mock.Anything).Return(nil, errors.New("error"))
|
|
|
|
} else {
|
|
|
|
fakeClient.On("Applications", mock.Anything).Return(applications, nil)
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
2016-06-20 15:11:07 +00:00
|
|
|
if !applicationsError {
|
|
|
|
if tasksError {
|
|
|
|
fakeClient.On("AllTasks", mock.Anything).Return(nil, errors.New("error"))
|
|
|
|
} else {
|
|
|
|
fakeClient.On("AllTasks", mock.Anything).Return(tasks, nil)
|
|
|
|
}
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
2016-02-09 22:10:24 +00:00
|
|
|
return fakeClient
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonLoadConfig(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
applicationsError bool
|
|
|
|
applications *marathon.Applications
|
|
|
|
tasksError bool
|
|
|
|
tasks *marathon.Tasks
|
|
|
|
expectedNil bool
|
|
|
|
expectedFrontends map[string]*types.Frontend
|
|
|
|
expectedBackends map[string]*types.Backend
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{},
|
|
|
|
tasks: &marathon.Tasks{},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{},
|
|
|
|
expectedBackends: map[string]*types.Backend{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applicationsError: true,
|
|
|
|
applications: &marathon.Applications{},
|
|
|
|
tasks: &marathon.Tasks{},
|
|
|
|
expectedNil: true,
|
|
|
|
expectedFrontends: map[string]*types.Frontend{},
|
|
|
|
expectedBackends: map[string]*types.Backend{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{},
|
|
|
|
tasksError: true,
|
|
|
|
tasks: &marathon.Tasks{},
|
|
|
|
expectedNil: true,
|
|
|
|
expectedFrontends: map[string]*types.Frontend{},
|
|
|
|
expectedBackends: map[string]*types.Backend{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "/test",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tasks: &marathon.Tasks{
|
|
|
|
Tasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
ID: "test",
|
|
|
|
AppID: "/test",
|
2017-01-06 15:26:50 +00:00
|
|
|
Host: "localhost",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
2017-01-06 15:26:50 +00:00
|
|
|
IPAddresses: []*marathon.IPAddress{
|
|
|
|
{
|
|
|
|
IPAddress: "127.0.0.1",
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{
|
|
|
|
`frontend-test`: {
|
2016-05-10 11:43:24 +00:00
|
|
|
Backend: "backend-test",
|
|
|
|
PassHostHeader: true,
|
|
|
|
EntryPoints: []string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
Routes: map[string]types.Route{
|
|
|
|
`route-host-test`: {
|
2016-03-27 00:05:17 +00:00
|
|
|
Rule: "Host:test.docker.localhost",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedBackends: map[string]*types.Backend{
|
|
|
|
"backend-test": {
|
|
|
|
Servers: map[string]types.Server{
|
|
|
|
"server-test": {
|
|
|
|
URL: "http://127.0.0.1:80",
|
|
|
|
Weight: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CircuitBreaker: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-08-13 16:55:15 +00:00
|
|
|
{
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-11 14:12:23 +00:00
|
|
|
ID: "/testLoadBalancerAndCircuitBreaker.dot",
|
2016-08-13 16:55:15 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.backend.loadbalancer.method": "drr",
|
|
|
|
"traefik.backend.circuitbreaker.expression": "NetworkErrorRatio() > 0.5",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tasks: &marathon.Tasks{
|
|
|
|
Tasks: []marathon.Task{
|
|
|
|
{
|
2016-10-11 14:12:23 +00:00
|
|
|
ID: "testLoadBalancerAndCircuitBreaker.dot",
|
|
|
|
AppID: "/testLoadBalancerAndCircuitBreaker.dot",
|
2017-01-06 15:26:50 +00:00
|
|
|
Host: "localhost",
|
2016-08-13 16:55:15 +00:00
|
|
|
Ports: []int{80},
|
2017-01-06 15:26:50 +00:00
|
|
|
IPAddresses: []*marathon.IPAddress{
|
|
|
|
{
|
|
|
|
IPAddress: "127.0.0.1",
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
2016-08-13 16:55:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{
|
2016-10-11 14:12:23 +00:00
|
|
|
`frontend-testLoadBalancerAndCircuitBreaker.dot`: {
|
|
|
|
Backend: "backend-testLoadBalancerAndCircuitBreaker.dot",
|
2016-08-13 16:55:15 +00:00
|
|
|
PassHostHeader: true,
|
|
|
|
EntryPoints: []string{},
|
|
|
|
Routes: map[string]types.Route{
|
2016-10-11 14:12:23 +00:00
|
|
|
`route-host-testLoadBalancerAndCircuitBreaker.dot`: {
|
|
|
|
Rule: "Host:testLoadBalancerAndCircuitBreaker.dot.docker.localhost",
|
2016-08-13 16:55:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedBackends: map[string]*types.Backend{
|
2016-10-11 14:12:23 +00:00
|
|
|
"backend-testLoadBalancerAndCircuitBreaker.dot": {
|
2016-08-13 16:55:15 +00:00
|
|
|
Servers: map[string]types.Server{
|
2016-10-11 14:12:23 +00:00
|
|
|
"server-testLoadBalancerAndCircuitBreaker-dot": {
|
2016-08-13 16:55:15 +00:00
|
|
|
URL: "http://127.0.0.1:80",
|
|
|
|
Weight: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CircuitBreaker: &types.CircuitBreaker{
|
|
|
|
Expression: "NetworkErrorRatio() > 0.5",
|
|
|
|
},
|
|
|
|
LoadBalancer: &types.LoadBalancer{
|
|
|
|
Method: "drr",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "/testMaxConn",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.backend.maxconn.amount": "1000",
|
|
|
|
"traefik.backend.maxconn.extractorfunc": "client.ip",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tasks: &marathon.Tasks{
|
|
|
|
Tasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
ID: "testMaxConn",
|
|
|
|
AppID: "/testMaxConn",
|
2017-01-06 15:26:50 +00:00
|
|
|
Host: "localhost",
|
2016-08-13 16:55:15 +00:00
|
|
|
Ports: []int{80},
|
2017-01-06 15:26:50 +00:00
|
|
|
IPAddresses: []*marathon.IPAddress{
|
|
|
|
{
|
|
|
|
IPAddress: "127.0.0.1",
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
2016-08-13 16:55:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{
|
|
|
|
`frontend-testMaxConn`: {
|
|
|
|
Backend: "backend-testMaxConn",
|
|
|
|
PassHostHeader: true,
|
|
|
|
EntryPoints: []string{},
|
|
|
|
Routes: map[string]types.Route{
|
|
|
|
`route-host-testMaxConn`: {
|
|
|
|
Rule: "Host:testMaxConn.docker.localhost",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedBackends: map[string]*types.Backend{
|
|
|
|
"backend-testMaxConn": {
|
|
|
|
Servers: map[string]types.Server{
|
|
|
|
"server-testMaxConn": {
|
|
|
|
URL: "http://127.0.0.1:80",
|
|
|
|
Weight: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MaxConn: &types.MaxConn{
|
|
|
|
Amount: 1000,
|
|
|
|
ExtractorFunc: "client.ip",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "/testMaxConnOnlySpecifyAmount",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.backend.maxconn.amount": "1000",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tasks: &marathon.Tasks{
|
|
|
|
Tasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
ID: "testMaxConnOnlySpecifyAmount",
|
|
|
|
AppID: "/testMaxConnOnlySpecifyAmount",
|
2017-01-06 15:26:50 +00:00
|
|
|
Host: "localhost",
|
2016-08-13 16:55:15 +00:00
|
|
|
Ports: []int{80},
|
2017-01-06 15:26:50 +00:00
|
|
|
IPAddresses: []*marathon.IPAddress{
|
|
|
|
{
|
|
|
|
IPAddress: "127.0.0.1",
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
2016-08-13 16:55:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{
|
|
|
|
`frontend-testMaxConnOnlySpecifyAmount`: {
|
|
|
|
Backend: "backend-testMaxConnOnlySpecifyAmount",
|
|
|
|
PassHostHeader: true,
|
|
|
|
EntryPoints: []string{},
|
|
|
|
Routes: map[string]types.Route{
|
|
|
|
`route-host-testMaxConnOnlySpecifyAmount`: {
|
|
|
|
Rule: "Host:testMaxConnOnlySpecifyAmount.docker.localhost",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedBackends: map[string]*types.Backend{
|
|
|
|
"backend-testMaxConnOnlySpecifyAmount": {
|
|
|
|
Servers: map[string]types.Server{
|
|
|
|
"server-testMaxConnOnlySpecifyAmount": {
|
|
|
|
URL: "http://127.0.0.1:80",
|
|
|
|
Weight: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MaxConn: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "/testMaxConnOnlyExtractorFunc",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.backend.maxconn.extractorfunc": "client.ip",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
tasks: &marathon.Tasks{
|
|
|
|
Tasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
ID: "testMaxConnOnlyExtractorFunc",
|
|
|
|
AppID: "/testMaxConnOnlyExtractorFunc",
|
2017-01-06 15:26:50 +00:00
|
|
|
Host: "localhost",
|
2016-08-13 16:55:15 +00:00
|
|
|
Ports: []int{80},
|
2017-01-06 15:26:50 +00:00
|
|
|
IPAddresses: []*marathon.IPAddress{
|
|
|
|
{
|
|
|
|
IPAddress: "127.0.0.1",
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
2016-08-13 16:55:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedFrontends: map[string]*types.Frontend{
|
|
|
|
`frontend-testMaxConnOnlyExtractorFunc`: {
|
|
|
|
Backend: "backend-testMaxConnOnlyExtractorFunc",
|
|
|
|
PassHostHeader: true,
|
|
|
|
EntryPoints: []string{},
|
|
|
|
Routes: map[string]types.Route{
|
|
|
|
`route-host-testMaxConnOnlyExtractorFunc`: {
|
|
|
|
Rule: "Host:testMaxConnOnlyExtractorFunc.docker.localhost",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedBackends: map[string]*types.Backend{
|
|
|
|
"backend-testMaxConnOnlyExtractorFunc": {
|
|
|
|
Servers: map[string]types.Server{
|
|
|
|
"server-testMaxConnOnlyExtractorFunc": {
|
|
|
|
URL: "http://127.0.0.1:80",
|
|
|
|
Weight: 0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MaxConn: nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
2016-02-09 22:10:24 +00:00
|
|
|
fakeClient := newFakeClient(c.applicationsError, c.applications, c.tasksError, c.tasks)
|
2015-11-13 10:50:32 +00:00
|
|
|
provider := &Marathon{
|
2016-03-21 09:37:02 +00:00
|
|
|
Domain: "docker.localhost",
|
|
|
|
ExposedByDefault: true,
|
|
|
|
marathonClient: fakeClient,
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
actualConfig := provider.loadMarathonConfig()
|
2016-06-20 15:11:07 +00:00
|
|
|
fakeClient.AssertExpectations(t)
|
2015-11-13 10:50:32 +00:00
|
|
|
if c.expectedNil {
|
|
|
|
if actualConfig != nil {
|
|
|
|
t.Fatalf("Should have been nil, got %v", actualConfig)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Compare backends
|
|
|
|
if !reflect.DeepEqual(actualConfig.Backends, c.expectedBackends) {
|
|
|
|
t.Fatalf("expected %#v, got %#v", c.expectedBackends, actualConfig.Backends)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(actualConfig.Frontends, c.expectedFrontends) {
|
|
|
|
t.Fatalf("expected %#v, got %#v", c.expectedFrontends, actualConfig.Frontends)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonTaskFilter(t *testing.T) {
|
|
|
|
cases := []struct {
|
2016-03-21 09:37:02 +00:00
|
|
|
task marathon.Task
|
|
|
|
applications *marathon.Applications
|
|
|
|
expected bool
|
|
|
|
exposedByDefault bool
|
2015-11-13 10:50:32 +00:00
|
|
|
}{
|
|
|
|
{
|
2016-03-21 09:37:02 +00:00
|
|
|
task: marathon.Task{},
|
|
|
|
applications: &marathon.Applications{},
|
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
applications: &marathon.Applications{},
|
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "foo",
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2016-10-27 13:49:07 +00:00
|
|
|
AppID: "multiple-ports",
|
2016-10-27 13:49:34 +00:00
|
|
|
Ports: []int{80, 443},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:07 +00:00
|
|
|
ID: "multiple-ports",
|
2016-06-20 15:11:07 +00:00
|
|
|
Ports: []int{80, 443},
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-10-27 13:49:34 +00:00
|
|
|
expected: true,
|
2016-03-21 09:37:02 +00:00
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2017-01-06 15:26:50 +00:00
|
|
|
AppID: "ipAddressOnePort",
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "ipAddressOnePort",
|
|
|
|
IPAddressPerTask: &marathon.IPAddressPerTask{
|
|
|
|
Discovery: &marathon.Discovery{
|
|
|
|
Ports: &[]marathon.Port{
|
|
|
|
{
|
|
|
|
Number: 8880,
|
|
|
|
Name: "p1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "ipAddressTwoPortsUseFirst",
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "ipAddressTwoPortsUseFirst",
|
|
|
|
IPAddressPerTask: &marathon.IPAddressPerTask{
|
|
|
|
Discovery: &marathon.Discovery{
|
|
|
|
Ports: &[]marathon.Port{
|
|
|
|
{
|
|
|
|
Number: 8898,
|
|
|
|
Name: "p1",
|
|
|
|
}, {
|
|
|
|
Number: 9999,
|
|
|
|
Name: "p1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "ipAddressValidTwoPorts",
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "ipAddressValidTwoPorts",
|
|
|
|
IPAddressPerTask: &marathon.IPAddressPerTask{
|
|
|
|
Discovery: &marathon.Discovery{
|
|
|
|
Ports: &[]marathon.Port{
|
|
|
|
{
|
|
|
|
Number: 8898,
|
|
|
|
Name: "p1",
|
|
|
|
}, {
|
|
|
|
Number: 9999,
|
|
|
|
Name: "p2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.portIndex": "0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:07 +00:00
|
|
|
ID: "disable",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.enable": "false",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
2015-12-05 18:59:01 +00:00
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-port-number",
|
2017-03-20 13:16:34 +00:00
|
|
|
Ports: []int{80},
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2017-03-20 13:16:34 +00:00
|
|
|
ID: "specify-port-number",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.port": "8080",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-03-20 13:16:34 +00:00
|
|
|
expected: true,
|
2016-03-21 09:37:02 +00:00
|
|
|
exposedByDefault: true,
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-port-index",
|
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "specify-port-index",
|
|
|
|
Ports: []int{80, 443},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.portIndex": "0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-out-of-range-port-index",
|
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "specify-out-of-range-port-index",
|
|
|
|
Ports: []int{80, 443},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.portIndex": "2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-both-port-index-and-number",
|
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "specify-both-port-index-and-number",
|
|
|
|
Ports: []int{80, 443},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.port": "443",
|
|
|
|
"traefik.portIndex": "1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "foo",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "foo",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
HealthChecks: &[]marathon.HealthCheck{
|
|
|
|
*marathon.NewDefaultHealthCheck(),
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-02-27 18:56:53 +00:00
|
|
|
expected: true,
|
2016-03-21 09:37:02 +00:00
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2016-10-27 13:49:07 +00:00
|
|
|
AppID: "healthcheck-false",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
2016-02-09 22:10:24 +00:00
|
|
|
HealthCheckResults: []*marathon.HealthCheckResult{
|
2015-11-13 10:50:32 +00:00
|
|
|
{
|
|
|
|
Alive: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:07 +00:00
|
|
|
ID: "healthcheck-false",
|
2016-06-20 15:11:07 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
HealthChecks: &[]marathon.HealthCheck{
|
|
|
|
*marathon.NewDefaultHealthCheck(),
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "foo",
|
|
|
|
Ports: []int{80},
|
2016-02-09 22:10:24 +00:00
|
|
|
HealthCheckResults: []*marathon.HealthCheckResult{
|
2015-11-13 10:50:32 +00:00
|
|
|
{
|
|
|
|
Alive: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Alive: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "foo",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
HealthChecks: &[]marathon.HealthCheck{
|
|
|
|
*marathon.NewDefaultHealthCheck(),
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: false,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2016-10-27 13:49:07 +00:00
|
|
|
AppID: "single-port",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:07 +00:00
|
|
|
ID: "single-port",
|
2016-06-20 15:11:07 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
2016-10-27 13:49:07 +00:00
|
|
|
AppID: "healthcheck-alive",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
2016-02-09 22:10:24 +00:00
|
|
|
HealthCheckResults: []*marathon.HealthCheckResult{
|
2015-11-13 10:50:32 +00:00
|
|
|
{
|
|
|
|
Alive: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:07 +00:00
|
|
|
ID: "healthcheck-alive",
|
2016-06-20 15:11:07 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
HealthChecks: &[]marathon.HealthCheck{
|
|
|
|
*marathon.NewDefaultHealthCheck(),
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2016-03-21 09:37:02 +00:00
|
|
|
expected: true,
|
|
|
|
exposedByDefault: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "disable-default-expose",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "disable-default-expose",
|
|
|
|
Ports: []int{80},
|
|
|
|
Labels: &map[string]string{},
|
2016-03-21 09:37:02 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
exposedByDefault: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "disable-default-expose-disable-in-label",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "disable-default-expose-disable-in-label",
|
|
|
|
Ports: []int{80},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-03-21 09:37:02 +00:00
|
|
|
"traefik.enable": "false",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
exposedByDefault: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "disable-default-expose-enable-in-label",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
applications: &marathon.Applications{
|
|
|
|
Apps: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "disable-default-expose-enable-in-label",
|
|
|
|
Ports: []int{80},
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-03-21 09:37:02 +00:00
|
|
|
"traefik.enable": "true",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
exposedByDefault: false,
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:44:32 +00:00
|
|
|
provider := &Marathon{}
|
2015-11-13 10:50:32 +00:00
|
|
|
for _, c := range cases {
|
2016-09-20 08:44:32 +00:00
|
|
|
actual := provider.taskFilter(c.task, c.applications, c.exposedByDefault)
|
2015-11-13 10:50:32 +00:00
|
|
|
if actual != c.expected {
|
2016-10-27 13:49:07 +00:00
|
|
|
t.Fatalf("App %s: expected %v, got %v", c.task.AppID, c.expected, actual)
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-20 23:15:09 +00:00
|
|
|
func TestMarathonAppConstraints(t *testing.T) {
|
|
|
|
cases := []struct {
|
2016-10-06 15:42:19 +00:00
|
|
|
application marathon.Application
|
|
|
|
filteredTasks []marathon.Task
|
|
|
|
expected bool
|
|
|
|
marathonLBCompatibility bool
|
2016-09-20 23:15:09 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
|
|
|
ID: "foo1",
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
AppID: "foo1",
|
|
|
|
},
|
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: false,
|
|
|
|
expected: false,
|
2016-09-20 23:15:09 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-10-06 15:42:19 +00:00
|
|
|
ID: "foo2",
|
2016-09-20 23:15:09 +00:00
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.tags": "valid",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{
|
|
|
|
{
|
2016-10-06 15:42:19 +00:00
|
|
|
AppID: "foo2",
|
2016-09-20 23:15:09 +00:00
|
|
|
},
|
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: false,
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
|
|
|
ID: "foo3",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"HAPROXY_GROUP": "valid",
|
|
|
|
"traefik.tags": "notvalid",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
AppID: "foo3",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
marathonLBCompatibility: true,
|
|
|
|
expected: true,
|
2016-09-20 23:15:09 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
2016-10-06 15:42:19 +00:00
|
|
|
provider := &Marathon{
|
|
|
|
MarathonLBCompatibility: c.marathonLBCompatibility,
|
|
|
|
}
|
|
|
|
constraint, _ := types.NewConstraint("tag==valid")
|
2016-11-09 18:27:04 +00:00
|
|
|
provider.Constraints = types.Constraints{constraint}
|
2016-09-20 23:15:09 +00:00
|
|
|
actual := provider.applicationFilter(c.application, c.filteredTasks)
|
|
|
|
if actual != c.expected {
|
|
|
|
t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.application)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
func TestMarathonTaskConstraints(t *testing.T) {
|
|
|
|
cases := []struct {
|
2016-10-06 15:42:19 +00:00
|
|
|
applications []marathon.Application
|
|
|
|
filteredTask marathon.Task
|
|
|
|
expected bool
|
|
|
|
marathonLBCompatibility bool
|
2016-09-20 23:15:09 +00:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
2016-09-20 23:41:34 +00:00
|
|
|
{
|
2016-09-20 23:15:09 +00:00
|
|
|
ID: "bar1",
|
|
|
|
Labels: &map[string]string{},
|
2016-09-20 23:41:34 +00:00
|
|
|
}, {
|
2016-09-20 23:15:09 +00:00
|
|
|
ID: "foo1",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.tags": "other",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
filteredTask: marathon.Task{
|
|
|
|
AppID: "foo1",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: false,
|
|
|
|
expected: false,
|
2016-09-20 23:15:09 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
2016-09-20 23:41:34 +00:00
|
|
|
{
|
2016-09-20 23:15:09 +00:00
|
|
|
ID: "foo2",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"traefik.tags": "valid",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
filteredTask: marathon.Task{
|
|
|
|
AppID: "foo2",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: false,
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "foo3",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"HAPROXY_GROUP": "valid",
|
|
|
|
"traefik.tags": "notvalid",
|
|
|
|
},
|
|
|
|
}, {
|
|
|
|
ID: "foo4",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"HAPROXY_GROUP": "notvalid",
|
|
|
|
"traefik.tags": "valid",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
filteredTask: marathon.Task{
|
|
|
|
AppID: "foo3",
|
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
marathonLBCompatibility: true,
|
|
|
|
expected: true,
|
2016-09-20 23:15:09 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
2016-10-06 15:42:19 +00:00
|
|
|
provider := &Marathon{
|
|
|
|
MarathonLBCompatibility: c.marathonLBCompatibility,
|
|
|
|
}
|
|
|
|
constraint, _ := types.NewConstraint("tag==valid")
|
2016-11-09 18:27:04 +00:00
|
|
|
provider.Constraints = types.Constraints{constraint}
|
2016-09-20 23:15:09 +00:00
|
|
|
apps := new(marathon.Applications)
|
|
|
|
apps.Apps = c.applications
|
|
|
|
actual := provider.taskFilter(c.filteredTask, apps, true)
|
|
|
|
if actual != c.expected {
|
|
|
|
t.Fatalf("expected %v, got %v: %v", c.expected, actual, c.filteredTask)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-13 10:50:32 +00:00
|
|
|
func TestMarathonApplicationFilter(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
application marathon.Application
|
|
|
|
filteredTasks []marathon.Task
|
|
|
|
expected bool
|
|
|
|
}{
|
|
|
|
{
|
2016-09-20 08:44:32 +00:00
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
filteredTasks: []marathon.Task{},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "test",
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "foo",
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
AppID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "foo",
|
|
|
|
Labels: &map[string]string{},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
filteredTasks: []marathon.Task{
|
|
|
|
{
|
|
|
|
AppID: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:44:32 +00:00
|
|
|
provider := &Marathon{}
|
2015-11-13 10:50:32 +00:00
|
|
|
for _, c := range cases {
|
2016-09-20 08:44:32 +00:00
|
|
|
actual := provider.applicationFilter(c.application, c.filteredTasks)
|
2015-11-13 10:50:32 +00:00
|
|
|
if actual != c.expected {
|
|
|
|
t.Fatalf("expected %v, got %v", c.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonGetPort(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
cases := []struct {
|
2015-12-05 18:59:01 +00:00
|
|
|
applications []marathon.Application
|
|
|
|
task marathon.Task
|
|
|
|
expected string
|
2015-11-13 10:50:32 +00:00
|
|
|
}{
|
|
|
|
{
|
2015-12-05 18:59:01 +00:00
|
|
|
applications: []marathon.Application{},
|
|
|
|
task: marathon.Task{},
|
|
|
|
expected: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "test1",
|
|
|
|
Labels: &map[string]string{},
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test2",
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
expected: "",
|
|
|
|
},
|
|
|
|
{
|
2015-12-05 18:59:01 +00:00
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
ID: "test1",
|
|
|
|
Labels: &map[string]string{},
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
task: marathon.Task{
|
2015-12-05 18:59:01 +00:00
|
|
|
AppID: "test1",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80},
|
|
|
|
},
|
|
|
|
expected: "80",
|
|
|
|
},
|
|
|
|
{
|
2015-12-05 18:59:01 +00:00
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
2016-10-27 13:49:34 +00:00
|
|
|
ID: "multiple-ports-take-first",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{},
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
task: marathon.Task{
|
2016-10-27 13:49:34 +00:00
|
|
|
AppID: "multiple-ports-take-first",
|
2015-11-13 10:50:32 +00:00
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
expected: "80",
|
|
|
|
},
|
2015-12-05 18:59:01 +00:00
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "specify-port-number",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.port": "443",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-port-number",
|
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
expected: "443",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "specify-port-index",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-12-05 18:59:01 +00:00
|
|
|
"traefik.portIndex": "1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "specify-port-index",
|
|
|
|
Ports: []int{80, 443},
|
|
|
|
},
|
|
|
|
expected: "443",
|
2017-01-31 14:48:21 +00:00
|
|
|
}, {
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "application-with-port",
|
|
|
|
Ports: []int{9999},
|
|
|
|
Labels: &map[string]string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "application-with-port",
|
|
|
|
Ports: []int{7777},
|
|
|
|
},
|
|
|
|
expected: "7777",
|
2015-12-05 18:59:01 +00:00
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range cases {
|
2015-12-05 18:59:01 +00:00
|
|
|
actual := provider.getPort(c.task, c.applications)
|
2015-11-13 10:50:32 +00:00
|
|
|
if actual != c.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", c.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonGetWeigh(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
applications []marathon.Application
|
|
|
|
task marathon.Task
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{},
|
|
|
|
task: marathon.Task{},
|
|
|
|
expected: "0",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test1",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.weight": "10",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test2",
|
|
|
|
},
|
|
|
|
expected: "0",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.test": "10",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
},
|
|
|
|
expected: "0",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.weight": "10",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
},
|
|
|
|
expected: "10",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
|
|
|
actual := provider.getWeight(a.task, a.applications)
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonGetDomain(t *testing.T) {
|
|
|
|
provider := &Marathon{
|
|
|
|
Domain: "docker.localhost",
|
|
|
|
}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
application marathon.Application
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{}},
|
|
|
|
expected: "docker.localhost",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.domain": "foo.bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: "foo.bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
|
|
|
actual := provider.getDomain(a.application)
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonGetProtocol(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
applications []marathon.Application
|
|
|
|
task marathon.Task
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{},
|
|
|
|
task: marathon.Task{},
|
|
|
|
expected: "http",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test1",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.protocol": "https",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test2",
|
|
|
|
},
|
|
|
|
expected: "http",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
},
|
|
|
|
expected: "http",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
applications: []marathon.Application{
|
|
|
|
{
|
|
|
|
ID: "test",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2015-11-13 10:50:32 +00:00
|
|
|
"traefik.protocol": "https",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
task: marathon.Task{
|
|
|
|
AppID: "test",
|
|
|
|
},
|
|
|
|
expected: "https",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
|
|
|
actual := provider.getProtocol(a.task, a.applications)
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarathonGetPassHostHeader(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
application marathon.Application
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{}},
|
|
|
|
expected: "true",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-05-10 11:43:24 +00:00
|
|
|
"traefik.frontend.passHostHeader": "false",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
2016-05-10 11:43:24 +00:00
|
|
|
expected: "false",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
|
|
|
actual := provider.getPassHostHeader(a.application)
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-01 10:07:05 +00:00
|
|
|
func TestMarathonGetEntryPoints(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
application marathon.Application
|
|
|
|
expected []string
|
|
|
|
}{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{}},
|
|
|
|
expected: []string{},
|
2016-02-01 10:07:05 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-02-01 10:07:05 +00:00
|
|
|
"traefik.frontend.entryPoints": "http,https",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: []string{"http", "https"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
|
|
|
actual := provider.getEntryPoints(a.application)
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(actual, a.expected) {
|
|
|
|
t.Fatalf("expected %#v, got %#v", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-27 00:05:17 +00:00
|
|
|
func TestMarathonGetFrontendRule(t *testing.T) {
|
2015-11-13 10:50:32 +00:00
|
|
|
applications := []struct {
|
2016-10-06 15:42:19 +00:00
|
|
|
application marathon.Application
|
|
|
|
expected string
|
|
|
|
marathonLBCompatibility bool
|
2015-11-13 10:50:32 +00:00
|
|
|
}{
|
|
|
|
{
|
2016-06-20 15:11:07 +00:00
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{}},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: true,
|
|
|
|
expected: "Host:.docker.localhost",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-10-06 15:42:19 +00:00
|
|
|
ID: "test",
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"HAPROXY_0_VHOST": "foo.bar",
|
|
|
|
},
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: false,
|
|
|
|
expected: "Host:test.docker.localhost",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-03-27 00:05:17 +00:00
|
|
|
"traefik.frontend.rule": "Host:foo.bar",
|
2016-10-06 15:42:19 +00:00
|
|
|
"HAPROXY_0_VHOST": "notvalid",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
marathonLBCompatibility: true,
|
|
|
|
expected: "Host:foo.bar",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
|
|
|
Labels: &map[string]string{
|
|
|
|
"HAPROXY_0_VHOST": "foo.bar",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
},
|
2016-10-06 15:42:19 +00:00
|
|
|
marathonLBCompatibility: true,
|
|
|
|
expected: "Host:foo.bar",
|
2015-11-13 10:50:32 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
2016-10-06 15:42:19 +00:00
|
|
|
provider := &Marathon{
|
|
|
|
Domain: "docker.localhost",
|
|
|
|
MarathonLBCompatibility: a.marathonLBCompatibility,
|
|
|
|
}
|
2015-11-13 10:50:32 +00:00
|
|
|
actual := provider.getFrontendRule(a.application)
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-20 18:55:10 +00:00
|
|
|
|
|
|
|
func TestMarathonGetBackend(t *testing.T) {
|
|
|
|
provider := &Marathon{}
|
|
|
|
|
|
|
|
applications := []struct {
|
|
|
|
application marathon.Application
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
application: marathon.Application{
|
|
|
|
ID: "foo",
|
2016-06-20 15:11:07 +00:00
|
|
|
Labels: &map[string]string{
|
2016-01-20 18:55:10 +00:00
|
|
|
"traefik.backend": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: "bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range applications {
|
2016-02-12 13:45:36 +00:00
|
|
|
actual := provider.getFrontendBackend(a.application)
|
2016-01-20 18:55:10 +00:00
|
|
|
if actual != a.expected {
|
|
|
|
t.Fatalf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-28 13:59:08 +00:00
|
|
|
|
|
|
|
func TestMarathonGetSubDomain(t *testing.T) {
|
|
|
|
providerGroups := &Marathon{GroupsAsSubDomains: true}
|
|
|
|
providerNoGroups := &Marathon{GroupsAsSubDomains: false}
|
|
|
|
|
|
|
|
apps := []struct {
|
|
|
|
path string
|
|
|
|
expected string
|
|
|
|
provider *Marathon
|
|
|
|
}{
|
|
|
|
{"/test", "test", providerNoGroups},
|
|
|
|
{"/test", "test", providerGroups},
|
|
|
|
{"/a/b/c/d", "d.c.b.a", providerGroups},
|
|
|
|
{"/b/a/d/c", "c.d.a.b", providerGroups},
|
|
|
|
{"/d/c/b/a", "a.b.c.d", providerGroups},
|
|
|
|
{"/c/d/a/b", "b.a.d.c", providerGroups},
|
|
|
|
{"/a/b/c/d", "a-b-c-d", providerNoGroups},
|
|
|
|
{"/b/a/d/c", "b-a-d-c", providerNoGroups},
|
|
|
|
{"/d/c/b/a", "d-c-b-a", providerNoGroups},
|
|
|
|
{"/c/d/a/b", "c-d-a-b", providerNoGroups},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, a := range apps {
|
|
|
|
actual := a.provider.getSubDomain(a.path)
|
|
|
|
|
|
|
|
if actual != a.expected {
|
|
|
|
t.Errorf("expected %q, got %q", a.expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|