mirror of
https://github.com/containous/traefik.git
synced 2025-09-05 01:44:24 +03:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f68d5a5765 | ||
|
36c0e63120 | ||
|
76465727d9 | ||
|
41c64ea81b | ||
|
de9eec1c92 | ||
|
482afed4a6 |
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine
|
FROM alpine:3.14
|
||||||
|
|
||||||
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
|
||||||
|
|
||||||
|
78
integration/docker_compose_test.go
Normal file
78
integration/docker_compose_test.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/integration/try"
|
||||||
|
"github.com/containous/traefik/testhelpers"
|
||||||
|
"github.com/containous/traefik/types"
|
||||||
|
"github.com/go-check/check"
|
||||||
|
checker "github.com/vdemeester/shakers"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
composeProject = "minimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Docker test suites
|
||||||
|
type DockerComposeSuite struct {
|
||||||
|
BaseSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerComposeSuite) SetUpSuite(c *check.C) {
|
||||||
|
s.createComposeProject(c, composeProject)
|
||||||
|
s.composeProject.Start(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerComposeSuite) TearDownSuite(c *check.C) {
|
||||||
|
// shutdown and delete compose project
|
||||||
|
if s.composeProject != nil {
|
||||||
|
s.composeProject.Stop(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
||||||
|
var serviceCount = 2
|
||||||
|
var composeService = "whoami1"
|
||||||
|
|
||||||
|
s.composeProject.Scale(c, composeService, serviceCount)
|
||||||
|
|
||||||
|
file := s.adaptFileForHost(c, "fixtures/docker/simple.toml")
|
||||||
|
defer os.Remove(file)
|
||||||
|
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||||
|
defer display(c)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
req := testhelpers.MustNewRequest(http.MethodGet, "http://127.0.0.1:8000/whoami", nil)
|
||||||
|
req.Host = "my.super.host"
|
||||||
|
|
||||||
|
_, err = try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
resp, err := http.Get("http://127.0.0.1:8080/api/providers/docker")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
var provider types.Configuration
|
||||||
|
c.Assert(json.Unmarshal(body, &provider), checker.IsNil)
|
||||||
|
|
||||||
|
// check that we have only one backend with n servers
|
||||||
|
c.Assert(provider.Backends, checker.HasLen, 1)
|
||||||
|
|
||||||
|
myBackend := provider.Backends["backend-"+composeService+"-integrationtest"+composeProject]
|
||||||
|
c.Assert(myBackend, checker.NotNil)
|
||||||
|
c.Assert(myBackend.Servers, checker.HasLen, serviceCount)
|
||||||
|
|
||||||
|
// check that we have only one frontend
|
||||||
|
c.Assert(provider.Frontends, checker.HasLen, 1)
|
||||||
|
}
|
4
integration/resources/compose/minimal.yml
Normal file
4
integration/resources/compose/minimal.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
whoami1:
|
||||||
|
image: emilevauge/whoami
|
||||||
|
labels:
|
||||||
|
- traefik.frontend.rule=PathPrefix:/whoami
|
@@ -16,9 +16,6 @@ theme:
|
|||||||
include_sidebar: true
|
include_sidebar: true
|
||||||
favicon: img/traefik.icon.png
|
favicon: img/traefik.icon.png
|
||||||
logo: img/traefik.logo.png
|
logo: img/traefik.logo.png
|
||||||
palette:
|
|
||||||
primary: 'blue'
|
|
||||||
accent: 'light blue'
|
|
||||||
feature:
|
feature:
|
||||||
tabs: false
|
tabs: false
|
||||||
palette:
|
palette:
|
||||||
|
@@ -369,11 +369,12 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
|
|||||||
servers := map[string][]dockerData{}
|
servers := map[string][]dockerData{}
|
||||||
serviceNames := make(map[string]struct{})
|
serviceNames := make(map[string]struct{})
|
||||||
for idx, container := range filteredContainers {
|
for idx, container := range filteredContainers {
|
||||||
if _, exists := serviceNames[container.ServiceName]; !exists {
|
serviceNameKey := getServiceNameKey(container, p.SwarmMode)
|
||||||
|
if _, exists := serviceNames[serviceNameKey]; !exists {
|
||||||
frontendName := p.getFrontendName(container, idx)
|
frontendName := p.getFrontendName(container, idx)
|
||||||
frontends[frontendName] = append(frontends[frontendName], container)
|
frontends[frontendName] = append(frontends[frontendName], container)
|
||||||
if len(container.ServiceName) > 0 {
|
if len(serviceNameKey) > 0 {
|
||||||
serviceNames[container.ServiceName] = struct{}{}
|
serviceNames[serviceNameKey] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backendName := getBackend(container)
|
backendName := getBackend(container)
|
||||||
@@ -403,6 +404,16 @@ func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Con
|
|||||||
return configuration
|
return configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getServiceNameKey(container dockerData, swarmMode bool) string {
|
||||||
|
serviceNameKey := container.ServiceName
|
||||||
|
|
||||||
|
if len(container.Labels[labelDockerComposeProject]) > 0 && len(container.Labels[labelDockerComposeService]) > 0 && !swarmMode {
|
||||||
|
serviceNameKey = container.Labels[labelDockerComposeService] + container.Labels[labelDockerComposeProject]
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceNameKey
|
||||||
|
}
|
||||||
|
|
||||||
// Regexp used to extract the name of the service and the name of the property for this service
|
// Regexp used to extract the name of the service and the name of the property for this service
|
||||||
// All properties are under the format traefik.<servicename>.frontent.*= except the port/weight/protocol directly after traefik.<servicename>.
|
// All properties are under the format traefik.<servicename>.frontent.*= except the port/weight/protocol directly after traefik.<servicename>.
|
||||||
var servicesPropertiesRegexp = regexp.MustCompile(`^traefik\.(?P<service_name>.+?)\.(?P<property_name>port|weight|protocol|frontend\.(.*))$`)
|
var servicesPropertiesRegexp = regexp.MustCompile(`^traefik\.(?P<service_name>.+?)\.(?P<property_name>port|weight|protocol|frontend\.(.*))$`)
|
||||||
|
@@ -852,6 +852,94 @@ func TestDockerLoadDockerConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
containers: []docker.ContainerJSON{
|
||||||
|
containerJSON(
|
||||||
|
name("test_0"),
|
||||||
|
labels(map[string]string{
|
||||||
|
labelDockerComposeProject: "myProject",
|
||||||
|
labelDockerComposeService: "myService",
|
||||||
|
}),
|
||||||
|
ports(nat.PortMap{
|
||||||
|
"80/tcp": {},
|
||||||
|
}),
|
||||||
|
withNetwork("bridge", ipv4("127.0.0.1")),
|
||||||
|
),
|
||||||
|
containerJSON(
|
||||||
|
name("test_1"),
|
||||||
|
labels(map[string]string{
|
||||||
|
labelDockerComposeProject: "myProject",
|
||||||
|
labelDockerComposeService: "myService",
|
||||||
|
}),
|
||||||
|
|
||||||
|
ports(nat.PortMap{
|
||||||
|
"80/tcp": {},
|
||||||
|
}),
|
||||||
|
|
||||||
|
withNetwork("bridge", ipv4("127.0.0.2")),
|
||||||
|
),
|
||||||
|
containerJSON(
|
||||||
|
name("test_2"),
|
||||||
|
labels(map[string]string{
|
||||||
|
labelDockerComposeProject: "myProject",
|
||||||
|
labelDockerComposeService: "myService2",
|
||||||
|
}),
|
||||||
|
|
||||||
|
ports(nat.PortMap{
|
||||||
|
"80/tcp": {},
|
||||||
|
}),
|
||||||
|
|
||||||
|
withNetwork("bridge", ipv4("127.0.0.3")),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expectedFrontends: map[string]*types.Frontend{
|
||||||
|
"frontend-Host-myService-myProject-docker-localhost-0": {
|
||||||
|
Backend: "backend-myService-myProject",
|
||||||
|
PassHostHeader: true,
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{},
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-frontend-Host-myService-myProject-docker-localhost-0": {
|
||||||
|
Rule: "Host:myService.myProject.docker.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"frontend-Host-myService2-myProject-docker-localhost-2": {
|
||||||
|
Backend: "backend-myService2-myProject",
|
||||||
|
PassHostHeader: true,
|
||||||
|
EntryPoints: []string{},
|
||||||
|
BasicAuth: []string{},
|
||||||
|
Routes: map[string]types.Route{
|
||||||
|
"route-frontend-Host-myService2-myProject-docker-localhost-2": {
|
||||||
|
Rule: "Host:myService2.myProject.docker.localhost",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedBackends: map[string]*types.Backend{
|
||||||
|
"backend-myService2-myProject": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"server-test_2": {
|
||||||
|
URL: "http://127.0.0.3:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CircuitBreaker: nil,
|
||||||
|
},
|
||||||
|
"backend-myService-myProject": {
|
||||||
|
Servers: map[string]types.Server{
|
||||||
|
"server-test_0": {
|
||||||
|
URL: "http://127.0.0.1:80",
|
||||||
|
Weight: 0,
|
||||||
|
}, "server-test_1": {
|
||||||
|
URL: "http://127.0.0.2:80",
|
||||||
|
Weight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
CircuitBreaker: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for caseID, test := range testCases {
|
for caseID, test := range testCases {
|
||||||
|
@@ -1,4 +1,39 @@
|
|||||||
mkdocs>=0.17.3
|
mkdocs==0.17.5
|
||||||
pymdown-extensions>=1.4
|
pymdown-extensions==4.12
|
||||||
mkdocs-bootswatch>=0.4.0
|
mkdocs-bootswatch==0.5.0
|
||||||
mkdocs-material>=2.2.6
|
mkdocs-material==2.9.4
|
||||||
|
|
||||||
|
appdirs==1.4.4
|
||||||
|
CacheControl==0.12.6
|
||||||
|
certifi==2020.12.5
|
||||||
|
chardet==4.0.0
|
||||||
|
click==8.1.3
|
||||||
|
colorama==0.4.4
|
||||||
|
contextlib2==0.6.0
|
||||||
|
distlib==0.3.1
|
||||||
|
distro==1.5.0
|
||||||
|
html5lib==1.1
|
||||||
|
idna==3.2
|
||||||
|
importlib-metadata==4.12.0
|
||||||
|
Jinja2==3.1.2
|
||||||
|
livereload==2.6.3
|
||||||
|
lockfile==0.12.2
|
||||||
|
Markdown==3.3.7
|
||||||
|
MarkupSafe==2.1.1
|
||||||
|
msgpack==1.0.2
|
||||||
|
ordered-set==4.0.2
|
||||||
|
packaging==20.9
|
||||||
|
pep517==0.10.0
|
||||||
|
progress==1.5
|
||||||
|
Pygments==2.12.0
|
||||||
|
pymdown-extensions==4.12
|
||||||
|
pyparsing==2.4.7
|
||||||
|
PyYAML==6.0.1
|
||||||
|
requests==2.25.1
|
||||||
|
retrying==1.3.3
|
||||||
|
six==1.15.0
|
||||||
|
toml==0.10.2
|
||||||
|
tornado==4.5.3
|
||||||
|
urllib3==1.26.5
|
||||||
|
webencodings==0.5.1
|
||||||
|
zipp==3.8.1
|
||||||
|
Reference in New Issue
Block a user