2015-11-13 13:50:32 +03:00
package provider
import (
"io/ioutil"
"os"
"strings"
"testing"
"text/template"
2016-05-20 18:17:38 +03:00
"github.com/containous/traefik/types"
2015-11-13 13:50:32 +03:00
)
type myProvider struct {
2016-01-14 00:46:44 +03:00
BaseProvider
2016-08-14 05:05:43 +03:00
TLS * ClientTLS
2015-11-13 13:50:32 +03:00
}
func ( p * myProvider ) Foo ( ) string {
return "bar"
}
func TestConfigurationErrors ( t * testing . T ) {
templateErrorFile , err := ioutil . TempFile ( "" , "provider-configuration-error" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( templateErrorFile . Name ( ) )
data := [ ] byte ( "Not a valid template {{ Bar }}" )
err = ioutil . WriteFile ( templateErrorFile . Name ( ) , data , 0700 )
if err != nil {
t . Fatal ( err )
}
templateInvalidTOMLFile , err := ioutil . TempFile ( "" , "provider-configuration-error" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( templateInvalidTOMLFile . Name ( ) )
data = [ ] byte ( ` Hello { { . Name } }
{ { Foo } } ` )
err = ioutil . WriteFile ( templateInvalidTOMLFile . Name ( ) , data , 0700 )
if err != nil {
t . Fatal ( err )
}
invalids := [ ] struct {
provider * myProvider
defaultTemplate string
expectedError string
funcMap template . FuncMap
templateObjects interface { }
} {
{
provider : & myProvider {
2016-01-14 00:46:44 +03:00
BaseProvider {
2015-11-13 13:50:32 +03:00
Filename : "/non/existent/template.tmpl" ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2015-11-13 13:50:32 +03:00
} ,
expectedError : "open /non/existent/template.tmpl: no such file or directory" ,
} ,
{
provider : & myProvider { } ,
defaultTemplate : "non/existent/template.tmpl" ,
expectedError : "Asset non/existent/template.tmpl not found" ,
} ,
{
provider : & myProvider {
2016-01-14 00:46:44 +03:00
BaseProvider {
2015-11-13 13:50:32 +03:00
Filename : templateErrorFile . Name ( ) ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2015-11-13 13:50:32 +03:00
} ,
expectedError : ` function "Bar" not defined ` ,
} ,
{
provider : & myProvider {
2016-01-14 00:46:44 +03:00
BaseProvider {
2015-11-13 13:50:32 +03:00
Filename : templateInvalidTOMLFile . Name ( ) ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2015-11-13 13:50:32 +03:00
} ,
2017-04-11 18:10:46 +03:00
expectedError : "Near line 1 (last key parsed 'Hello'): expected key separator '=', but got '<' instead" ,
2015-11-13 13:50:32 +03:00
funcMap : template . FuncMap {
"Foo" : func ( ) string {
return "bar"
} ,
} ,
templateObjects : struct { Name string } { Name : "bar" } ,
} ,
}
for _ , invalid := range invalids {
2017-04-15 16:49:53 +03:00
configuration , err := invalid . provider . GetConfiguration ( invalid . defaultTemplate , invalid . funcMap , nil )
2015-11-13 13:50:32 +03:00
if err == nil || ! strings . Contains ( err . Error ( ) , invalid . expectedError ) {
t . Fatalf ( "should have generate an error with %q, got %v" , invalid . expectedError , err )
}
if configuration != nil {
t . Fatalf ( "shouldn't have return a configuration object : %v" , configuration )
}
}
}
func TestGetConfiguration ( t * testing . T ) {
templateFile , err := ioutil . TempFile ( "" , "provider-configuration" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( templateFile . Name ( ) )
data := [ ] byte ( ` [ backends ]
[ backends . backend1 ]
[ backends . backend1 . circuitbreaker ]
expression = "NetworkErrorRatio() > 0.5"
[ backends . backend1 . servers . server1 ]
url = "http://172.17.0.2:80"
weight = 10
[ backends . backend1 . servers . server2 ]
url = "http://172.17.0.3:80"
weight = 1
[ frontends ]
[ frontends . frontend1 ]
backend = "backend1"
passHostHeader = true
[ frontends . frontend11 . routes . test_2 ]
rule = "Path"
value = "/test" ` )
err = ioutil . WriteFile ( templateFile . Name ( ) , data , 0700 )
if err != nil {
t . Fatal ( err )
}
provider := & myProvider {
2016-01-14 00:46:44 +03:00
BaseProvider {
2015-11-13 13:50:32 +03:00
Filename : templateFile . Name ( ) ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2015-11-13 13:50:32 +03:00
}
2017-04-15 16:49:53 +03:00
configuration , err := provider . GetConfiguration ( templateFile . Name ( ) , nil , nil )
2015-11-13 13:50:32 +03:00
if err != nil {
t . Fatalf ( "Shouldn't have error out, got %v" , err )
}
if configuration == nil {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Configuration should not be nil, but was" )
2015-11-13 13:50:32 +03:00
}
}
func TestReplace ( t * testing . T ) {
cases := [ ] struct {
str string
expected string
} {
{
str : "" ,
expected : "" ,
} ,
{
str : "foo" ,
expected : "bar" ,
} ,
{
str : "foo foo" ,
expected : "bar bar" ,
} ,
{
str : "somethingfoo" ,
expected : "somethingbar" ,
} ,
}
for _ , c := range cases {
2017-04-17 13:50:02 +03:00
actual := Replace ( "foo" , "bar" , c . str )
2015-11-13 13:50:32 +03:00
if actual != c . expected {
t . Fatalf ( "expected %q, got %q, for %q" , c . expected , actual , c . str )
}
}
}
2016-04-13 11:11:36 +03:00
func TestGetConfigurationReturnsCorrectMaxConnConfiguration ( t * testing . T ) {
templateFile , err := ioutil . TempFile ( "" , "provider-configuration" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( templateFile . Name ( ) )
data := [ ] byte ( ` [ backends ]
[ backends . backend1 ]
[ backends . backend1 . maxconn ]
amount = 10
extractorFunc = "request.host" ` )
err = ioutil . WriteFile ( templateFile . Name ( ) , data , 0700 )
if err != nil {
t . Fatal ( err )
}
provider := & myProvider {
BaseProvider {
Filename : templateFile . Name ( ) ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2016-04-13 11:11:36 +03:00
}
2017-04-15 16:49:53 +03:00
configuration , err := provider . GetConfiguration ( templateFile . Name ( ) , nil , nil )
2016-04-13 11:11:36 +03:00
if err != nil {
t . Fatalf ( "Shouldn't have error out, got %v" , err )
}
if configuration == nil {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Configuration should not be nil, but was" )
2016-04-13 11:11:36 +03:00
}
if configuration . Backends [ "backend1" ] . MaxConn . Amount != 10 {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Configuration did not parse MaxConn.Amount properly" )
2016-04-13 11:11:36 +03:00
}
if configuration . Backends [ "backend1" ] . MaxConn . ExtractorFunc != "request.host" {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Configuration did not parse MaxConn.ExtractorFunc properly" )
2016-04-13 11:11:36 +03:00
}
}
2016-05-20 18:17:38 +03:00
2016-08-14 05:05:43 +03:00
func TestNilClientTLS ( t * testing . T ) {
provider := & myProvider {
BaseProvider {
Filename : "" ,
} ,
nil ,
}
_ , err := provider . TLS . CreateTLSConfig ( )
if err != nil {
2017-05-26 18:03:14 +03:00
t . Fatal ( "CreateTLSConfig should assume that consumer does not want a TLS configuration if input is nil" )
2016-08-14 05:05:43 +03:00
}
}
2016-05-20 18:17:38 +03:00
func TestMatchingConstraints ( t * testing . T ) {
cases := [ ] struct {
2016-11-09 21:27:04 +03:00
constraints types . Constraints
2016-05-20 18:17:38 +03:00
tags [ ] string
expected bool
} {
// simple test: must match
{
2016-11-09 21:27:04 +03:00
constraints : types . Constraints {
2016-05-20 18:17:38 +03:00
{
Key : "tag" ,
MustMatch : true ,
Regex : "us-east-1" ,
} ,
} ,
tags : [ ] string {
"us-east-1" ,
} ,
expected : true ,
} ,
// simple test: must match but does not match
{
2016-11-09 21:27:04 +03:00
constraints : types . Constraints {
2016-05-20 18:17:38 +03:00
{
Key : "tag" ,
MustMatch : true ,
Regex : "us-east-1" ,
} ,
} ,
tags : [ ] string {
"us-east-2" ,
} ,
expected : false ,
} ,
// simple test: must not match
{
2016-11-09 21:27:04 +03:00
constraints : types . Constraints {
2016-05-20 18:17:38 +03:00
{
Key : "tag" ,
MustMatch : false ,
Regex : "us-east-1" ,
} ,
} ,
tags : [ ] string {
"us-east-1" ,
} ,
expected : false ,
} ,
// complex test: globbing
{
2016-11-09 21:27:04 +03:00
constraints : types . Constraints {
2016-05-20 18:17:38 +03:00
{
Key : "tag" ,
MustMatch : true ,
Regex : "us-east-*" ,
} ,
} ,
tags : [ ] string {
"us-east-1" ,
} ,
expected : true ,
} ,
// complex test: multiple constraints
{
2016-11-09 21:27:04 +03:00
constraints : types . Constraints {
2016-05-20 18:17:38 +03:00
{
Key : "tag" ,
MustMatch : true ,
Regex : "us-east-*" ,
} ,
{
Key : "tag" ,
MustMatch : false ,
Regex : "api" ,
} ,
} ,
tags : [ ] string {
"api" ,
"us-east-1" ,
} ,
expected : false ,
} ,
}
for i , c := range cases {
provider := myProvider {
BaseProvider {
Constraints : c . constraints ,
} ,
2016-08-14 05:05:43 +03:00
nil ,
2016-05-20 18:17:38 +03:00
}
actual , _ := provider . MatchConstraints ( c . tags )
if actual != c . expected {
2016-08-14 05:05:43 +03:00
t . Fatalf ( "test #%v: expected %t, got %t, for %#v" , i , c . expected , actual , c . constraints )
2016-05-20 18:17:38 +03:00
}
}
}
2016-12-03 12:12:22 +03:00
func TestDefaultFuncMap ( t * testing . T ) {
templateFile , err := ioutil . TempFile ( "" , "provider-configuration" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( templateFile . Name ( ) )
data := [ ] byte ( `
[ backends ]
[ backends . { { "backend-1" | replace "-" "" } } ]
[ backends . { { "BACKEND1" | tolower } } . circuitbreaker ]
expression = "NetworkErrorRatio() > 0.5"
[ backends . servers . server1 ]
url = "http://172.17.0.2:80"
weight = 10
[ backends . backend1 . servers . server2 ]
url = "http://172.17.0.3:80"
weight = 1
[ frontends ]
2017-04-15 17:46:44 +03:00
[ frontends . { { normalize "frontend/1" } } ]
2016-12-03 12:12:22 +03:00
{ { $ backend := "backend1/test/value" | split "/" } }
{ { $ backendid := index $ backend 1 } }
{ { if "backend1" | contains "backend" } }
backend = "backend1"
{ { end } }
passHostHeader = true
[ frontends . frontend - 1. routes . test_2 ]
rule = "Path"
value = "/test" ` )
err = ioutil . WriteFile ( templateFile . Name ( ) , data , 0700 )
if err != nil {
t . Fatal ( err )
}
provider := & myProvider {
BaseProvider {
Filename : templateFile . Name ( ) ,
} ,
nil ,
}
2017-04-15 16:49:53 +03:00
configuration , err := provider . GetConfiguration ( templateFile . Name ( ) , nil , nil )
2016-12-03 12:12:22 +03:00
if err != nil {
t . Fatalf ( "Shouldn't have error out, got %v" , err )
}
if configuration == nil {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Configuration should not be nil, but was" )
2016-12-03 12:12:22 +03:00
}
if _ , ok := configuration . Backends [ "backend1" ] ; ! ok {
2017-05-26 18:03:14 +03:00
t . Fatal ( "backend1 should exists, but it not" )
2016-12-03 12:12:22 +03:00
}
if _ , ok := configuration . Frontends [ "frontend-1" ] ; ! ok {
2017-05-26 18:03:14 +03:00
t . Fatal ( "Frontend frontend-1 should exists, but it not" )
2016-12-03 12:12:22 +03:00
}
}