diff options
author | 2021-11-12 08:22:34 -0800 | |
---|---|---|
committer | 2021-11-12 11:22:34 -0500 | |
commit | 2e6953c7dbd1d6b359911e1ce92e2567df07ca8c (patch) | |
tree | d91514ca867bb5b000bec3ea219e6a2ab0a0c244 /plugin/forwardcrd/setup.go | |
parent | 6953ab2b4f23f916a08b68ba51b9a26e41e9a748 (diff) | |
download | coredns-2e6953c7dbd1d6b359911e1ce92e2567df07ca8c.tar.gz coredns-2e6953c7dbd1d6b359911e1ce92e2567df07ca8c.tar.zst coredns-2e6953c7dbd1d6b359911e1ce92e2567df07ca8c.zip |
Initial implementation of ForwardCRD plugin (#4512)
* Add forwardcrd plugin README.md
Co-authored-by: Aidan Obley <aobley@vmware.com>
Signed-off-by: Christian Ang <angc@vmware.com>
* Create forwardcrd plugin
- Place forwardcrd before forward plugin in plugin list. This will avoid
forward from preventing the forwardcrd plugin from handling any queries
in the case of having a default upstream forwarder in a server block (as
is the case in the default kubernetes Corefile).
Co-authored-by: Aidan Obley <aobley@vmware.com>
Signed-off-by: Christian Ang <angc@vmware.com>
* Add Forward CRD
Signed-off-by: Christian Ang <angc@vmware.com>
* Add NewWithConfig to forward plugin
- allows external packages to instanciate forward plugins
Co-authored-by: Aidan Obley <aobley@vmware.com>
Signed-off-by: Christian Ang <angc@vmware.com>
* ForwardCRD plugin handles requests for Forward CRs
- add a Kubernetes controller that can read Forward CRs
- instances of the forward plugin are created based on Forward CRs from
the Kubernetes controller
- DNS requests are handled by calling matching Forward plugin instances
based on zone name
- Defaults to the kube-system namespace to align with Corefile RBAC
Signed-off-by: Christian Ang <angc@vmware.com>
Use klog v2 in forwardcrd plugin
* Refactor forward setup to use NewWithConfig
Co-authored-by: Christian Ang <angc@vmware.com>
Signed-off-by: Edwin Xie <exie@vmware.com>
* Use ParseInt instead of Atoi
- to ensure that the bitsize is 32 for later casting to uint32
Signed-off-by: Christian Ang <angc@vmware.com>
* Add @christianang to CODEOWNERS for forwardcrd
Signed-off-by: Christian Ang <angc@vmware.com>
Co-authored-by: Edwin Xie <exie@vmware.com>
Diffstat (limited to 'plugin/forwardcrd/setup.go')
-rw-r--r-- | plugin/forwardcrd/setup.go | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/plugin/forwardcrd/setup.go b/plugin/forwardcrd/setup.go new file mode 100644 index 000000000..6be322bc6 --- /dev/null +++ b/plugin/forwardcrd/setup.go @@ -0,0 +1,147 @@ +package forwardcrd + +import ( + "context" + "os" + "time" + + "github.com/coredns/caddy" + "github.com/coredns/coredns/core/dnsserver" + "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/plugin/dnstap" + clog "github.com/coredns/coredns/plugin/pkg/log" + + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" +) + +const pluginName = "forwardcrd" + +var log = clog.NewWithPlugin(pluginName) + +func init() { + plugin.Register(pluginName, setup) +} + +func setup(c *caddy.Controller) error { + klog.SetOutput(os.Stdout) + + k, err := parseForwardCRD(c) + if err != nil { + return plugin.Error(pluginName, err) + } + + err = k.InitKubeCache(context.Background()) + if err != nil { + return plugin.Error(pluginName, err) + } + + dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { + k.Next = next + return k + }) + + c.OnStartup(func() error { + go k.APIConn.Run(1) + + timeout := time.After(5 * time.Second) + ticker := time.NewTicker(100 * time.Millisecond) + for { + select { + case <-ticker.C: + if k.APIConn.HasSynced() { + return nil + } + case <-timeout: + return nil + } + } + }) + + c.OnStartup(func() error { + if taph := dnsserver.GetConfig(c).Handler("dnstap"); taph != nil { + if tapPlugin, ok := taph.(dnstap.Dnstap); ok { + k.APIConn.(*forwardCRDControl).tapPlugin = &tapPlugin + } + } + return nil + }) + + c.OnShutdown(func() error { + return k.APIConn.Stop() + }) + + return nil +} + +func parseForwardCRD(c *caddy.Controller) (*ForwardCRD, error) { + var ( + k *ForwardCRD + err error + i int + ) + + for c.Next() { + if i > 0 { + return nil, plugin.ErrOnce + } + i++ + k, err = parseStanza(c) + if err != nil { + return nil, err + } + } + + return k, nil +} + +func parseStanza(c *caddy.Controller) (*ForwardCRD, error) { + k := New() + + args := c.RemainingArgs() + k.Zones = plugin.OriginsFromArgsOrServerBlock(args, c.ServerBlockKeys) + + for c.NextBlock() { + switch c.Val() { + case "endpoint": + args := c.RemainingArgs() + if len(args) != 1 { + return nil, c.ArgErr() + } + k.APIServerEndpoint = args[0] + case "tls": + args := c.RemainingArgs() + if len(args) != 3 { + return nil, c.ArgErr() + } + k.APIClientCert, k.APIClientKey, k.APICertAuth = args[0], args[1], args[2] + case "kubeconfig": + args := c.RemainingArgs() + if len(args) != 1 && len(args) != 2 { + return nil, c.ArgErr() + } + overrides := &clientcmd.ConfigOverrides{} + if len(args) == 2 { + overrides.CurrentContext = args[1] + } + config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: args[0]}, + overrides, + ) + k.ClientConfig = config + case "namespace": + args := c.RemainingArgs() + if len(args) == 0 { + k.Namespace = "" + } else if len(args) == 1 { + k.Namespace = args[0] + } else { + return nil, c.ArgErr() + } + default: + return nil, c.Errf("unknown property '%s'", c.Val()) + } + } + + return k, nil +} |