mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 23:06:23 +08:00
ff8ce26cee
This functionality is required by the GCLOUD provider, which supports
recordsets of type DS but only for child records of the zone, to enable
further delegation. It does not support them at the apex of the zone (@)
because Google Cloud DNS is not itself a registrar which needs to model
this information.
A related change (14ff68b151
, #760) was
previously introduced to enable DS support in Google, which broke
integration tests with this provider.
To cleanly support this, we introduce a new provider capability
CanUseDSForChildren and appropriate integration tests. Further, it is no
longer possible to verify a provider has the proper capabilities for a
zone simply by existence of particular records; we adapt the capability
checks to enable inspection of the individual recordsets where this is
required.
Closes #762
163 lines
5 KiB
Go
163 lines
5 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 PTR 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
|
|
|
|
// CanUseTXTMulti indicates the provider can handle TXT records with multiple strings
|
|
CanUseTXTMulti
|
|
|
|
// 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 interchangably
|
|
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]
|
|
}
|
|
}
|