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"
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
2016-08-19 17:14:17 -07:00
"github.com/miekg/coredns/core/dnsserver"
2016-06-06 12:49:53 -07:00
"github.com/miekg/coredns/middleware"
2016-07-07 01:40:58 -07:00
"github.com/miekg/coredns/middleware/kubernetes/nametemplate"
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-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-08-19 17:14:17 -07:00
return 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-08-19 17:14:17 -07:00
return 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 ( )
} )
dnsserver . GetConfig ( c ) . AddMiddleware ( func ( next dnsserver . Handler ) dnsserver . Handler {
2016-06-06 12:49:53 -07:00
kubernetes . Next = next
return kubernetes
2016-08-19 17:14:17 -07:00
} )
return nil
2016-06-06 12:49:53 -07:00
}
2016-08-19 17:14:17 -07:00
func kubernetesParse ( c * caddy . Controller ) ( Kubernetes , error ) {
2016-08-05 18:19:51 -07:00
var err error
template := defaultNameTemplate
2016-08-19 17:14:17 -07:00
k8s := Kubernetes { ResyncPeriod : defaultResyncPeriod }
2016-07-07 01:40:58 -07:00
k8s . NameTemplate = new ( nametemplate . NameTemplate )
k8s . NameTemplate . SetTemplate ( template )
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 ( )
if len ( zones ) == 0 {
2016-08-19 17:14:17 -07:00
k8s . Zones = make ( [ ] string , len ( c . ServerBlockKeys ) )
copy ( k8s . Zones , c . ServerBlockKeys )
2016-06-06 12:49:53 -07:00
}
2016-07-07 01:40:58 -07:00
2016-08-19 17:14:17 -07:00
k8s . Zones = NormalizeZoneList ( zones )
2016-06-06 12:49:53 -07:00
middleware . Zones ( k8s . Zones ) . FullyQualify ( )
2016-08-19 17:14:17 -07:00
2016-08-05 18:19:51 -07:00
if k8s . Zones == nil || len ( k8s . Zones ) < 1 {
err = errors . New ( "Zone name must be provided for kubernetes middleware." )
2016-08-19 17:14:17 -07:00
return Kubernetes { } , err
2016-08-05 18:19:51 -07:00
}
2016-07-22 16:07:27 -07:00
2016-08-05 18:19:51 -07:00
for c . NextBlock ( ) {
2016-06-06 12:49:53 -07:00
switch c . Val ( ) {
2016-08-05 18:19:51 -07:00
case "template" :
2016-06-06 12:49:53 -07:00
args := c . RemainingArgs ( )
2016-08-05 18:19:51 -07:00
if len ( args ) != 0 {
template := strings . Join ( args , "" )
err = k8s . NameTemplate . SetTemplate ( template )
if err != nil {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , err
2016-08-05 18:19:51 -07:00
}
} else {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , c . ArgErr ( )
2016-06-06 12:49:53 -07:00
}
2016-07-22 16:07:27 -07:00
case "namespaces" :
args := c . RemainingArgs ( )
2016-08-05 18:19:51 -07:00
if len ( args ) != 0 {
k8s . Namespaces = append ( k8s . Namespaces , args ... )
} else {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , c . ArgErr ( )
2016-07-22 16:07:27 -07:00
}
2016-08-05 18:19:51 -07:00
case "endpoint" :
args := c . RemainingArgs ( )
if len ( args ) != 0 {
k8s . APIEndpoint = args [ 0 ]
} else {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , c . ArgErr ( )
2016-06-06 12:49:53 -07:00
}
2016-08-08 14:30:04 -07:00
case "resyncperiod" :
args := c . RemainingArgs ( )
if len ( args ) != 0 {
k8s . ResyncPeriod , err = time . ParseDuration ( args [ 0 ] )
if err != nil {
err = errors . New ( fmt . Sprintf ( "Unable to parse resync duration value. Value provided was '%v'. Example valid values: '15s', '5m', '1h'. Error was: %v" , args [ 0 ] , err ) )
2016-08-19 17:14:17 -07:00
return Kubernetes { } , err
2016-08-08 14:30:04 -07:00
}
} else {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , c . ArgErr ( )
2016-08-08 14:30:04 -07:00
}
2016-08-12 20:44:08 -07:00
case "labels" :
args := c . RemainingArgs ( )
if len ( args ) != 0 {
labelSelectorString := strings . Join ( args , " " )
k8s . LabelSelector , err = unversionedapi . ParseToLabelSelector ( labelSelectorString )
if err != nil {
err = errors . New ( fmt . Sprintf ( "Unable to parse label selector. Value provided was '%v'. Error was: %v" , labelSelectorString , err ) )
2016-08-19 17:14:17 -07:00
return Kubernetes { } , err
2016-08-12 20:44:08 -07:00
}
} else {
2016-08-19 17:14:17 -07:00
return Kubernetes { } , c . ArgErr ( )
2016-08-12 20:44:08 -07:00
}
2016-06-06 12:49:53 -07:00
}
}
return k8s , nil
}
}
2016-08-05 18:19:51 -07:00
err = errors . New ( "Kubernetes setup called without keyword 'kubernetes' in Corefile" )
2016-08-19 17:14:17 -07:00
return Kubernetes { } , err
2016-06-06 12:49:53 -07:00
}
2016-08-19 17:14:17 -07:00
const (
defaultNameTemplate = "{service}.{namespace}.{zone}"
defaultResyncPeriod = 5 * time . Minute
)