2020-03-10 22:13:20 +08:00
//go:generate stringer -type=Capability
2017-09-15 04:13:17 +08:00
package providers
2022-08-15 08:46:56 +08:00
import "log"
2017-09-15 04:13:17 +08:00
2018-01-10 01:53:16 +08:00
// Capability is a bitmasked set of "features" that a provider supports. Only use constants from this package.
2017-09-15 04:13:17 +08:00
type Capability uint32
const (
2022-03-03 00:19:15 +08:00
// Keep this list sorted.
// If you add something here, you probably want to also add it to
// pkg/normalize/validate.go checkProviderCapabilities() or
// somewhere near there.
// CanAutoDNSSEC indicates that the provider can automatically handle DNSSEC,
// so folks can ask for that.
CanAutoDNSSEC Capability = iota
// CanGetZones indicates the provider supports the get-zones subcommand.
CanGetZones
// CanUseAKAMAICDN indicates the provider support the specific AKAMAICDN records that only the Akamai EdgeDns provider supports
CanUseAKAMAICDN
2017-12-21 22:43:21 +08:00
// CanUseAlias indicates the provider support ALIAS records (or flattened CNAMES). Up to the provider to translate them to the appropriate record type.
2022-03-03 00:19:15 +08:00
CanUseAlias
// CanUseAzureAlias indicates the provider support the specific Azure_ALIAS records that only the Azure provider supports
CanUseAzureAlias
2017-12-21 22:43:21 +08:00
2018-01-11 06:06:15 +08:00
// CanUseCAA indicates the provider can handle CAA records
CanUseCAA
2020-06-19 05:24:13 +08:00
// CanUseDS indicates that the provider can handle DS record types. This
// implies CanUseDSForChildren without specifying the latter explicitly.
2020-05-30 22:40:21 +08:00
CanUseDS
2020-06-19 05:24:13 +08:00
// CanUseDSForChildren indicates the provider can handle DS record types, but
// only for children records, not at the root of the zone.
CanUseDSForChildren
2022-03-03 00:19:15 +08:00
// CanUseNAPTR indicates the provider can handle NAPTR records
CanUseNAPTR
2017-09-15 04:13:17 +08:00
// CanUsePTR indicates the provider can handle PTR records
CanUsePTR
2017-12-21 22:43:21 +08:00
2022-03-03 00:19:15 +08:00
// CanUseRoute53Alias indicates the provider support the specific R53_ALIAS records that only the Route53 provider supports
CanUseRoute53Alias
// CanUseSOA indicates the provider supports full management of a zone's SOA record
CanUseSOA
2019-03-28 22:40:13 +08:00
2017-09-15 04:13:17 +08:00
// CanUseSRV indicates the provider can handle SRV records
CanUseSRV
2017-12-21 22:43:21 +08:00
2019-01-29 06:26:20 +08:00
// CanUseSSHFP indicates the provider can handle SSHFP records
CanUseSSHFP
2017-09-15 21:03:29 +08:00
// CanUseTLSA indicates the provider can handle TLSA records
CanUseTLSA
2017-12-21 22:43:21 +08:00
2017-09-15 04:13:17 +08:00
// 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
// DocCreateDomains means provider can add domains with the `dnscontrol create-domains` command
DocCreateDomains
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 18:53:12 +08:00
2022-03-03 00:19:15 +08:00
// DocDualHost means provider allows full management of apex NS records, so we can safely dual-host with anothe provider
DocDualHost
2021-06-22 22:24:49 +08:00
2022-03-03 00:19:15 +08:00
// DocOfficiallySupported means it is actively used and maintained by stack exchange
DocOfficiallySupported
2017-09-15 04:13:17 +08:00
)
var providerCapabilities = map [ string ] map [ Capability ] bool { }
2020-01-13 00:24:10 +08:00
// ProviderHasCapability returns true if provider has capability.
func ProviderHasCapability ( pType string , cap Capability ) bool {
2017-09-15 04:13:17 +08:00
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 {
2017-10-03 23:53:56 +08:00
HasFeature bool
Unimplemented bool
Comment string
Link string
2017-09-15 04:13:17 +08:00
}
// DocumentationNotes is a full list of notes for a single provider
type DocumentationNotes map [ Capability ] * DocumentationNote
2020-07-07 08:18:24 +08:00
// ProviderMetadata is a common interface for DocumentationNotes and Capability to be used interchangeably
2017-09-15 04:13:17 +08:00
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 ) {
2018-01-05 08:19:35 +08:00
if providerCapabilities [ pName ] == nil {
providerCapabilities [ pName ] = map [ Capability ] bool { }
}
2017-09-15 04:13:17 +08:00
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
2018-01-05 08:19:35 +08:00
providerCapabilities [ pName ] [ k ] = v . HasFeature
2017-09-15 04:13:17 +08:00
}
default :
log . Fatalf ( "Unrecognized ProviderMetadata type: %T" , pm )
}
}
}
// Can is a small helper for concisely creating Documentation Notes
2017-09-15 04:25:39 +08:00
// comments are variadic for easy ommission. First is comment, second is link, the rest are ignored.
2017-09-15 04:13:17 +08:00
func Can ( comments ... string ) * DocumentationNote {
2017-09-15 04:25:39 +08:00
n := & DocumentationNote {
2017-09-15 04:13:17 +08:00
HasFeature : true ,
}
2017-09-15 04:25:39 +08:00
n . addStrings ( comments )
return n
2017-09-15 04:13:17 +08:00
}
// Cannot is a small helper for concisely creating Documentation Notes
2017-09-15 04:25:39 +08:00
// comments are variadic for easy ommission. First is comment, second is link, the rest are ignored.
2017-09-15 04:13:17 +08:00
func Cannot ( comments ... string ) * DocumentationNote {
2017-09-15 04:25:39 +08:00
n := & DocumentationNote {
2017-09-15 04:13:17 +08:00
HasFeature : false ,
2017-09-15 04:25:39 +08:00
}
n . addStrings ( comments )
return n
}
2017-10-03 23:53:56 +08:00
// 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
}
2017-09-15 04:25:39 +08:00
func ( n * DocumentationNote ) addStrings ( comments [ ] string ) {
if len ( comments ) > 0 {
n . Comment = comments [ 0 ]
}
if len ( comments ) > 1 {
n . Link = comments [ 1 ]
2017-09-15 04:13:17 +08:00
}
}