Add namespace_labels configuration for kubernetes plugin (#2707)

This commit is contained in:
Matt Greenfield 2019-03-22 08:32:40 -06:00 committed by Miek Gieben
parent 43c3e0ab68
commit a3dd8cdf8d
9 changed files with 278 additions and 40 deletions

View file

@ -56,6 +56,11 @@ kubernetes [ZONES...] {
* `kubeconfig` **KUBECONFIG** **CONTEXT** authenticates the connection to a remote k8s cluster using a kubeconfig file. It supports TLS, username and password, or token-based authentication. This option is ignored if connecting in-cluster (i.e., the endpoint is not specified). * `kubeconfig` **KUBECONFIG** **CONTEXT** authenticates the connection to a remote k8s cluster using a kubeconfig file. It supports TLS, username and password, or token-based authentication. This option is ignored if connecting in-cluster (i.e., the endpoint is not specified).
* `namespaces` **NAMESPACE [NAMESPACE...]** only exposes the k8s namespaces listed. * `namespaces` **NAMESPACE [NAMESPACE...]** only exposes the k8s namespaces listed.
If this option is omitted all namespaces are exposed If this option is omitted all namespaces are exposed
* `namespace_labels` **EXPRESSION** only expose the records for Kubernetes namespaces that match this label selector.
The label selector syntax is described in the
[Kubernetes User Guide - Labels](http://kubernetes.io/docs/user-guide/labels/). An example that
only exposes namespaces labeled as "istio-injection=enabled", would use:
`labels istio-injection=enabled`.
* `labels` **EXPRESSION** only exposes the records for Kubernetes objects that match this label selector. * `labels` **EXPRESSION** only exposes the records for Kubernetes objects that match this label selector.
The label selector syntax is described in the The label selector syntax is described in the
[Kubernetes User Guide - Labels](https://kubernetes.io/docs/user-guide/labels/). An example that [Kubernetes User Guide - Labels](https://kubernetes.io/docs/user-guide/labels/). An example that

View file

@ -54,6 +54,7 @@ type dnsControl struct {
client kubernetes.Interface client kubernetes.Interface
selector labels.Selector selector labels.Selector
namespaceSelector labels.Selector
svcController cache.Controller svcController cache.Controller
podController cache.Controller podController cache.Controller
@ -81,9 +82,12 @@ type dnsControlOpts struct {
initEndpointsCache bool initEndpointsCache bool
resyncPeriod time.Duration resyncPeriod time.Duration
ignoreEmptyService bool ignoreEmptyService bool
// Label handling. // Label handling.
labelSelector *meta.LabelSelector labelSelector *meta.LabelSelector
selector labels.Selector selector labels.Selector
namespaceLabelSelector *meta.LabelSelector
namespaceSelector labels.Selector
zones []string zones []string
endpointNameMode bool endpointNameMode bool
@ -94,6 +98,7 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns
dns := dnsControl{ dns := dnsControl{
client: kubeClient, client: kubeClient,
selector: opts.selector, selector: opts.selector,
namespaceSelector: opts.namespaceSelector,
stopCh: make(chan struct{}), stopCh: make(chan struct{}),
zones: opts.zones, zones: opts.zones,
endpointNameMode: opts.endpointNameMode, endpointNameMode: opts.endpointNameMode,
@ -140,10 +145,12 @@ func newdnsController(kubeClient kubernetes.Interface, opts dnsControlOpts) *dns
dns.nsLister, dns.nsController = cache.NewInformer( dns.nsLister, dns.nsController = cache.NewInformer(
&cache.ListWatch{ &cache.ListWatch{
ListFunc: namespaceListFunc(dns.client, dns.selector), ListFunc: namespaceListFunc(dns.client, dns.namespaceSelector),
WatchFunc: namespaceWatchFunc(dns.client, dns.selector), WatchFunc: namespaceWatchFunc(dns.client, dns.namespaceSelector),
}, },
&api.Namespace{}, opts.resyncPeriod, cache.ResourceEventHandlerFuncs{}) &api.Namespace{},
opts.resyncPeriod,
cache.ResourceEventHandlerFuncs{})
return &dns return &dns
} }

View file

@ -30,7 +30,7 @@ func (k *Kubernetes) External(state request.Request) ([]msg.Service, int) {
port := "*" port := "*"
protocol := "*" protocol := "*"
namespace := segs[last] namespace := segs[last]
if !k.namespaceExposed(namespace) || !k.namespace(namespace) { if !k.namespaceExposed(namespace) {
return nil, dns.RcodeNameError return nil, dns.RcodeNameError
} }

View file

@ -2,6 +2,7 @@ package kubernetes
import ( import (
"context" "context"
"fmt"
"testing" "testing"
"time" "time"
@ -380,6 +381,59 @@ func TestServeDNS(t *testing.T) {
} }
} }
var nsTestCases = []test.Case{
// A Service for an "exposed" namespace that "does exist"
{
Qname: "svc1.testns.svc.cluster.local.", Qtype: dns.TypeA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{
test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1"),
},
},
// A service for an "exposed" namespace that "doesn't exist"
{
Qname: "svc1.nsnoexist.svc.cluster.local.", Qtype: dns.TypeA,
Rcode: dns.RcodeNameError,
Ns: []dns.RR{
test.SOA("cluster.local. 300 IN SOA ns.dns.cluster.local. hostmaster.cluster.local. 1551484803 7200 1800 86400 30"),
},
},
}
func TestServeNamespaceDNS(t *testing.T) {
k := New([]string{"cluster.local."})
k.APIConn = &APIConnServeTest{}
k.Next = test.NextHandler(dns.RcodeSuccess, nil)
// if no namespaces are explicitly exposed, then they are all implicitly exposed
k.Namespaces = map[string]struct{}{}
ctx := context.TODO()
for i, tc := range nsTestCases {
r := tc.Msg()
w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := k.ServeDNS(ctx, w, r)
if err != tc.Error {
t.Errorf("Test %d expected no error, got %v", i, err)
return
}
if tc.Error != nil {
continue
}
resp := w.Msg
if resp == nil {
t.Fatalf("Test %d, got nil message and no error for %q", i, r.Question[0].Name)
}
// Before sorting, make sure that CNAMES do not appear after their target records
test.CNAMEOrder(resp)
test.SortAndCheck(resp, tc)
}
}
var notSyncedTestCases = []test.Case{ var notSyncedTestCases = []test.Case{
{ {
// We should get ServerFailure instead of NameError for missing records when we kubernetes hasn't synced // We should get ServerFailure instead of NameError for missing records when we kubernetes hasn't synced
@ -627,6 +681,9 @@ func (APIConnServeTest) GetNamespaceByName(name string) (*api.Namespace, error)
if name == "pod-nons" { // handler_pod_verified_test.go uses this for non-existent namespace. if name == "pod-nons" { // handler_pod_verified_test.go uses this for non-existent namespace.
return &api.Namespace{}, nil return &api.Namespace{}, nil
} }
if name == "nsnoexist" {
return nil, fmt.Errorf("namespace not found")
}
return &api.Namespace{ return &api.Namespace{
ObjectMeta: meta.ObjectMeta{ ObjectMeta: meta.ObjectMeta{
Name: name, Name: name,

View file

@ -217,6 +217,15 @@ func (k *Kubernetes) InitKubeCache() (err error) {
k.opts.selector = selector k.opts.selector = selector
} }
if k.opts.namespaceLabelSelector != nil {
var selector labels.Selector
selector, err = meta.LabelSelectorAsSelector(k.opts.namespaceLabelSelector)
if err != nil {
return fmt.Errorf("unable to create Selector for LabelSelector '%s': %q", k.opts.namespaceLabelSelector, err)
}
k.opts.namespaceSelector = selector
}
k.opts.initPodCache = k.podMode == podModeVerified k.opts.initPodCache = k.podMode == podModeVerified
k.opts.zones = k.Zones k.opts.zones = k.Zones
@ -302,13 +311,15 @@ func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service,
} }
namespace := r.namespace namespace := r.namespace
if !wildcard(namespace) && !k.namespaceExposed(namespace) {
return nil, errNoItems
}
podname := r.service podname := r.service
zonePath := msg.Path(zone, coredns)
ip := ""
// handle empty pod name // handle empty pod name
if podname == "" { if podname == "" {
if k.namespace(namespace) || wildcard(namespace) { if k.namespaceExposed(namespace) || wildcard(namespace) {
// NODATA // NODATA
return nil, nil return nil, nil
} }
@ -316,6 +327,8 @@ func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service,
return nil, errNoItems return nil, errNoItems
} }
zonePath := msg.Path(zone, coredns)
ip := ""
if strings.Count(podname, "-") == 3 && !strings.Contains(podname, "--") { if strings.Count(podname, "-") == 3 && !strings.Contains(podname, "--") {
ip = strings.Replace(podname, "-", ".", -1) ip = strings.Replace(podname, "-", ".", -1)
} else { } else {
@ -323,7 +336,7 @@ func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service,
} }
if k.podMode == podModeInsecure { if k.podMode == podModeInsecure {
if !wildcard(namespace) && !k.namespace(namespace) { // no wildcard, but namespace does not exist if !wildcard(namespace) && !k.namespaceExposed(namespace) { // no wildcard, but namespace does not exist
return nil, errNoItems return nil, errNoItems
} }
@ -338,8 +351,8 @@ func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service,
// PodModeVerified // PodModeVerified
err = errNoItems err = errNoItems
if wildcard(podname) && !wildcard(namespace) { if wildcard(podname) && !wildcard(namespace) {
// If namespace exist, err should be nil, so that we return nodata instead of NXDOMAIN // If namespace exists, err should be nil, so that we return NODATA instead of NXDOMAIN
if k.namespace(namespace) { if k.namespaceExposed(namespace) {
err = nil err = nil
} }
} }
@ -368,12 +381,24 @@ func (k *Kubernetes) findPods(r recordRequest, zone string) (pods []msg.Service,
// findServices returns the services matching r from the cache. // findServices returns the services matching r from the cache.
func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.Service, err error) { func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.Service, err error) {
zonePath := msg.Path(zone, coredns) if !wildcard(r.namespace) && !k.namespaceExposed(r.namespace) {
return nil, errNoItems
}
// handle empty service name
if r.service == "" {
if k.namespaceExposed(r.namespace) || wildcard(r.namespace) {
// NODATA
return nil, nil
}
// NXDOMAIN
return nil, errNoItems
}
err = errNoItems err = errNoItems
if wildcard(r.service) && !wildcard(r.namespace) { if wildcard(r.service) && !wildcard(r.namespace) {
// If namespace exist, err should be nil, so that we return nodata instead of NXDOMAIN // If namespace exists, err should be nil, so that we return NODATA instead of NXDOMAIN
if k.namespace(r.namespace) { if k.namespaceExposed(r.namespace) {
err = nil err = nil
} }
} }
@ -384,16 +409,6 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.
serviceList []*object.Service serviceList []*object.Service
) )
// handle empty service name
if r.service == "" {
if k.namespace(r.namespace) || wildcard(r.namespace) {
// NODATA
return nil, nil
}
// NXDOMAIN
return nil, errNoItems
}
if wildcard(r.service) || wildcard(r.namespace) { if wildcard(r.service) || wildcard(r.namespace) {
serviceList = k.APIConn.ServiceList() serviceList = k.APIConn.ServiceList()
endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EndpointsList() } endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EndpointsList() }
@ -403,12 +418,13 @@ func (k *Kubernetes) findServices(r recordRequest, zone string) (services []msg.
endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EpIndex(idx) } endpointsListFunc = func() []*object.Endpoints { return k.APIConn.EpIndex(idx) }
} }
zonePath := msg.Path(zone, coredns)
for _, svc := range serviceList { for _, svc := range serviceList {
if !(match(r.namespace, svc.Namespace) && match(r.service, svc.Name)) { if !(match(r.namespace, svc.Namespace) && match(r.service, svc.Name)) {
continue continue
} }
// If namespace has a wildcard, filter results against Corefile namespace list. // If request namespace is a wildcard, filter results against Corefile namespace list.
// (Namespaces without a wildcard were filtered before the call to this function.) // (Namespaces without a wildcard were filtered before the call to this function.)
if wildcard(r.namespace) && !k.namespaceExposed(svc.Namespace) { if wildcard(r.namespace) && !k.namespaceExposed(svc.Namespace) {
continue continue

View file

@ -1,20 +1,27 @@
package kubernetes package kubernetes
// namespace checks if namespace n exists in this cluster. This returns true // filteredNamespaceExists checks if namespace exists in this cluster
// even for non exposed namespaces, see namespaceExposed. // according to any `namespace_labels` plugin configuration specified.
func (k *Kubernetes) namespace(n string) bool { // Returns true even for namespaces not exposed by plugin configuration,
ns, err := k.APIConn.GetNamespaceByName(n) // see namespaceExposed.
func (k *Kubernetes) filteredNamespaceExists(namespace string) bool {
ns, err := k.APIConn.GetNamespaceByName(namespace)
if err != nil { if err != nil {
return false return false
} }
return ns.ObjectMeta.Name == n return ns.ObjectMeta.Name == namespace
} }
// namespaceExposed returns true when the namespace is exposed. // configuredNamespace returns true when the namespace is exposed through the plugin
func (k *Kubernetes) namespaceExposed(namespace string) bool { // `namespaces` configuration.
func (k *Kubernetes) configuredNamespace(namespace string) bool {
_, ok := k.Namespaces[namespace] _, ok := k.Namespaces[namespace]
if len(k.Namespaces) > 0 && !ok { if len(k.Namespaces) > 0 && !ok {
return false return false
} }
return true return true
} }
func (k *Kubernetes) namespaceExposed(namespace string) bool {
return k.configuredNamespace(namespace) && k.filteredNamespaceExists(namespace)
}

View file

@ -0,0 +1,72 @@
package kubernetes
import (
"testing"
)
func TestFilteredNamespaceExists(t *testing.T) {
tests := []struct{
expected bool
kubernetesNamespaces map[string]struct{}
testNamespace string
}{
{true, map[string]struct{}{}, "foobar" },
{false, map[string]struct{}{}, "nsnoexist" },
}
k := Kubernetes{}
k.APIConn = &APIConnServeTest{}
for i, test := range tests {
k.Namespaces = test.kubernetesNamespaces
actual := k.filteredNamespaceExists(test.testNamespace)
if actual != test.expected {
t.Errorf("Test %d failed. Filtered namespace %s was expected to exist", i, test.testNamespace)
}
}
}
func TestNamespaceExposed(t *testing.T) {
tests := []struct{
expected bool
kubernetesNamespaces map[string]struct{}
testNamespace string
}{
{true, map[string]struct{}{ "foobar": {} }, "foobar" },
{false, map[string]struct{}{ "foobar": {} }, "nsnoexist" },
{true, map[string]struct{}{}, "foobar" },
{true, map[string]struct{}{}, "nsnoexist" },
}
k := Kubernetes{}
k.APIConn = &APIConnServeTest{}
for i, test := range tests {
k.Namespaces = test.kubernetesNamespaces
actual := k.configuredNamespace(test.testNamespace)
if actual != test.expected {
t.Errorf("Test %d failed. Namespace %s was expected to be exposed", i, test.testNamespace)
}
}
}
func TestNamespaceValid(t *testing.T) {
tests := []struct{
expected bool
kubernetesNamespaces map[string]struct{}
testNamespace string
}{
{true, map[string]struct{}{ "foobar": {} }, "foobar" },
{false, map[string]struct{}{ "foobar": {} }, "nsnoexist" },
{true, map[string]struct{}{}, "foobar" },
{false, map[string]struct{}{}, "nsnoexist" },
}
k := Kubernetes{}
k.APIConn = &APIConnServeTest{}
for i, test := range tests {
k.Namespaces = test.kubernetesNamespaces
actual := k.namespaceExposed(test.testNamespace)
if actual != test.expected {
t.Errorf("Test %d failed. Namespace %s was expected to be valid", i, test.testNamespace)
}
}
}

View file

@ -234,6 +234,18 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
continue continue
} }
return nil, c.ArgErr() return nil, c.ArgErr()
case "namespace_labels":
args := c.RemainingArgs()
if len(args) > 0 {
namespaceLabelSelectorString := strings.Join(args, " ")
nls, err := meta.ParseToLabelSelector(namespaceLabelSelectorString)
if err != nil {
return nil, fmt.Errorf("unable to parse namespace_label selector value: '%v': %v", namespaceLabelSelectorString, err)
}
k8s.opts.namespaceLabelSelector = nls
continue
}
return nil, c.ArgErr()
case "fallthrough": case "fallthrough":
k8s.Fall.SetZonesFromArgs(c.RemainingArgs()) k8s.Fall.SetZonesFromArgs(c.RemainingArgs())
case "upstream": case "upstream":
@ -293,6 +305,10 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) {
} }
} }
if len(k8s.Namespaces) != 0 && k8s.opts.namespaceLabelSelector != nil {
return nil, c.Errf("namespaces and namespace_labels cannot both be set")
}
return k8s, nil return k8s, nil
} }

View file

@ -13,15 +13,16 @@ import (
func TestKubernetesParse(t *testing.T) { func TestKubernetesParse(t *testing.T) {
tests := []struct { tests := []struct {
input string // Corefile data as string input string // Corefile data as string
shouldErr bool // true if test case is expected to produce an error. shouldErr bool // true if test case is expected to produce an error.
expectedErrContent string // substring from the expected error. Empty for positive cases. expectedErrContent string // substring from the expected error. Empty for positive cases.
expectedZoneCount int // expected count of defined zones. expectedZoneCount int // expected count of defined zones.
expectedNSCount int // expected count of namespaces. expectedNSCount int // expected count of namespaces.
expectedResyncPeriod time.Duration // expected resync period value expectedResyncPeriod time.Duration // expected resync period value
expectedLabelSelector string // expected label selector value expectedLabelSelector string // expected label selector value
expectedPodMode string expectedNamespaceLabelSelector string // expected namespace label selector value
expectedFallthrough fall.F expectedPodMode string
expectedFallthrough fall.F
}{ }{
// positive // positive
{ {
@ -32,6 +33,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -43,6 +45,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -55,6 +58,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -68,6 +72,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -81,6 +86,7 @@ func TestKubernetesParse(t *testing.T) {
1, 1,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -94,6 +100,7 @@ func TestKubernetesParse(t *testing.T) {
2, 2,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -107,6 +114,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
30 * time.Second, 30 * time.Second,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -120,6 +128,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
15 * time.Minute, 15 * time.Minute,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -133,6 +142,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"environment=prod", "environment=prod",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -146,6 +156,36 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"application=nginx,environment in (production,qa,staging)", "application=nginx,environment in (production,qa,staging)",
"",
podModeDisabled,
fall.Zero,
},
{
`kubernetes coredns.local {
namespace_labels istio-injection=enabled
}`,
false,
"",
1,
0,
defaultResyncPeriod,
"",
"istio-injection=enabled",
podModeDisabled,
fall.Zero,
},
{
`kubernetes coredns.local {
namespaces foo bar
namespace_labels istio-injection=enabled
}`,
true,
"Error during parsing: namespaces and namespace_labels cannot both be set",
-1,
0,
defaultResyncPeriod,
"",
"istio-injection=enabled",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -163,6 +203,7 @@ func TestKubernetesParse(t *testing.T) {
2, 2,
15 * time.Minute, 15 * time.Minute,
"application=nginx,environment in (production,qa,staging)", "application=nginx,environment in (production,qa,staging)",
"",
podModeDisabled, podModeDisabled,
fall.Root, fall.Root,
}, },
@ -177,6 +218,7 @@ func TestKubernetesParse(t *testing.T) {
-1, -1,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -190,6 +232,7 @@ func TestKubernetesParse(t *testing.T) {
-1, -1,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -203,6 +246,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
0 * time.Minute, 0 * time.Minute,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -216,6 +260,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
0 * time.Second, 0 * time.Second,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -229,6 +274,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
0 * time.Second, 0 * time.Second,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -242,6 +288,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
0 * time.Second, 0 * time.Second,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -255,6 +302,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
0 * time.Second, 0 * time.Second,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -269,6 +317,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -283,6 +332,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeInsecure, podModeInsecure,
fall.Zero, fall.Zero,
}, },
@ -297,6 +347,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeVerified, podModeVerified,
fall.Zero, fall.Zero,
}, },
@ -311,6 +362,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeVerified, podModeVerified,
fall.Zero, fall.Zero,
}, },
@ -325,6 +377,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.F{Zones: []string{"ip6.arpa.", "inaddr.arpa.", "foo.com."}}, fall.F{Zones: []string{"ip6.arpa.", "inaddr.arpa.", "foo.com."}},
}, },
@ -339,6 +392,7 @@ func TestKubernetesParse(t *testing.T) {
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -352,6 +406,7 @@ kubernetes cluster.local`,
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -365,6 +420,7 @@ kubernetes cluster.local`,
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -378,6 +434,7 @@ kubernetes cluster.local`,
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },
@ -391,6 +448,7 @@ kubernetes cluster.local`,
0, 0,
defaultResyncPeriod, defaultResyncPeriod,
"", "",
"",
podModeDisabled, podModeDisabled,
fall.Zero, fall.Zero,
}, },