2016-08-19 17:14:17 -07:00
package kubernetes
2016-07-22 16:07:27 -07:00
import (
"strings"
"testing"
2016-08-08 14:30:04 -07:00
"time"
2016-08-12 20:44:08 -07:00
2016-08-19 17:14:17 -07:00
"github.com/mholt/caddy"
2016-08-12 20:44:08 -07:00
unversionedapi "k8s.io/kubernetes/pkg/api/unversioned"
2016-07-22 16:07:27 -07:00
)
func TestKubernetesParse ( t * testing . T ) {
tests := [ ] struct {
2016-08-12 20:44:08 -07:00
description string // Human-facing description of test case
input string // Corefile data as string
shouldErr bool // true if test case is exected to produce an error.
expectedErrContent string // substring from the expected error. Empty for positive cases.
expectedZoneCount int // expected count of defined zones.
expectedNTValid bool // NameTemplate to be initialized and valid
expectedNSCount int // expected count of namespaces.
expectedResyncPeriod time . Duration // expected resync period value
expectedLabelSelector string // expected label selector value
2016-07-22 16:07:27 -07:00
} {
// positive
{
2016-08-05 18:19:51 -07:00
"kubernetes keyword with one zone" ,
` kubernetes coredns.local ` ,
2016-07-22 16:07:27 -07:00
false ,
"" ,
2016-08-05 18:19:51 -07:00
1 ,
2016-07-22 16:07:27 -07:00
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"kubernetes keyword with multiple zones" ,
` kubernetes coredns.local test.local ` ,
2016-07-22 16:07:27 -07:00
false ,
"" ,
2016-08-05 18:19:51 -07:00
2 ,
2016-07-22 16:07:27 -07:00
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"kubernetes keyword with zone and empty braces" ,
` kubernetes coredns . local {
} ` ,
2016-07-22 16:07:27 -07:00
false ,
"" ,
2016-08-05 18:19:51 -07:00
1 ,
2016-07-22 16:07:27 -07:00
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"endpoint keyword with url" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
2016-08-05 18:19:51 -07:00
endpoint http : //localhost:9090
2016-07-22 16:07:27 -07:00
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"template keyword with valid template" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
template { service } . { namespace } . { zone }
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"namespaces keyword with one namespace" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
namespaces demo
} ` ,
false ,
"" ,
1 ,
true ,
1 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"namespaces keyword with multiple namespaces" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
namespaces demo test
} ` ,
false ,
"" ,
1 ,
true ,
2 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-08 14:30:04 -07:00
} ,
{
"resync period in seconds" ,
` kubernetes coredns . local {
resyncperiod 30 s
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
30 * time . Second ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-08 14:30:04 -07:00
} ,
{
"resync period in minutes" ,
` kubernetes coredns . local {
resyncperiod 15 m
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
15 * time . Minute ,
2016-08-12 20:44:08 -07:00
"" ,
} ,
{
"basic label selector" ,
` kubernetes coredns . local {
labels environment = prod
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
defaultResyncPeriod ,
"environment=prod" ,
} ,
{
"multi-label selector" ,
` kubernetes coredns . local {
labels environment in ( production , staging , qa ) , application = nginx
} ` ,
false ,
"" ,
1 ,
true ,
0 ,
defaultResyncPeriod ,
"application=nginx,environment in (production,qa,staging)" ,
2016-07-22 16:07:27 -07:00
} ,
2016-08-05 18:19:51 -07:00
{
"fully specified valid config" ,
` kubernetes coredns . local test . local {
2016-08-08 14:30:04 -07:00
resyncperiod 15 m
2016-08-05 18:19:51 -07:00
endpoint http : //localhost:8080
template { service } . { namespace } . { zone }
namespaces demo test
2016-08-12 20:44:08 -07:00
labels environment in ( production , staging , qa ) , application = nginx
2016-08-05 18:19:51 -07:00
} ` ,
false ,
"" ,
2 ,
true ,
2 ,
2016-08-08 14:30:04 -07:00
15 * time . Minute ,
2016-08-12 20:44:08 -07:00
"application=nginx,environment in (production,qa,staging)" ,
2016-08-05 18:19:51 -07:00
} ,
2016-07-22 16:07:27 -07:00
// negative
{
2016-08-05 18:19:51 -07:00
"no kubernetes keyword" ,
"" ,
true ,
"Kubernetes setup called without keyword 'kubernetes' in Corefile" ,
- 1 ,
false ,
- 1 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-05 18:19:51 -07:00
} ,
{
"kubernetes keyword without a zone" ,
` kubernetes ` ,
true ,
"Zone name must be provided for kubernetes middleware" ,
- 1 ,
true ,
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-05 18:19:51 -07:00
} ,
{
"endpoint keyword without an endpoint value" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
endpoint
} ` ,
true ,
"Wrong argument count or unexpected line ending after 'endpoint'" ,
- 1 ,
true ,
- 1 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"template keyword without a template value" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
template
} ` ,
true ,
2016-08-05 18:19:51 -07:00
"Wrong argument count or unexpected line ending after 'template'" ,
2016-07-22 16:07:27 -07:00
- 1 ,
false ,
2016-08-05 18:19:51 -07:00
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-07-22 16:07:27 -07:00
} ,
{
2016-08-05 18:19:51 -07:00
"template keyword with an invalid template value" ,
2016-07-22 16:07:27 -07:00
` kubernetes coredns . local {
template { namespace } . { zone }
} ` ,
true ,
2016-08-05 18:19:51 -07:00
"Record name template does not pass NameTemplate validation" ,
2016-07-22 16:07:27 -07:00
- 1 ,
false ,
2016-08-05 18:19:51 -07:00
0 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-05 18:19:51 -07:00
} ,
{
"namespace keyword without a namespace value" ,
` kubernetes coredns . local {
namespaces
} ` ,
true ,
"Parse error: Wrong argument count or unexpected line ending after 'namespaces'" ,
- 1 ,
true ,
2016-07-22 16:07:27 -07:00
- 1 ,
2016-08-08 14:30:04 -07:00
defaultResyncPeriod ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-08 14:30:04 -07:00
} ,
{
"resyncperiod keyword without a duration value" ,
` kubernetes coredns . local {
resyncperiod
} ` ,
true ,
"Wrong argument count or unexpected line ending after 'resyncperiod'" ,
- 1 ,
true ,
0 ,
0 * time . Minute ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-08 14:30:04 -07:00
} ,
{
"resync period no units" ,
` kubernetes coredns . local {
resyncperiod 15
} ` ,
true ,
"Unable to parse resync duration value. Value provided was " ,
- 1 ,
true ,
0 ,
0 * time . Second ,
2016-08-12 20:44:08 -07:00
"" ,
2016-08-08 14:30:04 -07:00
} ,
{
"resync period invalid" ,
` kubernetes coredns . local {
resyncperiod abc
} ` ,
true ,
"Unable to parse resync duration value. Value provided was " ,
- 1 ,
true ,
0 ,
0 * time . Second ,
2016-08-12 20:44:08 -07:00
"" ,
} ,
{
"labels with no selector value" ,
` kubernetes coredns . local {
labels
} ` ,
true ,
"Wrong argument count or unexpected line ending after 'labels'" ,
- 1 ,
true ,
0 ,
0 * time . Second ,
"" ,
} ,
{
"labels with invalid selector value" ,
` kubernetes coredns . local {
labels environment in ( production , qa
} ` ,
true ,
"Unable to parse label selector. Value provided was" ,
- 1 ,
true ,
0 ,
0 * time . Second ,
"" ,
2016-07-22 16:07:27 -07:00
} ,
}
2016-08-05 18:19:51 -07:00
t . Logf ( "Parser test cases count: %v" , len ( tests ) )
2016-07-22 16:07:27 -07:00
for i , test := range tests {
2016-08-19 17:14:17 -07:00
c := caddy . NewTestController ( "dns" , test . input )
2016-07-22 16:07:27 -07:00
k8sController , err := kubernetesParse ( c )
2016-08-05 18:19:51 -07:00
t . Logf ( "setup test: %2v -- %v\n" , i , test . description )
//t.Logf("controller: %v\n", k8sController)
2016-07-22 16:07:27 -07:00
if test . shouldErr && err == nil {
2016-08-05 18:19:51 -07:00
t . Errorf ( "Test %d: Expected error, but did not find error for input '%s'. Error was: '%v'" , i , test . input , err )
2016-07-22 16:07:27 -07:00
}
if err != nil {
if ! test . shouldErr {
t . Errorf ( "Test %d: Expected no error but found one for input %s. Error was: %v" , i , test . input , err )
2016-08-05 18:19:51 -07:00
continue
2016-07-22 16:07:27 -07:00
}
if test . shouldErr && ( len ( test . expectedErrContent ) < 1 ) {
t . Fatalf ( "Test %d: Test marked as expecting an error, but no expectedErrContent provided for input '%s'. Error was: '%v'" , i , test . input , err )
}
if test . shouldErr && ( test . expectedZoneCount >= 0 ) {
2016-08-05 18:19:51 -07:00
t . Errorf ( "Test %d: Test marked as expecting an error, but provides value for expectedZoneCount!=-1 for input '%s'. Error was: '%v'" , i , test . input , err )
2016-07-22 16:07:27 -07:00
}
if ! strings . Contains ( err . Error ( ) , test . expectedErrContent ) {
t . Errorf ( "Test %d: Expected error to contain: %v, found error: %v, input: %s" , i , test . expectedErrContent , err , test . input )
}
2016-08-05 18:19:51 -07:00
continue
2016-07-22 16:07:27 -07:00
}
// No error was raised, so validate initialization of k8sController
// Zones
foundZoneCount := len ( k8sController . Zones )
if foundZoneCount != test . expectedZoneCount {
t . Errorf ( "Test %d: Expected kubernetes controller to be initialized with %d zones, instead found %d zones: '%v' for input '%s'" , i , test . expectedZoneCount , foundZoneCount , k8sController . Zones , test . input )
}
// NameTemplate
if k8sController . NameTemplate == nil {
t . Errorf ( "Test %d: Expected kubernetes controller to be initialized with a NameTemplate. Instead found '%v' for input '%s'" , i , k8sController . NameTemplate , test . input )
} else {
foundNTValid := k8sController . NameTemplate . IsValid ( )
if foundNTValid != test . expectedNTValid {
t . Errorf ( "Test %d: Expected NameTemplate validity to be '%v', instead found '%v' for input '%s'" , i , test . expectedNTValid , foundNTValid , test . input )
}
}
// Namespaces
foundNSCount := len ( k8sController . Namespaces )
if foundNSCount != test . expectedNSCount {
t . Errorf ( "Test %d: Expected kubernetes controller to be initialized with %d namespaces. Instead found %d namespaces: '%v' for input '%s'" , i , test . expectedNSCount , foundNSCount , k8sController . Namespaces , test . input )
2016-08-08 14:30:04 -07:00
}
// ResyncPeriod
foundResyncPeriod := k8sController . ResyncPeriod
if foundResyncPeriod != test . expectedResyncPeriod {
2016-08-12 20:44:08 -07:00
t . Errorf ( "Test %d: Expected kubernetes controller to be initialized with resync period '%s'. Instead found period '%s' for input '%s'" , i , test . expectedResyncPeriod , foundResyncPeriod , test . input )
}
// Labels
if k8sController . LabelSelector != nil {
foundLabelSelectorString := unversionedapi . FormatLabelSelector ( k8sController . LabelSelector )
if foundLabelSelectorString != test . expectedLabelSelector {
t . Errorf ( "Test %d: Expected kubernetes controller to be initialized with label selector '%s'. Instead found selector '%s' for input '%s'" , i , test . expectedLabelSelector , foundLabelSelectorString , test . input )
}
2016-07-22 16:07:27 -07:00
}
}
}