Merge pull request #1538 from containous/merge-v1.2.3-master
Merge v1.2.3 master
This commit is contained in:
commit
5535318cda
6 changed files with 506 additions and 284 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,5 +1,20 @@
|
|||
# Change Log
|
||||
|
||||
## [v1.2.3](https://github.com/containous/traefik/tree/v1.2.3) (2017-04-13)
|
||||
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.2...v1.2.3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix too many redirect [\#1433](https://github.com/containous/traefik/pull/1433) ([emilevauge](https://github.com/emilevauge))
|
||||
|
||||
## [v1.2.2](https://github.com/containous/traefik/tree/v1.2.2) (2017-04-11)
|
||||
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.1...v1.2.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Carry PR 1271 [\#1417](https://github.com/containous/traefik/pull/1417) ([emilevauge](https://github.com/emilevauge))
|
||||
- Fix postloadconfig acme & Docker filter empty rule [\#1401](https://github.com/containous/traefik/pull/1401) ([emilevauge](https://github.com/emilevauge))
|
||||
|
||||
## [v1.2.1](https://github.com/containous/traefik/tree/v1.2.1) (2017-03-27)
|
||||
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.0...v1.2.1)
|
||||
|
||||
|
|
|
@ -523,6 +523,11 @@ func (p *Provider) containerFilter(container dockerData) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if len(p.getFrontendRule(container)) == 0 {
|
||||
log.Debugf("Filtering container with empty frontend rule %s", container.Name)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -540,8 +545,10 @@ func (p *Provider) getFrontendRule(container dockerData) string {
|
|||
if labels, err := getLabels(container, []string{"com.docker.compose.project", "com.docker.compose.service"}); err == nil {
|
||||
return "Host:" + p.getSubDomain(labels["com.docker.compose.service"]+"."+labels["com.docker.compose.project"]) + "." + p.Domain
|
||||
}
|
||||
|
||||
return "Host:" + p.getSubDomain(container.ServiceName) + "." + p.Domain
|
||||
if len(p.Domain) > 0 {
|
||||
return "Host:" + p.getSubDomain(container.ServiceName) + "." + p.Domain
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *Provider) getBackend(container dockerData) string {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/types"
|
||||
docker "github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
|
@ -488,127 +489,300 @@ func TestDockerGetLabels(t *testing.T) {
|
|||
|
||||
func TestDockerTraefikFilter(t *testing.T) {
|
||||
containers := []struct {
|
||||
container docker.ContainerJSON
|
||||
exposedByDefault bool
|
||||
expected bool
|
||||
container docker.ContainerJSON
|
||||
expected bool
|
||||
provider *Provider
|
||||
}{
|
||||
{
|
||||
container: containerJSON(),
|
||||
exposedByDefault: true,
|
||||
expected: false,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{},
|
||||
NetworkSettings: &docker.NetworkSettings{},
|
||||
},
|
||||
expected: false,
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.enable": "false",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: false,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "false",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
"443/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container-multi-ports",
|
||||
},
|
||||
Config: &container.Config{},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
"443/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.port": "80",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
"443/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.port": "80",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
"443/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.enable": "true",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "true",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.enable": "anything",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "anything",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: false,
|
||||
expected: false,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
"traefik.enable": "true",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": {},
|
||||
}),
|
||||
),
|
||||
exposedByDefault: false,
|
||||
expected: true,
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "true",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
Domain: "test",
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "true",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
container: docker.ContainerJSON{
|
||||
ContainerJSONBase: &docker.ContainerJSONBase{
|
||||
Name: "container",
|
||||
},
|
||||
Config: &container.Config{
|
||||
Labels: map[string]string{
|
||||
"traefik.enable": "true",
|
||||
"traefik.frontend.rule": "Host:i.love.this.host",
|
||||
},
|
||||
},
|
||||
NetworkSettings: &docker.NetworkSettings{
|
||||
NetworkSettingsBase: docker.NetworkSettingsBase{
|
||||
Ports: nat.PortMap{
|
||||
"80/tcp": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: &Provider{
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -616,12 +790,10 @@ func TestDockerTraefikFilter(t *testing.T) {
|
|||
e := e
|
||||
t.Run(strconv.Itoa(containerID), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
provider := Provider{}
|
||||
provider.ExposedByDefault = e.exposedByDefault
|
||||
dockerData := parseContainer(e.container)
|
||||
actual := provider.containerFilter(dockerData)
|
||||
actual := e.provider.containerFilter(dockerData)
|
||||
if actual != e.expected {
|
||||
t.Errorf("expected %v for %+v (%+v, %+v), got %+v", e.expected, e.container, e.container.NetworkSettings, e.container.ContainerJSONBase, actual)
|
||||
t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ func TestDockerGetServiceFrontendRule(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
container: containerJSON(name("foo")),
|
||||
expected: "Host:foo.",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
container: containerJSON(labels(map[string]string{
|
||||
|
|
|
@ -503,86 +503,122 @@ func TestSwarmGetLabels(t *testing.T) {
|
|||
|
||||
func TestSwarmTraefikFilter(t *testing.T) {
|
||||
services := []struct {
|
||||
service swarm.Service
|
||||
exposedByDefault bool
|
||||
expected bool
|
||||
networks map[string]*docker.NetworkResource
|
||||
service swarm.Service
|
||||
expected bool
|
||||
networks map[string]*docker.NetworkResource
|
||||
provider *Provider
|
||||
}{
|
||||
{
|
||||
service: swarmService(),
|
||||
exposedByDefault: true,
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
service: swarmService(),
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.enable": "false",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.enable": "true",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.enable": "anything",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.frontend.rule": "Host:foo.bar",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: true,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: false,
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: false,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
service: swarmService(serviceLabels(map[string]string{
|
||||
"traefik.enable": "true",
|
||||
"traefik.port": "80",
|
||||
})),
|
||||
exposedByDefault: false,
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
expected: true,
|
||||
networks: map[string]*docker.NetworkResource{},
|
||||
provider: &Provider{
|
||||
SwarmMode: true,
|
||||
Domain: "test",
|
||||
ExposedByDefault: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -591,11 +627,7 @@ func TestSwarmTraefikFilter(t *testing.T) {
|
|||
t.Run(strconv.Itoa(serviceID), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dockerData := parseService(e.service, e.networks)
|
||||
provider := &Provider{
|
||||
SwarmMode: true,
|
||||
}
|
||||
provider.ExposedByDefault = e.exposedByDefault
|
||||
actual := provider.containerFilter(dockerData)
|
||||
actual := e.provider.containerFilter(dockerData)
|
||||
if actual != e.expected {
|
||||
t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual)
|
||||
}
|
||||
|
|
278
server/server.go
278
server/server.go
|
@ -315,15 +315,16 @@ func (server *Server) postLoadConfig() {
|
|||
for _, frontend := range configuration.Frontends {
|
||||
|
||||
// check if one of the frontend entrypoints is configured with TLS
|
||||
TLSEnabled := false
|
||||
// and is configured with ACME
|
||||
ACMEEnabled := false
|
||||
for _, entrypoint := range frontend.EntryPoints {
|
||||
if server.globalConfiguration.EntryPoints[entrypoint].TLS != nil {
|
||||
TLSEnabled = true
|
||||
if server.globalConfiguration.ACME.EntryPoint == entrypoint && server.globalConfiguration.EntryPoints[entrypoint].TLS != nil {
|
||||
ACMEEnabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if TLSEnabled {
|
||||
if ACMEEnabled {
|
||||
for _, route := range frontend.Routes {
|
||||
rules := Rules{}
|
||||
domains, err := rules.ParseDomains(route.Rule)
|
||||
|
@ -547,13 +548,11 @@ func (server *Server) buildEntryPoints(globalConfiguration GlobalConfiguration)
|
|||
// provider configurations.
|
||||
func (server *Server) loadConfig(configurations configs, globalConfiguration GlobalConfiguration) (map[string]*serverEntryPoint, error) {
|
||||
serverEntryPoints := server.buildEntryPoints(globalConfiguration)
|
||||
redirectHandlers := make(map[string]http.Handler)
|
||||
|
||||
redirectHandlers := make(map[string]negroni.Handler)
|
||||
backends := map[string]http.Handler{}
|
||||
|
||||
backendsHealthcheck := map[string]*healthcheck.BackendHealthCheck{}
|
||||
|
||||
backend2FrontendMap := map[string]string{}
|
||||
|
||||
for _, configuration := range configurations {
|
||||
frontendNames := sortedFrontendNamesForConfig(configuration)
|
||||
frontend:
|
||||
|
@ -595,172 +594,170 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
|
|||
}
|
||||
|
||||
entryPoint := globalConfiguration.EntryPoints[entryPointName]
|
||||
negroni := negroni.New()
|
||||
if entryPoint.Redirect != nil {
|
||||
if redirectHandlers[entryPointName] != nil {
|
||||
newServerRoute.route.Handler(redirectHandlers[entryPointName])
|
||||
negroni.Use(redirectHandlers[entryPointName])
|
||||
} else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil {
|
||||
log.Errorf("Error loading entrypoint configuration for frontend %s: %v", frontendName, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
} else {
|
||||
newServerRoute.route.Handler(handler)
|
||||
negroni.Use(handler)
|
||||
redirectHandlers[entryPointName] = handler
|
||||
}
|
||||
} else {
|
||||
if backends[frontend.Backend] == nil {
|
||||
log.Debugf("Creating backend %s", frontend.Backend)
|
||||
var lb http.Handler
|
||||
rr, _ := roundrobin.New(saveBackend)
|
||||
if configuration.Backends[frontend.Backend] == nil {
|
||||
log.Errorf("Undefined backend '%s' for frontend %s", frontend.Backend, frontendName)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
}
|
||||
if backends[entryPointName+frontend.Backend] == nil {
|
||||
log.Debugf("Creating backend %s", frontend.Backend)
|
||||
var lb http.Handler
|
||||
rr, _ := roundrobin.New(saveBackend)
|
||||
if configuration.Backends[frontend.Backend] == nil {
|
||||
log.Errorf("Undefined backend '%s' for frontend %s", frontend.Backend, frontendName)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
|
||||
lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
|
||||
if err != nil {
|
||||
log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
|
||||
if err != nil {
|
||||
log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
|
||||
stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
|
||||
cookiename := "_TRAEFIK_BACKEND"
|
||||
var sticky *roundrobin.StickySession
|
||||
stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
|
||||
cookiename := "_TRAEFIK_BACKEND"
|
||||
var sticky *roundrobin.StickySession
|
||||
|
||||
if stickysession {
|
||||
sticky = roundrobin.NewStickySession(cookiename)
|
||||
}
|
||||
|
||||
switch lbMethod {
|
||||
case types.Drr:
|
||||
log.Debugf("Creating load-balancer drr")
|
||||
rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
|
||||
if stickysession {
|
||||
sticky = roundrobin.NewStickySession(cookiename)
|
||||
log.Debugf("Sticky session with cookie %v", cookiename)
|
||||
rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
|
||||
}
|
||||
|
||||
switch lbMethod {
|
||||
case types.Drr:
|
||||
log.Debugf("Creating load-balancer drr")
|
||||
rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
|
||||
if stickysession {
|
||||
log.Debugf("Sticky session with cookie %v", cookiename)
|
||||
rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
|
||||
lb = rebalancer
|
||||
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
|
||||
url, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
lb = rebalancer
|
||||
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
|
||||
url, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
backend2FrontendMap[url.String()] = frontendName
|
||||
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
|
||||
if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
|
||||
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
hcOpts := parseHealthCheckOptions(rebalancer, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||
if hcOpts != nil {
|
||||
log.Debugf("Setting up backend health check %s", *hcOpts)
|
||||
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
||||
}
|
||||
backend2FrontendMap[url.String()] = frontendName
|
||||
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
|
||||
if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
|
||||
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
case types.Wrr:
|
||||
log.Debugf("Creating load-balancer wrr")
|
||||
if stickysession {
|
||||
log.Debugf("Sticky session with cookie %v", cookiename)
|
||||
rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
|
||||
}
|
||||
lb = rr
|
||||
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
|
||||
url, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
backend2FrontendMap[url.String()] = frontendName
|
||||
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
|
||||
if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
|
||||
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
}
|
||||
hcOpts := parseHealthCheckOptions(rr, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||
hcOpts := parseHealthCheckOptions(rebalancer, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||
if hcOpts != nil {
|
||||
log.Debugf("Setting up backend health check %s", *hcOpts)
|
||||
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
||||
}
|
||||
}
|
||||
maxConns := configuration.Backends[frontend.Backend].MaxConn
|
||||
if maxConns != nil && maxConns.Amount != 0 {
|
||||
extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
|
||||
case types.Wrr:
|
||||
log.Debugf("Creating load-balancer wrr")
|
||||
if stickysession {
|
||||
log.Debugf("Sticky session with cookie %v", cookiename)
|
||||
rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
|
||||
}
|
||||
lb = rr
|
||||
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
|
||||
url, err := url.Parse(server.URL)
|
||||
if err != nil {
|
||||
log.Errorf("Error creating connlimit: %v", err)
|
||||
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
log.Debugf("Creating load-balancer connlimit")
|
||||
lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
|
||||
if err != nil {
|
||||
log.Errorf("Error creating connlimit: %v", err)
|
||||
backend2FrontendMap[url.String()] = frontendName
|
||||
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
|
||||
if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
|
||||
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
}
|
||||
// retry ?
|
||||
if globalConfiguration.Retry != nil {
|
||||
retries := len(configuration.Backends[frontend.Backend].Servers)
|
||||
if globalConfiguration.Retry.Attempts > 0 {
|
||||
retries = globalConfiguration.Retry.Attempts
|
||||
}
|
||||
lb = middlewares.NewRetry(retries, lb)
|
||||
log.Debugf("Creating retries max attempts %d", retries)
|
||||
hcOpts := parseHealthCheckOptions(rr, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||
if hcOpts != nil {
|
||||
log.Debugf("Setting up backend health check %s", *hcOpts)
|
||||
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
||||
}
|
||||
}
|
||||
maxConns := configuration.Backends[frontend.Backend].MaxConn
|
||||
if maxConns != nil && maxConns.Amount != 0 {
|
||||
extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
|
||||
if err != nil {
|
||||
log.Errorf("Error creating connlimit: %v", err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
log.Debugf("Creating load-balancer connlimit")
|
||||
lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
|
||||
if err != nil {
|
||||
log.Errorf("Error creating connlimit: %v", err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
}
|
||||
// retry ?
|
||||
if globalConfiguration.Retry != nil {
|
||||
retries := len(configuration.Backends[frontend.Backend].Servers)
|
||||
if globalConfiguration.Retry.Attempts > 0 {
|
||||
retries = globalConfiguration.Retry.Attempts
|
||||
}
|
||||
lb = middlewares.NewRetry(retries, lb)
|
||||
log.Debugf("Creating retries max attempts %d", retries)
|
||||
}
|
||||
|
||||
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
|
||||
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
|
||||
metricsMiddlewareBackend := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(frontend.Backend, server.globalConfiguration.Web.Metrics.Prometheus))
|
||||
negroni.Use(metricsMiddlewareBackend)
|
||||
}
|
||||
}
|
||||
if len(frontend.BasicAuth) > 0 {
|
||||
users := types.Users{}
|
||||
for _, user := range frontend.BasicAuth {
|
||||
users = append(users, user)
|
||||
}
|
||||
|
||||
var negroni = negroni.New()
|
||||
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
|
||||
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
|
||||
metricsMiddlewareBackend := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(frontend.Backend, server.globalConfiguration.Web.Metrics.Prometheus))
|
||||
negroni.Use(metricsMiddlewareBackend)
|
||||
}
|
||||
auth := &types.Auth{}
|
||||
auth.Basic = &types.Basic{
|
||||
Users: users,
|
||||
}
|
||||
|
||||
if len(frontend.BasicAuth) > 0 {
|
||||
users := types.Users{}
|
||||
for _, user := range frontend.BasicAuth {
|
||||
users = append(users, user)
|
||||
}
|
||||
|
||||
auth := &types.Auth{}
|
||||
auth.Basic = &types.Basic{
|
||||
Users: users,
|
||||
}
|
||||
authMiddleware, err := middlewares.NewAuthenticator(auth)
|
||||
if err != nil {
|
||||
log.Fatal("Error creating Auth: ", err)
|
||||
}
|
||||
negroni.Use(authMiddleware)
|
||||
authMiddleware, err := middlewares.NewAuthenticator(auth)
|
||||
if err != nil {
|
||||
log.Fatal("Error creating Auth: ", err)
|
||||
}
|
||||
|
||||
if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
|
||||
log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
|
||||
cbreaker, err := middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger))
|
||||
if err != nil {
|
||||
log.Errorf("Error creating circuit breaker: %v", err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
negroni.Use(cbreaker)
|
||||
} else {
|
||||
negroni.UseHandler(lb)
|
||||
negroni.Use(authMiddleware)
|
||||
}
|
||||
if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
|
||||
log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
|
||||
cbreaker, err := middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger))
|
||||
if err != nil {
|
||||
log.Errorf("Error creating circuit breaker: %v", err)
|
||||
log.Errorf("Skipping frontend %s...", frontendName)
|
||||
continue frontend
|
||||
}
|
||||
backends[frontend.Backend] = negroni
|
||||
negroni.Use(cbreaker)
|
||||
} else {
|
||||
log.Debugf("Reusing backend %s", frontend.Backend)
|
||||
negroni.UseHandler(lb)
|
||||
}
|
||||
if frontend.Priority > 0 {
|
||||
newServerRoute.route.Priority(frontend.Priority)
|
||||
}
|
||||
server.wireFrontendBackend(newServerRoute, backends[frontend.Backend])
|
||||
backends[entryPointName+frontend.Backend] = negroni
|
||||
} else {
|
||||
log.Debugf("Reusing backend %s", frontend.Backend)
|
||||
}
|
||||
if frontend.Priority > 0 {
|
||||
newServerRoute.route.Priority(frontend.Priority)
|
||||
}
|
||||
server.wireFrontendBackend(newServerRoute, backends[entryPointName+frontend.Backend])
|
||||
|
||||
err := newServerRoute.route.GetError()
|
||||
if err != nil {
|
||||
log.Errorf("Error building route: %s", err)
|
||||
|
@ -810,7 +807,7 @@ func (server *Server) wireFrontendBackend(serverRoute *serverRoute, handler http
|
|||
serverRoute.route.Handler(handler)
|
||||
}
|
||||
|
||||
func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *EntryPoint) (http.Handler, error) {
|
||||
func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *EntryPoint) (negroni.Handler, error) {
|
||||
regex := entryPoint.Redirect.Regex
|
||||
replacement := entryPoint.Redirect.Replacement
|
||||
if len(entryPoint.Redirect.EntryPoint) > 0 {
|
||||
|
@ -834,9 +831,8 @@ func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *En
|
|||
return nil, err
|
||||
}
|
||||
log.Debugf("Creating entryPoint redirect %s -> %s : %s -> %s", entryPointName, entryPoint.Redirect.EntryPoint, regex, replacement)
|
||||
negroni := negroni.New()
|
||||
negroni.Use(rewrite)
|
||||
return negroni, nil
|
||||
|
||||
return rewrite, nil
|
||||
}
|
||||
|
||||
func (server *Server) buildDefaultHTTPRouter() *mux.Router {
|
||||
|
|
Loading…
Add table
Reference in a new issue