coredns/plugin/forwardcrd/plugin_map_test.go
Christian Ang 2e6953c7db
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>
2021-11-12 11:22:34 -05:00

89 lines
2.9 KiB
Go

package forwardcrd
import (
"sync"
"testing"
"github.com/coredns/coredns/plugin/forward"
)
func TestPluginMap(t *testing.T) {
pluginInstanceMap := NewPluginInstanceMap()
zone1ForwardPlugin := forward.New()
zone2ForwardPlugin := forward.New()
// Testing concurrency to ensure map is thread-safe
// i.e should run with `go test -race`
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
pluginInstanceMap.Upsert("default/some-dns-zone", "zone-1.test", zone1ForwardPlugin)
wg.Done()
}()
wg.Add(1)
go func() {
pluginInstanceMap.Upsert("default/another-dns-zone", "zone-2.test", zone2ForwardPlugin)
wg.Done()
}()
wg.Wait()
if plugin, exists := pluginInstanceMap.Get("zone-1.test."); exists && plugin != zone1ForwardPlugin {
t.Fatalf("Expected plugin instance map to get plugin with address: %p but was: %p", zone1ForwardPlugin, plugin)
}
if plugin, exists := pluginInstanceMap.Get("zone-2.test"); exists && plugin != zone2ForwardPlugin {
t.Fatalf("Expected plugin instance map to get plugin with address: %p but was: %p", zone2ForwardPlugin, plugin)
}
if _, exists := pluginInstanceMap.Get("non-existant-zone.test"); exists {
t.Fatal("Expected plugin instance map to not return a plugin")
}
// list
plugins := pluginInstanceMap.List()
if len(plugins) != 2 {
t.Fatalf("Expected plugin instance map to have len %d, got: %d", 2, len(plugins))
}
if plugins[0] != zone1ForwardPlugin && plugins[0] != zone2ForwardPlugin {
t.Fatalf("Expected plugin instance map to list plugin[0] with address: %p or %p but was: %p", zone1ForwardPlugin, zone2ForwardPlugin, plugins[0])
}
if plugins[1] != zone1ForwardPlugin && plugins[1] != zone2ForwardPlugin {
t.Fatalf("Expected plugin instance map to list plugin[1] with address: %p or %p but was: %p", zone1ForwardPlugin, zone2ForwardPlugin, plugins[1])
}
// update record with the same key
oldPlugin, update := pluginInstanceMap.Upsert("default/some-dns-zone", "new-zone-1.test", zone1ForwardPlugin)
if !update {
t.Fatalf("Expected Upsert to be an update")
}
if oldPlugin != zone1ForwardPlugin {
t.Fatalf("Expected Upsert to return the old plugin %#v, got: %#v", zone1ForwardPlugin, oldPlugin)
}
if plugin, exists := pluginInstanceMap.Get("new-zone-1.test"); exists && plugin != zone1ForwardPlugin {
t.Fatalf("Expected plugin instance map to get plugin with address: %p but was: %p", zone1ForwardPlugin, plugin)
}
if _, exists := pluginInstanceMap.Get("zone-1.test"); exists {
t.Fatalf("Expected plugin instance map to not get plugin with zone: %s", "zone-1.test")
}
// delete record by key
deletedPlugin := pluginInstanceMap.Delete("default/some-dns-zone")
if _, exists := pluginInstanceMap.Get("new-zone-1.test"); exists {
t.Fatalf("Expected plugin instance map to not get plugin with zone: %s", "new-zone-1.test")
}
if deletedPlugin == nil || deletedPlugin != zone1ForwardPlugin {
t.Fatalf("Expected Delete to return the deleted plugin %#v, got: %#v", zone1ForwardPlugin, deletedPlugin)
}
}