2017-07-06 16:28:13 +02:00
package integration
2015-09-27 15:59:51 +02:00
import (
2017-04-17 12:50:02 +02:00
"context"
2017-11-23 18:50:03 +08:00
"crypto/tls"
2017-05-17 15:22:44 +02:00
"fmt"
2017-11-23 18:50:03 +08:00
"io/ioutil"
2015-09-27 15:59:51 +02:00
"net/http"
2017-04-17 12:50:02 +02:00
"os"
"sync"
2015-09-27 15:59:51 +02:00
"time"
2018-01-24 17:52:03 +01:00
"github.com/abronan/valkeyrie"
"github.com/abronan/valkeyrie/store"
"github.com/abronan/valkeyrie/store/consul"
2016-08-16 19:13:18 +02:00
"github.com/containous/staert"
2017-04-17 12:50:02 +02:00
"github.com/containous/traefik/cluster"
2017-05-17 15:22:44 +02:00
"github.com/containous/traefik/integration/try"
2017-08-25 12:22:03 -04:00
"github.com/containous/traefik/types"
2016-04-02 12:40:21 +02:00
"github.com/go-check/check"
2015-09-27 15:59:51 +02:00
checker "github.com/vdemeester/shakers"
)
2016-03-27 16:27:56 +02:00
// Consul test suites (using libcompose)
2016-04-28 01:43:43 +02:00
type ConsulSuite struct {
BaseSuite
kv store . Store
}
2016-03-27 16:27:56 +02:00
2016-07-07 17:25:42 +02:00
func ( s * ConsulSuite ) setupConsul ( c * check . C ) {
2016-03-27 16:27:56 +02:00
s . createComposeProject ( c , "consul" )
2016-04-28 01:43:43 +02:00
s . composeProject . Start ( c )
consul . Register ( )
2018-01-24 17:52:03 +01:00
kv , err := valkeyrie . NewStore (
2016-04-28 01:43:43 +02:00
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 . kv = kv
// wait for consul
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , try . KVExists ( kv , "test" ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2016-03-27 16:27:56 +02:00
}
2016-07-07 17:25:42 +02:00
func ( s * ConsulSuite ) setupConsulTLS ( c * check . C ) {
s . createComposeProject ( c , "consul_tls" )
s . composeProject . Start ( c )
consul . Register ( )
2017-08-25 12:22:03 -04:00
clientTLS := & types . ClientTLS {
2016-07-07 17:25:42 +02:00
CA : "resources/tls/ca.cert" ,
Cert : "resources/tls/consul.cert" ,
Key : "resources/tls/consul.key" ,
InsecureSkipVerify : true ,
}
TLSConfig , err := clientTLS . CreateTLSConfig ( )
c . Assert ( err , checker . IsNil )
2018-01-24 17:52:03 +01:00
kv , err := valkeyrie . NewStore (
2016-07-07 17:25:42 +02:00
store . CONSUL ,
[ ] string { s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress + ":8585" } ,
& store . Config {
ConnectionTimeout : 10 * time . Second ,
TLS : TLSConfig ,
} ,
)
if err != nil {
c . Fatal ( "Cannot create store consul" )
}
s . kv = kv
// wait for consul
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , try . KVExists ( kv , "test" ) )
2016-07-07 17:25:42 +02:00
c . Assert ( err , checker . IsNil )
}
2016-06-24 09:58:42 +02:00
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 ) { }
2015-09-27 15:59:51 +02:00
func ( s * ConsulSuite ) TestSimpleConfiguration ( c * check . C ) {
2016-07-07 17:25:42 +02:00
s . setupConsul ( c )
2016-04-28 01:43:43 +02:00
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
file := s . adaptFile ( c , "fixtures/consul/simple.toml" , struct { ConsulHost string } { consulHost } )
defer os . Remove ( file )
2017-05-17 15:22:44 +02:00
2017-09-13 10:34:04 +02:00
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
2015-09-27 15:59:51 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2015-11-03 23:06:31 +01:00
defer cmd . Process . Kill ( )
2015-09-27 15:59:51 +02:00
2016-03-15 18:57:56 +01:00
// Expected a 404 as we did not configure anything
2017-05-17 15:22:44 +02:00
err = try . GetRequest ( "http://127.0.0.1:8000/" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
2016-03-15 18:57:56 +01:00
c . Assert ( err , checker . IsNil )
2015-09-27 15:59:51 +02:00
}
2016-04-28 01:43:43 +02:00
func ( s * ConsulSuite ) TestNominalConfiguration ( c * check . C ) {
2016-07-07 17:25:42 +02:00
s . setupConsul ( c )
2016-04-28 01:43:43 +02:00
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
file := s . adaptFile ( c , "fixtures/consul/simple.toml" , struct { ConsulHost string } { consulHost } )
defer os . Remove ( file )
2017-05-17 15:22:44 +02:00
2017-09-13 10:34:04 +02:00
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
2016-04-28 01:43:43 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
whoami1IP := s . composeProject . Container ( c , "whoami1" ) . NetworkSettings . IPAddress
whoami2IP := s . composeProject . Container ( c , "whoami2" ) . NetworkSettings . IPAddress
whoami3IP := s . composeProject . Container ( c , "whoami3" ) . NetworkSettings . IPAddress
whoami4IP := s . composeProject . Container ( c , "whoami4" ) . NetworkSettings . IPAddress
2016-04-28 01:43:43 +02:00
backend1 := map [ string ] string {
"traefik/backends/backend1/circuitbreaker/expression" : "NetworkErrorRatio() > 0.5" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend1/servers/server1/url" : "http://" + whoami1IP + ":80" ,
2016-04-28 01:43:43 +02:00
"traefik/backends/backend1/servers/server1/weight" : "10" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend1/servers/server2/url" : "http://" + whoami2IP + ":80" ,
2016-04-28 01:43:43 +02:00
"traefik/backends/backend1/servers/server2/weight" : "1" ,
}
backend2 := map [ string ] string {
"traefik/backends/backend2/loadbalancer/method" : "drr" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend2/servers/server1/url" : "http://" + whoami3IP + ":80" ,
2016-04-28 01:43:43 +02:00
"traefik/backends/backend2/servers/server1/weight" : "1" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend2/servers/server2/url" : "http://" + whoami4IP + ":80" ,
2016-04-28 01:43:43 +02:00
"traefik/backends/backend2/servers/server2/weight" : "2" ,
}
frontend1 := map [ string ] string {
"traefik/frontends/frontend1/backend" : "backend2" ,
"traefik/frontends/frontend1/entrypoints" : "http" ,
2016-06-06 22:33:29 +02:00
"traefik/frontends/frontend1/priority" : "1" ,
2016-04-28 01:43:43 +02:00
"traefik/frontends/frontend1/routes/test_1/rule" : "Host:test.localhost" ,
}
frontend2 := map [ string ] string {
"traefik/frontends/frontend2/backend" : "backend1" ,
"traefik/frontends/frontend2/entrypoints" : "http" ,
2016-06-06 22:33:29 +02:00
"traefik/frontends/frontend2/priority" : "10" ,
2016-04-28 01:43:43 +02:00
"traefik/frontends/frontend2/routes/test_2/rule" : "Path:/test" ,
}
for key , value := range backend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range backend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
// wait for consul
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , try . KVExists ( s . kv , "traefik/frontends/frontend2/routes/test_2/rule" ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
// wait for traefik
2017-05-17 15:22:44 +02:00
err = try . GetRequest ( "http://127.0.0.1:8081/api/providers" , 60 * time . Second , try . BodyContains ( "Path:/test" ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
req . Host = "test.localhost"
2017-05-17 15:22:44 +02:00
err = try . Request ( req , 500 * time . Millisecond ,
2017-11-20 09:40:03 +01:00
try . StatusCodeIs ( http . StatusOK ) ,
2017-05-17 15:22:44 +02:00
try . BodyContainsOr ( whoami3IP , whoami4IP ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/test" , nil )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
err = try . Request ( req , 500 * time . Millisecond ,
2017-11-20 09:40:03 +01:00
try . StatusCodeIs ( http . StatusOK ) ,
2017-05-17 15:22:44 +02:00
try . BodyContainsOr ( whoami1IP , whoami2IP ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/test2" , nil )
2018-04-23 10:54:03 +02:00
c . Assert ( err , checker . IsNil )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusNotFound ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
2018-04-23 10:54:03 +02:00
c . Assert ( err , checker . IsNil )
2016-04-28 01:43:43 +02:00
req . Host = "test2.localhost"
2018-04-23 10:54:03 +02:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusNotFound ) )
2016-04-28 01:43:43 +02:00
c . Assert ( err , checker . IsNil )
}
2016-06-24 09:58:42 +02:00
func ( s * ConsulSuite ) TestGlobalConfiguration ( c * check . C ) {
2016-07-07 17:25:42 +02:00
s . setupConsul ( c )
2016-06-24 09:58:42 +02:00
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
err := s . kv . Put ( "traefik/entrypoints/http/address" , [ ] byte ( ":8001" ) , nil )
c . Assert ( err , checker . IsNil )
// wait for consul
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , try . KVExists ( s . kv , "traefik/entrypoints/http/address" ) )
2016-06-24 09:58:42 +02:00
c . Assert ( err , checker . IsNil )
// start traefik
2017-09-13 10:34:04 +02:00
cmd , display := s . traefikCmd (
2017-07-10 14:58:31 +02:00
withConfigFile ( "fixtures/simple_web.toml" ) ,
"--consul" ,
"--consul.endpoint=" + consulHost + ":8500" )
2017-09-13 10:34:04 +02:00
defer display ( c )
2016-06-24 09:58:42 +02:00
err = cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
whoami1IP := s . composeProject . Container ( c , "whoami1" ) . NetworkSettings . IPAddress
whoami2IP := s . composeProject . Container ( c , "whoami2" ) . NetworkSettings . IPAddress
whoami3IP := s . composeProject . Container ( c , "whoami3" ) . NetworkSettings . IPAddress
whoami4IP := s . composeProject . Container ( c , "whoami4" ) . NetworkSettings . IPAddress
2016-06-24 09:58:42 +02:00
backend1 := map [ string ] string {
"traefik/backends/backend1/circuitbreaker/expression" : "NetworkErrorRatio() > 0.5" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend1/servers/server1/url" : "http://" + whoami1IP + ":80" ,
2016-06-24 09:58:42 +02:00
"traefik/backends/backend1/servers/server1/weight" : "10" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend1/servers/server2/url" : "http://" + whoami2IP + ":80" ,
2016-06-24 09:58:42 +02:00
"traefik/backends/backend1/servers/server2/weight" : "1" ,
}
backend2 := map [ string ] string {
"traefik/backends/backend2/loadbalancer/method" : "drr" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend2/servers/server1/url" : "http://" + whoami3IP + ":80" ,
2016-06-24 09:58:42 +02:00
"traefik/backends/backend2/servers/server1/weight" : "1" ,
2017-05-17 15:22:44 +02:00
"traefik/backends/backend2/servers/server2/url" : "http://" + whoami4IP + ":80" ,
2016-06-24 09:58:42 +02:00
"traefik/backends/backend2/servers/server2/weight" : "2" ,
}
frontend1 := map [ string ] string {
"traefik/frontends/frontend1/backend" : "backend2" ,
"traefik/frontends/frontend1/entrypoints" : "http" ,
"traefik/frontends/frontend1/priority" : "1" ,
"traefik/frontends/frontend1/routes/test_1/rule" : "Host:test.localhost" ,
}
frontend2 := map [ string ] string {
"traefik/frontends/frontend2/backend" : "backend1" ,
"traefik/frontends/frontend2/entrypoints" : "http" ,
"traefik/frontends/frontend2/priority" : "10" ,
"traefik/frontends/frontend2/routes/test_2/rule" : "Path:/test" ,
}
for key , value := range backend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range backend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
// wait for consul
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , try . KVExists ( s . kv , "traefik/frontends/frontend2/routes/test_2/rule" ) )
2016-06-24 09:58:42 +02:00
c . Assert ( err , checker . IsNil )
// wait for traefik
2017-05-17 15:22:44 +02:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 60 * time . Second , try . BodyContains ( "Path:/test" ) )
2016-06-24 09:58:42 +02:00
c . Assert ( err , checker . IsNil )
//check
2017-05-17 15:22:44 +02:00
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8001/" , nil )
2016-06-24 09:58:42 +02:00
c . Assert ( err , checker . IsNil )
req . Host = "test.localhost"
2017-05-17 15:22:44 +02:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
2016-06-24 09:58:42 +02:00
c . Assert ( err , checker . IsNil )
}
2016-07-07 17:25:42 +02:00
2016-07-20 11:48:39 +02:00
func ( s * ConsulSuite ) TestCommandStoreConfig ( c * check . C ) {
s . setupConsul ( c )
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
2017-09-13 10:34:04 +02:00
cmd , display := s . traefikCmd (
2017-05-17 15:22:44 +02:00
"storeconfig" ,
2017-07-10 14:58:31 +02:00
withConfigFile ( "fixtures/simple_web.toml" ) ,
2017-05-17 15:22:44 +02:00
"--consul.endpoint=" + consulHost + ":8500" )
2017-09-13 10:34:04 +02:00
defer display ( c )
2016-07-20 11:48:39 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
// wait for traefik finish without error
2017-11-21 10:24:03 +01:00
err = cmd . Wait ( )
c . Assert ( err , checker . IsNil )
2016-07-20 11:48:39 +02:00
2017-11-21 10:24:03 +01:00
expectedData := map [ string ] string {
2016-07-20 11:48:39 +02:00
"/traefik/loglevel" : "DEBUG" ,
"/traefik/defaultentrypoints/0" : "http" ,
"/traefik/entrypoints/http/address" : ":8000" ,
2018-01-11 09:46:03 +01:00
"/traefik/api/entrypoint" : "traefik" ,
2017-05-17 15:22:44 +02:00
"/traefik/consul/endpoint" : consulHost + ":8500" ,
2016-07-20 11:48:39 +02:00
}
2017-11-21 10:24:03 +01:00
for key , value := range expectedData {
2016-07-20 11:48:39 +02:00
var p * store . KVPair
2017-05-17 15:22:44 +02:00
err = try . Do ( 60 * time . Second , func ( ) error {
2017-11-17 17:22:03 +01:00
p , err = s . kv . Get ( key , nil )
2017-05-17 15:22:44 +02:00
return err
2016-07-20 11:48:39 +02:00
} )
c . Assert ( err , checker . IsNil )
c . Assert ( string ( p . Value ) , checker . Equals , value )
}
}
2016-08-16 19:13:18 +02:00
2017-11-21 10:24:03 +01:00
func ( s * ConsulSuite ) TestCommandStoreConfigWithFile ( c * check . C ) {
s . setupConsul ( c )
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
cmd , display := s . traefikCmd (
"storeconfig" ,
withConfigFile ( "fixtures/simple_default.toml" ) ,
"--consul.endpoint=" + consulHost + ":8500" ,
"--file.filename=fixtures/file/dir/simple1.toml" )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
// wait for traefik finish without error
err = cmd . Wait ( )
c . Assert ( err , checker . IsNil )
expectedData := map [ string ] string {
"/traefik/backends/backend1/servers/server1/url" : "http://172.17.0.2:80" ,
"/traefik/frontends/frontend1/backend" : "backend1" ,
"/traefik/frontends/frontend1/routes/test_1/rule" : "Path:/test1" ,
}
for key , value := range expectedData {
var p * store . KVPair
err = try . Do ( 10 * time . Second , func ( ) error {
p , err = s . kv . Get ( key , nil )
return err
} )
c . Assert ( err , checker . IsNil )
c . Assert ( string ( p . Value ) , checker . Equals , value )
}
checkNotExistsMap := [ ] string {
"/traefik/file" ,
}
for _ , value := range checkNotExistsMap {
err = try . Do ( 10 * time . Second , func ( ) error {
if exists , err := s . kv . Exists ( value , nil ) ; err == nil && exists {
return fmt . Errorf ( "%s key is not suppose to exist in KV" , value )
}
return nil
} )
c . Assert ( err , checker . IsNil )
}
}
2016-08-16 19:13:18 +02:00
type TestStruct struct {
String string
Int int
}
func ( s * ConsulSuite ) TestDatastore ( c * check . C ) {
s . setupConsul ( c )
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
kvSource , err := staert . NewKvSource ( store . CONSUL , [ ] string { consulHost + ":8500" } , & store . Config {
ConnectionTimeout : 10 * time . Second ,
} , "traefik" )
c . Assert ( err , checker . IsNil )
ctx := context . Background ( )
2016-11-16 08:56:52 +00:00
datastore1 , err := cluster . NewDataStore ( ctx , * kvSource , & TestStruct { } , nil )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
2016-11-16 08:56:52 +00:00
datastore2 , err := cluster . NewDataStore ( ctx , * kvSource , & TestStruct { } , nil )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
2016-09-23 18:27:01 +02:00
setter1 , _ , err := datastore1 . Begin ( )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
err = setter1 . Commit ( & TestStruct {
String : "foo" ,
Int : 1 ,
} )
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
err = try . Do ( 3 * time . Second , datastoreContains ( datastore1 , "foo" ) )
c . Assert ( err , checker . IsNil )
err = try . Do ( 3 * time . Second , datastoreContains ( datastore2 , "foo" ) )
c . Assert ( err , checker . IsNil )
2016-08-16 19:13:18 +02:00
2016-09-23 18:27:01 +02:00
setter2 , _ , err := datastore2 . Begin ( )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
err = setter2 . Commit ( & TestStruct {
String : "bar" ,
Int : 2 ,
} )
c . Assert ( err , checker . IsNil )
2017-05-17 15:22:44 +02:00
err = try . Do ( 3 * time . Second , datastoreContains ( datastore1 , "bar" ) )
c . Assert ( err , checker . IsNil )
err = try . Do ( 3 * time . Second , datastoreContains ( datastore2 , "bar" ) )
c . Assert ( err , checker . IsNil )
2016-08-16 19:13:18 +02:00
wg := & sync . WaitGroup { }
wg . Add ( 4 )
go func ( ) {
for i := 0 ; i < 100 ; i ++ {
2016-09-23 18:27:01 +02:00
setter1 , _ , err := datastore1 . Begin ( )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
err = setter1 . Commit ( & TestStruct {
String : "datastore1" ,
Int : i ,
} )
c . Assert ( err , checker . IsNil )
}
wg . Done ( )
} ( )
go func ( ) {
for i := 0 ; i < 100 ; i ++ {
2016-09-23 18:27:01 +02:00
setter2 , _ , err := datastore2 . Begin ( )
2016-08-16 19:13:18 +02:00
c . Assert ( err , checker . IsNil )
err = setter2 . Commit ( & TestStruct {
String : "datastore2" ,
Int : i ,
} )
c . Assert ( err , checker . IsNil )
}
wg . Done ( )
} ( )
go func ( ) {
for i := 0 ; i < 100 ; i ++ {
test1 := datastore1 . Get ( ) . ( * TestStruct )
c . Assert ( test1 , checker . NotNil )
}
wg . Done ( )
} ( )
go func ( ) {
for i := 0 ; i < 100 ; i ++ {
test2 := datastore2 . Get ( ) . ( * TestStruct )
c . Assert ( test2 , checker . NotNil )
}
wg . Done ( )
} ( )
wg . Wait ( )
}
2017-05-17 15:22:44 +02:00
func datastoreContains ( datastore * cluster . Datastore , expectedValue string ) func ( ) error {
return func ( ) error {
kvStruct := datastore . Get ( ) . ( * TestStruct )
if kvStruct . String != expectedValue {
return fmt . Errorf ( "Got %s, wanted %s" , kvStruct . String , expectedValue )
}
return nil
}
}
2017-11-23 18:50:03 +08:00
func ( s * ConsulSuite ) TestSNIDynamicTlsConfig ( c * check . C ) {
s . setupConsul ( c )
consulHost := s . composeProject . Container ( c , "consul" ) . NetworkSettings . IPAddress
// start Træfik
file := s . adaptFile ( c , "fixtures/consul/simple_https.toml" , struct { ConsulHost string } { consulHost } )
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 ( )
// prepare to config
whoami1IP := s . composeProject . Container ( c , "whoami1" ) . NetworkSettings . IPAddress
whoami2IP := s . composeProject . Container ( c , "whoami2" ) . NetworkSettings . IPAddress
whoami3IP := s . composeProject . Container ( c , "whoami3" ) . NetworkSettings . IPAddress
whoami4IP := s . composeProject . Container ( c , "whoami4" ) . NetworkSettings . IPAddress
snitestComCert , err := ioutil . ReadFile ( "fixtures/https/snitest.com.cert" )
c . Assert ( err , checker . IsNil )
snitestComKey , err := ioutil . ReadFile ( "fixtures/https/snitest.com.key" )
c . Assert ( err , checker . IsNil )
snitestOrgCert , err := ioutil . ReadFile ( "fixtures/https/snitest.org.cert" )
c . Assert ( err , checker . IsNil )
snitestOrgKey , err := ioutil . ReadFile ( "fixtures/https/snitest.org.key" )
c . Assert ( err , checker . IsNil )
backend1 := map [ string ] string {
"traefik/backends/backend1/circuitbreaker/expression" : "NetworkErrorRatio() > 0.5" ,
"traefik/backends/backend1/servers/server1/url" : "http://" + whoami1IP + ":80" ,
"traefik/backends/backend1/servers/server1/weight" : "1" ,
"traefik/backends/backend1/servers/server2/url" : "http://" + whoami2IP + ":80" ,
"traefik/backends/backend1/servers/server2/weight" : "1" ,
}
backend2 := map [ string ] string {
"traefik/backends/backend2/loadbalancer/method" : "drr" ,
"traefik/backends/backend2/servers/server1/url" : "http://" + whoami3IP + ":80" ,
"traefik/backends/backend2/servers/server1/weight" : "1" ,
"traefik/backends/backend2/servers/server2/url" : "http://" + whoami4IP + ":80" ,
"traefik/backends/backend2/servers/server2/weight" : "1" ,
}
frontend1 := map [ string ] string {
"traefik/frontends/frontend1/backend" : "backend2" ,
"traefik/frontends/frontend1/entrypoints" : "https" ,
"traefik/frontends/frontend1/priority" : "1" ,
"traefik/frontends/frontend1/routes/test_1/rule" : "Host:snitest.com" ,
}
frontend2 := map [ string ] string {
"traefik/frontends/frontend2/backend" : "backend1" ,
"traefik/frontends/frontend2/entrypoints" : "https" ,
"traefik/frontends/frontend2/priority" : "10" ,
"traefik/frontends/frontend2/routes/test_2/rule" : "Host:snitest.org" ,
}
tlsconfigure1 := map [ string ] string {
2018-01-23 16:30:07 +01:00
"traefik/tls/snitestcom/entrypoints" : "https" ,
"traefik/tls/snitestcom/certificate/keyfile" : string ( snitestComKey ) ,
"traefik/tls/snitestcom/certificate/certfile" : string ( snitestComCert ) ,
2017-11-23 18:50:03 +08:00
}
tlsconfigure2 := map [ string ] string {
2018-01-23 16:30:07 +01:00
"traefik/tls/snitestorg/entrypoints" : "https" ,
"traefik/tls/snitestorg/certificate/keyfile" : string ( snitestOrgKey ) ,
"traefik/tls/snitestorg/certificate/certfile" : string ( snitestOrgCert ) ,
2017-11-23 18:50:03 +08:00
}
// config backends,frontends and first tls keypair
for key , value := range backend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range backend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range frontend2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
for key , value := range tlsconfigure1 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
tr1 := & http . Transport {
TLSClientConfig : & tls . Config {
InsecureSkipVerify : true ,
ServerName : "snitest.com" ,
} ,
}
tr2 := & http . Transport {
TLSClientConfig : & tls . Config {
InsecureSkipVerify : true ,
ServerName : "snitest.org" ,
} ,
}
// wait for consul
err = try . Do ( 60 * time . Second , func ( ) error {
2018-01-23 16:30:07 +01:00
_ , err := s . kv . Get ( "traefik/tls/snitestcom/certificate/keyfile" , nil )
2017-11-23 18:50:03 +08:00
return err
} )
c . Assert ( err , checker . IsNil )
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8081/api/providers" , 60 * time . Second , try . BodyContains ( "MIIEpQIBAAKCAQEA1RducBK6EiFDv3TYB8ZcrfKWRVaSfHzWicO3J5WdST9oS7hG" ) )
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "https://127.0.0.1:4443/" , nil )
c . Assert ( err , checker . IsNil )
client := & http . Client { Transport : tr1 }
req . Host = tr1 . TLSClientConfig . ServerName
req . Header . Set ( "Host" , tr1 . TLSClientConfig . ServerName )
req . Header . Set ( "Accept" , "*/*" )
var resp * http . Response
resp , err = client . Do ( req )
c . Assert ( err , checker . IsNil )
cn := resp . TLS . PeerCertificates [ 0 ] . Subject . CommonName
c . Assert ( cn , checker . Equals , "snitest.com" )
// now we configure the second keypair in consul and the request for host "snitest.org" will use the second keypair
for key , value := range tlsconfigure2 {
err := s . kv . Put ( key , [ ] byte ( value ) , nil )
c . Assert ( err , checker . IsNil )
}
// wait for consul
err = try . Do ( 60 * time . Second , func ( ) error {
2018-01-23 16:30:07 +01:00
_ , err := s . kv . Get ( "traefik/tls/snitestorg/certificate/keyfile" , nil )
2017-11-23 18:50:03 +08:00
return err
} )
c . Assert ( err , checker . IsNil )
// waiting for traefik to pull configuration
err = try . GetRequest ( "http://127.0.0.1:8081/api/providers" , 30 * time . Second , try . BodyContains ( "MIIEogIBAAKCAQEAvG9kL+vF57+MICehzbqcQAUlAOSl5r" ) )
c . Assert ( err , checker . IsNil )
req , err = http . NewRequest ( http . MethodGet , "https://127.0.0.1:4443/" , nil )
c . Assert ( err , checker . IsNil )
client = & http . Client { Transport : tr2 }
req . Host = tr2 . TLSClientConfig . ServerName
req . Header . Set ( "Host" , tr2 . TLSClientConfig . ServerName )
req . Header . Set ( "Accept" , "*/*" )
resp , err = client . Do ( req )
2017-12-04 20:04:08 +01:00
c . Assert ( err , checker . IsNil )
2017-11-23 18:50:03 +08:00
cn = resp . TLS . PeerCertificates [ 0 ] . Subject . CommonName
c . Assert ( cn , checker . Equals , "snitest.org" )
}