Add KV store providers (dynamic configuration only)
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
This commit is contained in:
parent
028683666d
commit
9b9f4be6a4
61 changed files with 5825 additions and 70 deletions
159
integration/consul_test.go
Normal file
159
integration/consul_test.go
Normal file
|
@ -0,0 +1,159 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie"
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/consul"
|
||||
"github.com/containous/traefik/v2/integration/try"
|
||||
"github.com/containous/traefik/v2/pkg/api"
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Consul test suites (using libcompose)
|
||||
type ConsulSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "consul")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
consul.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.CONSUL,
|
||||
[]string{s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store consul")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for consul
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := "http://" + s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + ":8500"
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{address})
|
||||
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()
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("@consul"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-consul.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = ioutil.WriteFile(expectedJSON, got, 0666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
159
integration/etcd_test.go
Normal file
159
integration/etcd_test.go
Normal file
|
@ -0,0 +1,159 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie"
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
|
||||
"github.com/containous/traefik/v2/integration/try"
|
||||
"github.com/containous/traefik/v2/pkg/api"
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// etcd test suites (using libcompose)
|
||||
type EtcdSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "etcd")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
etcdv3.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.ETCDV3,
|
||||
[]string{s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store etcd")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for etcd
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + ":2379"
|
||||
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{address})
|
||||
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()
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("@etcd"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-etcd.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = ioutil.WriteFile(expectedJSON, got, 0666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
16
integration/fixtures/consul/simple.toml
Normal file
16
integration/fixtures/consul/simple.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.consul]
|
||||
rootKey = "traefik"
|
||||
endpoints = ["{{ .ConsulAddress }}"]
|
16
integration/fixtures/etcd/simple.toml
Normal file
16
integration/fixtures/etcd/simple.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.etcd]
|
||||
rootKey = "traefik"
|
||||
endpoints = ["{{ .EtcdAddress }}"]
|
16
integration/fixtures/redis/simple.toml
Normal file
16
integration/fixtures/redis/simple.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.redis]
|
||||
rootKey = "traefik"
|
||||
endpoints = ["{{ .RedisAddress }}"]
|
16
integration/fixtures/zookeeper/simple.toml
Normal file
16
integration/fixtures/zookeeper/simple.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.zookeeper]
|
||||
rootKey = "traefik"
|
||||
endpoints = ["{{ .ZkAddress }}"]
|
|
@ -36,6 +36,8 @@ func Test(t *testing.T) {
|
|||
// tests launched from a container
|
||||
check.Suite(&AccessLogSuite{})
|
||||
check.Suite(&AcmeSuite{})
|
||||
check.Suite(&EtcdSuite{})
|
||||
check.Suite(&ConsulSuite{})
|
||||
check.Suite(&ConsulCatalogSuite{})
|
||||
check.Suite(&DockerComposeSuite{})
|
||||
check.Suite(&DockerSuite{})
|
||||
|
@ -51,6 +53,7 @@ func Test(t *testing.T) {
|
|||
check.Suite(&MarathonSuite{})
|
||||
check.Suite(&MarathonSuite15{})
|
||||
check.Suite(&RateLimitSuite{})
|
||||
check.Suite(&RedisSuite{})
|
||||
check.Suite(&RestSuite{})
|
||||
check.Suite(&RetrySuite{})
|
||||
check.Suite(&SimpleSuite{})
|
||||
|
@ -58,6 +61,7 @@ func Test(t *testing.T) {
|
|||
check.Suite(&TLSClientHeadersSuite{})
|
||||
check.Suite(&TracingSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&ZookeeperSuite{})
|
||||
}
|
||||
if *host {
|
||||
// tests launched from the host
|
||||
|
|
159
integration/redis_test.go
Normal file
159
integration/redis_test.go
Normal file
|
@ -0,0 +1,159 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie"
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/redis"
|
||||
"github.com/containous/traefik/v2/integration/try"
|
||||
"github.com/containous/traefik/v2/pkg/api"
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Redis test suites (using libcompose)
|
||||
type RedisSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "redis")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
redis.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.REDIS,
|
||||
[]string{s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store redis")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := s.composeProject.Container(c, "redis").NetworkSettings.IPAddress + ":6379"
|
||||
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{address})
|
||||
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()
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("@redis"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = ioutil.WriteFile(expectedJSON, got, 0666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
4
integration/resources/compose/consul.yml
Normal file
4
integration/resources/compose/consul.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
consul:
|
||||
image: consul:1.6
|
||||
ports:
|
||||
- "8500:8500"
|
5
integration/resources/compose/etcd.yml
Normal file
5
integration/resources/compose/etcd.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
etcd:
|
||||
image: quay.io/coreos/etcd:v3.3.18
|
||||
command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2380
|
||||
ports:
|
||||
- "2379:2379"
|
4
integration/resources/compose/redis.yml
Normal file
4
integration/resources/compose/redis.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
redis:
|
||||
image: redis:5.0
|
||||
ports:
|
||||
- "6379:6379"
|
4
integration/resources/compose/zookeeper.yml
Normal file
4
integration/resources/compose/zookeeper.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
zookeeper:
|
||||
image: zookeeper:3.5
|
||||
ports:
|
||||
- "2181:2181"
|
219
integration/testdata/rawdata-consul.json
vendored
Normal file
219
integration/testdata/rawdata-consul.json
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"routers": {
|
||||
"Router0@consul": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"compressor@consul",
|
||||
"striper@consul"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv1.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"Router1@consul": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv2.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {
|
||||
"domains": [
|
||||
{
|
||||
"main": "aaa.localhost",
|
||||
"sans": [
|
||||
"aaa.aaa.localhost",
|
||||
"bbb.aaa.localhost"
|
||||
]
|
||||
},
|
||||
{
|
||||
"main": "bbb.localhost",
|
||||
"sans": [
|
||||
"aaa.bbb.localhost",
|
||||
"bbb.bbb.localhost"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"api@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 2147483646,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 2147483645,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"compressor@consul": {
|
||||
"compress": {},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@consul"
|
||||
]
|
||||
},
|
||||
"dashboard_redirect@internal": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"dashboard_stripprefix@internal": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"striper@consul": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"forceSlash": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@consul"
|
||||
]
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"Service03@consul": {
|
||||
"weighted": {
|
||||
"services": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"weight": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"weight": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"api@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"api@internal"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"mirror@consul": {
|
||||
"mirroring": {
|
||||
"service": "simplesvc",
|
||||
"mirrors": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"percent": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"percent": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@consul": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.1:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.1:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@consul",
|
||||
"Router1@consul"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.0.1.1:8888": "UP",
|
||||
"http://10.0.1.1:8889": "UP"
|
||||
}
|
||||
},
|
||||
"srvcA@consul": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.2:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.2:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"srvcB@consul": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.3:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.3:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
219
integration/testdata/rawdata-etcd.json
vendored
Normal file
219
integration/testdata/rawdata-etcd.json
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"routers": {
|
||||
"Router0@etcd": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"compressor@etcd",
|
||||
"striper@etcd"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv1.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"Router1@etcd": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv2.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {
|
||||
"domains": [
|
||||
{
|
||||
"main": "aaa.localhost",
|
||||
"sans": [
|
||||
"aaa.aaa.localhost",
|
||||
"bbb.aaa.localhost"
|
||||
]
|
||||
},
|
||||
{
|
||||
"main": "bbb.localhost",
|
||||
"sans": [
|
||||
"aaa.bbb.localhost",
|
||||
"bbb.bbb.localhost"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"api@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 2147483646,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 2147483645,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"compressor@etcd": {
|
||||
"compress": {},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@etcd"
|
||||
]
|
||||
},
|
||||
"dashboard_redirect@internal": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"dashboard_stripprefix@internal": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"striper@etcd": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"forceSlash": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@etcd"
|
||||
]
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"Service03@etcd": {
|
||||
"weighted": {
|
||||
"services": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"weight": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"weight": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"api@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"api@internal"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"mirror@etcd": {
|
||||
"mirroring": {
|
||||
"service": "simplesvc",
|
||||
"mirrors": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"percent": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"percent": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@etcd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.1:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.1:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@etcd",
|
||||
"Router1@etcd"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.0.1.1:8888": "UP",
|
||||
"http://10.0.1.1:8889": "UP"
|
||||
}
|
||||
},
|
||||
"srvcA@etcd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.2:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.2:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"srvcB@etcd": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.3:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.3:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
219
integration/testdata/rawdata-redis.json
vendored
Normal file
219
integration/testdata/rawdata-redis.json
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"routers": {
|
||||
"Router0@redis": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"compressor@redis",
|
||||
"striper@redis"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv1.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"Router1@redis": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv2.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {
|
||||
"domains": [
|
||||
{
|
||||
"main": "aaa.localhost",
|
||||
"sans": [
|
||||
"aaa.aaa.localhost",
|
||||
"bbb.aaa.localhost"
|
||||
]
|
||||
},
|
||||
{
|
||||
"main": "bbb.localhost",
|
||||
"sans": [
|
||||
"aaa.bbb.localhost",
|
||||
"bbb.bbb.localhost"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"api@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 2147483646,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 2147483645,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"compressor@redis": {
|
||||
"compress": {},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@redis"
|
||||
]
|
||||
},
|
||||
"dashboard_redirect@internal": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"dashboard_stripprefix@internal": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"striper@redis": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"forceSlash": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@redis"
|
||||
]
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"Service03@redis": {
|
||||
"weighted": {
|
||||
"services": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"weight": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"weight": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"api@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"api@internal"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"mirror@redis": {
|
||||
"mirroring": {
|
||||
"service": "simplesvc",
|
||||
"mirrors": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"percent": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"percent": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@redis": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.1:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.1:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@redis",
|
||||
"Router1@redis"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.0.1.1:8888": "UP",
|
||||
"http://10.0.1.1:8889": "UP"
|
||||
}
|
||||
},
|
||||
"srvcA@redis": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.2:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.2:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"srvcB@redis": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.3:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.3:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
219
integration/testdata/rawdata-zk.json
vendored
Normal file
219
integration/testdata/rawdata-zk.json
vendored
Normal file
|
@ -0,0 +1,219 @@
|
|||
{
|
||||
"routers": {
|
||||
"Router0@zookeeper": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"compressor@zookeeper",
|
||||
"striper@zookeeper"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv1.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"Router1@zookeeper": {
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"service": "simplesvc",
|
||||
"rule": "Host(`kv2.localhost`)",
|
||||
"priority": 42,
|
||||
"tls": {
|
||||
"domains": [
|
||||
{
|
||||
"main": "aaa.localhost",
|
||||
"sans": [
|
||||
"aaa.aaa.localhost",
|
||||
"bbb.aaa.localhost"
|
||||
]
|
||||
},
|
||||
{
|
||||
"main": "bbb.localhost",
|
||||
"sans": [
|
||||
"aaa.bbb.localhost",
|
||||
"bbb.bbb.localhost"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
"api@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 2147483646,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 2147483645,
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"traefik"
|
||||
]
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"compressor@zookeeper": {
|
||||
"compress": {},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@zookeeper"
|
||||
]
|
||||
},
|
||||
"dashboard_redirect@internal": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"dashboard_stripprefix@internal": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"striper@zookeeper": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"forceSlash": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@zookeeper"
|
||||
]
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"Service03@zookeeper": {
|
||||
"weighted": {
|
||||
"services": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"weight": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"weight": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"api@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"api@internal"
|
||||
]
|
||||
},
|
||||
"dashboard@internal": {
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"dashboard@internal"
|
||||
]
|
||||
},
|
||||
"mirror@zookeeper": {
|
||||
"mirroring": {
|
||||
"service": "simplesvc",
|
||||
"mirrors": [
|
||||
{
|
||||
"name": "srvcA",
|
||||
"percent": 42
|
||||
},
|
||||
{
|
||||
"name": "srvcB",
|
||||
"percent": 42
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"simplesvc@zookeeper": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.1:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.1:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled",
|
||||
"usedBy": [
|
||||
"Router0@zookeeper",
|
||||
"Router1@zookeeper"
|
||||
],
|
||||
"serverStatus": {
|
||||
"http://10.0.1.1:8888": "UP",
|
||||
"http://10.0.1.1:8889": "UP"
|
||||
}
|
||||
},
|
||||
"srvcA@zookeeper": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.2:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.2:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
},
|
||||
"srvcB@zookeeper": {
|
||||
"loadBalancer": {
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://10.0.1.3:8888"
|
||||
},
|
||||
{
|
||||
"url": "http://10.0.1.3:8889"
|
||||
}
|
||||
],
|
||||
"passHostHeader": true
|
||||
},
|
||||
"status": "enabled"
|
||||
}
|
||||
}
|
||||
}
|
159
integration/zk_test.go
Normal file
159
integration/zk_test.go
Normal file
|
@ -0,0 +1,159 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/abronan/valkeyrie"
|
||||
"github.com/abronan/valkeyrie/store"
|
||||
"github.com/abronan/valkeyrie/store/zookeeper"
|
||||
"github.com/containous/traefik/v2/integration/try"
|
||||
"github.com/containous/traefik/v2/pkg/api"
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Zk test suites (using libcompose)
|
||||
type ZookeeperSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "zookeeper")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
zookeeper.Register()
|
||||
kv, err := valkeyrie.NewStore(
|
||||
store.ZK,
|
||||
[]string{s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181"},
|
||||
&store.Config{
|
||||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store zookeeper")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for zk
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) TearDownTest(c *check.C) {
|
||||
// shutdown and delete compose project
|
||||
if s.composeProject != nil {
|
||||
s.composeProject.Stop(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) TearDownSuite(c *check.C) {}
|
||||
|
||||
func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
|
||||
address := s.composeProject.Container(c, "zookeeper").NetworkSettings.IPAddress + ":2181"
|
||||
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{address})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("@zookeeper"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-zk.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = ioutil.WriteFile(expectedJSON, got, 0666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := ioutil.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue