mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
New feature: IGNORE_TARGET. Rename INGORE to IGNORE_NAME (#806)
This commit is contained in:
@ -2,39 +2,4 @@
|
||||
name: IGNORE
|
||||
---
|
||||
|
||||
IGNORE can be used to ignore some records presents in zone.
|
||||
All records (independently of their type) of that name will be completely ignored.
|
||||
|
||||
IGNORE is like NO_PURGE except it acts only on some specific records instead of the whole zone.
|
||||
|
||||
IGNORE is generally used in very specific situations:
|
||||
|
||||
* Some records are managed by some other system and DNSControl is only used to manage some records and/or keep them updated. For example a DNS record that is managed by Kubernetes External DNS, but DNSControl is used to manage the rest of the zone. In this case we don't want dnscontrol to try to delete the externally managed record.
|
||||
* To work-around a pseudo record type that is not supported by DNSControl. For example some providers have a fake DNS record type called "URL" which creates a redirect. DNSControl normally deletes these records because it doesn't understand them. IGNORE will leave those records alone.
|
||||
|
||||
In this example, dnscontrol will insert/update the "baz.example.com" record but will leave unchanged the "foo.example.com" and "bar.example.com" ones.
|
||||
|
||||
{% include startExample.html %}
|
||||
{% highlight js %}
|
||||
D("example.com",
|
||||
IGNORE("foo"),
|
||||
IGNORE("bar"),
|
||||
A("baz", "1.2.3.4")
|
||||
);
|
||||
{%endhighlight%}
|
||||
{% include endExample.html %}
|
||||
|
||||
IGNORE also supports glob patterns in the style of the [gobwas/glob](https://github.com/gobwas/glob) library. All of
|
||||
the following patterns will work:
|
||||
|
||||
* `IGNORE("*.foo")` will ignore all records in the style of `bar.foo`, but will not ignore records using a double
|
||||
subdomain, such as `foo.bar.foo`.
|
||||
* `IGNORE("**.foo")` will ignore all subdomains of `foo`, including double subdomains.
|
||||
* `IGNORE("?oo")` will ignore all records of three symbols ending in `oo`, for example `foo` and `zoo`. It will
|
||||
not match `.`
|
||||
* `IGNORE("[abc]oo")` will ignore records `aoo`, `boo` and `coo`. `IGNORE("[a-c]oo")` is equivalent.
|
||||
* `IGNORE("[!abc]oo")` will ignore all three symbol records ending in `oo`, except for `aoo`, `boo`, `coo`. `IGNORE("[!a-c]oo")` is equivalent.
|
||||
* `IGNORE("{bar,[fz]oo}` will ignore `bar`, `foo` and `zoo`.
|
||||
* `IGNORE("\\*.foo")` will ignore the literal record `*.foo`.
|
||||
|
||||
It is considered as an error to try to manage an ignored record.
|
||||
IGNORE has been renamed to `IGNORE_NAME`. IGNORE will continue to function, but its use is deprecated. Please update your configuration files to use `IGNORE_NAME`.
|
||||
|
40
docs/_functions/domain/IGNORE_NAME.md
Normal file
40
docs/_functions/domain/IGNORE_NAME.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
name: IGNORE_NAME
|
||||
---
|
||||
|
||||
IGNORE_NAME can be used to ignore some records present in zone.
|
||||
All records (independently of their type) of that name will be completely ignored.
|
||||
|
||||
IGNORE_NAME is like NO_PURGE except it acts only on some specific records instead of the whole zone.
|
||||
|
||||
IGNORE_NAME is generally used in very specific situations:
|
||||
|
||||
* Some records are managed by some other system and DNSControl is only used to manage some records and/or keep them updated. For example a DNS record that is managed by Kubernetes External DNS, but DNSControl is used to manage the rest of the zone. In this case we don't want DNSControl to try to delete the externally managed record.
|
||||
* To work-around a pseudo record type that is not supported by DNSControl. For example some providers have a fake DNS record type called "URL" which creates a redirect. DNSControl normally deletes these records because it doesn't understand them. IGNORE_NAME will leave those records alone.
|
||||
|
||||
In this example, DNSControl will insert/update the "baz.example.com" record but will leave unchanged the "foo.example.com" and "bar.example.com" ones.
|
||||
|
||||
{% include startExample.html %}
|
||||
{% highlight js %}
|
||||
D("example.com",
|
||||
IGNORE_NAME("foo"),
|
||||
IGNORE_NAME("bar"),
|
||||
A("baz", "1.2.3.4")
|
||||
);
|
||||
{%endhighlight%}
|
||||
{% include endExample.html %}
|
||||
|
||||
IGNORE_NAME also supports glob patterns in the style of the [gobwas/glob](https://github.com/gobwas/glob) library. All of
|
||||
the following patterns will work:
|
||||
|
||||
* `IGNORE_NAME("*.foo")` will ignore all records in the style of `bar.foo`, but will not ignore records using a double
|
||||
subdomain, such as `foo.bar.foo`.
|
||||
* `IGNORE_NAME("**.foo")` will ignore all subdomains of `foo`, including double subdomains.
|
||||
* `IGNORE_NAME("?oo")` will ignore all records of three symbols ending in `oo`, for example `foo` and `zoo`. It will
|
||||
not match `.`
|
||||
* `IGNORE_NAME("[abc]oo")` will ignore records `aoo`, `boo` and `coo`. `IGNORE_NAME("[a-c]oo")` is equivalent.
|
||||
* `IGNORE_NAME("[!abc]oo")` will ignore all three symbol records ending in `oo`, except for `aoo`, `boo`, `coo`. `IGNORE_NAME("[!a-c]oo")` is equivalent.
|
||||
* `IGNORE_NAME("{bar,[fz]oo}")` will ignore `bar`, `foo` and `zoo`.
|
||||
* `IGNORE_NAME("\\*.foo")` will ignore the literal record `*.foo`.
|
||||
|
||||
It is considered as an error to try to manage an ignored record.
|
34
docs/_functions/domain/IGNORE_TARGET.md
Normal file
34
docs/_functions/domain/IGNORE_TARGET.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
name: IGNORE_TARGET
|
||||
parameters:
|
||||
- pattern
|
||||
- rType
|
||||
---
|
||||
|
||||
IGNORE_TARGET can be used to ignore some records present in zone based on the record's target and type. IGNORE_TARGET currently only supports CNAME record types.
|
||||
|
||||
IGNORE_TARGET is like NO_PURGE except it acts only on some specific records instead of the whole zone.
|
||||
|
||||
IGNORE_TARGET is generally used in very specific situations:
|
||||
|
||||
* Some records are managed by some other system and DNSControl is only used to manage some records and/or keep them updated. For example a DNS record that is created by AWS Certificate Manager for validation, but DNSControl is used to manage the rest of the zone. In this case we don't want DNSControl to try to delete the externally managed record.
|
||||
|
||||
In this example, DNSControl will insert/update the "baz.example.com" record but will leave unchanged a CNAME to "foo.acm-validations.aws" record.
|
||||
|
||||
{% include startExample.html %}
|
||||
{% highlight js %}
|
||||
D("example.com",
|
||||
IGNORE_TARGET('**.acm-validations.aws.', 'CNAME'),
|
||||
A("baz", "1.2.3.4")
|
||||
);
|
||||
{%endhighlight%}
|
||||
{% include endExample.html %}
|
||||
|
||||
IGNORE_TARGET also supports glob patterns in the style of the [gobwas/glob](https://github.com/gobwas/glob#example) library. Some example patterns:
|
||||
|
||||
* `IGNORE_TARGET("example.com", "CNAME")` will ignore all CNAME records with targets of exactly `example.com`.
|
||||
* `IGNORE_TARGET("*.foo", "CNAME")` will ignore all CNAME records with targets in the style of `bar.foo`, but will not ignore records with targets using a double subdomain, such as `foo.bar.foo`.
|
||||
* `IGNORE_TARGET("**.bar", "CNAME")` will ignore all CNAME records with target subdomains of `bar`, including double subdomains such as `www.foo.bar`.
|
||||
* `IGNORE_TARGET("dev.*.foo", "CNAME")` will ignore all CNAME records with targets in the style of `dev.bar.foo`, but will not ignore records with targets using a double subdomain, such as `dev.foo.bar.foo`.
|
||||
|
||||
It is considered as an error to try to manage an ignored record.
|
@ -162,7 +162,8 @@ func makeChanges(t *testing.T, prv providers.DNSServiceProvider, dc *models.Doma
|
||||
//}
|
||||
dom.Records = append(dom.Records, &rc)
|
||||
}
|
||||
dom.IgnoredLabels = tst.IgnoredLabels
|
||||
dom.IgnoredNames = tst.IgnoredNames
|
||||
dom.IgnoredTargets = tst.IgnoredTargets
|
||||
models.PostProcessRecords(dom.Records)
|
||||
dom2, _ := dom.Copy()
|
||||
|
||||
@ -301,9 +302,10 @@ type TestGroup struct {
|
||||
}
|
||||
|
||||
type TestCase struct {
|
||||
Desc string
|
||||
Records []*rec
|
||||
IgnoredLabels []string
|
||||
Desc string
|
||||
Records []*rec
|
||||
IgnoredNames []string
|
||||
IgnoredTargets []*models.IgnoreTarget
|
||||
}
|
||||
|
||||
type rec models.RecordConfig
|
||||
@ -426,9 +428,18 @@ func tlsa(name string, usage, selector, matchingtype uint8, target string) *rec
|
||||
return r
|
||||
}
|
||||
|
||||
func ignore(name string) *rec {
|
||||
func ignoreName(name string) *rec {
|
||||
r := &rec{
|
||||
Type: "IGNORE",
|
||||
Type: "IGNORE_NAME",
|
||||
}
|
||||
r.SetLabel(name, "**current-domain**")
|
||||
return r
|
||||
}
|
||||
|
||||
func ignoreTarget(name string, typ string) *rec {
|
||||
r := &rec{
|
||||
Type: "IGNORE_TARGET",
|
||||
Target: typ,
|
||||
}
|
||||
r.SetLabel(name, "**current-domain**")
|
||||
return r
|
||||
@ -490,10 +501,16 @@ func testgroup(desc string, items ...interface{}) *TestGroup {
|
||||
|
||||
func tc(desc string, recs ...*rec) *TestCase {
|
||||
var records []*rec
|
||||
var ignored []string
|
||||
var ignoredNames []string
|
||||
var ignoredTargets []*models.IgnoreTarget
|
||||
for _, r := range recs {
|
||||
if r.Type == "IGNORE" {
|
||||
ignored = append(ignored, r.GetLabel())
|
||||
if r.Type == "IGNORE_NAME" {
|
||||
ignoredNames = append(ignoredNames, r.GetLabel())
|
||||
} else if r.Type == "IGNORE_TARGET" {
|
||||
ignoredTargets = append(ignoredTargets, &models.IgnoreTarget{
|
||||
Pattern: r.GetLabel(),
|
||||
Type: r.Target,
|
||||
})
|
||||
} else {
|
||||
records = append(records, r)
|
||||
}
|
||||
@ -501,7 +518,8 @@ func tc(desc string, recs ...*rec) *TestCase {
|
||||
return &TestCase{
|
||||
Desc: desc,
|
||||
Records: records,
|
||||
IgnoredLabels: ignored,
|
||||
IgnoredNames: ignoredNames,
|
||||
IgnoredTargets: ignoredTargets,
|
||||
}
|
||||
}
|
||||
|
||||
@ -637,12 +655,20 @@ func makeTests(t *testing.T) []*TestGroup {
|
||||
tc("NS Record pointing to @", ns("foo", "**current-domain**")),
|
||||
),
|
||||
|
||||
testgroup("IGNORE function",
|
||||
testgroup("IGNORE_NAME function",
|
||||
tc("Create some records", txt("foo", "simple"), a("foo", "1.2.3.4")),
|
||||
tc("Add a new record - ignoring foo", a("bar", "1.2.3.4"), ignore("foo")),
|
||||
tc("Add a new record - ignoring foo", a("bar", "1.2.3.4"), ignoreName("foo")),
|
||||
clear(),
|
||||
tc("Create some records", txt("bar.foo", "simple"), a("bar.foo", "1.2.3.4")),
|
||||
tc("Add a new record - ignoring *.foo", a("bar", "1.2.3.4"), ignore("*.foo")),
|
||||
tc("Add a new record - ignoring *.foo", a("bar", "1.2.3.4"), ignoreName("*.foo")),
|
||||
),
|
||||
|
||||
testgroup("IGNORE_TARGET function",
|
||||
tc("Create some records", cname("foo", "test.foo.com."), cname("bar", "test.foo.com.")),
|
||||
tc("Add a new record - ignoring foo", cname("bar", "bar.foo.com."), ignoreTarget("test.foo.com.", "CNAME")),
|
||||
clear(),
|
||||
tc("Create some records", cname("bar.foo", "a.b.foo.com."), a("bar.foo", "1.2.3.4")),
|
||||
tc("Add a new record - ignoring **.foo.com targets", a("bar", "1.2.3.4"), ignoreTarget("**.foo.com.", "CNAME")),
|
||||
),
|
||||
|
||||
testgroup("single TXT",
|
||||
|
@ -126,3 +126,13 @@ func (config *DNSConfig) DomainContainingFQDN(fqdn string) *DomainConfig {
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// IgnoreTarget describes an IGNORE_TARGET rule.
|
||||
type IgnoreTarget struct {
|
||||
Pattern string `json:"pattern"` // Glob pattern
|
||||
Type string `json:"type"` // All caps rtype name.
|
||||
}
|
||||
|
||||
func (i *IgnoreTarget) String() string {
|
||||
return i.Pattern
|
||||
}
|
||||
|
@ -8,16 +8,17 @@ import (
|
||||
|
||||
// DomainConfig describes a DNS domain (tecnically a DNS zone).
|
||||
type DomainConfig struct {
|
||||
Name string `json:"name"` // NO trailing "."
|
||||
RegistrarName string `json:"registrar"`
|
||||
DNSProviderNames map[string]int `json:"dnsProviders"`
|
||||
Name string `json:"name"` // NO trailing "."
|
||||
RegistrarName string `json:"registrar"`
|
||||
DNSProviderNames map[string]int `json:"dnsProviders"`
|
||||
|
||||
Metadata map[string]string `json:"meta,omitempty"`
|
||||
Records Records `json:"records"`
|
||||
Nameservers []*Nameserver `json:"nameservers,omitempty"`
|
||||
KeepUnknown bool `json:"keepunknown,omitempty"`
|
||||
IgnoredLabels []string `json:"ignored_labels,omitempty"`
|
||||
AutoDNSSEC bool `json:"auto_dnssec,omitempty"`
|
||||
Metadata map[string]string `json:"meta,omitempty"`
|
||||
Records Records `json:"records"`
|
||||
Nameservers []*Nameserver `json:"nameservers,omitempty"`
|
||||
KeepUnknown bool `json:"keepunknown,omitempty"`
|
||||
IgnoredNames []string `json:"ignored_names,omitempty"`
|
||||
IgnoredTargets []*IgnoreTarget `json:"ignored_targets,omitempty"`
|
||||
AutoDNSSEC bool `json:"auto_dnssec,omitempty"`
|
||||
//DNSSEC bool `json:"dnssec,omitempty"`
|
||||
|
||||
// These fields contain instantiated provider instances once everything is linked up.
|
||||
|
@ -35,8 +35,11 @@ func New(dc *models.DomainConfig, extraValues ...func(*models.RecordConfig) map[
|
||||
dc: dc,
|
||||
extraValues: extraValues,
|
||||
|
||||
// compile IGNORE glob patterns
|
||||
compiledIgnoredLabels: compileIgnoredLabels(dc.IgnoredLabels),
|
||||
// compile IGNORE_NAME glob patterns
|
||||
compiledIgnoredNames: compileIgnoredNames(dc.IgnoredNames),
|
||||
|
||||
// compile IGNORE_TARGET glob patterns
|
||||
compiledIgnoredTargets: compileIgnoredTargets(dc.IgnoredTargets),
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +47,8 @@ type differ struct {
|
||||
dc *models.DomainConfig
|
||||
extraValues []func(*models.RecordConfig) map[string]string
|
||||
|
||||
compiledIgnoredLabels []glob.Glob
|
||||
compiledIgnoredNames []glob.Glob
|
||||
compiledIgnoredTargets []glob.Glob
|
||||
}
|
||||
|
||||
// get normalized content for record. target, ttl, mxprio, and specified metadata
|
||||
@ -93,16 +97,20 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr
|
||||
existingByNameAndType := map[models.RecordKey][]*models.RecordConfig{}
|
||||
desiredByNameAndType := map[models.RecordKey][]*models.RecordConfig{}
|
||||
for _, e := range existing {
|
||||
if d.matchIgnored(e.GetLabel()) {
|
||||
printer.Debugf("Ignoring record %s %s due to IGNORE\n", e.GetLabel(), e.Type)
|
||||
if d.matchIgnoredName(e.GetLabel()) {
|
||||
printer.Debugf("Ignoring record %s %s due to IGNORE_NAME\n", e.GetLabel(), e.Type)
|
||||
} else if d.matchIgnoredTarget(e.GetTargetField(), e.Type) {
|
||||
printer.Debugf("Ignoring record %s %s due to IGNORE_TARGET\n", e.GetLabel(), e.Type)
|
||||
} else {
|
||||
k := e.Key()
|
||||
existingByNameAndType[k] = append(existingByNameAndType[k], e)
|
||||
}
|
||||
}
|
||||
for _, dr := range desired {
|
||||
if d.matchIgnored(dr.GetLabel()) {
|
||||
panic(fmt.Sprintf("Trying to update/add IGNOREd record: %s %s", dr.GetLabel(), dr.Type))
|
||||
if d.matchIgnoredName(dr.GetLabel()) {
|
||||
panic(fmt.Sprintf("Trying to update/add IGNORE_NAMEd record: %s %s", dr.GetLabel(), dr.Type))
|
||||
} else if d.matchIgnoredTarget(dr.GetTargetField(), dr.Type) {
|
||||
panic(fmt.Sprintf("Trying to update/add IGNORE_TARGETd record: %s %s", dr.GetLabel(), dr.Type))
|
||||
} else {
|
||||
k := dr.Key()
|
||||
desiredByNameAndType[k] = append(desiredByNameAndType[k], dr)
|
||||
@ -312,13 +320,13 @@ func sortedKeys(m map[string]*models.RecordConfig) []string {
|
||||
return s
|
||||
}
|
||||
|
||||
func compileIgnoredLabels(ignoredLabels []string) []glob.Glob {
|
||||
result := make([]glob.Glob, 0, len(ignoredLabels))
|
||||
func compileIgnoredNames(ignoredNames []string) []glob.Glob {
|
||||
result := make([]glob.Glob, 0, len(ignoredNames))
|
||||
|
||||
for _, tst := range ignoredLabels {
|
||||
for _, tst := range ignoredNames {
|
||||
g, err := glob.Compile(tst, '.')
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile IGNORE pattern %q: %v", tst, err))
|
||||
panic(fmt.Sprintf("Failed to compile IGNORE_NAME pattern %q: %v", tst, err))
|
||||
}
|
||||
|
||||
result = append(result, g)
|
||||
@ -327,11 +335,46 @@ func compileIgnoredLabels(ignoredLabels []string) []glob.Glob {
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *differ) matchIgnored(name string) bool {
|
||||
for _, tst := range d.compiledIgnoredLabels {
|
||||
func compileIgnoredTargets(ignoredTargets []*models.IgnoreTarget) []glob.Glob {
|
||||
result := make([]glob.Glob, 0, len(ignoredTargets))
|
||||
|
||||
for _, tst := range ignoredTargets {
|
||||
fmt.Sprintf("rType for IGNORE_TARGET %v", tst.Type)
|
||||
|
||||
if tst.Type != "CNAME" {
|
||||
panic(fmt.Sprintf("Invalid rType for IGNORE_TARGET %v", tst.Type))
|
||||
}
|
||||
|
||||
g, err := glob.Compile(tst.Pattern, '.')
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile IGNORE_TARGET pattern %q: %v", tst, err))
|
||||
}
|
||||
|
||||
result = append(result, g)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (d *differ) matchIgnoredName(name string) bool {
|
||||
for _, tst := range d.compiledIgnoredNames {
|
||||
if tst.Match(name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *differ) matchIgnoredTarget(target string, rType string) bool {
|
||||
if rType != "CNAME" {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, tst := range d.compiledIgnoredTargets {
|
||||
if tst.Match(target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -158,15 +158,16 @@ 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{}, valFuncs...)
|
||||
return checkLengthsFull(t, existing, desired, unCount, createCount, delCount, modCount, keepUnknown, []string{}, nil, valFuncs...)
|
||||
}
|
||||
|
||||
func checkLengthsFull(t *testing.T, existing, desired []*models.RecordConfig, unCount, createCount, delCount, modCount int, keepUnknown bool, ignoredRecords []string, 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 []string, ignoredTargets []*models.IgnoreTarget, valFuncs ...func(*models.RecordConfig) map[string]string) (un, cre, del, mod Changeset) {
|
||||
dc := &models.DomainConfig{
|
||||
Name: "example.com",
|
||||
Records: desired,
|
||||
KeepUnknown: keepUnknown,
|
||||
IgnoredLabels: ignoredRecords,
|
||||
Name: "example.com",
|
||||
Records: desired,
|
||||
KeepUnknown: keepUnknown,
|
||||
IgnoredNames: ignoredRecords,
|
||||
IgnoredTargets: ignoredTargets,
|
||||
}
|
||||
d := New(dc, valFuncs...)
|
||||
un, cre, del, mod = d.IncrementalDiff(existing)
|
||||
@ -209,7 +210,7 @@ func TestIgnoredRecords(t *testing.T) {
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("www3 MX 1 2.2.2.2"),
|
||||
}
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"})
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"}, nil)
|
||||
}
|
||||
|
||||
func TestModifyingIgnoredRecords(t *testing.T) {
|
||||
@ -228,10 +229,10 @@ func TestModifyingIgnoredRecords(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"})
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "www2"}, nil)
|
||||
}
|
||||
|
||||
func TestGlobIgnoredRecords(t *testing.T) {
|
||||
func TestGlobIgnoredName(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 MX 1 1.1.1.1"),
|
||||
myRecord("foo.www2 MX 1 1.1.1.1"),
|
||||
@ -241,10 +242,10 @@ func TestGlobIgnoredRecords(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"})
|
||||
checkLengthsFull(t, existing, desired, 0, 0, 0, 1, false, []string{"www1", "*.www2", "**.www3"}, nil)
|
||||
}
|
||||
|
||||
func TestInvalidGlobIgnoredRecord(t *testing.T) {
|
||||
func TestInvalidGlobIgnoredName(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 MX 1 1.1.1.1"),
|
||||
myRecord("www2 MX 1 1.1.1.1"),
|
||||
@ -256,11 +257,64 @@ func TestInvalidGlobIgnoredRecord(t *testing.T) {
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("should panic: invalid glob pattern for IGNORE")
|
||||
t.Errorf("should panic: invalid glob pattern for IGNORE_NAME")
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, []string{"www1", "www2", "[.www3"})
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, []string{"www1", "www2", "[.www3"}, nil)
|
||||
}
|
||||
|
||||
func TestGlobIgnoredTarget(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 CNAME 1 ignoreme.com"),
|
||||
myRecord("foo.www2 MX 1 1.1.1.2"),
|
||||
myRecord("foo.bar.www3 MX 1 1.1.1.1"),
|
||||
myRecord("www4 MX 1 1.1.1.1"),
|
||||
}
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("foo.www2 MX 1 1.1.1.2"),
|
||||
myRecord("foo.bar.www3 MX 1 1.1.1.1"),
|
||||
myRecord("www4 MX 1 2.2.2.2"),
|
||||
}
|
||||
checkLengthsFull(t, existing, desired, 2, 0, 0, 1, false, nil, []*models.IgnoreTarget{{Pattern: "ignoreme.com", Type: "CNAME"}})
|
||||
}
|
||||
|
||||
func TestInvalidGlobIgnoredTarget(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 MX 1 1.1.1.1"),
|
||||
myRecord("www2 MX 1 1.1.1.1"),
|
||||
myRecord("www3 MX 1 1.1.1.1"),
|
||||
}
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("www4 MX 1 2.2.2.2"),
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("should panic: invalid glob pattern for IGNORE_TARGET")
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, nil, []*models.IgnoreTarget{{Pattern: "[.www3", Type: "CNAME"}} )
|
||||
}
|
||||
|
||||
func TestInvalidTypeIgnoredTarget(t *testing.T) {
|
||||
existing := []*models.RecordConfig{
|
||||
myRecord("www1 MX 1 1.1.1.1"),
|
||||
myRecord("www2 MX 1 1.1.1.1"),
|
||||
myRecord("www3 MX 1 1.1.1.1"),
|
||||
}
|
||||
desired := []*models.RecordConfig{
|
||||
myRecord("www4 MX 1 2.2.2.2"),
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("should panic: Invalid rType for IGNORE_TARGET A")
|
||||
}
|
||||
}()
|
||||
|
||||
checkLengthsFull(t, existing, desired, 0, 1, 0, 0, false, nil, []*models.IgnoreTarget{{Pattern: "1.1.1.1", Type: "A"}} )
|
||||
}
|
||||
|
||||
// from https://github.com/StackExchange/dnscontrol/issues/552
|
||||
@ -284,12 +338,12 @@ func TestCaas(t *testing.T) {
|
||||
desired[1].SetTargetCAA(3, "issue", "amazon.com.")
|
||||
desired[2].SetTargetCAA(3, "issuewild", "letsencrypt.org.")
|
||||
|
||||
checkLengthsFull(t, existing, desired, 3, 0, 0, 0, false, nil)
|
||||
checkLengthsFull(t, existing, desired, 3, 0, 0, 0, false, nil, nil)
|
||||
|
||||
// Make sure it passes with a different ordering. Not ok.
|
||||
desired[2].SetTargetCAA(3, "issue", "letsencrypt.org.")
|
||||
desired[1].SetTargetCAA(3, "issue", "amazon.com.")
|
||||
desired[0].SetTargetCAA(3, "issuewild", "letsencrypt.org.")
|
||||
|
||||
checkLengthsFull(t, existing, desired, 3, 0, 0, 0, false, nil)
|
||||
checkLengthsFull(t, existing, desired, 3, 0, 0, 0, false, nil, nil)
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ function newDomain(name, registrar) {
|
||||
dnsProviders: {},
|
||||
defaultTTL: 0,
|
||||
nameservers: [],
|
||||
ignored_labels: [],
|
||||
ignored_names: [],
|
||||
ignored_targets: [],
|
||||
};
|
||||
}
|
||||
|
||||
@ -494,11 +495,25 @@ function format_tt(transform_table) {
|
||||
|
||||
// IGNORE(name)
|
||||
function IGNORE(name) {
|
||||
// deprecated, use IGNORE_NAME
|
||||
return IGNORE_NAME(name);
|
||||
}
|
||||
|
||||
// IGNORE_NAME(name)
|
||||
function IGNORE_NAME(name) {
|
||||
return function(d) {
|
||||
d.ignored_labels.push(name);
|
||||
d.ignored_names.push(name);
|
||||
};
|
||||
}
|
||||
|
||||
// IGNORE_TARGET(target)
|
||||
function IGNORE_TARGET(target, rType) {
|
||||
return function(d) {
|
||||
d.ignored_targets.push({pattern: target, type: rType});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// IMPORT_TRANSFORM(translation_table, domain)
|
||||
var IMPORT_TRANSFORM = recordBuilder('IMPORT_TRANSFORM', {
|
||||
args: [['translation_table'], ['domain'], ['ttl', _.isNumber]],
|
||||
|
@ -1,3 +1,5 @@
|
||||
D("foo.com", "none"
|
||||
, IGNORE("testignore")
|
||||
, IGNORE_NAME("testignore")
|
||||
, IGNORE_TARGET("testtarget", "CNAME")
|
||||
, IGNORE("legacyignore")
|
||||
);
|
||||
|
@ -7,9 +7,13 @@
|
||||
"registrar": "none",
|
||||
"dnsProviders": {},
|
||||
"records": [],
|
||||
"ignored_labels": [
|
||||
"testignore"
|
||||
]
|
||||
"ignored_names": [
|
||||
"testignore",
|
||||
"legacyignore"
|
||||
],
|
||||
"ignored_targets": [
|
||||
{"pattern":"testtarget","type":"CNAME"}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
"registrar": "none",
|
||||
"dnsProviders": {},
|
||||
"records": [],
|
||||
"ignored_labels": [
|
||||
"ignored_names": [
|
||||
"\\*.testignore"
|
||||
]
|
||||
}
|
||||
|
219
pkg/js/static.go
219
pkg/js/static.go
@ -212,117 +212,118 @@ var _escData = map[string]*_escFile{
|
||||
"/helpers.js": {
|
||||
name: "helpers.js",
|
||||
local: "pkg/js/helpers.js",
|
||||
size: 25306,
|
||||
size: 25616,
|
||||
modtime: 0,
|
||||
compressed: `
|
||||
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
|
||||
hjskFLAWqHsOMBIs/l8AAAD//+WKkZfaYgAA
|
||||
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
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
Reference in New Issue
Block a user