2019-03-11 16:54:05 +03:00
package integration
import (
2019-06-11 16:12:04 +03:00
"bytes"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
2019-03-11 16:54:05 +03:00
"net/http"
"os"
"path/filepath"
2019-06-11 16:12:04 +03:00
"regexp"
2019-03-11 16:54:05 +03:00
"time"
"github.com/go-check/check"
2019-06-11 16:12:04 +03:00
"github.com/pmezard/go-difflib/difflib"
2022-11-21 20:36:05 +03:00
"github.com/rs/zerolog/log"
2020-09-16 16:46:04 +03:00
"github.com/traefik/traefik/v2/integration/try"
"github.com/traefik/traefik/v2/pkg/api"
2019-03-11 16:54:05 +03:00
checker "github.com/vdemeester/shakers"
)
2019-06-11 16:12:04 +03:00
var updateExpected = flag . Bool ( "update_expected" , false , "Update expected files in testdata" )
2020-05-11 13:06:07 +03:00
// K8sSuite tests suite.
2019-03-11 16:54:05 +03:00
type K8sSuite struct { BaseSuite }
func ( s * K8sSuite ) SetUpSuite ( c * check . C ) {
s . createComposeProject ( c , "k8s" )
2021-11-25 13:10:06 +03:00
s . composeUp ( c )
2019-03-11 16:54:05 +03:00
2019-08-11 13:22:14 +03:00
abs , err := filepath . Abs ( "./fixtures/k8s/config.skip/kubeconfig.yaml" )
2019-03-11 16:54:05 +03:00
c . Assert ( err , checker . IsNil )
2020-02-24 18:06:05 +03:00
err = try . Do ( 60 * time . Second , func ( ) error {
2019-03-11 16:54:05 +03:00
_ , err := os . Stat ( abs )
return err
2020-02-24 18:06:05 +03:00
} )
2019-03-11 16:54:05 +03:00
c . Assert ( err , checker . IsNil )
err = os . Setenv ( "KUBECONFIG" , abs )
c . Assert ( err , checker . IsNil )
2019-03-14 17:56:06 +03:00
}
func ( s * K8sSuite ) TearDownSuite ( c * check . C ) {
2021-11-25 13:10:06 +03:00
s . composeDown ( c )
2019-03-14 17:56:06 +03:00
2019-08-11 13:22:14 +03:00
generatedFiles := [ ] string {
"./fixtures/k8s/config.skip/kubeconfig.yaml" ,
"./fixtures/k8s/config.skip/k3s.log" ,
"./fixtures/k8s/coredns.yaml" ,
"./fixtures/k8s/rolebindings.yaml" ,
"./fixtures/k8s/traefik.yaml" ,
2020-12-10 16:58:04 +03:00
"./fixtures/k8s/ccm.yaml" ,
2019-03-14 17:56:06 +03:00
}
2019-08-11 13:22:14 +03:00
for _ , filename := range generatedFiles {
2021-11-25 13:10:06 +03:00
if err := os . Remove ( filename ) ; err != nil {
2022-11-21 20:36:05 +03:00
log . Warn ( ) . Err ( err ) . Send ( )
2019-08-11 13:22:14 +03:00
}
2019-03-14 17:56:06 +03:00
}
}
2019-03-11 16:54:05 +03:00
2019-06-11 16:12:04 +03:00
func ( s * K8sSuite ) TestIngressConfiguration ( c * check . C ) {
2019-03-11 16:54:05 +03:00
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_default.toml" ) )
defer display ( c )
2019-03-14 17:56:06 +03:00
err := cmd . Start ( )
2019-03-11 16:54:05 +03:00
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2019-03-11 16:54:05 +03:00
2019-11-14 21:28:04 +03:00
testConfiguration ( c , "testdata/rawdata-ingress.json" , "8080" )
2019-03-14 17:56:06 +03:00
}
2020-11-20 02:18:04 +03:00
func ( s * K8sSuite ) TestIngressLabelSelector ( c * check . C ) {
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_ingress_label_selector.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
testConfiguration ( c , "testdata/rawdata-ingress-label-selector.json" , "8080" )
}
2019-06-11 16:12:04 +03:00
func ( s * K8sSuite ) TestCRDConfiguration ( c * check . C ) {
2019-03-14 17:56:06 +03:00
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_crd.toml" ) )
defer display ( c )
2019-03-11 16:54:05 +03:00
2019-03-14 17:56:06 +03:00
err := cmd . Start ( )
2019-03-11 16:54:05 +03:00
c . Assert ( err , checker . IsNil )
2020-10-09 10:32:03 +03:00
defer s . killCmd ( cmd )
2019-03-11 16:54:05 +03:00
2019-11-14 21:28:04 +03:00
testConfiguration ( c , "testdata/rawdata-crd.json" , "8000" )
2019-06-11 16:12:04 +03:00
}
2020-11-20 02:18:04 +03:00
func ( s * K8sSuite ) TestCRDLabelSelector ( c * check . C ) {
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_crd_label_selector.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
testConfiguration ( c , "testdata/rawdata-crd-label-selector.json" , "8000" )
}
2020-12-15 18:40:05 +03:00
func ( s * K8sSuite ) TestGatewayConfiguration ( c * check . C ) {
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_gateway.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
testConfiguration ( c , "testdata/rawdata-gateway.json" , "8080" )
}
2021-03-02 23:34:03 +03:00
func ( s * K8sSuite ) TestIngressclass ( c * check . C ) {
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/k8s_ingressclass.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
testConfiguration ( c , "testdata/rawdata-ingressclass.json" , "8080" )
}
2019-11-14 21:28:04 +03:00
func testConfiguration ( c * check . C , path , apiPort string ) {
err := try . GetRequest ( "http://127.0.0.1:" + apiPort + "/api/entrypoints" , 20 * time . Second , try . BodyContains ( ` "name":"web" ` ) )
2019-08-11 13:22:14 +03:00
c . Assert ( err , checker . IsNil )
2019-06-11 16:12:04 +03:00
expectedJSON := filepath . FromSlash ( path )
if * updateExpected {
fi , err := os . Create ( expectedJSON )
c . Assert ( err , checker . IsNil )
err = fi . Close ( )
c . Assert ( err , checker . IsNil )
}
var buf bytes . Buffer
2020-02-24 18:06:05 +03:00
err = try . GetRequest ( "http://127.0.0.1:" + apiPort + "/api/rawdata" , 1 * time . Minute , try . StatusCodeIs ( http . StatusOK ) , matchesConfig ( expectedJSON , & buf ) )
2019-03-11 16:54:05 +03:00
2019-06-11 16:12:04 +03:00
if ! * updateExpected {
if err != nil {
c . Error ( err )
}
return
}
if err != nil {
c . Logf ( "In file update mode, got expected error: %v" , err )
}
var rtRepr api . RunTimeRepresentation
err = json . Unmarshal ( buf . Bytes ( ) , & rtRepr )
2019-03-14 17:56:06 +03:00
c . Assert ( err , checker . IsNil )
2019-03-11 16:54:05 +03:00
2019-06-11 16:12:04 +03:00
newJSON , err := json . MarshalIndent ( rtRepr , "" , "\t" )
2019-03-14 17:56:06 +03:00
c . Assert ( err , checker . IsNil )
2019-03-11 16:54:05 +03:00
2021-03-04 22:08:03 +03:00
err = os . WriteFile ( expectedJSON , newJSON , 0 o644 )
2019-03-11 16:54:05 +03:00
c . Assert ( err , checker . IsNil )
2019-06-11 16:12:04 +03:00
c . Errorf ( "We do not want a passing test in file update mode" )
}
func matchesConfig ( wantConfig string , buf * bytes . Buffer ) try . ResponseCondition {
return func ( res * http . Response ) error {
2021-03-04 22:08:03 +03:00
body , err := io . ReadAll ( res . Body )
2019-06-11 16:12:04 +03:00
if err != nil {
2020-05-11 13:06:07 +03:00
return fmt . Errorf ( "failed to read response body: %w" , err )
2019-06-11 16:12:04 +03:00
}
if err := res . Body . Close ( ) ; err != nil {
return err
}
var obtained api . RunTimeRepresentation
err = json . Unmarshal ( body , & obtained )
if err != nil {
return err
}
if buf != nil {
buf . Reset ( )
if _ , err := io . Copy ( buf , bytes . NewReader ( body ) ) ; err != nil {
return err
}
}
got , err := json . MarshalIndent ( obtained , "" , "\t" )
if err != nil {
return err
}
2021-03-04 22:08:03 +03:00
expected , err := os . ReadFile ( wantConfig )
2019-06-11 16:12:04 +03:00
if err != nil {
return err
}
// The pods IPs are dynamic, so we cannot predict them,
// which is why we have to ignore them in the comparison.
rxURL := regexp . MustCompile ( ` "(url|address)":\s+(".*") ` )
sanitizedExpected := rxURL . ReplaceAll ( expected , [ ] byte ( ` "$1": "XXXX" ` ) )
sanitizedGot := rxURL . ReplaceAll ( got , [ ] byte ( ` "$1": "XXXX" ` ) )
rxServerStatus := regexp . MustCompile ( ` "http://.*?":\s+(".*") ` )
sanitizedExpected = rxServerStatus . ReplaceAll ( sanitizedExpected , [ ] byte ( ` "http://XXXX": $1 ` ) )
sanitizedGot = rxServerStatus . ReplaceAll ( sanitizedGot , [ ] byte ( ` "http://XXXX": $1 ` ) )
if bytes . Equal ( sanitizedExpected , sanitizedGot ) {
return nil
}
diff := difflib . UnifiedDiff {
FromFile : "Expected" ,
A : difflib . SplitLines ( string ( sanitizedExpected ) ) ,
ToFile : "Got" ,
B : difflib . SplitLines ( string ( sanitizedGot ) ) ,
Context : 3 ,
}
text , err := difflib . GetUnifiedDiffString ( diff )
if err != nil {
return err
}
return errors . New ( text )
}
2019-03-11 16:54:05 +03:00
}