2017-07-06 17:28:13 +03:00
package integration
2016-04-20 21:54:57 +03:00
import (
2018-01-24 20:18:03 +03:00
"crypto/md5"
"crypto/rand"
2016-04-20 21:54:57 +03:00
"fmt"
2018-01-24 20:18:03 +03:00
"io"
2016-04-20 21:54:57 +03:00
"net/http"
"os"
2019-11-14 18:40:05 +03:00
"strconv"
2016-04-20 21:54:57 +03:00
"strings"
"time"
"github.com/go-check/check"
2020-09-16 16:46:04 +03:00
"github.com/traefik/traefik/v2/integration/try"
"github.com/traefik/traefik/v2/pkg/log"
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
2016-04-20 21:54:57 +03:00
checker "github.com/vdemeester/shakers"
)
2017-07-10 17:58:12 +03:00
const (
traefikTestLogFile = "traefik.log"
traefikTestAccessLogFile = "access.log"
)
2020-05-11 13:06:07 +03:00
// AccessLogSuite tests suite.
2016-04-20 21:54:57 +03:00
type AccessLogSuite struct { BaseSuite }
2018-01-11 12:04:03 +03:00
type accessLogValue struct {
2019-01-18 17:18:04 +03:00
formatOnly bool
code string
user string
routerName string
serviceURL string
2018-01-11 12:04:03 +03:00
}
func ( s * AccessLogSuite ) SetUpSuite ( c * check . C ) {
s . createComposeProject ( c , "access_log" )
2021-11-25 13:10:06 +03:00
s . composeUp ( c )
2018-01-11 12:04:03 +03:00
}
2018-02-05 11:48:03 +03:00
func ( s * AccessLogSuite ) TearDownTest ( c * check . C ) {
displayTraefikLogFile ( c , traefikTestLogFile )
2019-09-13 20:28:04 +03:00
_ = os . Remove ( traefikTestAccessLogFile )
2018-02-05 11:48:03 +03:00
}
2016-04-20 21:54:57 +03:00
func ( s * AccessLogSuite ) TestAccessLog ( c * check . C ) {
2018-01-11 12:04:03 +03:00
ensureWorkingDirectoryIsClean ( )
2016-04-20 21:54:57 +03:00
// Start Traefik
2017-09-13 11:34:04 +03:00
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2019-01-18 17:18:04 +03:00
defer func ( ) {
2021-03-04 22:08:03 +03:00
traefikLog , err := os . ReadFile ( traefikTestLogFile )
2019-01-18 17:18:04 +03:00
c . Assert ( err , checker . IsNil )
2019-09-13 20:28:04 +03:00
log . WithoutContext ( ) . Info ( string ( traefikLog ) )
2019-01-18 17:18:04 +03:00
} ( )
2016-04-20 21:54:57 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2017-05-17 16:22:44 +03:00
2018-01-11 12:04:03 +03:00
waitForTraefik ( c , "server1" )
checkStatsForLogFile ( c )
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
// Make some requests
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "frontend1.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "frontend2.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogOutput ( c )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , 3 )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
func ( s * AccessLogSuite ) TestAccessLogAuthFrontend ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "401" ,
user : "-" ,
routerName : "rt-authFrontend" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
2020-06-18 17:02:04 +03:00
{
formatOnly : false ,
code : "401" ,
user : "test" ,
routerName : "rt-authFrontend" ,
serviceURL : "-" ,
} ,
{
formatOnly : false ,
code : "200" ,
user : "test" ,
routerName : "rt-authFrontend" ,
2021-11-25 13:10:06 +03:00
serviceURL : "http://172.31.42" ,
2020-06-18 17:02:04 +03:00
} ,
2018-01-11 12:04:03 +03:00
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-11 12:04:03 +03:00
err := cmd . Start ( )
2017-05-17 16:22:44 +03:00
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-11 12:04:03 +03:00
checkStatsForLogFile ( c )
waitForTraefik ( c , "authFrontend" )
2016-04-20 21:54:57 +03:00
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
2020-06-18 17:02:04 +03:00
// Test auth entrypoint
2018-01-11 12:04:03 +03:00
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8006/" , nil )
2016-04-28 13:53:02 +03:00
c . Assert ( err , checker . IsNil )
2018-01-11 12:04:03 +03:00
req . Host = "frontend.auth.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusUnauthorized ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
2020-06-18 17:02:04 +03:00
req . SetBasicAuth ( "test" , "" )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusUnauthorized ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
req . SetBasicAuth ( "test" , "test" )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
2018-01-11 12:04:03 +03:00
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
2019-01-18 17:18:04 +03:00
func ( s * AccessLogSuite ) TestAccessLogDigestAuthMiddleware ( c * check . C ) {
2018-01-11 12:04:03 +03:00
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "401" ,
user : "-" ,
routerName : "rt-digestAuthMiddleware" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
2020-06-18 17:02:04 +03:00
{
formatOnly : false ,
code : "401" ,
user : "test" ,
routerName : "rt-digestAuthMiddleware" ,
serviceURL : "-" ,
} ,
2018-01-24 20:18:03 +03:00
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "200" ,
user : "test" ,
routerName : "rt-digestAuthMiddleware" ,
2021-11-25 13:10:06 +03:00
serviceURL : "http://172.31.42" ,
2018-01-24 20:18:03 +03:00
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-24 20:18:03 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-24 20:18:03 +03:00
checkStatsForLogFile ( c )
2019-01-18 17:18:04 +03:00
waitForTraefik ( c , "digestAuthMiddleware" )
2018-01-24 20:18:03 +03:00
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-24 20:18:03 +03:00
// Test auth entrypoint
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8008/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "entrypoint.digest.auth.docker.local"
resp , err := try . ResponseUntilStatusCode ( req , 500 * time . Millisecond , http . StatusUnauthorized )
c . Assert ( err , checker . IsNil )
2020-06-18 17:02:04 +03:00
digest := digestParts ( resp )
digest [ "uri" ] = "/"
digest [ "method" ] = http . MethodGet
digest [ "username" ] = "test"
digest [ "password" ] = "wrong"
2018-01-24 20:18:03 +03:00
2020-06-18 17:02:04 +03:00
req . Header . Set ( "Authorization" , getDigestAuthorization ( digest ) )
2018-01-24 20:18:03 +03:00
req . Header . Set ( "Content-Type" , "application/json" )
2020-06-18 17:02:04 +03:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusUnauthorized ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
digest [ "password" ] = "test"
req . Header . Set ( "Authorization" , getDigestAuthorization ( digest ) )
2018-01-24 20:18:03 +03:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-24 20:18:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-24 20:18:03 +03:00
}
// Thanks to mvndaai for digest authentication
// https://stackoverflow.com/questions/39474284/how-do-you-do-a-http-post-with-digest-authentication-in-golang/39481441#39481441
func digestParts ( resp * http . Response ) map [ string ] string {
result := map [ string ] string { }
if len ( resp . Header [ "Www-Authenticate" ] ) > 0 {
wantedHeaders := [ ] string { "nonce" , "realm" , "qop" , "opaque" }
responseHeaders := strings . Split ( resp . Header [ "Www-Authenticate" ] [ 0 ] , "," )
for _ , r := range responseHeaders {
for _ , w := range wantedHeaders {
if strings . Contains ( r , w ) {
result [ w ] = strings . Split ( r , ` " ` ) [ 1 ]
}
}
}
}
return result
}
func getMD5 ( data string ) string {
digest := md5 . New ( )
2018-08-06 21:00:03 +03:00
if _ , err := digest . Write ( [ ] byte ( data ) ) ; err != nil {
2019-09-13 20:28:04 +03:00
log . WithoutContext ( ) . Error ( err )
2018-08-06 21:00:03 +03:00
}
2018-01-24 20:18:03 +03:00
return fmt . Sprintf ( "%x" , digest . Sum ( nil ) )
}
func getCnonce ( ) string {
b := make ( [ ] byte , 8 )
2018-08-06 21:00:03 +03:00
if _ , err := io . ReadFull ( rand . Reader , b ) ; err != nil {
2019-09-13 20:28:04 +03:00
log . WithoutContext ( ) . Error ( err )
2018-08-06 21:00:03 +03:00
}
2018-01-24 20:18:03 +03:00
return fmt . Sprintf ( "%x" , b ) [ : 16 ]
}
func getDigestAuthorization ( digestParts map [ string ] string ) string {
d := digestParts
ha1 := getMD5 ( d [ "username" ] + ":" + d [ "realm" ] + ":" + d [ "password" ] )
ha2 := getMD5 ( d [ "method" ] + ":" + d [ "uri" ] )
nonceCount := "00000001"
cnonce := getCnonce ( )
response := getMD5 ( fmt . Sprintf ( "%s:%s:%s:%s:%s:%s" , ha1 , d [ "nonce" ] , nonceCount , cnonce , d [ "qop" ] , ha2 ) )
authorization := fmt . Sprintf ( ` Digest username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop=%s, response="%s", opaque="%s", algorithm="MD5" ` ,
d [ "username" ] , d [ "realm" ] , d [ "nonce" ] , d [ "uri" ] , cnonce , nonceCount , d [ "qop" ] , response , d [ "opaque" ] )
return authorization
}
2018-01-11 12:04:03 +03:00
func ( s * AccessLogSuite ) TestAccessLogFrontendRedirect ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "302" ,
user : "-" ,
routerName : "rt-frontendRedirect" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
{
formatOnly : true ,
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-11 12:04:03 +03:00
err := cmd . Start ( )
2016-04-28 13:53:02 +03:00
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-11 12:04:03 +03:00
checkStatsForLogFile ( c )
waitForTraefik ( c , "frontendRedirect" )
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
// Test frontend redirect
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8005/test" , nil )
c . Assert ( err , checker . IsNil )
req . Host = ""
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
func ( s * AccessLogSuite ) TestAccessLogRateLimit ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
formatOnly : true ,
} ,
{
formatOnly : true ,
} ,
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "429" ,
user : "-" ,
routerName : "rt-rateLimit" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-11 12:04:03 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-11 12:04:03 +03:00
checkStatsForLogFile ( c )
waitForTraefik ( c , "rateLimit" )
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
// Test rate limit
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8007/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "ratelimit.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusTooManyRequests ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
func ( s * AccessLogSuite ) TestAccessLogBackendNotFound ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "404" ,
user : "-" ,
routerName : "-" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-11 12:04:03 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-11 12:04:03 +03:00
waitForTraefik ( c , "server1" )
checkStatsForLogFile ( c )
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
// Test rate limit
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "backendnotfound.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusNotFound ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
func ( s * AccessLogSuite ) TestAccessLogFrontendWhitelist ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "403" ,
user : "-" ,
routerName : "rt-frontendWhitelist" ,
serviceURL : "-" ,
2018-01-11 12:04:03 +03:00
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
2018-02-05 11:48:03 +03:00
2018-01-11 12:04:03 +03:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-01-11 12:04:03 +03:00
checkStatsForLogFile ( c )
waitForTraefik ( c , "frontendWhitelist" )
// Verify Traefik started OK
2018-02-05 11:48:03 +03:00
checkTraefikStarted ( c )
2018-01-11 12:04:03 +03:00
// Test rate limit
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "frontend.whitelist.docker.local"
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusForbidden ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
2018-02-05 11:48:03 +03:00
count := checkAccessLogExactValuesOutput ( c , expected )
2018-01-11 12:04:03 +03:00
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
2018-02-05 11:48:03 +03:00
checkNoOtherTraefikProblems ( c )
2018-01-11 12:04:03 +03:00
}
2018-10-25 19:00:05 +03:00
func ( s * AccessLogSuite ) TestAccessLogAuthFrontendSuccess ( c * check . C ) {
ensureWorkingDirectoryIsClean ( )
expected := [ ] accessLogValue {
{
2019-01-18 17:18:04 +03:00
formatOnly : false ,
code : "200" ,
user : "test" ,
routerName : "rt-authFrontend" ,
2021-11-25 13:10:06 +03:00
serviceURL : "http://172.31.42" ,
2018-10-25 19:00:05 +03:00
} ,
}
// Start Traefik
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/access_log_config.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2018-10-25 19:00:05 +03:00
checkStatsForLogFile ( c )
waitForTraefik ( c , "authFrontend" )
// Verify Traefik started OK
checkTraefikStarted ( c )
// Test auth entrypoint
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8006/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = "frontend.auth.docker.local"
req . SetBasicAuth ( "test" , "test" )
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasBody ( ) )
c . Assert ( err , checker . IsNil )
// Verify access.log output as expected
count := checkAccessLogExactValuesOutput ( c , expected )
c . Assert ( count , checker . GreaterOrEqualThan , len ( expected ) )
// Verify no other Traefik problems
checkNoOtherTraefikProblems ( c )
}
2018-02-05 11:48:03 +03:00
func checkNoOtherTraefikProblems ( c * check . C ) {
2021-03-04 22:08:03 +03:00
traefikLog , err := os . ReadFile ( traefikTestLogFile )
2018-01-11 12:04:03 +03:00
c . Assert ( err , checker . IsNil )
if len ( traefikLog ) > 0 {
fmt . Printf ( "%s\n" , string ( traefikLog ) )
}
}
2018-02-05 11:48:03 +03:00
func checkAccessLogOutput ( c * check . C ) int {
lines := extractLines ( c )
2016-04-28 13:53:02 +03:00
count := 0
for i , line := range lines {
if len ( line ) > 0 {
count ++
2017-08-11 13:04:58 +03:00
CheckAccessLogFormat ( c , line , i )
2016-04-20 21:54:57 +03:00
}
}
2018-01-11 12:04:03 +03:00
return count
}
2016-04-20 21:54:57 +03:00
2018-02-05 11:48:03 +03:00
func checkAccessLogExactValuesOutput ( c * check . C , values [ ] accessLogValue ) int {
lines := extractLines ( c )
2018-01-11 12:04:03 +03:00
count := 0
for i , line := range lines {
2019-01-18 17:18:04 +03:00
fmt . Println ( line )
2018-01-11 12:04:03 +03:00
if len ( line ) > 0 {
count ++
if values [ i ] . formatOnly {
CheckAccessLogFormat ( c , line , i )
} else {
checkAccessLogExactValues ( c , line , i , values [ i ] )
}
}
}
return count
}
2018-02-05 11:48:03 +03:00
func extractLines ( c * check . C ) [ ] string {
2021-03-04 22:08:03 +03:00
accessLog , err := os . ReadFile ( traefikTestAccessLogFile )
2018-01-11 12:04:03 +03:00
c . Assert ( err , checker . IsNil )
2019-11-14 18:40:05 +03:00
2018-01-11 12:04:03 +03:00
lines := strings . Split ( string ( accessLog ) , "\n" )
2019-11-14 18:40:05 +03:00
var clean [ ] string
for _ , line := range lines {
if ! strings . Contains ( line , "/api/rawdata" ) {
clean = append ( clean , line )
}
}
return clean
2018-01-11 12:04:03 +03:00
}
func checkStatsForLogFile ( c * check . C ) {
err := try . Do ( 1 * time . Second , func ( ) error {
if _ , errStat := os . Stat ( traefikTestLogFile ) ; errStat != nil {
2020-05-11 13:06:07 +03:00
return fmt . Errorf ( "could not get stats for log file: %w" , errStat )
2018-01-11 12:04:03 +03:00
}
return nil
} )
c . Assert ( err , checker . IsNil )
}
func ensureWorkingDirectoryIsClean ( ) {
os . Remove ( traefikTestAccessLogFile )
os . Remove ( traefikTestLogFile )
}
func checkTraefikStarted ( c * check . C ) [ ] byte {
2021-03-04 22:08:03 +03:00
traefikLog , err := os . ReadFile ( traefikTestLogFile )
2016-04-28 13:53:02 +03:00
c . Assert ( err , checker . IsNil )
if len ( traefikLog ) > 0 {
2016-04-20 21:54:57 +03:00
fmt . Printf ( "%s\n" , string ( traefikLog ) )
}
2018-01-11 12:04:03 +03:00
return traefikLog
2016-04-20 21:54:57 +03:00
}
2017-08-11 13:04:58 +03:00
func CheckAccessLogFormat ( c * check . C , line string , i int ) {
2018-03-14 16:12:04 +03:00
results , err := accesslog . ParseAccessLog ( line )
c . Assert ( err , checker . IsNil )
c . Assert ( results , checker . HasLen , 14 )
c . Assert ( results [ accesslog . OriginStatus ] , checker . Matches , ` ^(-|\d { 3})$ ` )
2019-11-14 18:40:05 +03:00
count , _ := strconv . Atoi ( results [ accesslog . RequestCount ] )
c . Assert ( count , checker . GreaterOrEqualThan , i + 1 )
c . Assert ( results [ accesslog . RouterName ] , checker . Matches , ` "(rt-.+@docker|api@internal)" ` )
c . Assert ( results [ accesslog . ServiceURL ] , checker . HasPrefix , ` "http:// ` )
2018-03-14 16:12:04 +03:00
c . Assert ( results [ accesslog . Duration ] , checker . Matches , ` ^\d+ms$ ` )
2017-08-11 13:04:58 +03:00
}
2018-01-11 12:04:03 +03:00
func checkAccessLogExactValues ( c * check . C , line string , i int , v accessLogValue ) {
2018-03-14 16:12:04 +03:00
results , err := accesslog . ParseAccessLog ( line )
2018-01-11 12:04:03 +03:00
c . Assert ( err , checker . IsNil )
2018-03-14 16:12:04 +03:00
c . Assert ( results , checker . HasLen , 14 )
2018-01-24 20:18:03 +03:00
if len ( v . user ) > 0 {
2018-03-14 16:12:04 +03:00
c . Assert ( results [ accesslog . ClientUsername ] , checker . Equals , v . user )
2018-01-24 20:18:03 +03:00
}
2018-03-14 16:12:04 +03:00
c . Assert ( results [ accesslog . OriginStatus ] , checker . Equals , v . code )
2019-11-14 18:40:05 +03:00
count , _ := strconv . Atoi ( results [ accesslog . RequestCount ] )
c . Assert ( count , checker . GreaterOrEqualThan , i + 1 )
2019-06-21 10:54:04 +03:00
c . Assert ( results [ accesslog . RouterName ] , checker . Matches , ` ^"? ` + v . routerName + ` .*(@docker)?$ ` )
2019-01-18 17:18:04 +03:00
c . Assert ( results [ accesslog . ServiceURL ] , checker . Matches , ` ^"? ` + v . serviceURL + ` .*$ ` )
2018-03-14 16:12:04 +03:00
c . Assert ( results [ accesslog . Duration ] , checker . Matches , ` ^\d+ms$ ` )
2018-01-11 12:04:03 +03:00
}
func waitForTraefik ( c * check . C , containerName string ) {
2019-11-14 18:40:05 +03:00
time . Sleep ( 1 * time . Second )
2018-01-11 12:04:03 +03:00
// Wait for Traefik to turn ready.
2019-05-16 11:58:06 +03:00
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8080/api/rawdata" , nil )
2018-01-11 12:04:03 +03:00
c . Assert ( err , checker . IsNil )
err = try . Request ( req , 2 * time . Second , try . StatusCodeIs ( http . StatusOK ) , try . BodyContains ( containerName ) )
c . Assert ( err , checker . IsNil )
2016-04-20 21:54:57 +03:00
}
2018-02-05 11:48:03 +03:00
func displayTraefikLogFile ( c * check . C , path string ) {
if c . Failed ( ) {
if _ , err := os . Stat ( path ) ; ! os . IsNotExist ( err ) {
2021-03-04 22:08:03 +03:00
content , errRead := os . ReadFile ( path )
2018-02-05 11:48:03 +03:00
fmt . Printf ( "%s: Traefik logs: \n" , c . TestName ( ) )
if errRead == nil {
fmt . Println ( content )
} else {
fmt . Println ( errRead )
}
} else {
fmt . Printf ( "%s: No Traefik logs.\n" , c . TestName ( ) )
}
errRemove := os . Remove ( path )
if errRemove != nil {
fmt . Println ( errRemove )
}
}
}