1
+ // Package kubernetai implements a plugin which can embed a number of kubernetes plugins in the same dns server.
1
2
package kubernetai
2
3
3
4
import (
4
5
"context"
5
6
6
7
"github.com/coredns/coredns/plugin"
7
8
"github.com/coredns/coredns/plugin/kubernetes"
9
+ "github.com/coredns/coredns/plugin/kubernetes/object"
8
10
clog "github.com/coredns/coredns/plugin/pkg/log"
11
+ "github.com/coredns/coredns/plugin/transfer"
9
12
"github.com/coredns/coredns/request"
10
13
"github.com/miekg/dns"
11
14
)
12
15
13
16
var log = clog .NewWithPlugin ("kubernetai" )
14
17
18
+ // embeddedKubernetesPluginInterface describes the kubernetes plugin interface that kubernetai requires/uses.
19
+ type embeddedKubernetesPluginInterface interface {
20
+ plugin.Handler
21
+ transfer.Transferer
22
+ PodWithIP (ip string ) (pod * object.Pod )
23
+ Zones () (zones plugin.Zones )
24
+ }
25
+
26
+ // embeddedKubernetes wraps a real kubernetes plugin
27
+ type embeddedKubernetes struct {
28
+ * kubernetes.Kubernetes
29
+ }
30
+
31
+ var _ embeddedKubernetesPluginInterface = & embeddedKubernetes {}
32
+
33
+ func newEmbeddedKubernetes (k * kubernetes.Kubernetes ) * embeddedKubernetes {
34
+ return & embeddedKubernetes {
35
+ Kubernetes : k ,
36
+ }
37
+ }
38
+
39
+ // PodWithIP satisfies the embeddedKubernetesPluginInterface by adding this additional method not exported from the kubernetes plugin.
40
+ func (ek embeddedKubernetes ) PodWithIP (ip string ) * object.Pod {
41
+ if ek .Kubernetes == nil {
42
+ return nil
43
+ }
44
+ ps := ek .Kubernetes .APIConn .PodIndex (ip )
45
+ if len (ps ) == 0 {
46
+ return nil
47
+ }
48
+ return ps [0 ]
49
+ }
50
+
51
+ // Zones satisfies the embeddedKubernetesPluginInterface by providing access to the kubernetes plugin Zones.
52
+ func (ek embeddedKubernetes ) Zones () plugin.Zones {
53
+ if ek .Kubernetes == nil {
54
+ return nil
55
+ }
56
+ return plugin .Zones (ek .Kubernetes .Zones )
57
+ }
58
+
15
59
// Kubernetai handles multiple Kubernetes
16
60
type Kubernetai struct {
17
61
Zones []string
18
- Kubernetes []* kubernetes. Kubernetes
62
+ Kubernetes []embeddedKubernetesPluginInterface
19
63
autoPathSearch []string // Local search path from /etc/resolv.conf. Needed for autopath.
20
- p podHandlerItf
21
64
}
22
65
23
66
// New creates a Kubernetai containing one Kubernetes with zones
24
67
func New (zones []string ) (Kubernetai , * kubernetes.Kubernetes ) {
25
68
h := Kubernetai {
26
69
autoPathSearch : searchFromResolvConf (),
27
- p : & podHandler {},
28
70
}
29
71
k := kubernetes .New (zones )
30
- h .Kubernetes = append (h .Kubernetes , k )
72
+ ek := newEmbeddedKubernetes (k )
73
+ h .Kubernetes = append (h .Kubernetes , ek )
31
74
return h , k
32
75
}
33
76
@@ -43,7 +86,7 @@ func (k8i Kubernetai) AutoPath(state request.Request) []string {
43
86
// Abort if zone is not in kubernetai stanza.
44
87
var zMatch bool
45
88
for _ , k8s := range k8i .Kubernetes {
46
- zone := plugin . Zones ( k8s .Zones ).Matches (state .Name ())
89
+ zone := k8s .Zones ( ).Matches (state .Name ())
47
90
if zone != "" {
48
91
zMatch = true
49
92
break
@@ -55,13 +98,13 @@ func (k8i Kubernetai) AutoPath(state request.Request) []string {
55
98
56
99
// Add autopath result for the handled zones
57
100
for _ , k := range k8i .Kubernetes {
58
- pod := k8i . p . PodWithIP (* k , state .IP ())
101
+ pod := k . PodWithIP (state .IP ())
59
102
if pod == nil {
60
103
return nil
61
104
}
62
105
63
106
search := make ([]string , 3 )
64
- for _ , z := range k .Zones {
107
+ for _ , z := range k .Zones () {
65
108
if z == "." {
66
109
search [0 ] = pod .Namespace + ".svc."
67
110
search [1 ] = "svc."
@@ -80,6 +123,19 @@ func (k8i Kubernetai) AutoPath(state request.Request) []string {
80
123
return searchPath
81
124
}
82
125
126
+ // Transfer supports the transfer plugin, implementing the Transferer interface, by calling Transfer on each of the embedded plugins.
127
+ func (k8i Kubernetai ) Transfer (zone string , serial uint32 ) (retCh <- chan []dns.RR , err error ) {
128
+ for _ , k := range k8i .Kubernetes {
129
+ retCh , err = k .Transfer (zone , serial )
130
+ if err == transfer .ErrNotAuthoritative {
131
+ continue
132
+ }
133
+ return
134
+ }
135
+ // none of the embedded plugins were authoritative
136
+ return nil , transfer .ErrNotAuthoritative
137
+ }
138
+
83
139
func searchFromResolvConf () []string {
84
140
rc , err := dns .ClientConfigFromFile ("/etc/resolv.conf" )
85
141
if err != nil {
@@ -93,7 +149,7 @@ func searchFromResolvConf() []string {
93
149
func (k8i Kubernetai ) Health () bool {
94
150
healthy := true
95
151
for _ , k := range k8i .Kubernetes {
96
- healthy = healthy && k .APIConn .HasSynced ()
152
+ healthy = healthy && k .( * embeddedKubernetes ). APIConn .HasSynced ()
97
153
if ! healthy {
98
154
break
99
155
}
0 commit comments