1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

Check for duplicate records much earlier (#467)

* Check for duplicate records much earlier.

* Change GetTargetDiffable to ToDiffable

* fixup!
This commit is contained in:
Tom Limoncelli
2019-04-22 15:41:39 -04:00
committed by GitHub
parent b19074e6dc
commit 61a00a7d7e
4 changed files with 98 additions and 0 deletions

View File

@@ -387,6 +387,8 @@ func NormalizeAndValidateConfig(config *models.DNSConfig) (errs []error) {
if err != nil {
errs = append(errs, err)
}
// Check for duplicates
errs = append(errs, checkDuplicates(d.Records)...)
// Validate FQDN consistency
for _, r := range d.Records {
if r.NameFQDN == "" || !strings.HasSuffix(r.NameFQDN, d.Name) {
@@ -416,6 +418,18 @@ func checkCNAMEs(dc *models.DomainConfig) (errs []error) {
return
}
func checkDuplicates(records []*models.RecordConfig) (errs []error) {
seen := map[string]*models.RecordConfig{}
for _, r := range records {
diffable := fmt.Sprintf("%s %s %s", r.GetLabelFQDN(), r.Type, r.ToDiffable())
if seen[diffable] != nil {
errs = append(errs, errors.Errorf("Exact duplicate record found: %s", diffable))
}
seen[diffable] = r
}
return errs
}
func checkProviderCapabilities(dc *models.DomainConfig) error {
types := []struct {
rType string

View File

@@ -213,6 +213,54 @@ func TestCAAValidation(t *testing.T) {
}
}
func TestCheckDuplicates(t *testing.T) {
records := []*models.RecordConfig{
// The only difference is the target:
makeRC("www", "example.com", "4.4.4.4", models.RecordConfig{Type: "A"}),
makeRC("www", "example.com", "5.5.5.5", models.RecordConfig{Type: "A"}),
// The only difference is the rType:
makeRC("aaa", "example.com", "uniquestring.com.", models.RecordConfig{Type: "NS"}),
makeRC("aaa", "example.com", "uniquestring.com.", models.RecordConfig{Type: "PTR"}),
// The only difference is the TTL.
makeRC("zzz", "example.com", "4.4.4.4", models.RecordConfig{Type: "A", TTL: 111}),
makeRC("zzz", "example.com", "4.4.4.4", models.RecordConfig{Type: "A", TTL: 222}),
// Three records each with a different target.
makeRC("@", "example.com", "ns1.foo.com.", models.RecordConfig{Type: "NS"}),
makeRC("@", "example.com", "ns2.foo.com.", models.RecordConfig{Type: "NS"}),
makeRC("@", "example.com", "ns3.foo.com.", models.RecordConfig{Type: "NS"}),
}
errs := checkDuplicates(records)
if len(errs) != 0 {
t.Errorf("Expect duplicate NOT found but found %q", errs)
}
}
func TestCheckDuplicates_dup_a(t *testing.T) {
records := []*models.RecordConfig{
// A records that are exact dupliates.
makeRC("@", "example.com", "1.1.1.1", models.RecordConfig{Type: "A"}),
makeRC("@", "example.com", "1.1.1.1", models.RecordConfig{Type: "A"}),
}
errs := checkDuplicates(records)
if len(errs) == 0 {
t.Error("Expect duplicate found but found none")
}
}
func TestCheckDuplicates_dup_ns(t *testing.T) {
records := []*models.RecordConfig{
// Three records, the last 2 are duplicates.
// NB: This is a common issue.
makeRC("@", "example.com", "ns1.foo.com.", models.RecordConfig{Type: "NS"}),
makeRC("@", "example.com", "ns2.foo.com.", models.RecordConfig{Type: "NS"}),
makeRC("@", "example.com", "ns2.foo.com.", models.RecordConfig{Type: "NS"}),
}
errs := checkDuplicates(records)
if len(errs) == 0 {
t.Error("Expect duplicate found but found none")
}
}
func TestTLSAValidation(t *testing.T) {
config := &models.DNSConfig{
Domains: []*models.DomainConfig{