diff --git a/plugin/kubernetes/README.md b/plugin/kubernetes/README.md index cb51ae458..be13a1bf2 100644 --- a/plugin/kubernetes/README.md +++ b/plugin/kubernetes/README.md @@ -53,6 +53,7 @@ kubernetes [ZONES...] { will automatically perform a healthcheck and proxy to the healthy k8s API endpoint. * `tls` **CERT** **KEY** **CACERT** are the TLS cert, key and the CA cert file names for remote k8s connection. This option is ignored if connecting in-cluster (i.e. 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. endpoint is not specified). * `namespaces` **NAMESPACE [NAMESPACE...]**, only exposes the k8s namespaces listed. If this option is omitted all namespaces are exposed * `labels` **EXPRESSION** only exposes the records for Kubernetes objects that match this label selector. diff --git a/plugin/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go index 9c5089bd7..5be8e558e 100644 --- a/plugin/kubernetes/kubernetes.go +++ b/plugin/kubernetes/kubernetes.go @@ -37,6 +37,7 @@ type Kubernetes struct { APICertAuth string APIClientCert string APIClientKey string + ClientConfig clientcmd.ClientConfig APIConn dnsController Namespaces map[string]bool podMode string @@ -153,6 +154,9 @@ func (k *Kubernetes) IsNameError(err error) bool { } func (k *Kubernetes) getClientConfig() (*rest.Config, error) { + if k.ClientConfig != nil { + return k.ClientConfig.ClientConfig() + } loadingRules := &clientcmd.ClientConfigLoadingRules{} overrides := &clientcmd.ConfigOverrides{} clusterinfo := clientcmdapi.Cluster{} diff --git a/plugin/kubernetes/setup.go b/plugin/kubernetes/setup.go index 9e2129f6a..abfd8193f 100644 --- a/plugin/kubernetes/setup.go +++ b/plugin/kubernetes/setup.go @@ -19,6 +19,7 @@ import ( "github.com/mholt/caddy" "github.com/miekg/dns" meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/clientcmd" ) var log = clog.NewWithPlugin("kubernetes") @@ -261,6 +262,17 @@ func ParseStanza(c *caddy.Controller) (*Kubernetes, error) { return nil, fmt.Errorf("unable to parse ignore value: '%v'", ignore) } } + case "kubeconfig": + args := c.RemainingArgs() + if len(args) == 2 { + config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: args[0]}, + &clientcmd.ConfigOverrides{CurrentContext: args[1]}, + ) + k8s.ClientConfig = config + continue + } + return nil, c.ArgErr() default: return nil, c.Errf("unknown property '%s'", c.Val()) } diff --git a/plugin/kubernetes/setup_test.go b/plugin/kubernetes/setup_test.go index 68e490d76..97cb1ff64 100644 --- a/plugin/kubernetes/setup_test.go +++ b/plugin/kubernetes/setup_test.go @@ -397,6 +397,48 @@ kubernetes cluster.local`, fall.Zero, nil, }, + { + `kubernetes coredns.local { + kubeconfig +}`, + true, + "Wrong argument count or unexpected line ending after", + -1, + 0, + defaultResyncPeriod, + "", + podModeDisabled, + fall.Zero, + nil, + }, + { + `kubernetes coredns.local { + kubeconfig file context extraarg +}`, + true, + "Wrong argument count or unexpected line ending after", + -1, + 0, + defaultResyncPeriod, + "", + podModeDisabled, + fall.Zero, + nil, + }, + { + `kubernetes coredns.local { + kubeconfig file context +}`, + false, + "", + 1, + 0, + defaultResyncPeriod, + "", + podModeDisabled, + fall.Zero, + nil, + }, } for i, test := range tests {