dnscontrol/providers/capabilities.go
Tom Limoncelli 8dea9edc34
Re-engineer TXT records for simplicity and better compliance (#1063)
TXT records are now handled different.

1. The raw input from dnsconfig.js is passed all the way to the provider. The provider can determine if it can or can't handle such records (auditrecords.go) and processes them internally as such.
2. The CanUseTXTMulti capability is no longer needed.

* DSPs now register a table of functions
* Use audits for txt record variations
* unit tests pass. integration fails.
* fix deepcopy problem
* rename to AuditRecordSupport
* Reduce use of TXTMulti
* Remove CanUseTXTMulti
* fix Test Skip
* fix DO
* fix vultr
* fix NDC
* msdns fixes
* Fix powerdns and cloudflare
* HEDNS: Fix usage of target field to resolve TXT handling (#1067)
* Fix HEXONET

Co-authored-by: Robert Blenkinsopp <robert@blenkinsopp.net>
Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
2021-03-07 13:19:22 -05:00

159 lines
4.9 KiB
Go

//go:generate stringer -type=Capability
package providers
import (
"log"
)
// Capability is a bitmasked set of "features" that a provider supports. Only use constants from this package.
type Capability uint32
const (
// If you add something to this list, you probably want to add it to pkg/normalize/validate.go checkProviderCapabilities() or somewhere near there.
// CanUseAlias indicates the provider support ALIAS records (or flattened CNAMES). Up to the provider to translate them to the appropriate record type.
CanUseAlias Capability = iota
// CanUseCAA indicates the provider can handle CAA records
CanUseCAA
// CanUseDS indicates that the provider can handle DS record types. This
// implies CanUseDSForChildren without specifying the latter explicitly.
CanUseDS
// CanUseDSForChildren indicates the provider can handle DS record types, but
// only for children records, not at the root of the zone.
CanUseDSForChildren
// CanUsePTR indicates the provider can handle PTR records
CanUsePTR
// CanUseNAPTR indicates the provider can handle NAPTR records
CanUseNAPTR
// CanUseSRV indicates the provider can handle SRV records
CanUseSRV
// CanUseSSHFP indicates the provider can handle SSHFP records
CanUseSSHFP
// CanUseTLSA indicates the provider can handle TLSA records
CanUseTLSA
// CanAutoDNSSEC indicates that the provider can automatically handle DNSSEC,
// so folks can ask for that.
CanAutoDNSSEC
// CantUseNOPURGE indicates NO_PURGE is broken for this provider. To make it
// work would require complex emulation of an incremental update mechanism,
// so it is easier to simply mark this feature as not working for this
// provider.
CantUseNOPURGE
// DocOfficiallySupported means it is actively used and maintained by stack exchange
DocOfficiallySupported
// DocDualHost means provider allows full management of apex NS records, so we can safely dual-host with anothe provider
DocDualHost
// DocCreateDomains means provider can add domains with the `dnscontrol create-domains` command
DocCreateDomains
// CanUseRoute53Alias indicates the provider support the specific R53_ALIAS records that only the Route53 provider supports
CanUseRoute53Alias
// CanGetZones indicates the provider supports the get-zones subcommand.
CanGetZones
// CanUseAzureAlias indicates the provider support the specific Azure_ALIAS records that only the Azure provider supports
CanUseAzureAlias
)
var providerCapabilities = map[string]map[Capability]bool{}
// ProviderHasCapability returns true if provider has capability.
func ProviderHasCapability(pType string, cap Capability) bool {
if providerCapabilities[pType] == nil {
return false
}
return providerCapabilities[pType][cap]
}
// DocumentationNote is a way for providers to give more detail about what features they support.
type DocumentationNote struct {
HasFeature bool
Unimplemented bool
Comment string
Link string
}
// DocumentationNotes is a full list of notes for a single provider
type DocumentationNotes map[Capability]*DocumentationNote
// ProviderMetadata is a common interface for DocumentationNotes and Capability to be used interchangeably
type ProviderMetadata interface{}
// Notes is a collection of all documentation notes, keyed by provider type
var Notes = map[string]DocumentationNotes{}
func unwrapProviderCapabilities(pName string, meta []ProviderMetadata) {
if providerCapabilities[pName] == nil {
providerCapabilities[pName] = map[Capability]bool{}
}
for _, pm := range meta {
switch x := pm.(type) {
case Capability:
providerCapabilities[pName][x] = true
case DocumentationNotes:
if Notes[pName] == nil {
Notes[pName] = DocumentationNotes{}
}
for k, v := range x {
Notes[pName][k] = v
providerCapabilities[pName][k] = v.HasFeature
}
default:
log.Fatalf("Unrecognized ProviderMetadata type: %T", pm)
}
}
}
// Can is a small helper for concisely creating Documentation Notes
// comments are variadic for easy ommission. First is comment, second is link, the rest are ignored.
func Can(comments ...string) *DocumentationNote {
n := &DocumentationNote{
HasFeature: true,
}
n.addStrings(comments)
return n
}
// Cannot is a small helper for concisely creating Documentation Notes
// comments are variadic for easy ommission. First is comment, second is link, the rest are ignored.
func Cannot(comments ...string) *DocumentationNote {
n := &DocumentationNote{
HasFeature: false,
}
n.addStrings(comments)
return n
}
// Unimplemented is a small helper for concisely creating Documentation Notes
// comments are variadic for easy ommission. First is comment, second is link, the rest are ignored.
func Unimplemented(comments ...string) *DocumentationNote {
n := &DocumentationNote{
HasFeature: false,
Unimplemented: true,
}
n.addStrings(comments)
return n
}
func (n *DocumentationNote) addStrings(comments []string) {
if len(comments) > 0 {
n.Comment = comments[0]
}
if len(comments) > 1 {
n.Link = comments[1]
}
}