2016-08-19 17:14:17 -07:00
package kubernetes
2016-06-06 12:49:53 -07:00
import (
2016-08-05 18:19:51 -07:00
"errors"
2016-08-08 14:30:04 -07:00
"fmt"
2017-08-08 05:05:34 -07:00
"log"
2017-02-01 12:56:10 -05:00
"net"
2016-07-07 01:40:58 -07:00
"strings"
2016-08-05 18:19:51 -07:00
"time"
2016-06-06 12:49:53 -07:00
2017-02-21 22:51:47 -08:00
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/middleware"
2017-05-30 08:20:39 -04:00
"github.com/coredns/coredns/middleware/pkg/dnsutil"
"github.com/coredns/coredns/middleware/proxy"
2017-06-28 18:44:30 -04:00
"github.com/miekg/dns"
2016-08-19 17:14:17 -07:00
"github.com/mholt/caddy"
2016-11-05 07:57:08 -04:00
unversionedapi "k8s.io/client-go/1.5/pkg/api/unversioned"
2016-06-06 12:49:53 -07:00
)
2016-08-19 17:14:17 -07:00
func init ( ) {
caddy . RegisterPlugin ( "kubernetes" , caddy . Plugin {
ServerType : "dns" ,
Action : setup ,
} )
}
2016-06-06 12:49:53 -07:00
2016-08-19 17:14:17 -07:00
func setup ( c * caddy . Controller ) error {
2016-06-06 12:49:53 -07:00
kubernetes , err := kubernetesParse ( c )
2016-08-05 18:19:51 -07:00
if err != nil {
2016-09-10 09:16:25 +01:00
return middleware . Error ( "kubernetes" , err )
2016-08-05 18:19:51 -07:00
}
2016-06-06 12:49:53 -07:00
2016-08-19 17:14:17 -07:00
err = kubernetes . InitKubeCache ( )
2016-06-06 12:49:53 -07:00
if err != nil {
2016-09-10 09:16:25 +01:00
return middleware . Error ( "kubernetes" , err )
2016-06-06 12:49:53 -07:00
}
2016-08-19 17:14:17 -07:00
// Register KubeCache start and stop functions with Caddy
c . OnStartup ( func ( ) error {
go kubernetes . APIConn . Run ( )
return nil
} )
c . OnShutdown ( func ( ) error {
return kubernetes . APIConn . Stop ( )
} )
2016-09-19 11:26:00 +01:00
dnsserver . GetConfig ( c ) . AddMiddleware ( func ( next middleware . Handler ) middleware . Handler {
2016-06-06 12:49:53 -07:00
kubernetes . Next = next
return kubernetes
2016-08-19 17:14:17 -07:00
} )
2017-08-10 21:31:36 +01:00
// Also register kubernetes for use in autopath.
dnsserver . GetConfig ( c ) . RegisterHandler ( kubernetes )
2016-08-19 17:14:17 -07:00
return nil
2016-06-06 12:49:53 -07:00
}
2016-09-23 11:08:23 -03:00
func kubernetesParse ( c * caddy . Controller ) ( * Kubernetes , error ) {
2017-05-22 16:05:48 -04:00
k8s := & Kubernetes {
2017-08-03 23:14:11 -07:00
ResyncPeriod : defaultResyncPeriod ,
interfaceAddrsFunc : localPodIP ,
PodMode : PodModeDisabled ,
Proxy : proxy . Proxy { } ,
2017-05-22 16:05:48 -04:00
}
2016-07-07 01:40:58 -07:00
2017-08-10 19:26:31 +01:00
k8s . autoPathSearch = searchFromResolvConf ( )
2016-06-06 12:49:53 -07:00
for c . Next ( ) {
if c . Val ( ) == "kubernetes" {
2016-07-07 01:40:58 -07:00
zones := c . RemainingArgs ( )
2017-08-10 20:53:15 +01:00
if len ( zones ) != 0 {
k8s . Zones = zones
middleware . Zones ( k8s . Zones ) . Normalize ( )
} else {
2016-08-19 17:14:17 -07:00
k8s . Zones = make ( [ ] string , len ( c . ServerBlockKeys ) )
2017-08-10 20:53:15 +01:00
for i := 0 ; i < len ( c . ServerBlockKeys ) ; i ++ {
k8s . Zones [ i ] = middleware . Host ( c . ServerBlockKeys [ i ] ) . Normalize ( )
}
2016-06-06 12:49:53 -07:00
}
2016-07-07 01:40:58 -07:00
2016-08-05 18:19:51 -07:00
if k8s . Zones == nil || len ( k8s . Zones ) < 1 {
2017-02-22 07:25:58 +00:00
return nil , errors . New ( "zone name must be provided for kubernetes middleware" )
2016-08-05 18:19:51 -07:00
}
2016-07-22 16:07:27 -07:00
2016-11-14 19:31:08 +00:00
k8s . primaryZone = - 1
for i , z := range k8s . Zones {
if strings . HasSuffix ( z , "in-addr.arpa." ) || strings . HasSuffix ( z , "ip6.arpa." ) {
continue
}
k8s . primaryZone = i
break
}
if k8s . primaryZone == - 1 {
2017-02-22 07:25:58 +00:00
return nil , errors . New ( "non-reverse zone name must be given for Kubernetes" )
2016-11-14 19:31:08 +00:00
}
2016-08-05 18:19:51 -07:00
for c . NextBlock ( ) {
2016-06-06 12:49:53 -07:00
switch c . Val ( ) {
2017-02-01 12:56:10 -05:00
case "cidrs" :
2017-08-08 05:05:34 -07:00
// DEPRECATION WARNING
log . Printf ( "[WARNING] \"cidrs\" will be removed for CoreDNS soon. See https://coredns.io/2017/07/23/corefile-explained#reverse-zones for the replacement" )
2017-02-01 12:56:10 -05:00
args := c . RemainingArgs ( )
if len ( args ) > 0 {
for _ , cidrStr := range args {
_ , cidr , err := net . ParseCIDR ( cidrStr )
if err != nil {
2017-06-14 09:37:10 -07:00
return nil , fmt . Errorf ( "invalid cidr: %s" , cidrStr )
2017-02-01 12:56:10 -05:00
}
k8s . ReverseCidrs = append ( k8s . ReverseCidrs , * cidr )
}
continue
}
return nil , c . ArgErr ( )
2017-01-11 16:23:10 -05:00
case "pods" :
args := c . RemainingArgs ( )
if len ( args ) == 1 {
switch args [ 0 ] {
2017-01-20 02:22:11 -05:00
case PodModeDisabled , PodModeInsecure , PodModeVerified :
2017-01-11 16:23:10 -05:00
k8s . PodMode = args [ 0 ]
default :
2017-06-14 09:37:10 -07:00
return nil , fmt . Errorf ( "wrong value for pods: %s, must be one of: disabled, verified, insecure" , args [ 0 ] )
2017-01-11 16:23:10 -05:00
}
continue
}
return nil , c . ArgErr ( )
2016-07-22 16:07:27 -07:00
case "namespaces" :
args := c . RemainingArgs ( )
2016-09-23 18:07:06 -04:00
if len ( args ) > 0 {
2016-08-05 18:19:51 -07:00
k8s . Namespaces = append ( k8s . Namespaces , args ... )
2016-09-23 11:08:23 -03:00
continue
2016-07-22 16:07:27 -07:00
}
2016-09-23 11:08:23 -03:00
return nil , c . ArgErr ( )
2016-08-05 18:19:51 -07:00
case "endpoint" :
args := c . RemainingArgs ( )
2016-09-23 18:07:06 -04:00
if len ( args ) > 0 {
2016-08-05 18:19:51 -07:00
k8s . APIEndpoint = args [ 0 ]
2016-09-23 11:08:23 -03:00
continue
2016-06-06 12:49:53 -07:00
}
2016-09-23 11:08:23 -03:00
return nil , c . ArgErr ( )
2016-09-23 18:07:06 -04:00
case "tls" : // cert key cacertfile
args := c . RemainingArgs ( )
if len ( args ) == 3 {
k8s . APIClientCert , k8s . APIClientKey , k8s . APICertAuth = args [ 0 ] , args [ 1 ] , args [ 2 ]
continue
}
return nil , c . ArgErr ( )
2016-08-08 14:30:04 -07:00
case "resyncperiod" :
args := c . RemainingArgs ( )
2016-09-23 18:07:06 -04:00
if len ( args ) > 0 {
2016-09-23 11:08:23 -03:00
rp , err := time . ParseDuration ( args [ 0 ] )
2016-08-08 14:30:04 -07:00
if err != nil {
2017-06-14 09:37:10 -07:00
return nil , fmt . Errorf ( "unable to parse resync duration value: '%v': %v" , args [ 0 ] , err )
2016-08-08 14:30:04 -07:00
}
2016-09-23 11:08:23 -03:00
k8s . ResyncPeriod = rp
continue
2016-08-08 14:30:04 -07:00
}
2016-09-23 11:08:23 -03:00
return nil , c . ArgErr ( )
2016-08-12 20:44:08 -07:00
case "labels" :
args := c . RemainingArgs ( )
2016-09-23 18:07:06 -04:00
if len ( args ) > 0 {
2016-08-12 20:44:08 -07:00
labelSelectorString := strings . Join ( args , " " )
2016-09-23 11:08:23 -03:00
ls , err := unversionedapi . ParseToLabelSelector ( labelSelectorString )
2016-08-12 20:44:08 -07:00
if err != nil {
2017-06-14 09:37:10 -07:00
return nil , fmt . Errorf ( "unable to parse label selector value: '%v': %v" , labelSelectorString , err )
2016-08-12 20:44:08 -07:00
}
2016-09-23 11:08:23 -03:00
k8s . LabelSelector = ls
continue
2016-08-12 20:44:08 -07:00
}
2016-09-23 11:08:23 -03:00
return nil , c . ArgErr ( )
2017-04-19 16:08:30 -04:00
case "fallthrough" :
args := c . RemainingArgs ( )
if len ( args ) == 0 {
k8s . Fallthrough = true
continue
}
return nil , c . ArgErr ( )
2017-05-30 08:20:39 -04:00
case "upstream" :
args := c . RemainingArgs ( )
if len ( args ) == 0 {
return nil , c . ArgErr ( )
}
ups , err := dnsutil . ParseHostPortOrFile ( args ... )
if err != nil {
return nil , err
}
k8s . Proxy = proxy . NewLookup ( ups )
2017-06-14 09:38:00 -04:00
case "federation" : // name zone
args := c . RemainingArgs ( )
if len ( args ) == 2 {
k8s . Federations = append ( k8s . Federations , Federation {
name : args [ 0 ] ,
zone : args [ 1 ] ,
} )
continue
}
2017-06-14 09:37:10 -07:00
return nil , fmt . Errorf ( "incorrect number of arguments for federation, got %v, expected 2" , len ( args ) )
2016-06-06 12:49:53 -07:00
}
}
return k8s , nil
}
}
2017-06-14 09:37:10 -07:00
return nil , errors . New ( "kubernetes setup called without keyword 'kubernetes' in Corefile" )
2016-06-06 12:49:53 -07:00
}
2016-08-19 17:14:17 -07:00
2017-08-10 19:26:31 +01:00
func searchFromResolvConf ( ) [ ] string {
rc , err := dns . ClientConfigFromFile ( "/etc/resolv.conf" )
if err != nil {
return nil
}
middleware . Zones ( rc . Search ) . Normalize ( )
return rc . Search
}
2016-08-19 17:14:17 -07:00
const (
2017-08-09 04:06:48 -07:00
defaultResyncPeriod = 5 * time . Minute
defautNdots = 0
defaultOnNXDOMAIN = dns . RcodeSuccess
2016-08-19 17:14:17 -07:00
)