2017-07-06 16:28:13 +02:00
package integration
2015-09-27 15:59:51 +02:00
import (
2017-05-17 15:22:44 +02:00
"fmt"
2015-09-27 15:59:51 +02:00
"net/http"
2017-09-26 10:22:03 +02:00
"os"
2017-05-17 15:22:44 +02:00
"strings"
2017-09-26 10:22:03 +02:00
"syscall"
2015-09-27 15:59:51 +02:00
"time"
2017-05-17 15:22:44 +02:00
"github.com/containous/traefik/integration/try"
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"
)
2015-11-03 23:06:31 +01:00
// SimpleSuite
type SimpleSuite struct { BaseSuite }
2015-09-27 15:59:51 +02:00
func ( s * SimpleSuite ) TestInvalidConfigShouldFail ( c * check . C ) {
2017-07-10 14:58:31 +02:00
cmd , output := s . cmdTraefik ( withConfigFile ( "fixtures/invalid_configuration.toml" ) )
2016-04-19 19:23:08 +02:00
2017-05-17 15:22:44 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2016-04-19 19:23:08 +02:00
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
err = try . Do ( 500 * time . Millisecond , func ( ) error {
expected := "Near line 0 (last key parsed ''): bare keys cannot contain '{'"
2017-07-10 14:58:31 +02:00
actual := output . String ( )
2017-05-17 15:22:44 +02:00
if ! strings . Contains ( actual , expected ) {
return fmt . Errorf ( "Got %s, wanted %s" , actual , expected )
}
return nil
} )
c . Assert ( err , checker . IsNil )
2015-09-27 15:59:51 +02:00
}
func ( s * SimpleSuite ) TestSimpleDefaultConfig ( c * check . C ) {
2017-07-10 14:58:31 +02:00
cmd , _ := s . cmdTraefik ( withConfigFile ( "fixtures/simple_default.toml" ) )
2017-05-17 15:22:44 +02:00
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
// TODO validate : run on 80
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-11-03 23:06:31 +01:00
}
func ( s * SimpleSuite ) TestWithWebConfig ( c * check . C ) {
2017-07-10 14:58:31 +02:00
cmd , _ := s . cmdTraefik ( withConfigFile ( "fixtures/simple_web.toml" ) )
2017-05-17 15:22:44 +02:00
2015-11-03 23:06:31 +01:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
err = try . GetRequest ( "http://127.0.0.1:8080/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
2015-11-03 23:06:31 +01:00
c . Assert ( err , checker . IsNil )
2015-09-27 15:59:51 +02:00
}
2016-06-02 15:17:04 +02:00
func ( s * SimpleSuite ) TestDefaultEntryPoints ( c * check . C ) {
2017-07-10 14:58:31 +02:00
cmd , output := s . cmdTraefik ( "--debug" )
2016-06-02 15:17:04 +02:00
2017-05-17 15:22:44 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2016-06-02 15:17:04 +02:00
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
err = try . Do ( 500 * time . Millisecond , func ( ) error {
2018-01-22 12:16:03 +01:00
expected := ` \"DefaultEntryPoints\":[\"http\"] `
2017-07-10 14:58:31 +02:00
actual := output . String ( )
2017-05-17 15:22:44 +02:00
if ! strings . Contains ( actual , expected ) {
return fmt . Errorf ( "Got %s, wanted %s" , actual , expected )
}
return nil
} )
c . Assert ( err , checker . IsNil )
2016-06-02 15:17:04 +02:00
}
func ( s * SimpleSuite ) TestPrintHelp ( c * check . C ) {
2017-07-10 14:58:31 +02:00
cmd , output := s . cmdTraefik ( "--help" )
2016-06-02 15:17:04 +02:00
2017-05-17 15:22:44 +02:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2016-06-02 15:17:04 +02:00
defer cmd . Process . Kill ( )
2017-05-17 15:22:44 +02:00
err = try . Do ( 500 * time . Millisecond , func ( ) error {
expected := "Usage:"
notExpected := "panic:"
2017-07-10 14:58:31 +02:00
actual := output . String ( )
2017-05-17 15:22:44 +02:00
if strings . Contains ( actual , notExpected ) {
return fmt . Errorf ( "Got %s" , actual )
}
if ! strings . Contains ( actual , expected ) {
return fmt . Errorf ( "Got %s, wanted %s" , actual , expected )
}
return nil
} )
c . Assert ( err , checker . IsNil )
2016-06-02 15:17:04 +02:00
}
2017-09-26 10:22:03 +02:00
func ( s * SimpleSuite ) TestRequestAcceptGraceTimeout ( c * check . C ) {
s . createComposeProject ( c , "reqacceptgrace" )
s . composeProject . Start ( c )
whoami := "http://" + s . composeProject . Container ( c , "whoami" ) . NetworkSettings . IPAddress + ":80"
file := s . adaptFile ( c , "fixtures/reqacceptgrace.toml" , struct {
Server string
} { whoami } )
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 ( )
// Wait for Traefik to turn ready.
err = try . GetRequest ( "http://127.0.0.1:8000/" , 2 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
// Make sure exposed service is ready.
err = try . GetRequest ( "http://127.0.0.1:8000/service" , 3 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2018-03-22 10:18:03 -07:00
// Check that /ping endpoint is responding with 200.
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 3 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2017-09-26 10:22:03 +02:00
// Send SIGTERM to Traefik.
proc , err := os . FindProcess ( cmd . Process . Pid )
c . Assert ( err , checker . IsNil )
err = proc . Signal ( syscall . SIGTERM )
c . Assert ( err , checker . IsNil )
// Give Traefik time to process the SIGTERM and send a request half-way
// into the request accepting grace period, by which requests should
// still get served.
time . Sleep ( 5 * time . Second )
resp , err := http . Get ( "http://127.0.0.1:8000/service" )
c . Assert ( err , checker . IsNil )
defer resp . Body . Close ( )
c . Assert ( resp . StatusCode , checker . Equals , http . StatusOK )
2018-03-22 10:18:03 -07:00
// ping endpoint should now return a Service Unavailable.
resp , err = http . Get ( "http://127.0.0.1:8001/ping" )
c . Assert ( err , checker . IsNil )
defer resp . Body . Close ( )
c . Assert ( resp . StatusCode , checker . Equals , http . StatusServiceUnavailable )
2017-09-26 10:22:03 +02:00
// Expect Traefik to shut down gracefully once the request accepting grace
// period has elapsed.
waitErr := make ( chan error )
go func ( ) {
waitErr <- cmd . Wait ( )
} ( )
select {
case err := <- waitErr :
c . Assert ( err , checker . IsNil )
case <- time . After ( 10 * time . Second ) :
// By now we are ~5 seconds out of the request accepting grace period
// (start + 5 seconds sleep prior to the mid-grace period request +
// 10 seconds timeout = 15 seconds > 10 seconds grace period).
// Something must have gone wrong if we still haven't terminated at
// this point.
c . Fatal ( "Traefik did not terminate in time" )
}
}
2017-11-09 16:12:04 +01:00
func ( s * SimpleSuite ) TestApiOnSameEntryPoint ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--defaultEntryPoints=http" , "--entryPoints=Name:http Address::8000" , "--api.entryPoint=http" , "--debug" , "--docker" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
// TODO validate : run on 80
// Expected a 404 as we did not configure anything
err = try . GetRequest ( "http://127.0.0.1:8000/test" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2017-11-30 12:18:03 +01:00
func ( s * SimpleSuite ) TestStatsWithMultipleEntryPoint ( c * check . C ) {
s . createComposeProject ( c , "stats" )
s . composeProject . Start ( c )
whoami1 := "http://" + s . composeProject . Container ( c , "whoami1" ) . NetworkSettings . IPAddress + ":80"
whoami2 := "http://" + s . composeProject . Container ( c , "whoami2" ) . NetworkSettings . IPAddress + ":80"
file := s . adaptFile ( c , "fixtures/simple_stats.toml" , struct {
Server1 string
Server2 string
} { whoami1 , whoami2 } )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8080/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/health" , 1 * time . Second , try . BodyContains ( ` "total_status_code_count": { "200":2} ` ) )
c . Assert ( err , checker . IsNil )
}
2017-11-09 16:12:04 +01:00
func ( s * SimpleSuite ) TestNoAuthOnPing ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( withConfigFile ( "./fixtures/simple_auth.toml" ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8001/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusUnauthorized ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestWebCompatibilityWithoutPath ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--defaultEntryPoints=http" , "--entryPoints=Name:http Address::8000" , "--web" , "--debug" , "--docker" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
// TODO validate : run on 80
// Expected a 404 as we did not configure anything
err = try . GetRequest ( "http://127.0.0.1:8000/test" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestWebCompatibilityWithPath ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--defaultEntryPoints=http" , "--entryPoints=Name:http Address::8000" , "--web.path=/test" , "--debug" , "--docker" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
// TODO validate : run on 80
// Expected a 404 as we did not configure anything
err = try . GetRequest ( "http://127.0.0.1:8000/notfound" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/test/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/test/ping" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/test/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2017-11-30 16:10:02 +01:00
func ( s * SimpleSuite ) TestDefaultEntrypointHTTP ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--entryPoints=Name:http Address::8000" , "--debug" , "--docker" , "--api" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestWithUnexistingEntrypoint ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--defaultEntryPoints=https,http" , "--entryPoints=Name:http Address::8000" , "--debug" , "--docker" , "--api" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2018-01-19 14:30:04 +01:00
func ( s * SimpleSuite ) TestMetricsPrometheusDefaultEntrypoint ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
cmd , output := s . traefikCmd ( "--defaultEntryPoints=http" , "--entryPoints=Name:http Address::8000" , "--web" , "--web.metrics.prometheus.buckets=0.1,0.3,1.2,5.0" , "--docker" , "--debug" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/metrics" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2018-02-16 11:04:04 +01:00
func ( s * SimpleSuite ) TestMultipleProviderSameBackendName ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeProject . Start ( c )
ipWhoami01 := s . composeProject . Container ( c , "whoami1" ) . NetworkSettings . IPAddress
ipWhoami02 := s . composeProject . Container ( c , "whoami2" ) . NetworkSettings . IPAddress
file := s . adaptFile ( c , "fixtures/multiple_provider.toml" , struct { IP string } {
IP : ipWhoami02 ,
} )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer cmd . Process . Kill ( )
err = try . GetRequest ( "http://127.0.0.1:8080/api/providers" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . BodyContains ( ipWhoami01 ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/file" , 1 * time . Second , try . BodyContains ( ipWhoami02 ) )
c . Assert ( err , checker . IsNil )
}