Support regex redirect by frontend

This commit is contained in:
Ludovic Fernandez 2017-12-15 11:48:03 +01:00 committed by Traefiker
parent bddad57a7b
commit 7ecd6d20ba
22 changed files with 405 additions and 195 deletions

View file

@ -42,7 +42,7 @@ const (
defaultPassHostHeader = "true"
defaultFrontendPriority = "0"
defaultCircuitBreakerExpression = "NetworkErrorRatio() > 1"
defaultFrontendRedirect = ""
defaultFrontendRedirectEntryPoint = ""
defaultBackendLoadBalancerMethod = "wrr"
defaultBackendMaxconnExtractorfunc = "request.host"
)
@ -276,7 +276,6 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
"getEntryPoints": getFuncSliceStringLabel(types.LabelFrontendEntryPoints),
"getBasicAuth": getFuncSliceStringLabel(types.LabelFrontendAuthBasic),
"getFrontendRule": p.getFrontendRule,
"getRedirect": getFuncStringLabel(types.LabelFrontendRedirect, ""),
"hasCircuitBreakerLabel": hasLabel(types.LabelBackendCircuitbreakerExpression),
"getCircuitBreakerExpression": getFuncStringLabel(types.LabelBackendCircuitbreakerExpression, defaultCircuitBreakerExpression),
"hasLoadBalancerLabel": hasLoadBalancerLabel,
@ -289,7 +288,6 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
"getStickinessCookieName": getFuncStringLabel(types.LabelBackendLoadbalancerStickinessCookieName, ""),
"getIsBackendLBSwarm": getIsBackendLBSwarm,
"getServiceBackend": getServiceBackend,
"getServiceRedirect": getFuncServiceStringLabel(types.SuffixFrontendRedirect, defaultFrontendRedirect),
"getWhitelistSourceRange": getFuncSliceStringLabel(types.LabelTraefikFrontendWhitelistSourceRange),
"hasRequestHeaders": hasLabel(types.LabelFrontendRequestHeaders),
@ -343,6 +341,15 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
"getServiceFrontendRule": p.getServiceFrontendRule,
"getServicePassHostHeader": getFuncServiceStringLabel(types.SuffixFrontendPassHostHeader, defaultPassHostHeader),
"getServicePriority": getFuncServiceStringLabel(types.SuffixFrontendPriority, defaultFrontendPriority),
"hasRedirect": hasRedirect,
"getRedirectEntryPoint": getFuncStringLabel(types.LabelFrontendRedirectEntryPoint, defaultFrontendRedirectEntryPoint),
"getRedirectRegex": getFuncStringLabel(types.LabelFrontendRedirectRegex, ""),
"getRedirectReplacement": getFuncStringLabel(types.LabelFrontendRedirectReplacement, ""),
"hasServiceRedirect": hasServiceRedirect,
"getServiceRedirectEntryPoint": getFuncServiceStringLabel(types.SuffixFrontendRedirectEntryPoint, defaultFrontendRedirectEntryPoint),
"getServiceRedirectReplacement": getFuncServiceStringLabel(types.SuffixFrontendRedirectReplacement, ""),
"getServiceRedirectRegex": getFuncServiceStringLabel(types.SuffixFrontendRedirectRegex, ""),
}
// filter containers
filteredContainers := fun.Filter(func(container dockerData) bool {
@ -865,3 +872,26 @@ func parseTasks(task swarmtypes.Task, serviceDockerData dockerData, networkMap m
}
return dockerData
}
// TODO will be rewrite when merge on master
func hasServiceRedirect(container dockerData, serviceName string) bool {
serviceLabels, ok := extractServicesLabels(container.Labels)[serviceName]
if !ok || len(serviceLabels) == 0 {
return false
}
value, ok := serviceLabels[types.SuffixFrontendRedirectEntryPoint]
frep := ok && len(value) > 0
value, ok = serviceLabels[types.SuffixFrontendRedirectRegex]
frrg := ok && len(value) > 0
value, ok = serviceLabels[types.SuffixFrontendRedirectReplacement]
frrp := ok && len(value) > 0
return frep || frrg && frrp
}
// TODO will be rewrite when merge on master
func hasRedirect(container dockerData) bool {
return hasLabel(types.LabelFrontendRedirectEntryPoint)(container) ||
hasLabel(types.LabelFrontendRedirectReplacement)(container) && hasLabel(types.LabelFrontendRedirectRegex)(container)
}

View file

@ -712,7 +712,6 @@ func TestDockerLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"route-frontend-Host-test-docker-localhost-0": {
Rule: "Host:test.docker.localhost",
@ -737,10 +736,10 @@ func TestDockerLoadDockerConfig(t *testing.T) {
containerJSON(
name("test1"),
labels(map[string]string{
types.LabelBackend: "foobar",
types.LabelFrontendEntryPoints: "http,https",
types.LabelFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
types.LabelFrontendRedirect: "https",
types.LabelBackend: "foobar",
types.LabelFrontendEntryPoints: "http,https",
types.LabelFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
types.LabelFrontendRedirectEntryPoint: "https",
}),
ports(nat.PortMap{
"80/tcp": {},
@ -764,7 +763,9 @@ func TestDockerLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{"http", "https"},
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
Redirect: "https",
Redirect: &types.Redirect{
EntryPoint: "https",
},
Routes: map[string]types.Route{
"route-frontend-Host-test1-docker-localhost-0": {
Rule: "Host:test1.docker.localhost",
@ -776,7 +777,6 @@ func TestDockerLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"route-frontend-Host-test2-docker-localhost-1": {
Rule: "Host:test2.docker.localhost",
@ -824,7 +824,6 @@ func TestDockerLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{"http", "https"},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"route-frontend-Host-test1-docker-localhost-0": {
Rule: "Host:test1.docker.localhost",

View file

@ -8,6 +8,7 @@ import (
"github.com/containous/traefik/types"
docker "github.com/docker/docker/api/types"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/assert"
)
func TestDockerGetServicePort(t *testing.T) {
@ -136,10 +137,10 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
containerJSON(
name("foo"),
labels(map[string]string{
"traefik.service.port": "2503",
"traefik.service.frontend.entryPoints": "http,https",
"traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
"traefik.service.frontend.redirect": "https",
"traefik.service.port": "2503",
"traefik.service.frontend.entryPoints": "http,https",
"traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
"traefik.service.frontend.redirect.entryPoint": "https",
}),
ports(nat.PortMap{
"80/tcp": {},
@ -153,7 +154,9 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{"http", "https"},
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
Redirect: "https",
Redirect: &types.Redirect{
EntryPoint: "https",
},
Routes: map[string]types.Route{
"service-service": {
Rule: "Host:foo.docker.localhost",
@ -178,16 +181,16 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
containerJSON(
name("test1"),
labels(map[string]string{
"traefik.service.port": "2503",
"traefik.service.protocol": "https",
"traefik.service.weight": "80",
"traefik.service.frontend.backend": "foobar",
"traefik.service.frontend.passHostHeader": "false",
"traefik.service.frontend.rule": "Path:/mypath",
"traefik.service.frontend.priority": "5000",
"traefik.service.frontend.entryPoints": "http,https,ws",
"traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
"traefik.service.frontend.redirect": "https",
"traefik.service.port": "2503",
"traefik.service.protocol": "https",
"traefik.service.weight": "80",
"traefik.service.frontend.backend": "foobar",
"traefik.service.frontend.passHostHeader": "false",
"traefik.service.frontend.rule": "Path:/mypath",
"traefik.service.frontend.priority": "5000",
"traefik.service.frontend.entryPoints": "http,https,ws",
"traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
"traefik.service.frontend.redirect.entryPoint": "https",
}),
ports(nat.PortMap{
"80/tcp": {},
@ -214,7 +217,9 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
Priority: 5000,
EntryPoints: []string{"http", "https", "ws"},
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
Redirect: "https",
Redirect: &types.Redirect{
EntryPoint: "https",
},
Routes: map[string]types.Route{
"service-service": {
Rule: "Path:/mypath",
@ -226,7 +231,6 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"service-anotherservice": {
Rule: "Path:/anotherpath",
@ -274,9 +278,11 @@ func TestDockerLoadDockerServiceConfig(t *testing.T) {
actualConfig := provider.loadDockerConfig(dockerDataList)
// Compare backends
assert.EqualValues(t, test.expectedBackends, actualConfig.Backends)
if !reflect.DeepEqual(actualConfig.Backends, test.expectedBackends) {
t.Fatalf("expected %#v, got %#v", test.expectedBackends, actualConfig.Backends)
}
assert.EqualValues(t, test.expectedFrontends, actualConfig.Frontends)
if !reflect.DeepEqual(actualConfig.Frontends, test.expectedFrontends) {
t.Fatalf("expected %#v, got %#v", test.expectedFrontends, actualConfig.Frontends)
}

View file

@ -516,7 +516,6 @@ func TestSwarmLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"route-frontend-Host-test-docker-localhost-0": {
Rule: "Host:test.docker.localhost",
@ -547,11 +546,11 @@ func TestSwarmLoadDockerConfig(t *testing.T) {
swarmService(
serviceName("test1"),
serviceLabels(map[string]string{
types.LabelPort: "80",
types.LabelBackend: "foobar",
types.LabelFrontendEntryPoints: "http,https",
types.LabelFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
types.LabelFrontendRedirect: "https",
types.LabelPort: "80",
types.LabelBackend: "foobar",
types.LabelFrontendEntryPoints: "http,https",
types.LabelFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
types.LabelFrontendRedirectEntryPoint: "https",
}),
withEndpointSpec(modeVIP),
withEndpoint(virtualIP("1", "127.0.0.1/24")),
@ -572,7 +571,9 @@ func TestSwarmLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{"http", "https"},
BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
Redirect: "https",
Redirect: &types.Redirect{
EntryPoint: "https",
},
Routes: map[string]types.Route{
"route-frontend-Host-test1-docker-localhost-0": {
Rule: "Host:test1.docker.localhost",
@ -584,7 +585,6 @@ func TestSwarmLoadDockerConfig(t *testing.T) {
PassHostHeader: true,
EntryPoints: []string{},
BasicAuth: []string{},
Redirect: "",
Routes: map[string]types.Route{
"route-frontend-Host-test2-docker-localhost-1": {
Rule: "Host:test2.docker.localhost",