mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-12-09 13:46:07 +08:00
working on RP
This commit is contained in:
parent
e42dbcda57
commit
76dbb0ed67
12 changed files with 203 additions and 61 deletions
|
|
@ -115,6 +115,7 @@ func matrixData() *FeatureMatrix {
|
|||
DomainModifierNaptr = "[`NAPTR`](../language-reference/domain-modifiers/NAPTR.md)"
|
||||
DomainModifierOpenpgpkey = "[`DNSKEY`](../language-reference/domain-modifiers/OPENPGPKEY.md)"
|
||||
DomainModifierPtr = "[`PTR`](../language-reference/domain-modifiers/PTR.md)"
|
||||
DomainModifierRP = "[`RP`](../language-reference/domain-modifiers/RP.md)"
|
||||
DomainModifierSMIMEA = "[`SMIMEA`](../language-reference/domain-modifiers/SMIMEA.md)"
|
||||
DomainModifierSoa = "[`SOA`](../language-reference/domain-modifiers/SOA.md)"
|
||||
DomainModifierSrv = "[`SRV`](../language-reference/domain-modifiers/SRV.md)"
|
||||
|
|
@ -280,6 +281,10 @@ func matrixData() *FeatureMatrix {
|
|||
DomainModifierPtr,
|
||||
providers.CanUsePTR,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierRP,
|
||||
providers.CanUseRP,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierSMIMEA,
|
||||
providers.CanUseSMIMEA,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func init() {
|
|||
}
|
||||
```
|
||||
|
||||
STep 2b: Create the struct
|
||||
Step 2b: Create the struct
|
||||
|
||||
Create a struct that will store the fields of this rtype.
|
||||
|
||||
|
|
@ -172,6 +172,108 @@ TODO:
|
|||
* Run the integration tests for BIND
|
||||
* Write documentation
|
||||
|
||||
## Add a capability for the record type
|
||||
|
||||
You'll need to mark which providers support this record type. The
|
||||
initial PR should implement this record for the `BIND` provider at
|
||||
a minimum. `BIND` outputs non-standard rtypes as a comment.
|
||||
|
||||
- Add the capability to the file `dnscontrol/providers/capabilities.go` (look for `CanUseAlias` and add
|
||||
it to the end of the list.)
|
||||
- Run stringer to auto-update the file `dnscontrol/providers/capability_string.go`
|
||||
|
||||
```shell
|
||||
pushd providers/
|
||||
go tool stringer -type=Capability
|
||||
popd
|
||||
```
|
||||
alternatively
|
||||
|
||||
```shell
|
||||
pushd providers/
|
||||
go generate
|
||||
popd
|
||||
```
|
||||
|
||||
- Add this feature to the feature matrix in `dnscontrol/build/generate/featureMatrix.go`. Add it to the variable `matrix` maintaining alphabetical ordering, which should look like this:
|
||||
|
||||
{% code title="dnscontrol/build/generate/featureMatrix.go" %}
|
||||
```diff
|
||||
func matrixData() *FeatureMatrix {
|
||||
const (
|
||||
...
|
||||
DomainModifierCaa = "[`CAA`](language-reference/domain-modifiers/CAA.md)"
|
||||
+ DomainModifierFoo = "[`FOO`](language-reference/domain-modifiers/FOO.md)"
|
||||
DomainModifierLoc = "[`LOC`](language-reference/domain-modifiers/LOC.md)"
|
||||
...
|
||||
)
|
||||
matrix := &FeatureMatrix{
|
||||
Providers: map[string]FeatureMap{},
|
||||
Features: []string{
|
||||
...
|
||||
DomainModifierCaa,
|
||||
+ DomainModifierFoo,
|
||||
DomainModifierLoc,
|
||||
...
|
||||
},
|
||||
}
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
then add it later in the file with a `setCapability()` statement, which should look like this:
|
||||
|
||||
{% code title="dnscontrol/build/generate/featureMatrix.go" %}
|
||||
```diff
|
||||
...
|
||||
+ setCapability(
|
||||
+ DomainModifierFoo,
|
||||
+ providers.CanUseFOO,
|
||||
+ )
|
||||
...
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
- Add the capability to the list of features that zones are validated
|
||||
against (i.e. if you want DNSControl to report an error if this
|
||||
feature is used with a DNS provider that doesn't support it). That's
|
||||
in the `checkProviderCapabilities` function in
|
||||
`pkg/normalize/validate.go`. It should look like this:
|
||||
|
||||
{% code title="pkg/normalize/validate.go" %}
|
||||
```diff
|
||||
var providerCapabilityChecks = []pairTypeCapability{
|
||||
...
|
||||
+ capabilityCheck("FOO", providers.CanUseFOO),
|
||||
...
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
- Mark the `bind` provider as supporting this record type by updating `dnscontrol/providers/bind/bindProvider.go` (look for `providers.CanUse` and you'll see what to do).
|
||||
|
||||
DNSControl will warn/error if this new record is used with a
|
||||
provider that does not support the capability.
|
||||
|
||||
- Add the capability to the validations in `pkg/normalize/validate.go`
|
||||
by adding it to `providerCapabilityChecks`
|
||||
- Some capabilities can't be tested for. If
|
||||
such testing can't be done, add it to the whitelist in function
|
||||
`TestCapabilitiesAreFiltered` in
|
||||
`pkg/normalize/capabilities_test.go`
|
||||
|
||||
If the capabilities testing is not configured correctly, `go test ./...`
|
||||
will report something like the `MISSING` message below. In this
|
||||
example we removed `providers.CanUseCAA` from the
|
||||
`providerCapabilityChecks` list.
|
||||
|
||||
```text
|
||||
--- FAIL: TestCapabilitiesAreFiltered (0.00s)
|
||||
capabilities_test.go:66: ok: providers.CanUseAlias (0) is checked for with "ALIAS"
|
||||
capabilities_test.go:68: MISSING: providers.CanUseCAA (1) is not checked by checkProviderCapabilities
|
||||
capabilities_test.go:66: ok: providers.CanUseNAPTR (3) is checked for with "NAPTR"
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Update providers
|
||||
|
||||
When a provider needs to create a THING, they have two choices
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ func makeTests() []*TestGroup {
|
|||
),
|
||||
|
||||
testgroup("RP",
|
||||
requires(providers.CanUseRP),
|
||||
tc("Create RP", rp("foo", "user.example.com.", "bar.com.")),
|
||||
tc("Create RP", rp("foo", "other.example.com.", "bar.com.")),
|
||||
tc("Create RP", rp("foo", "other.example.com.", "example.com.")),
|
||||
|
|
|
|||
|
|
@ -763,6 +763,7 @@ var providerCapabilityChecks = []pairTypeCapability{
|
|||
capabilityCheck("OPENPGPKEY", providers.CanUseOPENPGPKEY),
|
||||
capabilityCheck("PTR", providers.CanUsePTR),
|
||||
capabilityCheck("R53_ALIAS", providers.CanUseRoute53Alias),
|
||||
capabilityCheck("RP", providers.CanUseRP),
|
||||
capabilityCheck("SMIMEA", providers.CanUseSMIMEA),
|
||||
capabilityCheck("SOA", providers.CanUseSOA),
|
||||
capabilityCheck("SRV", providers.CanUseSRV),
|
||||
|
|
|
|||
|
|
@ -48,3 +48,19 @@ func (handle *RP) CopyToLegacyFields(rec *models.RecordConfig) {
|
|||
rp := rec.F.(*RP)
|
||||
_ = rec.SetTarget(rp.Mbox + " " + rp.Txt)
|
||||
}
|
||||
|
||||
// func (handle *RP) TestData() {
|
||||
// return []itest.TestGroup[
|
||||
// itest.Testgroup("RP",
|
||||
// itest.tc("Create RP", rp("foo", "user.example.com.", "bar.com.")),
|
||||
// itest.tc("Create RP", rp("foo", "other.example.com.", "bar.com.")),
|
||||
// itest.tc("Create RP", rp("foo", "other.example.com.", "example.com.")),
|
||||
// ),
|
||||
// itest.Testgroup("RP-apex",
|
||||
// itest.tc("Create RP", rp("@", "user.example.com.", "bar.com.")),
|
||||
// itest.tc("Create RP", rp("@", "other.example.com.", "bar.com.")),
|
||||
// itest.tc("Create RP", rp("@", "other.example.com.", "example.com.")),
|
||||
// ),
|
||||
// ]
|
||||
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/domaintags"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/miekg/dns/dnsutil"
|
||||
)
|
||||
|
||||
|
|
@ -57,6 +58,22 @@ func NewRecordConfigFromRaw(t string, ttl uint32, args []any, dc *models.DomainC
|
|||
return rec, nil
|
||||
}
|
||||
|
||||
func NewRecordConfigFromString(name string, ttl uint32, t string, s string, dc *models.DomainConfig) (*models.RecordConfig, error) {
|
||||
if _, ok := Func[t]; !ok {
|
||||
return nil, fmt.Errorf("record type %q is not supported", t)
|
||||
}
|
||||
if t == "" {
|
||||
panic("rtypecontrol: NewRecordConfigFromStruct: empty record type")
|
||||
}
|
||||
|
||||
rec, err := dns.NewRR(fmt.Sprintf("$ORIGIN .\n. %d IN %s %s", ttl, t, s))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewRecordConfigFromStruct(name, ttl, t, rec, dc)
|
||||
|
||||
}
|
||||
|
||||
func NewRecordConfigFromStruct(name string, ttl uint32, t string, fields any, dc *models.DomainConfig) (*models.RecordConfig, error) {
|
||||
if _, ok := Func[t]; !ok {
|
||||
return nil, fmt.Errorf("record type %q is not supported", t)
|
||||
|
|
@ -73,11 +90,6 @@ func NewRecordConfigFromStruct(name string, ttl uint32, t string, fields any, dc
|
|||
}
|
||||
setRecordNames(rec, dc, name)
|
||||
|
||||
// // Fill in the .F/.Fields* fields.
|
||||
// err := Func[t].FromArgs(dc, rec, []any{name, fields.(*dns.RP).Mbox, fields.(*dns.RP).Txt})
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
err := Func[t].FromStruct(dc, rec, name, fields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -36,18 +36,19 @@ var features = providers.DocumentationNotes{
|
|||
// The default for unlisted capabilities is 'Cannot'.
|
||||
// See providers/capabilities.go for the entire list of capabilities.
|
||||
providers.CanAutoDNSSEC: providers.Can("Just writes out a comment indicating DNSSEC was requested"),
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanConcur: providers.Can(),
|
||||
providers.CanGetZones: providers.Can(),
|
||||
providers.CanUseCAA: providers.Can(),
|
||||
providers.CanUseDHCID: providers.Can(),
|
||||
providers.CanUseDNAME: providers.Can(),
|
||||
providers.CanUseDS: providers.Can(),
|
||||
providers.CanUseDNSKEY: providers.Can(),
|
||||
providers.CanUseDS: providers.Can(),
|
||||
providers.CanUseHTTPS: providers.Can(),
|
||||
providers.CanUseLOC: providers.Can(),
|
||||
providers.CanUseNAPTR: providers.Can(),
|
||||
providers.CanUseOPENPGPKEY: providers.Can(),
|
||||
providers.CanUsePTR: providers.Can(),
|
||||
providers.CanUseRP: providers.Can(),
|
||||
providers.CanUseSMIMEA: providers.Can(),
|
||||
providers.CanUseSOA: providers.Can(),
|
||||
providers.CanUseSRV: providers.Can(),
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ const (
|
|||
// CanUseRoute53Alias indicates the provider support the specific R53_ALIAS records that only the Route53 provider supports
|
||||
CanUseRoute53Alias
|
||||
|
||||
// CanUseRP indicates the provider can handle RP records
|
||||
CanUseRP
|
||||
|
||||
// CanUseSMIMEA indicates the provider can handle SMIMEA records
|
||||
CanUseSMIMEA
|
||||
|
||||
|
|
|
|||
|
|
@ -25,23 +25,24 @@ func _() {
|
|||
_ = x[CanUseNAPTR-14]
|
||||
_ = x[CanUsePTR-15]
|
||||
_ = x[CanUseRoute53Alias-16]
|
||||
_ = x[CanUseSMIMEA-17]
|
||||
_ = x[CanUseSOA-18]
|
||||
_ = x[CanUseSRV-19]
|
||||
_ = x[CanUseSSHFP-20]
|
||||
_ = x[CanUseSVCB-21]
|
||||
_ = x[CanUseTLSA-22]
|
||||
_ = x[CanUseDNSKEY-23]
|
||||
_ = x[CanUseOPENPGPKEY-24]
|
||||
_ = x[DocCreateDomains-25]
|
||||
_ = x[DocDualHost-26]
|
||||
_ = x[DocOfficiallySupported-27]
|
||||
_ = x[CanUseAKAMAITLC-28]
|
||||
_ = x[CanUseRP-17]
|
||||
_ = x[CanUseSMIMEA-18]
|
||||
_ = x[CanUseSOA-19]
|
||||
_ = x[CanUseSRV-20]
|
||||
_ = x[CanUseSSHFP-21]
|
||||
_ = x[CanUseSVCB-22]
|
||||
_ = x[CanUseTLSA-23]
|
||||
_ = x[CanUseDNSKEY-24]
|
||||
_ = x[CanUseOPENPGPKEY-25]
|
||||
_ = x[DocCreateDomains-26]
|
||||
_ = x[DocDualHost-27]
|
||||
_ = x[DocOfficiallySupported-28]
|
||||
_ = x[CanUseAKAMAITLC-29]
|
||||
}
|
||||
|
||||
const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSMIMEACanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupportedCanUseAKAMAITLC"
|
||||
const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseRPCanUseSMIMEACanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupportedCanUseAKAMAITLC"
|
||||
|
||||
var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 223, 232, 241, 252, 262, 272, 284, 300, 316, 327, 349, 364}
|
||||
var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 219, 231, 240, 249, 260, 270, 280, 292, 308, 324, 335, 357, 372}
|
||||
|
||||
func (i Capability) String() string {
|
||||
idx := int(i) - 0
|
||||
|
|
|
|||
|
|
@ -77,13 +77,16 @@ func init() {
|
|||
//providers.RegisterCustomRecordType("CF_TEMP_REDIRECT", providerName, "")
|
||||
providers.RegisterCustomRecordType("CF_WORKER_ROUTE", providerName, "")
|
||||
providers.RegisterMaintainer(providerName, providerMaintainer)
|
||||
|
||||
// providers.SupportedRecordTypes(provderName,
|
||||
// "CLOUDFLAREAPI_SINGLE_REDIRECT",
|
||||
// )
|
||||
}
|
||||
|
||||
// cloudflareProvider is the handle for API calls.
|
||||
type cloudflareProvider struct {
|
||||
ipConversions []transform.IPConversion
|
||||
ignoredLabels []string
|
||||
//manageRedirects bool // Old "Page Rule"-style redirects.
|
||||
manageWorkers bool
|
||||
accountID string
|
||||
cfClient *cloudflare.API
|
||||
|
|
@ -137,15 +140,6 @@ func (c *cloudflareProvider) GetZoneRecords(domain string, meta map[string]strin
|
|||
}
|
||||
}
|
||||
|
||||
// if c.manageRedirects { // if old-style "page rules" are still being managed.
|
||||
// fmt.Printf("DEBUG: Getting old-style page rules for %s???\n", domain)
|
||||
// // prs, err := c.getPageRules(domainID, domain)
|
||||
// // if err != nil {
|
||||
// // return nil, err
|
||||
// // }
|
||||
// // records = append(records, prs...)
|
||||
// }
|
||||
|
||||
if c.manageSingleRedirects { // if new xor old
|
||||
// Download the list of Single Redirects.
|
||||
// For each one, generate a SINGLEREDIRECT record
|
||||
|
|
@ -285,11 +279,6 @@ func genComparable(rec *models.RecordConfig) string {
|
|||
|
||||
func (c *cloudflareProvider) mkCreateCorrection(newrec *models.RecordConfig, domainID, msg string) []*models.Correction {
|
||||
switch newrec.Type {
|
||||
// case "PAGE_RULE":
|
||||
// return []*models.Correction{{
|
||||
// Msg: msg,
|
||||
// F: func() error { return c.createPageRule(domainID, *newrec.CloudflareRedirect) },
|
||||
// }}
|
||||
case "WORKER_ROUTE":
|
||||
return []*models.Correction{{
|
||||
Msg: msg,
|
||||
|
|
@ -310,8 +299,6 @@ func (c *cloudflareProvider) mkCreateCorrection(newrec *models.RecordConfig, dom
|
|||
func (c *cloudflareProvider) mkChangeCorrection(oldrec, newrec *models.RecordConfig, domainID string, msg string) []*models.Correction {
|
||||
var idTxt string
|
||||
switch oldrec.Type {
|
||||
// case "PAGE_RULE":
|
||||
// idTxt = oldrec.Original.(cloudflare.PageRule).ID
|
||||
case "WORKER_ROUTE":
|
||||
idTxt = oldrec.Original.(cloudflare.WorkerRoute).ID
|
||||
case "CLOUDFLAREAPI_SINGLE_REDIRECT":
|
||||
|
|
@ -322,13 +309,6 @@ func (c *cloudflareProvider) mkChangeCorrection(oldrec, newrec *models.RecordCon
|
|||
msg = msg + color.YellowString(" id=%v", idTxt)
|
||||
|
||||
switch newrec.Type {
|
||||
// case "PAGE_RULE":
|
||||
// return []*models.Correction{{
|
||||
// Msg: msg,
|
||||
// F: func() error {
|
||||
// return c.updatePageRule(idTxt, domainID, *newrec.CloudflareRedirect)
|
||||
// },
|
||||
// }}
|
||||
case "CLOUDFLAREAPI_SINGLE_REDIRECT":
|
||||
return []*models.Correction{{
|
||||
Msg: msg,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
|
||||
"github.com/StackExchange/dnscontrol/v4/models"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/rtypecontrol"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/rtypeinfo"
|
||||
"github.com/StackExchange/dnscontrol/v4/pkg/txtutil"
|
||||
"github.com/go-gandi/go-gandi/livedns"
|
||||
)
|
||||
|
|
@ -18,25 +20,42 @@ func nativeToRecords(n livedns.DomainRecord, origin string) (rcs []*models.Recor
|
|||
// records for a label, all the IP addresses are listed in
|
||||
// n.RrsetValues rather than having many livedns.DomainRecord's.
|
||||
// We must split them out into individual records, one for each value.
|
||||
|
||||
dc := models.MakeFakeDomainConfig(origin)
|
||||
|
||||
for _, value := range n.RrsetValues {
|
||||
rc := &models.RecordConfig{
|
||||
TTL: uint32(n.RrsetTTL),
|
||||
Original: n,
|
||||
}
|
||||
rc.SetLabel(n.RrsetName, origin)
|
||||
var rc *models.RecordConfig
|
||||
var err error
|
||||
|
||||
switch rtype := n.RrsetType; rtype {
|
||||
case "ALIAS":
|
||||
rc.Type = "ALIAS"
|
||||
err = rc.SetTarget(value)
|
||||
default:
|
||||
err = rc.PopulateFromStringFunc(rtype, value, origin, txtutil.ParseQuoted)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unparsable record received from gandi: %w", err)
|
||||
}
|
||||
rtype := n.RrsetType
|
||||
|
||||
if rtypeinfo.IsModernType(rtype) {
|
||||
// func NewRecordConfigFromString(name string, ttl uint32, t string, s string, dc *models.DomainConfig) (*models.RecordConfig, error) {
|
||||
rc, err = rtypecontrol.NewRecordConfigFromString(n.RrsetName, uint32(n.RrsetTTL), rtype, value, dc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unparsable record received from gandi: %w", err)
|
||||
}
|
||||
rc.Original = n
|
||||
} else {
|
||||
rc = &models.RecordConfig{
|
||||
TTL: uint32(n.RrsetTTL),
|
||||
Original: n,
|
||||
}
|
||||
rc.SetLabel(n.RrsetName, origin)
|
||||
|
||||
switch rtype := n.RrsetType; rtype {
|
||||
case "ALIAS":
|
||||
rc.Type = "ALIAS"
|
||||
err = rc.SetTarget(value)
|
||||
default:
|
||||
err = rc.PopulateFromStringFunc(rtype, value, origin, txtutil.ParseQuoted)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unparsable record received from gandi: %w", err)
|
||||
}
|
||||
}
|
||||
rcs = append(rcs, rc)
|
||||
|
||||
}
|
||||
|
||||
return rcs, nil
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ var features = providers.DocumentationNotes{
|
|||
providers.CanUseDSForChildren: providers.Can(),
|
||||
providers.CanUseLOC: providers.Cannot(),
|
||||
providers.CanUsePTR: providers.Can(),
|
||||
providers.CanUseRP: providers.Can(),
|
||||
providers.CanUseSRV: providers.Can(),
|
||||
providers.CanUseSSHFP: providers.Can(),
|
||||
providers.CanUseTLSA: providers.Can(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue