Ctrl K
ComunidadGuías…

adguardhome/txt_rewrite_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package adguardhome

import (
	"context"
	"reflect"
	"strings"
	"testing"

	"sigs.k8s.io/external-dns/endpoint"
	"sigs.k8s.io/external-dns/plan"
)

func TestTXTRewriteValues(t *testing.T) {
	for _, tt := range []struct {
		name   string
		target string
		value  string
	}{
		{name: "plain", target: "verification-token", value: "verification-token"},
		{name: "spaces", target: "v=spf1 include:example.com -all", value: `v=spf1\032include:example.com\032-all`},
		{name: "quoted ownership", target: `"heritage=external-dns,external-dns/owner=test"`, value: `heritage=external-dns\044external-dns/owner=test`},
		{name: "reserved characters", target: `a,b$important "quoted" C:\path`, value: `a\044b\036important\032\034quoted\034\032C:\092path`},
		{name: "quoted escapes", target: `"a\"b\\c\044\036"`, value: `a\034b\092c\044\036`},
		{name: "trailing space", target: "token ", value: `token\032`},
		{name: "label-like content", target: "token;labels=not-json", value: "token;labels=not-json"},
		{name: "management marker in content", target: "$managed by external-dns", value: `\036managed\032by\032external-dns`},
		{name: "metadata-like content", target: "$managed by external-dns;labels=not-json", value: `\036managed\032by\032external-dns;labels=not-json`},
		{name: "unicode", target: "é", value: `\195\169`},
		{name: "decimal byte", target: `"\255"`, value: `\255`},
		{name: "empty", target: "", value: ""},
		{name: "quoted empty", target: `""`, value: ""},
		{name: "maximum length", target: strings.Repeat("x", 255), value: strings.Repeat("x", 255)},
	} {
		t.Run(tt.name, func(t *testing.T) {
			c := &mockAdguardClient{}
			p := &AdguardHomeProvider{client: c, ruleFormat: rewriteRuleFormat()}
			e := &endpoint.Endpoint{DNSName: "txt.example.com", RecordType: endpoint.RecordTypeTXT, Targets: endpoint.Targets{tt.target}, Labels: endpoint.Labels{"owner": "test"}}
			if err := p.ApplyChanges(context.Background(), &plan.Changes{Create: []*endpoint.Endpoint{e}}); err != nil {
				t.Fatal(err)
			}
			if len(c.rules) != 2 || c.rules[1] != "|txt.example.com|$dnstype=TXT,dnsrewrite=NOERROR;TXT;"+tt.value {
				t.Fatalf("unexpected rules: %v", c.rules)
			}
			records, err := p.Records(context.Background())
			if err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(records, []*endpoint.Endpoint{e}) {
				t.Fatalf("TXT endpoint changed: got %+v, want %+v", records, e)
			}
			before := append([]string(nil), c.rules...)
			if err = p.ApplyChanges(context.Background(), &plan.Changes{}); err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(c.rules, before) {
				t.Fatalf("reconciliation changed TXT rules: %v", c.rules)
			}
			p.ruleFormat = legacyRuleFormat()
			if err = p.migrateRules(context.Background()); err != nil {
				t.Fatal(err)
			}
			records, err = p.Records(context.Background())
			if err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(records, []*endpoint.Endpoint{e}) {
				t.Fatalf("rollback changed TXT endpoint: got %+v, want %+v", records, e)
			}
		})
	}
}

func TestTXTRewriteValidation(t *testing.T) {
	for _, target := range []string{
		strings.Repeat("x", 256),
		strings.Repeat("é", 128),
		`"unterminated`,
		`"a" "b"`,
		`"bad\999"`,
		`"bad\256"`,
		`"bad\"`,
		"injected\n||example.com^",
	} {
		t.Run(target, func(t *testing.T) {
			c := &mockAdguardClient{rules: []string{"# existing rule"}}
			p := &AdguardHomeProvider{client: c, ruleFormat: rewriteRuleFormat()}
			err := p.ApplyChanges(context.Background(), &plan.Changes{Create: []*endpoint.Endpoint{
				{DNSName: "txt.example.com", RecordType: endpoint.RecordTypeTXT, Targets: endpoint.Targets{target}},
			}})
			if err == nil {
				t.Fatal("expected invalid TXT value to fail")
			}
			if !reflect.DeepEqual(c.rules, []string{"# existing rule"}) {
				t.Fatalf("invalid value overwrote rules: %v", c.rules)
			}
		})
	}
}

func TestTXTRewriteMigrationAndRollback(t *testing.T) {
	legacy := []string{
		"# keep this comment",
		`# "heritage=external-dns,external-dns/owner=test" app.example.com $managed by external-dns;ref:test;labels={"owner":"test"}`,
		"# v=spf1 include:example.com -all app.example.com $managed by external-dns;ref:test",
	}
	a := setupRewriteTest(t, legacy, "true")
	p, err := newInitializedTestProvider(false)
	if err != nil {
		t.Fatal(err)
	}
	rewritten, writes := a.snapshot()
	if writes != 1 || len(rewritten) != 5 || rewritten[2] != `|app.example.com|$dnstype=TXT,dnsrewrite=NOERROR;TXT;heritage=external-dns\044external-dns/owner=test` || rewritten[4] != `|app.example.com|$dnstype=TXT,dnsrewrite=NOERROR;TXT;v=spf1\032include:example.com\032-all` {
		t.Fatalf("TXT-only startup migration got rules %v, writes %d", rewritten, writes)
	}
	records, err := p.Records(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	want := []*endpoint.Endpoint{{DNSName: "app.example.com", RecordType: endpoint.RecordTypeTXT, Targets: endpoint.Targets{`"heritage=external-dns,external-dns/owner=test"`, "v=spf1 include:example.com -all"}, Labels: endpoint.Labels{"owner": "test"}}}
	if !reflect.DeepEqual(records, want) {
		t.Fatalf("migrated TXT records got %+v, want %+v", records, want)
	}
	t.Setenv(envUseDNSRewrite, "false")
	if _, err = newInitializedTestProvider(false); err != nil {
		t.Fatal(err)
	}
	if rules, writes := a.snapshot(); !reflect.DeepEqual(rules, legacy) || writes != 2 {
		t.Fatalf("rollback got rules %v, writes %d; want %v, writes 2", rules, writes, legacy)
	}
}

func TestTXTRewriteSharesHostnameWithA(t *testing.T) {
	for _, enabled := range []bool{false, true} {
		name := "legacy"
		if enabled {
			name = "rewrite"
		}
		t.Run(name, func(t *testing.T) {
			c := &mockAdguardClient{}
			format := legacyRuleFormat()
			if enabled {
				format = rewriteRuleFormat()
			}
			p := &AdguardHomeProvider{client: c, ruleFormat: format}
			ctx := context.Background()
			a := &endpoint.Endpoint{DNSName: "app.example.com", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"192.0.2.10"}, Labels: endpoint.Labels{"kind": "address"}}
			txt := &endpoint.Endpoint{DNSName: "app.example.com", RecordType: endpoint.RecordTypeTXT, Targets: endpoint.Targets{"first", "second"}, Labels: endpoint.Labels{"kind": "text"}}
			if err := p.ApplyChanges(ctx, &plan.Changes{Create: []*endpoint.Endpoint{a, txt}}); err != nil {
				t.Fatal(err)
			}
			records, err := p.Records(ctx)
			if err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(records, []*endpoint.Endpoint{a, txt}) {
				t.Fatalf("A and TXT records merged: %+v", records)
			}
			updated := &endpoint.Endpoint{DNSName: txt.DNSName, RecordType: txt.RecordType, Targets: endpoint.Targets{"updated"}, Labels: txt.Labels}
			if err = p.ApplyChanges(ctx, &plan.Changes{UpdateOld: []*endpoint.Endpoint{txt}, UpdateNew: []*endpoint.Endpoint{updated}}); err != nil {
				t.Fatal(err)
			}
			if err = p.ApplyChanges(ctx, &plan.Changes{Delete: []*endpoint.Endpoint{updated}}); err != nil {
				t.Fatal(err)
			}
			records, err = p.Records(ctx)
			if err != nil {
				t.Fatal(err)
			}
			if !reflect.DeepEqual(records, []*endpoint.Endpoint{a}) {
				t.Fatalf("deleting TXT changed A record: %+v", records)
			}
		})
	}
}