Files
coredns/plugin/nomad/nomad_test.go
Olli Janatuinen 83ce0baeac plugin/nomad: Add a Nomad plugin (#7467)
Signed-off-by: Olli Janatuinen <olli.janatuinen@gmail.com>
2025-09-30 09:35:32 -07:00

205 lines
6.2 KiB
Go

package nomad
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/test"
nomad "github.com/hashicorp/nomad/api"
"github.com/miekg/dns"
)
func TestNomad(t *testing.T) {
var demoNomad = Nomad{
Next: test.ErrorHandler(),
ttl: uint32(defaultTTL),
Zone: "service.nomad",
clients: make([]*nomad.Client, 0),
}
var cases = []test.Case{
{
Qname: "example.default.service.nomad.",
Qtype: dns.TypeA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{
test.A("example.default.service.nomad. 30 IN A 1.2.3.4"),
},
},
{
Qname: "example.default.service.nomad.",
Qtype: dns.TypeAAAA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{},
},
{
Qname: "fakeipv6.default.service.nomad.",
Qtype: dns.TypeAAAA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{
test.AAAA("fakeipv6.default.service.nomad. 30 IN AAAA 1:2:3::4"),
},
},
{
Qname: "fakeipv6.default.service.nomad.",
Qtype: dns.TypeA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{},
},
{
Qname: "multi.default.service.nomad.",
Qtype: dns.TypeA,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{
test.A("multi.default.service.nomad. 30 IN A 1.2.3.4"),
test.A("multi.default.service.nomad. 30 IN A 1.2.3.5"),
test.A("multi.default.service.nomad. 30 IN A 1.2.3.6"),
},
},
{
Qname: "nonexistent.default.service.nomad.",
Qtype: dns.TypeA,
Rcode: dns.RcodeNameError,
Answer: []dns.RR{
test.SOA("nonexistent.default.service.nomad. 30 IN SOA ns1.nonexistent.default.service.nomad. hostmaster.service.nomad. 0 3600 600 86400 30"),
},
},
{
Qname: "example.default.service.nomad.",
Qtype: dns.TypeSRV,
Rcode: dns.RcodeSuccess,
Answer: []dns.RR{test.SRV("example.default.service.nomad. 30 IN SRV 10 10 23202 example.default.service.nomad.")},
Extra: []dns.RR{test.A("example.default.service.nomad. 30 IN A 1.2.3.4")},
},
}
ctx := context.Background()
// Setup a fake Nomad servers.
nomadServer1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/v1/service/example":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":23202,"ServiceName":"example"}]`))
case "/v1/service/fakeipv6":
w.Write([]byte(`[{"Address":"1:2:3::4","Namespace":"default","Port":8000,"ServiceName":"fakeipv6"}]`))
case "/v1/service/multi":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":25395,"ServiceName":"multi"},{"Address":"1.2.3.5","Namespace":"default","Port":20888,"ServiceName":"multi"},{"Address":"1.2.3.6","Namespace":"default","Port":26292,"ServiceName":"multi"}]`))
case "/v1/service/nonexistent":
w.Write([]byte(`[]`))
case "/v1/agent/self":
w.Write([]byte(`{"Member":{"Name":"foobar1"}}`))
}
}))
defer nomadServer1.Close()
nomadServer2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/v1/service/example":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":23202,"ServiceName":"example"}]`))
case "/v1/service/fakeipv6":
w.Write([]byte(`[{"Address":"1:2:3::4","Namespace":"default","Port":8000,"ServiceName":"fakeipv6"}]`))
case "/v1/service/multi":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":25395,"ServiceName":"multi"},{"Address":"1.2.3.5","Namespace":"default","Port":20888,"ServiceName":"multi"},{"Address":"1.2.3.6","Namespace":"default","Port":26292,"ServiceName":"multi"}]`))
case "/v1/service/nonexistent":
w.Write([]byte(`[]`))
case "/v1/agent/self":
w.Write([]byte(`{"Member":{"Name":"foobar2"}}`))
}
}))
defer nomadServer2.Close()
nomadServer3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/v1/service/example":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":23202,"ServiceName":"example"}]`))
case "/v1/service/fakeipv6":
w.Write([]byte(`[{"Address":"1:2:3::4","Namespace":"default","Port":8000,"ServiceName":"fakeipv6"}]`))
case "/v1/service/multi":
w.Write([]byte(`[{"Address":"1.2.3.4","Namespace":"default","Port":25395,"ServiceName":"multi"},{"Address":"1.2.3.5","Namespace":"default","Port":20888,"ServiceName":"multi"},{"Address":"1.2.3.6","Namespace":"default","Port":26292,"ServiceName":"multi"}]`))
case "/v1/service/nonexistent":
w.Write([]byte(`[]`))
case "/v1/agent/self":
w.Write([]byte(`{"Member":{"Name":"foobar3"}}`))
}
}))
defer nomadServer3.Close()
// Configure the plugin to use the fake Nomad server.
cfg := nomad.DefaultConfig()
cfg.Address = nomadServer1.URL
client1, err := nomad.NewClient(cfg)
if err != nil {
t.Errorf("Failed to create Nomad client: %v", err)
return
}
demoNomad.clients = append(demoNomad.clients, client1)
cfg = nomad.DefaultConfig()
cfg.Address = nomadServer2.URL
client2, err := nomad.NewClient(cfg)
if err != nil {
t.Errorf("Failed to create Nomad client: %v", err)
return
}
demoNomad.clients = append(demoNomad.clients, client2)
cfg = nomad.DefaultConfig()
cfg.Address = nomadServer3.URL
client3, err := nomad.NewClient(cfg)
if err != nil {
t.Errorf("Failed to create Nomad client: %v", err)
return
}
demoNomad.clients = append(demoNomad.clients, client3)
client, _ := demoNomad.getClient()
if client != client1 {
t.Errorf("Expected client1")
}
nomadServer1.Close()
client, _ = demoNomad.getClient()
if client == client1 {
t.Errorf("Expected client2")
}
client, err = demoNomad.getClient()
if err != nil {
t.Errorf("Expected no error, but got %v", err)
}
if client == nil {
t.Errorf("Expected client2 but got nil")
}
if client != client2 {
t.Errorf("Expected client2")
}
runTests(ctx, t, &demoNomad, cases)
}
func runTests(ctx context.Context, t *testing.T, n *Nomad, cases []test.Case) {
t.Helper()
for i, tc := range cases {
r := tc.Msg()
w := dnstest.NewRecorder(&test.ResponseWriter{})
_, err := n.ServeDNS(ctx, w, r)
if err != tc.Error {
t.Errorf("Test %d: %v (%v) (%v)", i, err, w, r)
return
}
if w.Msg == nil {
t.Errorf("Test %d: nil message", i)
}
if err := test.SortAndCheck(w.Msg, tc); err != nil {
t.Errorf("Test %d: %v", i, err)
}
}
}