mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
FEATURE: Add rTypes restrictions to IGNORE_NAME (#1808)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/StackExchange/dnscontrol/v3/models"
|
||||
@@ -42,11 +43,18 @@ func New(dc *models.DomainConfig, extraValues ...func(*models.RecordConfig) map[
|
||||
}
|
||||
}
|
||||
|
||||
// An ignoredName must match both the name glob and one of the recordTypes in rTypes. If rTypes is empty, any
|
||||
// record type will match.
|
||||
type ignoredName struct {
|
||||
nameGlob glob.Glob
|
||||
rTypes []string
|
||||
}
|
||||
|
||||
type differ struct {
|
||||
dc *models.DomainConfig
|
||||
extraValues []func(*models.RecordConfig) map[string]string
|
||||
|
||||
compiledIgnoredNames []glob.Glob
|
||||
compiledIgnoredNames []ignoredName
|
||||
compiledIgnoredTargets []glob.Glob
|
||||
}
|
||||
|
||||
@@ -99,7 +107,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
||||
// Gather the existing records. Skip over any that should be ignored.
|
||||
for _, e := range existing {
|
||||
//fmt.Printf("********** DEBUG: existing %v %v %v\n", e.GetLabel(), e.Type, e.GetTargetCombined())
|
||||
if d.matchIgnoredName(e.GetLabel()) {
|
||||
if d.matchIgnoredName(e.GetLabel(), e.Type) {
|
||||
//fmt.Printf("Ignoring record %s %s due to IGNORE_NAME\n", e.GetLabel(), e.Type)
|
||||
printer.Debugf("Ignoring record %s %s due to IGNORE_NAME\n", e.GetLabel(), e.Type)
|
||||
} else if d.matchIgnoredTarget(e.GetTargetField(), e.Type) {
|
||||
@@ -115,7 +123,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
||||
//fmt.Printf("********** DEBUG: desired list %+v\n", desired)
|
||||
for _, dr := range desired {
|
||||
//fmt.Printf("********** DEBUG: desired %v %v %v -- %v %v\n", dr.GetLabel(), dr.Type, dr.GetTargetCombined(), apexException(dr), d.matchIgnoredName(dr.GetLabel()))
|
||||
if d.matchIgnoredName(dr.GetLabel()) {
|
||||
if d.matchIgnoredName(dr.GetLabel(), dr.Type) {
|
||||
//if !apexException(dr) || !ignoreNameException(dr) {
|
||||
if (!ignoreNameException(dr)) && (!apexException(dr)) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("trying to update/add IGNORE_NAMEd record: %s %s", dr.GetLabel(), dr.Type)
|
||||
@@ -345,16 +353,23 @@ func sortedKeys(m map[string]*models.RecordConfig) []string {
|
||||
return s
|
||||
}
|
||||
|
||||
func compileIgnoredNames(ignoredNames []string) []glob.Glob {
|
||||
result := make([]glob.Glob, 0, len(ignoredNames))
|
||||
var spaceCommaTokenizerRegexp = regexp.MustCompile(`\s*,\s*`)
|
||||
|
||||
func compileIgnoredNames(ignoredNames []*models.IgnoreName) []ignoredName {
|
||||
result := make([]ignoredName, 0, len(ignoredNames))
|
||||
|
||||
for _, tst := range ignoredNames {
|
||||
g, err := glob.Compile(tst, '.')
|
||||
g, err := glob.Compile(tst.Pattern, '.')
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile IGNORE_NAME pattern %q: %v", tst, err))
|
||||
panic(fmt.Sprintf("Failed to compile IGNORE_NAME pattern %q: %v", tst.Pattern, err))
|
||||
}
|
||||
|
||||
result = append(result, g)
|
||||
t := []string{}
|
||||
if tst.Types != "" {
|
||||
t = spaceCommaTokenizerRegexp.Split(tst.Types, -1)
|
||||
}
|
||||
|
||||
result = append(result, ignoredName{nameGlob: g, rTypes: t})
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -379,11 +394,19 @@ func compileIgnoredTargets(ignoredTargets []*models.IgnoreTarget) []glob.Glob {
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *differ) matchIgnoredName(name string) bool {
|
||||
func (d *differ) matchIgnoredName(name string, rType string) bool {
|
||||
for _, tst := range d.compiledIgnoredNames {
|
||||
//fmt.Printf("********** DEBUG: matchIgnoredName %q %q %v\n", name, tst, tst.Match(name))
|
||||
if tst.Match(name) {
|
||||
return true
|
||||
//fmt.Printf("********** DEBUG: matchIgnoredName %q %q %v %v\n", name, rType, tst, tst.nameGlob.Match(name))
|
||||
if tst.nameGlob.Match(name) {
|
||||
if tst.rTypes == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, rt := range tst.rTypes {
|
||||
if rt == "*" || rt == rType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@@ -158,10 +158,10 @@ func checkLengths(t *testing.T, existing, desired []*models.RecordConfig, unCoun
|
||||
}
|
||||
|
||||
func checkLengthsWithKeepUnknown(t *testing.T, existing, desired []*models.RecordConfig, unCount, createCount, delCount, modCount int, keepUnknown bool, valFuncs ...func(*models.RecordConfig) map[string]string) (un, cre, del, mod Changeset) {
|
||||
return checkLengthsFull(t, existing, desired, unCount, createCount, delCount, modCount, keepUnknown, []string{}, nil, valFuncs...)
|
||||
return checkLengthsFull(t, existing, desired, unCount, createCount, delCount, modCount, keepUnknown, []*models.IgnoreName{}, nil, valFuncs...)
|
||||
}
|
||||
|
||||
func checkLengthsFull(t *testing.T, existing, desired []*models.RecordConfig, unCount, createCount, delCount, modCount int, keepUnknown bool, ignoredRecords []string, ignoredTargets []*models.IgnoreTarget, valFuncs ...func(*models.RecordConfig) map[string]string) (un, cre, del, mod Changeset) {
|
||||
func checkLengthsFull(t *testing.T, existing, desired []*models.RecordConfig, unCount, createCount, delCount, modCount int, keepUnknown bool, ignoredRecords []*models.IgnoreName, ignoredTargets []*models.IgnoreTarget, valFuncs ...func(*models.RecordConfig) map[string]string) (un, cre, del, mod Changeset) {
|
||||
dc := &models.DomainConfig{
|
||||
Name: "example.com",
|
||||
Records: desired,
|
||||
@@ -206,14 +206,23 @@ func TestNoPurge(t *testing.T) {
|
||||
|
||||
func TestIgnoredRecords(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 A 1 1.1.1.1"),
|
||||
myRecord("www1 MX 1 1.1.1.1"),
|
||||
myRecord("www2 A 1 1.1.1.1"),
|
||||
myRecord("www2 CNAME 1 www"),
|
||||
myRecord("www2 MX 1 1.1.1.1"),
|
||||
myRecord("www3 MX 1 1.1.1.1"),
|
||||
}
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("www3 MX 1 2.2.2.2"),
|
||||
}
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"}, nil)
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false,
|
||||
[]*models.IgnoreName{
|
||||
{Pattern: "www1", Types: "*"},
|
||||
{Pattern: "www2", Types: "A,MX, CNAME"},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func TestModifyingIgnoredRecords(t *testing.T) {
|
||||
@@ -232,7 +241,10 @@ func TestModifyingIgnoredRecords(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"}, nil)
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false,
|
||||
[]*models.IgnoreName{{Pattern: "www1", Types: "MX"}, {Pattern: "www2", Types: "*"}},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func TestGlobIgnoredName(t *testing.T) {
|
||||
@@ -245,7 +257,14 @@ func TestGlobIgnoredName(t *testing.T) {
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("www4 MX 1 2.2.2.2"),
|
||||
}
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "*.www2", "**.www3"}, nil)
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false,
|
||||
[]*models.IgnoreName{
|
||||
{Pattern: "www1", Types: "*"},
|
||||
{Pattern: "*.www2", Types: "*"},
|
||||
{Pattern: "**.www3", Types: "*"},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func TestInvalidGlobIgnoredName(t *testing.T) {
|
||||
@@ -264,7 +283,10 @@ func TestInvalidGlobIgnoredName(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, []string{"www1", "www2", "[.www3"}, nil)
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false,
|
||||
[]*models.IgnoreName{{Pattern: "www1"}, {Pattern: "*.www2"}, {Pattern: "[.www3"}},
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func TestGlobIgnoredTarget(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user