mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-02-24 15:43:08 +08:00
NEW FEATURE: IMPORT_TRANSFORM_STRIP (#3181)
This commit is contained in:
parent
2abbab0c84
commit
1872b12116
7 changed files with 131 additions and 34 deletions
|
@ -53,6 +53,7 @@
|
|||
* [IGNORE_NAME](language-reference/domain-modifiers/IGNORE_NAME.md)
|
||||
* [IGNORE_TARGET](language-reference/domain-modifiers/IGNORE_TARGET.md)
|
||||
* [IMPORT_TRANSFORM](language-reference/domain-modifiers/IMPORT_TRANSFORM.md)
|
||||
* [IMPORT_TRANSFORM_STRIP](language-reference/domain-modifiers/IMPORT_TRANSFORM_STRIP.md)
|
||||
* [INCLUDE](language-reference/domain-modifiers/INCLUDE.md)
|
||||
* [LOC](language-reference/domain-modifiers/LOC.md)
|
||||
* [LOC_BUILDER_DD](language-reference/domain-modifiers/LOC_BUILDER_DD.md)
|
||||
|
|
|
@ -3,6 +3,7 @@ name: IMPORT_TRANSFORM
|
|||
parameters:
|
||||
- transform table
|
||||
- domain
|
||||
- ttl
|
||||
- modifiers...
|
||||
ts_ignore: true
|
||||
---
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
name: IMPORT_TRANSFORM_STRIP
|
||||
parameters:
|
||||
- transform table
|
||||
- domain
|
||||
- ttl
|
||||
- suffixstrip
|
||||
- modifiers...
|
||||
ts_ignore: true
|
||||
---
|
||||
|
||||
{% hint style="warning" %}
|
||||
Don't use this feature. It was added for a very specific situation at Stack Overflow.
|
||||
{% endhint %}
|
||||
|
||||
`IMPORT_TRANSFORM_STRIP` is the same as `IMPORT_TRANSFORM` with an additional parameter: `suffixstrip`.
|
||||
|
||||
When `IMPORT_TRANSFORM_STRIP` is generating the label for new records, it
|
||||
checks the label. If the label ends with `suffixstrip`, that suffix is removed.
|
||||
If the label does not end with `suffixstrip`, an error is returned.
|
||||
|
||||
For example, if the domain is `com.extra` and the label is `foo.com`,
|
||||
`IMPORT_TRANSFORM` would generate a label `foo.com.com.extra`.
|
||||
`IMPORT_TRANSFORM_STRIP(... , '.com')` would generate
|
||||
the label `foo.com.extra` instead.
|
|
@ -1031,7 +1031,7 @@ function IGNORE_TARGET(target, rType) {
|
|||
return IGNORE('*', rType, target);
|
||||
}
|
||||
|
||||
// IMPORT_TRANSFORM(translation_table, domain)
|
||||
// IMPORT_TRANSFORM(translation_table, domain, ttl)
|
||||
var IMPORT_TRANSFORM = recordBuilder('IMPORT_TRANSFORM', {
|
||||
args: [['translation_table'], ['domain'], ['ttl', _.isNumber]],
|
||||
transform: function (record, args, modifiers) {
|
||||
|
@ -1042,6 +1042,18 @@ var IMPORT_TRANSFORM = recordBuilder('IMPORT_TRANSFORM', {
|
|||
},
|
||||
});
|
||||
|
||||
// IMPORT_TRANSFORM_STRIP(translation_table, domain, ttl, suffixstrip)
|
||||
var IMPORT_TRANSFORM_STRIP = recordBuilder('IMPORT_TRANSFORM', {
|
||||
args: [['translation_table'], ['domain'], ['ttl', _.isNumber], ['suffixstrip']],
|
||||
transform: function (record, args, modifiers) {
|
||||
record.name = '@';
|
||||
record.target = args.domain;
|
||||
record.meta['transform_table'] = format_tt(args.translation_table);
|
||||
record.ttl = args.ttl;
|
||||
record.meta['transform_suffixstrip'] = args.suffixstrip;
|
||||
},
|
||||
});
|
||||
|
||||
// PURGE()
|
||||
function PURGE(d) {
|
||||
d.KeepUnknown = false;
|
||||
|
|
30
pkg/js/parse_tests/007-importTransformTTL.js
Normal file → Executable file
30
pkg/js/parse_tests/007-importTransformTTL.js
Normal file → Executable file
|
@ -1,5 +1,25 @@
|
|||
var TRANSFORM_INT = [
|
||||
{low: "0.0.0.0", high: "1.1.1.1", newBase: "2.2.2.2" }
|
||||
]
|
||||
D("foo2.com","reg");
|
||||
D("foo.com","reg",IMPORT_TRANSFORM(TRANSFORM_INT,"foo2.com",60))
|
||||
var TRANSFORM_NEWIP = [{
|
||||
low: "0.0.0.0",
|
||||
high: "1.1.1.1",
|
||||
newIP: "2.2.2.2"
|
||||
}];
|
||||
var TRANSFORM_BASE = [{
|
||||
low: "0.0.0.0",
|
||||
high: "1.1.1.1",
|
||||
newBase: "4.4.4.4"
|
||||
}, {
|
||||
low: "7.7.7.7",
|
||||
high: "8.8.8.8",
|
||||
newBase: "9.9.9.9"
|
||||
},
|
||||
];
|
||||
|
||||
D("foo1.com", "reg");
|
||||
|
||||
D("foo2.com", "reg",
|
||||
IMPORT_TRANSFORM(TRANSFORM_BASE, "foo1.com", 60)
|
||||
);
|
||||
|
||||
D("foo3.com", "reg",
|
||||
IMPORT_TRANSFORM_STRIP(TRANSFORM_NEWIP, "foo1.com", 99, ".com")
|
||||
);
|
||||
|
|
|
@ -1,28 +1,45 @@
|
|||
{
|
||||
"registrars": [],
|
||||
"dns_providers": [],
|
||||
"domains": [
|
||||
{
|
||||
"name": "foo1.com",
|
||||
"registrar": "reg",
|
||||
"dnsProviders": {},
|
||||
"name": "foo2.com",
|
||||
"records": [],
|
||||
"registrar": "reg"
|
||||
"records": []
|
||||
},
|
||||
{
|
||||
"name": "foo2.com",
|
||||
"registrar": "reg",
|
||||
"dnsProviders": {},
|
||||
"name": "foo.com",
|
||||
"records": [
|
||||
{
|
||||
"meta": {
|
||||
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ 2.2.2.2 ~ "
|
||||
},
|
||||
"type": "IMPORT_TRANSFORM",
|
||||
"name": "@",
|
||||
"target": "foo2.com",
|
||||
"ttl": 60,
|
||||
"type": "IMPORT_TRANSFORM"
|
||||
"meta": {
|
||||
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ 4.4.4.4 ~ ; 7.7.7.7 ~ 8.8.8.8 ~ 9.9.9.9 ~ "
|
||||
},
|
||||
"target": "foo1.com"
|
||||
}
|
||||
],
|
||||
"registrar": "reg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo3.com",
|
||||
"registrar": "reg",
|
||||
"dnsProviders": {},
|
||||
"records": [
|
||||
{
|
||||
"type": "IMPORT_TRANSFORM",
|
||||
"name": "@",
|
||||
"ttl": 99,
|
||||
"meta": {
|
||||
"transform_suffixstrip": ".com",
|
||||
"transform_table": "0.0.0.0 ~ 1.1.1.1 ~ ~ 2.2.2.2"
|
||||
},
|
||||
"target": "foo1.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"registrars": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -119,7 +119,7 @@ func checkLabel(label string, rType string, domain string, meta map[string]strin
|
|||
}
|
||||
if label == domain || strings.HasSuffix(label, "."+domain) {
|
||||
if m := meta["skip_fqdn_check"]; m != "true" {
|
||||
return fmt.Errorf(errorRepeat(label, domain))
|
||||
return fmt.Errorf("%s", errorRepeat(label, domain))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,27 @@ func transformCNAME(target, oldDomain, newDomain string) string {
|
|||
return dnsutil.AddOrigin(result, newDomain) + "."
|
||||
}
|
||||
|
||||
func newRec(rec *models.RecordConfig, ttl uint32) *models.RecordConfig {
|
||||
rec2, _ := rec.Copy()
|
||||
if ttl != 0 {
|
||||
rec2.TTL = ttl
|
||||
}
|
||||
return rec2
|
||||
}
|
||||
|
||||
func transformLabel(label, suffixstrip string) (string, error) {
|
||||
if suffixstrip == "" {
|
||||
return label, nil
|
||||
}
|
||||
if !strings.HasSuffix(label, suffixstrip) {
|
||||
return "", fmt.Errorf("label %q does not end with %q", label, suffixstrip)
|
||||
}
|
||||
return label[:len(label)-len(suffixstrip)], nil
|
||||
}
|
||||
|
||||
// import_transform imports the records of one zone into another, modifying records along the way.
|
||||
func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []transform.IPConversion, ttl uint32) error {
|
||||
func importTransform(srcDomain, dstDomain *models.DomainConfig,
|
||||
transforms []transform.IPConversion, ttl uint32, suffixstrip string) error {
|
||||
// Read srcDomain.Records, transform, and append to dstDomain.Records:
|
||||
// 1. Skip any that aren't A or CNAMEs.
|
||||
// 2. Append destDomainname to the end of the label.
|
||||
|
@ -259,15 +278,6 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
if dstDomain.Records.HasRecordTypeName(rec.Type, rec.GetLabelFQDN()) {
|
||||
continue
|
||||
}
|
||||
newRec := func() *models.RecordConfig {
|
||||
rec2, _ := rec.Copy()
|
||||
newlabel := rec2.GetLabelFQDN()
|
||||
rec2.SetLabel(newlabel, dstDomain.Name)
|
||||
if ttl != 0 {
|
||||
rec2.TTL = ttl
|
||||
}
|
||||
return rec2
|
||||
}
|
||||
switch rec.Type {
|
||||
case "A":
|
||||
trs, err := transform.IPToList(net.ParseIP(rec.GetTargetField()), transforms)
|
||||
|
@ -275,12 +285,22 @@ func importTransform(srcDomain, dstDomain *models.DomainConfig, transforms []tra
|
|||
return fmt.Errorf("import_transform: TransformIP(%v, %v) returned err=%s", rec.GetTargetField(), transforms, err)
|
||||
}
|
||||
for _, tr := range trs {
|
||||
r := newRec()
|
||||
r := newRec(rec, ttl)
|
||||
l, err := transformLabel(r.GetLabelFQDN(), suffixstrip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.SetLabel(l, dstDomain.Name)
|
||||
r.SetTarget(tr.String())
|
||||
dstDomain.Records = append(dstDomain.Records, r)
|
||||
}
|
||||
case "CNAME":
|
||||
r := newRec()
|
||||
r := newRec(rec, ttl)
|
||||
l, err := transformLabel(r.GetLabelFQDN(), suffixstrip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.SetLabel(l, dstDomain.Name)
|
||||
r.SetTarget(transformCNAME(r.GetTargetField(), srcDomain.Name, dstDomain.Name))
|
||||
dstDomain.Records = append(dstDomain.Records, r)
|
||||
default:
|
||||
|
@ -445,6 +465,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
|
|||
for _, domain := range config.Domains {
|
||||
for _, rec := range domain.Records {
|
||||
if rec.Type == "IMPORT_TRANSFORM" {
|
||||
suffixstrip := rec.Metadata["transform_suffixstrip"]
|
||||
table, err := transform.DecodeTransformTable(rec.Metadata["transform_table"])
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
|
@ -455,7 +476,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
|
|||
err = fmt.Errorf("IMPORT_TRANSFORM mentions non-existant domain %q", rec.GetTargetField())
|
||||
errs = append(errs, err)
|
||||
}
|
||||
err = importTransform(c, domain, table, rec.TTL)
|
||||
err = importTransform(c, domain, table, rec.TTL, suffixstrip)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue