Merge 'v1.4.2' into master

This commit is contained in:
Fernandez Ludovic 2017-11-03 13:51:24 +01:00
commit 2070aa9443
16 changed files with 304 additions and 87 deletions

View file

@ -29,11 +29,12 @@ import (
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/docker/go-connections/sockets"
"github.com/pkg/errors"
)
const (
// SwarmAPIVersion is a constant holding the version of the Provider API traefik will use
SwarmAPIVersion string = "1.24"
SwarmAPIVersion = "1.24"
// SwarmDefaultWatchTime is the duration of the interval when polling docker
SwarmDefaultWatchTime = 15 * time.Second
@ -306,8 +307,8 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
frontends := map[string][]dockerData{}
backends := map[string]dockerData{}
servers := map[string][]dockerData{}
for _, container := range filteredContainers {
frontendName := p.getFrontendName(container)
for idx, container := range filteredContainers {
frontendName := p.getFrontendName(container, idx)
frontends[frontendName] = append(frontends[frontendName], container)
backendName := p.getBackend(container)
backends[backendName] = container
@ -522,9 +523,16 @@ func (p *Provider) getMaxConnExtractorFunc(container dockerData) string {
}
func (p *Provider) containerFilter(container dockerData) bool {
_, err := strconv.Atoi(container.Labels[types.LabelPort])
var err error
portLabel := "traefik.port label"
if p.hasServices(container) {
portLabel = "traefik.<serviceName>.port or " + portLabel + "s"
err = checkServiceLabelPort(container)
} else {
_, err = strconv.Atoi(container.Labels[types.LabelPort])
}
if len(container.NetworkSettings.Ports) == 0 && err != nil {
log.Debugf("Filtering container without port and no traefik.port label %s", container.Name)
log.Debugf("Filtering container without port and no %s %s : %s", portLabel, container.Name, err.Error())
return false
}
@ -554,9 +562,46 @@ func (p *Provider) containerFilter(container dockerData) bool {
return true
}
func (p *Provider) getFrontendName(container dockerData) string {
// checkServiceLabelPort checks if all service names have a port service label
// or if port container label exists for default value
func checkServiceLabelPort(container dockerData) error {
// If port container label is present, there is a default values for all ports, use it for the check
_, err := strconv.Atoi(container.Labels[types.LabelPort])
if err != nil {
serviceLabelPorts := make(map[string]struct{})
serviceLabels := make(map[string]struct{})
portRegexp := regexp.MustCompile(`^traefik\.(?P<service_name>.+?)\.port$`)
for label := range container.Labels {
// Get all port service labels
portLabel := portRegexp.FindStringSubmatch(label)
if portLabel != nil && len(portLabel) > 0 {
serviceLabelPorts[portLabel[0]] = struct{}{}
}
// Get only one instance of all service names from service labels
servicesLabelNames := servicesPropertiesRegexp.FindStringSubmatch(label)
if servicesLabelNames != nil && len(servicesLabelNames) > 0 {
serviceLabels[strings.Split(servicesLabelNames[0], ".")[1]] = struct{}{}
}
}
// If the number of service labels is different than the number of port services label
// there is an error
if len(serviceLabels) == len(serviceLabelPorts) {
for labelPort := range serviceLabelPorts {
_, err = strconv.Atoi(container.Labels[labelPort])
if err != nil {
break
}
}
} else {
err = errors.New("Port service labels missing, please use traefik.port as default value or define all port service labels")
}
}
return err
}
func (p *Provider) getFrontendName(container dockerData, idx int) string {
// Replace '.' with '-' in quoted keys because of this issue https://github.com/BurntSushi/toml/issues/78
return provider.Normalize(p.getFrontendRule(container))
return provider.Normalize(p.getFrontendRule(container) + "-" + strconv.Itoa(idx))
}
// GetFrontendRule returns the frontend rule for the specified container, using
@ -597,7 +642,7 @@ func (p *Provider) getIPAddress(container dockerData) string {
}
}
if "host" == container.NetworkSettings.NetworkMode {
if container.NetworkSettings.NetworkMode.IsHost() {
if container.Node != nil {
if container.Node.IPAddress != "" {
return container.Node.IPAddress
@ -607,6 +652,21 @@ func (p *Provider) getIPAddress(container dockerData) string {
return "127.0.0.1"
}
if container.NetworkSettings.NetworkMode.IsContainer() {
dockerClient, err := p.createClient()
if err != nil {
log.Warnf("Unable to get IP address for container %s, error: %s", container.Name, err)
return ""
}
ctx := context.Background()
containerInspected, err := dockerClient.ContainerInspect(ctx, container.NetworkSettings.NetworkMode.ConnectedContainer())
if err != nil {
log.Warnf("Unable to get IP address for container %s : Failed to inspect container ID %s, error: %s", container.Name, container.NetworkSettings.NetworkMode.ConnectedContainer(), err)
return ""
}
return p.getIPAddress(parseContainer(containerInspected))
}
if p.UseBindPortIP {
port := p.getPort(container)
for netport, portBindings := range container.NetworkSettings.Ports {