Merge branch 'v1.5' into master
This commit is contained in:
commit
f5adea1061
15 changed files with 196 additions and 35 deletions
|
@ -64,7 +64,7 @@ Once your environment is set up and the Træfik repository cloned you can build
|
||||||
cd ~/go/src/github.com/containous/traefik
|
cd ~/go/src/github.com/containous/traefik
|
||||||
|
|
||||||
# Get go-bindata. Please note, the ellipses are required
|
# Get go-bindata. Please note, the ellipses are required
|
||||||
go get github.com/jteeuwen/go-bindata/...
|
go get github.com/containous/go-bindata/...
|
||||||
|
|
||||||
# Start build
|
# Start build
|
||||||
|
|
||||||
|
|
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
@ -1492,6 +1492,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "daede4415dbd8614087d38fc4d8cba45d679bbb7185bfca805091ef7b295341f"
|
inputs-digest = "f87576548de74d86b0e93a28551b97317addba5731345338272fdbb8a22ad77f"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -295,6 +295,7 @@ func (a *ACME) leadershipListener(elected bool) error {
|
||||||
|
|
||||||
// CreateLocalConfig creates a tls.config using local ACME configuration
|
// CreateLocalConfig creates a tls.config using local ACME configuration
|
||||||
func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, certs *safe.Safe, checkOnDemandDomain func(domain string) bool) error {
|
func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, certs *safe.Safe, checkOnDemandDomain func(domain string) bool) error {
|
||||||
|
defer a.runJobs()
|
||||||
err := a.init()
|
err := a.init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -333,7 +334,9 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, certs *safe.Safe, checkO
|
||||||
|
|
||||||
a.client, err = a.buildACMEClient(account)
|
a.client, err = a.buildACMEClient(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
log.Errorf(`Failed to build ACME client: %s
|
||||||
|
Let's Encrypt functionality will be limited until traefik is restarted.`, err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if needRegister {
|
if needRegister {
|
||||||
|
@ -374,7 +377,6 @@ func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, certs *safe.Safe, checkO
|
||||||
|
|
||||||
a.retrieveCertificates()
|
a.retrieveCertificates()
|
||||||
a.renewCertificates()
|
a.renewCertificates()
|
||||||
a.runJobs()
|
|
||||||
|
|
||||||
ticker := time.NewTicker(24 * time.Hour)
|
ticker := time.NewTicker(24 * time.Hour)
|
||||||
safe.Go(func() {
|
safe.Go(func() {
|
||||||
|
|
|
@ -4,7 +4,7 @@ RUN apk --update upgrade \
|
||||||
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
|
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
RUN go get github.com/jteeuwen/go-bindata/... \
|
RUN go get github.com/containous/go-bindata/... \
|
||||||
&& go get github.com/golang/lint/golint \
|
&& go get github.com/golang/lint/golint \
|
||||||
&& go get github.com/kisielk/errcheck \
|
&& go get github.com/kisielk/errcheck \
|
||||||
&& go get github.com/client9/misspell/cmd/misspell
|
&& go get github.com/client9/misspell/cmd/misspell
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/containous/traefik/version"
|
"github.com/containous/traefik/version"
|
||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
|
"github.com/ogier/pflag"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,6 +76,9 @@ Complete documentation is available at https://traefik.io`,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := f.Parse(usedCmd); err != nil {
|
if _, err := f.Parse(usedCmd); err != nil {
|
||||||
|
if err == pflag.ErrHelp {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
fmtlog.Printf("Error parsing command: %s\n", err)
|
fmtlog.Printf("Error parsing command: %s\n", err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ The following rules are both `Matchers` and `Modifiers`, so the `Matcher` portio
|
||||||
By default, routes will be sorted (in descending order) using rules length (to avoid path overlap):
|
By default, routes will be sorted (in descending order) using rules length (to avoid path overlap):
|
||||||
`PathPrefix:/12345` will be matched before `PathPrefix:/1234` that will be matched before `PathPrefix:/1`.
|
`PathPrefix:/12345` will be matched before `PathPrefix:/1234` that will be matched before `PathPrefix:/1`.
|
||||||
|
|
||||||
You can customize priority by frontend:
|
You can customize priority by frontend. The priority value is added to the rule length during sorting:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[frontends]
|
[frontends]
|
||||||
|
@ -254,7 +254,7 @@ You can customize priority by frontend:
|
||||||
rule = "PathPrefix:/toto"
|
rule = "PathPrefix:/toto"
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, `frontend1` will be matched before `frontend2` (`10 > 5`).
|
Here, `frontend1` will be matched before `frontend2` (`(3 + 10 == 13) > (4 + 5 == 9)`).
|
||||||
|
|
||||||
#### Custom headers
|
#### Custom headers
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,18 @@ entryPoint = "https"
|
||||||
If `HTTP-01` challenge is used, `acme.httpChallenge.entryPoint` has to be defined and reachable by Let's Encrypt through the port 80.
|
If `HTTP-01` challenge is used, `acme.httpChallenge.entryPoint` has to be defined and reachable by Let's Encrypt through the port 80.
|
||||||
These are Let's Encrypt limitations as described on the [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72).
|
These are Let's Encrypt limitations as described on the [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72).
|
||||||
|
|
||||||
|
### Let's Encrypt downtime
|
||||||
|
|
||||||
|
Let's Encrypt functionality will be limited until Træfik is restarted.
|
||||||
|
|
||||||
|
If Let's Encrypt is not reachable, these certificates will be used :
|
||||||
|
- ACME certificates already generated before downtime
|
||||||
|
- Expired ACME certificates
|
||||||
|
- Provided certificates
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Default Træfik certificate will be used instead of ACME certificates for new (sub)domains (which need Let's Encrypt challenge).
|
||||||
|
|
||||||
### `storage`
|
### `storage`
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
|
### TOML
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.http]
|
[entryPoints.http]
|
||||||
|
@ -64,6 +66,37 @@
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
For more information about the CLI, see the documentation about [Traefik command](/basics/#traefik).
|
||||||
|
|
||||||
|
```shell
|
||||||
|
--entryPoints='Name:http Address::80'
|
||||||
|
--entryPoints='Name:https Address::443 TLS'
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Whitespace is used as option separator and `,` is used as value separator for the list.
|
||||||
|
The names of the options are case-insensitive.
|
||||||
|
|
||||||
|
All available options:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
Name:foo
|
||||||
|
Address::80
|
||||||
|
TLS:goo,gii
|
||||||
|
TLS
|
||||||
|
CA:car
|
||||||
|
CA.Optional:true
|
||||||
|
Redirect.EntryPoint:https
|
||||||
|
Redirect.Regex:http://localhost/(.*)
|
||||||
|
Redirect.Replacement:http://mydomain/$1
|
||||||
|
Compress:true
|
||||||
|
WhiteListSourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16
|
||||||
|
ProxyProtocol.TrustedIPs:192.168.0.1
|
||||||
|
ProxyProtocol.Insecure:tue
|
||||||
|
ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24
|
||||||
|
```
|
||||||
|
|
||||||
## Basic
|
## Basic
|
||||||
|
|
||||||
|
@ -118,7 +151,11 @@ To redirect an entrypoint rewriting the URL.
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Please note that `regex` and `replacement` do not have to be set in the `redirect` structure if an entrypoint is defined for the redirection (they will not be used in this case).
|
Please note that `regex` and `replacement` do not have to be set in the `redirect` structure if an `entrypoint` is defined for the redirection (they will not be used in this case).
|
||||||
|
|
||||||
|
Care should be taken when defining replacement expand variables: `$1x` is equivalent to `${1x}`, not `${1}x` (see [Regexp.Expand](https://golang.org/pkg/regexp/#Regexp.Expand)), so use `${1}` syntax.
|
||||||
|
|
||||||
|
Regular expressions and replacements can be tested using online tools such as [Go Playground](https://play.golang.org/p/mWU9p-wk2ru) or the [Regex101](https://regex101.com/r/58sIgx/2).
|
||||||
|
|
||||||
## TLS
|
## TLS
|
||||||
|
|
||||||
|
|
|
@ -35,14 +35,14 @@ TL;DR:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ traefik \
|
$ traefik \
|
||||||
--entrypoints=Name:http Address::80 Redirect.EntryPoint:https \
|
--entrypoints='Name:http Address::80 Redirect.EntryPoint:https' \
|
||||||
--entrypoints=Name:https Address::443 TLS \
|
--entrypoints='Name:https Address::443 TLS' \
|
||||||
--defaultentrypoints=http,https
|
--defaultentrypoints=http,https
|
||||||
```
|
```
|
||||||
|
|
||||||
To listen to different ports, we need to create an entry point for each.
|
To listen to different ports, we need to create an entry point for each.
|
||||||
|
|
||||||
The CLI syntax is `--entrypoints=Name:a_name Address:an_ip_or_empty:a_port options`.
|
The CLI syntax is `--entrypoints='Name:a_name Address:an_ip_or_empty:a_port options'`.
|
||||||
If you want to redirect traffic from one entry point to another, it's the option `Redirect.EntryPoint:entrypoint_name`.
|
If you want to redirect traffic from one entry point to another, it's the option `Redirect.EntryPoint:entrypoint_name`.
|
||||||
|
|
||||||
By default, we don't want to configure all our services to listen on http and https, we add a default entry point configuration: `--defaultentrypoints=http,https`.
|
By default, we don't want to configure all our services to listen on http and https, we add a default entry point configuration: `--defaultentrypoints=http,https`.
|
||||||
|
@ -94,8 +94,8 @@ services:
|
||||||
image: traefik:1.5
|
image: traefik:1.5
|
||||||
command:
|
command:
|
||||||
- "--api"
|
- "--api"
|
||||||
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
|
- "--entrypoints='Name:http Address::80 Redirect.EntryPoint:https'"
|
||||||
- "--entrypoints=Name:https Address::443 TLS"
|
- "--entrypoints='Name:https Address::443 TLS'"
|
||||||
- "--defaultentrypoints=http,https"
|
- "--defaultentrypoints=http,https"
|
||||||
- "--acme"
|
- "--acme"
|
||||||
- "--acme.storage=/etc/traefik/acme/acme.json"
|
- "--acme.storage=/etc/traefik/acme/acme.json"
|
||||||
|
@ -204,8 +204,8 @@ services:
|
||||||
command:
|
command:
|
||||||
- "storeconfig"
|
- "storeconfig"
|
||||||
- "--api"
|
- "--api"
|
||||||
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
|
- "--entrypoints='Name:http Address::80 Redirect.EntryPoint:https'"
|
||||||
- "--entrypoints=Name:https Address::443 TLS"
|
- "--entrypoints='Name:https Address::443 TLS'"
|
||||||
- "--defaultentrypoints=http,https"
|
- "--defaultentrypoints=http,https"
|
||||||
- "--acme"
|
- "--acme"
|
||||||
- "--acme.storage=traefik/acme/account"
|
- "--acme.storage=traefik/acme/account"
|
||||||
|
|
|
@ -110,7 +110,7 @@ entryPoint = "http"
|
||||||
|
|
||||||
This is the minimum configuration required to do the following:
|
This is the minimum configuration required to do the following:
|
||||||
|
|
||||||
- Log `ERROR`-level messages (or more severe) to the console, but silence `DEBUG`-level messagse
|
- Log `ERROR`-level messages (or more severe) to the console, but silence `DEBUG`-level messages
|
||||||
- Check for new versions of Træfik periodically
|
- Check for new versions of Træfik periodically
|
||||||
- Create two entry points, namely an `HTTP` endpoint on port `80`, and an `HTTPS` endpoint on port `443` where all incoming traffic on port `80` will immediately get redirected to `HTTPS`.
|
- Create two entry points, namely an `HTTP` endpoint on port `80`, and an `HTTPS` endpoint on port `443` where all incoming traffic on port `80` will immediately get redirected to `HTTPS`.
|
||||||
- Enable the Docker configuration backend and listen for container events on the Docker unix socket we've mounted earlier. However, **new containers will not be exposed by Træfik by default, we'll get into this in a bit!**
|
- Enable the Docker configuration backend and listen for container events on the Docker unix socket we've mounted earlier. However, **new containers will not be exposed by Træfik by default, we'll get into this in a bit!**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Key-value store configuration
|
# Key-value store configuration
|
||||||
|
|
||||||
Both [static global configuration](/user-guide/kv-config/#static-configuration-in-key-value-store) and [dynamic](/user-guide/kv-config/#dynamic-configuration-in-key-value-store) configuration can be sorted in a Key-value store.
|
Both [static global configuration](/user-guide/kv-config/#static-configuration-in-key-value-store) and [dynamic](/user-guide/kv-config/#dynamic-configuration-in-key-value-store) configuration can be stored in a Key-value store.
|
||||||
|
|
||||||
This section explains how to launch Træfik using a configuration loaded from a Key-value store.
|
This section explains how to launch Træfik using a configuration loaded from a Key-value store.
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,19 @@ func (s *AcmeSuite) TestOnHostRuleRetrieveAcmeCertificateWithDynamicWildcard(c *
|
||||||
s.retrieveAcmeCertificate(c, testCase)
|
s.retrieveAcmeCertificate(c, testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test Let's encrypt down
|
||||||
|
func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile("fixtures/acme/wrong_acme.toml"))
|
||||||
|
defer display(c)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
// Expected traefik works
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/providers", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
// Doing an HTTPS request and test the response certificate
|
// Doing an HTTPS request and test the response certificate
|
||||||
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase AcmeTestCase) {
|
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase AcmeTestCase) {
|
||||||
file := s.adaptFile(c, testCase.traefikConfFilePath, struct {
|
file := s.adaptFile(c, testCase.traefikConfFilePath, struct {
|
||||||
|
|
34
integration/fixtures/acme/wrong_acme.toml
Normal file
34
integration/fixtures/acme/wrong_acme.toml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
logLevel = "DEBUG"
|
||||||
|
|
||||||
|
defaultEntryPoints = ["http", "https"]
|
||||||
|
|
||||||
|
[api]
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":8081"
|
||||||
|
[entryPoints.https]
|
||||||
|
address = ":5001"
|
||||||
|
[entryPoints.https.tls]
|
||||||
|
|
||||||
|
|
||||||
|
[acme]
|
||||||
|
email = "test@traefik.io"
|
||||||
|
storage = "/dev/null"
|
||||||
|
entryPoint = "https"
|
||||||
|
OnHostRule = true
|
||||||
|
caServer = "http://wrongurl:4000/directory"
|
||||||
|
|
||||||
|
[file]
|
||||||
|
|
||||||
|
[backends]
|
||||||
|
[backends.backend]
|
||||||
|
[backends.backend.servers.server1]
|
||||||
|
url = "http://127.0.0.1:9010"
|
||||||
|
|
||||||
|
|
||||||
|
[frontends]
|
||||||
|
[frontends.frontend]
|
||||||
|
backend = "backend"
|
||||||
|
[frontends.frontend.routes.test]
|
||||||
|
rule = "Host:traefik.acme.wtf"
|
|
@ -352,20 +352,18 @@ func listServices(ctx context.Context, dockerClient client.APIClient) ([]dockerD
|
||||||
|
|
||||||
for _, service := range serviceList {
|
for _, service := range serviceList {
|
||||||
dData := parseService(service, networkMap)
|
dData := parseService(service, networkMap)
|
||||||
if len(dData.NetworkSettings.Networks) > 0 {
|
|
||||||
useSwarmLB := isBackendLBSwarm(dData)
|
|
||||||
|
|
||||||
if useSwarmLB {
|
if isBackendLBSwarm(dData) {
|
||||||
|
if len(dData.NetworkSettings.Networks) > 0 {
|
||||||
dockerDataList = append(dockerDataList, dData)
|
dockerDataList = append(dockerDataList, dData)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isGlobalSvc := service.Spec.Mode.Global != nil
|
||||||
|
dockerDataListTasks, err = listTasks(ctx, dockerClient, service.ID, dData, networkMap, isGlobalSvc)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
} else {
|
} else {
|
||||||
isGlobalSvc := service.Spec.Mode.Global != nil
|
dockerDataList = append(dockerDataList, dockerDataListTasks...)
|
||||||
|
|
||||||
dockerDataListTasks, err = listTasks(ctx, dockerClient, service.ID, dData, networkMap, isGlobalSvc)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn(err)
|
|
||||||
} else {
|
|
||||||
dockerDataList = append(dockerDataList, dockerDataListTasks...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,10 +379,11 @@ func parseService(service swarmtypes.Service, networkMap map[string]*dockertypes
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.Spec.EndpointSpec != nil {
|
if service.Spec.EndpointSpec != nil {
|
||||||
switch service.Spec.EndpointSpec.Mode {
|
if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeDNSRR {
|
||||||
case swarmtypes.ResolutionModeDNSRR:
|
if isBackendLBSwarm(dData) {
|
||||||
log.Warnf("Ignored endpoint-mode not supported, service name: %s", service.Spec.Annotations.Name)
|
log.Warnf("Ignored %s endpoint-mode not supported, service name: %s. Fallback to Træfik load balancing", swarmtypes.ResolutionModeDNSRR, service.Spec.Annotations.Name)
|
||||||
case swarmtypes.ResolutionModeVIP:
|
}
|
||||||
|
} else if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeVIP {
|
||||||
dData.NetworkSettings.Networks = make(map[string]*networkData)
|
dData.NetworkSettings.Networks = make(map[string]*networkData)
|
||||||
for _, virtualIP := range service.Endpoint.VirtualIPs {
|
for _, virtualIP := range service.Endpoint.VirtualIPs {
|
||||||
networkService := networkMap[virtualIP.NetworkID]
|
networkService := networkMap[virtualIP.NetworkID]
|
||||||
|
|
|
@ -80,6 +80,7 @@ type fakeServicesClient struct {
|
||||||
dockerVersion string
|
dockerVersion string
|
||||||
networks []dockertypes.NetworkResource
|
networks []dockertypes.NetworkResource
|
||||||
services []swarm.Service
|
services []swarm.Service
|
||||||
|
tasks []swarm.Task
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +96,15 @@ func (c *fakeServicesClient) NetworkList(ctx context.Context, options dockertype
|
||||||
return c.networks, c.err
|
return c.networks, c.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fakeServicesClient) TaskList(ctx context.Context, options dockertypes.TaskListOptions) ([]swarm.Task, error) {
|
||||||
|
return c.tasks, c.err
|
||||||
|
}
|
||||||
|
|
||||||
func TestListServices(t *testing.T) {
|
func TestListServices(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
services []swarm.Service
|
services []swarm.Service
|
||||||
|
tasks []swarm.Task
|
||||||
dockerVersion string
|
dockerVersion string
|
||||||
networks []dockertypes.NetworkResource
|
networks []dockertypes.NetworkResource
|
||||||
expectedServices []string
|
expectedServices []string
|
||||||
|
@ -120,7 +126,8 @@ func TestListServices(t *testing.T) {
|
||||||
swarmService(
|
swarmService(
|
||||||
serviceName("service2"),
|
serviceName("service2"),
|
||||||
serviceLabels(map[string]string{
|
serviceLabels(map[string]string{
|
||||||
labelDockerNetwork: "barnet",
|
labelDockerNetwork: "barnet",
|
||||||
|
labelBackendLoadBalancerSwarm: "true",
|
||||||
}),
|
}),
|
||||||
withEndpointSpec(modeDNSSR)),
|
withEndpointSpec(modeDNSSR)),
|
||||||
},
|
},
|
||||||
|
@ -145,7 +152,8 @@ func TestListServices(t *testing.T) {
|
||||||
swarmService(
|
swarmService(
|
||||||
serviceName("service2"),
|
serviceName("service2"),
|
||||||
serviceLabels(map[string]string{
|
serviceLabels(map[string]string{
|
||||||
labelDockerNetwork: "barnet",
|
labelDockerNetwork: "barnet",
|
||||||
|
labelBackendLoadBalancerSwarm: "true",
|
||||||
}),
|
}),
|
||||||
withEndpointSpec(modeDNSSR)),
|
withEndpointSpec(modeDNSSR)),
|
||||||
},
|
},
|
||||||
|
@ -174,13 +182,65 @@ func TestListServices(t *testing.T) {
|
||||||
"service1",
|
"service1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Should return service1 and service2",
|
||||||
|
services: []swarm.Service{
|
||||||
|
swarmService(
|
||||||
|
serviceName("service1"),
|
||||||
|
serviceLabels(map[string]string{
|
||||||
|
labelDockerNetwork: "barnet",
|
||||||
|
}),
|
||||||
|
withEndpointSpec(modeVIP),
|
||||||
|
withEndpoint(
|
||||||
|
virtualIP("yk6l57rfwizjzxxzftn4amaot", "10.11.12.13/24"),
|
||||||
|
virtualIP("2", "10.11.12.99/24"),
|
||||||
|
)),
|
||||||
|
swarmService(
|
||||||
|
serviceName("service2"),
|
||||||
|
serviceLabels(map[string]string{
|
||||||
|
labelDockerNetwork: "barnet",
|
||||||
|
}),
|
||||||
|
withEndpointSpec(modeDNSSR)),
|
||||||
|
},
|
||||||
|
tasks: []swarm.Task{
|
||||||
|
swarmTask("id1", taskStatus(taskState(swarm.TaskStateRunning))),
|
||||||
|
swarmTask("id2", taskStatus(taskState(swarm.TaskStateRunning))),
|
||||||
|
},
|
||||||
|
dockerVersion: "1.30",
|
||||||
|
networks: []dockertypes.NetworkResource{
|
||||||
|
{
|
||||||
|
Name: "network_name",
|
||||||
|
ID: "yk6l57rfwizjzxxzftn4amaot",
|
||||||
|
Created: time.Now(),
|
||||||
|
Scope: "swarm",
|
||||||
|
Driver: "overlay",
|
||||||
|
EnableIPv6: false,
|
||||||
|
Internal: true,
|
||||||
|
Ingress: false,
|
||||||
|
ConfigOnly: false,
|
||||||
|
Options: map[string]string{
|
||||||
|
"com.docker.network.driver.overlay.vxlanid_list": "4098",
|
||||||
|
"com.docker.network.enable_ipv6": "false",
|
||||||
|
},
|
||||||
|
Labels: map[string]string{
|
||||||
|
"com.docker.stack.namespace": "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedServices: []string{
|
||||||
|
"service1.0",
|
||||||
|
"service1.0",
|
||||||
|
"service2.0",
|
||||||
|
"service2.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for caseID, test := range testCases {
|
for caseID, test := range testCases {
|
||||||
test := test
|
test := test
|
||||||
t.Run(strconv.Itoa(caseID), func(t *testing.T) {
|
t.Run(strconv.Itoa(caseID), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
dockerClient := &fakeServicesClient{services: test.services, dockerVersion: test.dockerVersion, networks: test.networks}
|
dockerClient := &fakeServicesClient{services: test.services, tasks: test.tasks, dockerVersion: test.dockerVersion, networks: test.networks}
|
||||||
|
|
||||||
serviceDockerData, err := listServices(context.Background(), dockerClient)
|
serviceDockerData, err := listServices(context.Background(), dockerClient)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
Loading…
Reference in a new issue