Files
sultan/pkg/agent/hostinfo_test.go
T

97 lines
3.2 KiB
Go

package agent
import (
"context"
"errors"
"net"
"os"
"path/filepath"
"testing"
)
// fakeResolver beantwortet CNAME- und PTR-Anfragen aus Tabellen.
type fakeResolver struct {
cname map[string]string
ptr map[string][]string
}
func (f fakeResolver) LookupCNAME(_ context.Context, host string) (string, error) {
if c, ok := f.cname[host]; ok {
return c, nil
}
return "", errors.New("no such host")
}
func (f fakeResolver) LookupAddr(_ context.Context, addr string) ([]string, error) {
if p, ok := f.ptr[addr]; ok {
return p, nil
}
return nil, errors.New("no such host")
}
// FQDN: explizit > Hostname mit Punkt > aufgelöster Hostname (Suchdomain) >
// Reverse-Lookup der Backend-Adresse > kurzer Hostname.
func TestDetectFQDN(t *testing.T) {
res := fakeResolver{
cname: map[string]string{"webdocker11": "webdocker11.lan.r25dc.de.", "kurz": "kurz"},
ptr: map[string][]string{"10.0.0.11": {"backend11.lan.r25dc.de."}},
}
tests := []struct {
name, explicit, hostname, backend, want string
}{
{"explizit gewinnt", "web.example.de", "webdocker11", "10.0.0.11", "web.example.de"},
{"Hostname ist schon FQDN", "", "pi.home.arpa", "10.0.0.11", "pi.home.arpa"},
{"über Suchdomain aufgelöst", "", "webdocker11", "10.0.0.11", "webdocker11.lan.r25dc.de"},
{"Reverse-Lookup der Backend-Adresse", "", "kurz", "10.0.0.11", "backend11.lan.r25dc.de"},
{"nichts auflösbar: kurzer Hostname", "", "solo", "10.9.9.9", "solo"},
{"Groß/Klein und Leerraum", " Web.Example.DE ", "x", "", "web.example.de"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := detectFQDN(context.Background(), res, tt.explicit, tt.hostname, tt.backend); got != tt.want {
t.Errorf("detectFQDN = %q, erwartet %q", got, tt.want)
}
})
}
}
// NetBird: Interface wt0, sonst eine Adresse aus 100.64.0.0/10 (CGNAT, wie
// NetBird sie vergibt).
func TestNetBirdIP(t *testing.T) {
ip := net.ParseIP
tests := []struct {
name string
addrs map[string][]net.IP
want string
}{
{"wt0", map[string][]net.IP{"eth0": {ip("10.0.0.11")}, "wt0": {ip("fe80::1"), ip("100.92.10.4")}}, "100.92.10.4"},
{"CGNAT auf anderem Interface", map[string][]net.IP{"eth0": {ip("10.0.0.11")}, "nb0": {ip("100.64.3.2")}}, "100.64.3.2"},
{"kein Overlay", map[string][]net.IP{"eth0": {ip("10.0.0.11")}, "lo": {ip("127.0.0.1")}}, ""},
{"100.128.x ist kein CGNAT", map[string][]net.IP{"eth0": {ip("100.128.0.1")}}, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := netbirdIP(tt.addrs); got != tt.want {
t.Errorf("netbirdIP = %q, erwartet %q", got, tt.want)
}
})
}
}
// Ohne Docker (systemd-Agent) kommt das Betriebssystem aus /etc/os-release.
func TestOSPrettyName(t *testing.T) {
dir := t.TempDir()
p := filepath.Join(dir, "os-release")
os.WriteFile(p, []byte("NAME=\"Debian GNU/Linux\"\nPRETTY_NAME=\"Debian GNU/Linux 13 (trixie)\"\nID=debian\n"), 0o644)
if got := osPrettyName(p); got != "Debian GNU/Linux 13 (trixie)" {
t.Errorf("osPrettyName = %q", got)
}
os.WriteFile(p, []byte("NAME=Alpine\nID=alpine\n"), 0o644)
if got := osPrettyName(p); got != "Alpine" {
t.Errorf("ohne PRETTY_NAME: %q, erwartet NAME", got)
}
if got := osPrettyName(filepath.Join(dir, "fehlt")); got != "" {
t.Errorf("fehlende Datei: %q", got)
}
}