Files
dns-autoresolver/internal/store/loader_test.go
T
vasyansk 9ccb304d2e feat(api): read zone records without template + snapshot-to-template
LoadDomain requires a template, so a zone without one could never be
viewed or snapshotted. Adds a template-free path: store.LoadZone /
service.ZoneRef / DomainService.ZoneRecords read a zone's live records
straight from the provider (no diff, no template). GET
/domains/{did}/records exposes read-only viewing; POST
/domains/{did}/template-from-zone snapshots only managed record types
(NS/SOA excluded) into a new template and auto-attaches it to the domain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
2026-07-05 12:00:27 +07:00

126 lines
3.7 KiB
Go

package store
import (
"testing"
"github.com/google/uuid"
"github.com/vasyakrg/dns-autoresolver/internal/diff"
"github.com/vasyakrg/dns-autoresolver/internal/model"
"github.com/vasyakrg/dns-autoresolver/internal/store/db"
"github.com/vasyakrg/dns-autoresolver/internal/store/dto"
)
func TestLoadDomainAndSaveCheckRun(t *testing.T) {
s, ctx := newStore(t)
acc, err := s.Queries().CreateAccount(ctx, db.CreateAccountParams{
ID: uuid.New(), ProjectID: defaultProject,
Provider: "selectel", SecretEnc: "enc-blob", Comment: "prod",
})
if err != nil {
t.Fatal(err)
}
doc := dto.TemplateDoc{Records: []dto.RecordDTO{
{Type: "A", Name: "www.example.com.", TTL: 300, Values: []string{"1.2.3.4"}},
}}
tpl, err := s.Queries().CreateTemplate(ctx, db.CreateTemplateParams{
ID: uuid.New(), ProjectID: defaultProject, Name: "base", Doc: &doc,
})
if err != nil {
t.Fatal(err)
}
domain, err := s.Queries().CreateDomain(ctx, db.CreateDomainParams{
ID: uuid.New(), ProjectID: defaultProject, ProviderAccountID: acc.ID,
ZoneName: "example.com", ZoneID: "zone-1", TemplateID: &tpl.ID,
})
if err != nil {
t.Fatal(err)
}
ref, err := s.LoadDomain(ctx, defaultProject, domain.ID)
if err != nil {
t.Fatal(err)
}
if ref.ZoneID != "zone-1" || ref.Provider != "selectel" || ref.SecretEnc != "enc-blob" {
t.Fatalf("domain ref mismatch: %+v", ref)
}
if len(ref.Template.Records) != 1 {
t.Fatalf("expected template records, got %+v", ref.Template)
}
cs := diff.Changeset{Diffs: []diff.RecordDiff{
{Kind: diff.Add, Type: model.A, Name: "www.example.com."},
{Kind: diff.Delete, Type: model.A, Name: "old.example.com."},
}}
if err := s.SaveCheckRun(ctx, domain.ID, cs); err != nil {
t.Fatal(err)
}
var count int
if err := s.pool.QueryRow(ctx, "SELECT count(*) FROM check_runs WHERE domain_id = $1", domain.ID).Scan(&count); err != nil {
t.Fatal(err)
}
if count != 1 {
t.Fatalf("expected 1 check_runs row, got %d", count)
}
}
func TestLoadDomainNoTemplate(t *testing.T) {
s, ctx := newStore(t)
acc, err := s.Queries().CreateAccount(ctx, db.CreateAccountParams{
ID: uuid.New(), ProjectID: defaultProject,
Provider: "selectel", SecretEnc: "enc-blob", Comment: "prod",
})
if err != nil {
t.Fatal(err)
}
domain, err := s.Queries().CreateDomain(ctx, db.CreateDomainParams{
ID: uuid.New(), ProjectID: defaultProject, ProviderAccountID: acc.ID,
ZoneName: "example.com", ZoneID: "zone-2", TemplateID: nil,
})
if err != nil {
t.Fatal(err)
}
if _, err := s.LoadDomain(ctx, defaultProject, domain.ID); err == nil {
t.Fatal("expected error for domain without template, got nil")
}
}
// TestLoadZoneNoTemplate covers the Task 1 gap: a domain with no attached
// template must still be resolvable to its provider-access ref (ZoneRef) so
// its live records can be read/snapshotted — unlike LoadDomain, LoadZone
// must NOT error out on a nil template doc.
func TestLoadZoneNoTemplate(t *testing.T) {
s, ctx := newStore(t)
acc, err := s.Queries().CreateAccount(ctx, db.CreateAccountParams{
ID: uuid.New(), ProjectID: defaultProject,
Provider: "selectel", SecretEnc: "enc-blob", Comment: "prod",
})
if err != nil {
t.Fatal(err)
}
domain, err := s.Queries().CreateDomain(ctx, db.CreateDomainParams{
ID: uuid.New(), ProjectID: defaultProject, ProviderAccountID: acc.ID,
ZoneName: "example.com", ZoneID: "zone-3", TemplateID: nil,
})
if err != nil {
t.Fatal(err)
}
ref, err := s.LoadZone(ctx, defaultProject, domain.ID)
if err != nil {
t.Fatalf("expected LoadZone to succeed without a template, got error: %v", err)
}
if ref.ZoneID != "zone-3" || ref.Provider != "selectel" || ref.SecretEnc != "enc-blob" {
t.Fatalf("zone ref mismatch: %+v", ref)
}
}