Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
3.6 KiB
Go
94 lines
3.6 KiB
Go
// SPDX-License-Identifier: LicenseRef-DDI-Proprietary
|
|
|
|
package httpapi
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.beugsiud.de/beug.k/DDI/server/internal/service"
|
|
)
|
|
|
|
func fileByPath(files []service.GeneratedFile, path string) *service.GeneratedFile {
|
|
for i := range files {
|
|
if files[i].Path == path {
|
|
return &files[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestGeneratorSettingsAndPreview(t *testing.T) {
|
|
e := newEnv(t)
|
|
admin := e.adminClient()
|
|
viewer := e.userClient(admin, "vera", "viewer")
|
|
|
|
var g service.GeneratorSettings
|
|
admin.mustStatus(200, "GET", "/api/v1/settings/generator", nil).json(t, &g)
|
|
if g.DNS.DefaultTTL != 3600 || g.DHCP.ValidLifetime != 3600 || len(g.DHCP.Interfaces) != 1 {
|
|
t.Fatalf("defaults %+v", g)
|
|
}
|
|
|
|
admin.mustStatus(201, "POST", "/api/v1/networks", map[string]any{
|
|
"cidr": "192.0.2.0/24", "name": "Office", "gateway": "192.0.2.1", "domain": "office.test",
|
|
"dhcp_enabled": true, "pools": []map[string]string{{"start": "192.0.2.100", "end": "192.0.2.199"}},
|
|
"dns_servers": []string{"192.0.2.53"},
|
|
})
|
|
admin.mustStatus(201, "POST", "/api/v1/addresses", map[string]any{"ip": "192.0.2.10", "type": "static", "hostname": "www"})
|
|
admin.mustStatus(201, "POST", "/api/v1/addresses", map[string]any{"ip": "192.0.2.53", "type": "static", "hostname": "ns1"})
|
|
admin.mustStatus(201, "POST", "/api/v1/addresses", map[string]any{"ip": "192.0.2.150", "type": "manual_dhcp",
|
|
"mac": "00:11:22:33:44:55", "hostname": "printer"})
|
|
|
|
// Without DNS settings only DHCP can be generated.
|
|
var p service.ConfigPreview
|
|
viewer.mustStatus(200, "GET", "/api/v1/config/preview", nil).json(t, &p)
|
|
if p.DNSError == nil || p.DNSError.Code != "dns_settings_missing" {
|
|
t.Errorf("dns error %+v", p.DNSError)
|
|
}
|
|
if p.DHCPError != nil || len(p.DHCP) != 1 {
|
|
t.Fatalf("dhcp: %+v %+v", p.DHCPError, p.DHCP)
|
|
}
|
|
kea := p.DHCP[0].Content
|
|
for _, want := range []string{"192.0.2.0/24", "00:11:22:33:44:55", "192.0.2.150", "192.0.2.100", "192.0.2.199"} {
|
|
if !strings.Contains(kea, want) {
|
|
t.Errorf("Kea config misses %q:\n%s", want, kea)
|
|
}
|
|
}
|
|
|
|
g.DNS.PrimaryNS = "ns1.office.test"
|
|
g.DNS.Hostmaster = "bad@mail@box"
|
|
g.DNS.NameServers = []service.GeneratorNS{{Name: "ns1.office.test", Addresses: []string{"192.0.2.53"}}}
|
|
r := admin.mustStatus(422, "PUT", "/api/v1/settings/generator", g)
|
|
if p := r.problem(t).Problems; len(p) == 0 || p[0].Field != "dns.hostmaster" {
|
|
t.Errorf("hostmaster problems %+v", p)
|
|
}
|
|
g.DNS.Hostmaster = "hostmaster@office.test"
|
|
viewer.mustStatus(403, "PUT", "/api/v1/settings/generator", g)
|
|
admin.mustStatus(200, "PUT", "/api/v1/settings/generator", g).json(t, &g)
|
|
if g.DNS.Hostmaster != "hostmaster.office.test" {
|
|
t.Errorf("hostmaster not normalized: %q", g.DNS.Hostmaster)
|
|
}
|
|
|
|
p = service.ConfigPreview{} // json.Unmarshal keeps fields absent from the new response
|
|
viewer.mustStatus(200, "GET", "/api/v1/config/preview", nil).json(t, &p)
|
|
if p.DNSError != nil {
|
|
t.Fatalf("dns error %+v", p.DNSError)
|
|
}
|
|
conf := fileByPath(p.DNS, "ddi-suite.conf")
|
|
zone := fileByPath(p.DNS, "zones/db.office.test")
|
|
rev := fileByPath(p.DNS, "zones/db.2.0.192.in-addr.arpa")
|
|
if conf == nil || zone == nil || rev == nil {
|
|
t.Fatalf("missing files: %+v", p.DNS)
|
|
}
|
|
if !strings.Contains(conf.Content, "office.test") || !strings.Contains(zone.Content, "192.0.2.10") ||
|
|
!strings.Contains(zone.Content, "printer") || !strings.Contains(rev.Content, "www.office.test.") {
|
|
t.Errorf("unexpected DNS output:\n%s\n%s\n%s", conf.Content, zone.Content, rev.Content)
|
|
}
|
|
|
|
var audit auditPage
|
|
admin.mustStatus(200, "GET", "/api/v1/audit?action=settings.generator", nil).json(t, &audit)
|
|
if len(audit.Items) != 1 {
|
|
t.Errorf("settings change not audited: %+v", audit.Items)
|
|
}
|
|
}
|